485 lines
10 KiB
C
485 lines
10 KiB
C
#include "infohelper.h"
|
|
#include "lpctool_serial.h"
|
|
#include "bootcom.h"
|
|
#include "toolcom.h"
|
|
|
|
#define VERSION_MAJOR 0
|
|
#define VERSION_MINOR 9
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <unistd.h>
|
|
#include <sys/types.h>
|
|
#include <sys/stat.h>
|
|
#include <fcntl.h>
|
|
|
|
unsigned long radr, f0adr, f1adr, gadr;
|
|
|
|
void printHeader(void)
|
|
{
|
|
printf("\nlpctool V%i.%i\n\n", VERSION_MAJOR, VERSION_MINOR);
|
|
printf("This Software is free Software under GNU GPL 3 or later\n");
|
|
printf("(c) 2007 Ch. Klippel <ck@mamalala.net>\n\n");
|
|
}
|
|
|
|
void printUsage(void)
|
|
{
|
|
printf("usage: lpctool [-d NAME] [-i] [-r [NAME]] [-R ADDRESS] [-X [ADDRESS]] [-a [NAME] [-A ADRDESS]] [-e] [-b [NAME] [-B ADDRESS]] [-E] [-s] [-S] [-c] [-C] [-v] [-V]\n\n");
|
|
printf(" -d NAME specify serial device, default is /dev/ttyS0\n");
|
|
printf(" -i use compiled-in flash-tool instead of external ram image file\n");
|
|
printf(" -r NAME specify file for ram, default is ramtool.bin\n");
|
|
printf(" -R ADDRESS optionally specifies the start-address to load into ram\n");
|
|
printf(" default is 0x40000200 - must be specified in hex\n");
|
|
printf(" -X ADDRESS set the execution address for the uploaded ram image\n");
|
|
printf(" defualt is 0x40000200, omiting the address disables execution\n");
|
|
printf(" -a NAME specify file for flash #0, default is flash0.bin\n");
|
|
printf(" -A ADDRESS optionally specifies the start-address to load into flash #0\n");
|
|
printf(" default is 0x80000000 - must be specified in hex\n");
|
|
printf(" -e completely erase the first flash before writing\n");
|
|
printf(" default is no erase\n");
|
|
printf(" -b NAME specify file for flash #1, default is flash1.bin\n");
|
|
printf(" -B ADDRESS optionally specifies the start-address to load into flash #1\n");
|
|
printf(" default is 0x82000000 - must be specified in hex\n");
|
|
printf(" -E completely erase the second flash before writing\n");
|
|
printf(" defualt is no erase\n");
|
|
printf(" -S only erase the first sector in flash before writing\n");
|
|
printf(" this is a lot faster if only the first sector is used\n");
|
|
printf(" -c write flash0 in chunk mode instead of write-all\n");
|
|
printf(" -C write flash1 in chunk mode instead of write-all\n");
|
|
printf(" in chunk mode, parts with 4 consectuive 0xFFFFFFFF or more\n");
|
|
printf(" in the image are skipped. speeds upload when the image has\n");
|
|
printf(" gaps. defualt is off\n");
|
|
printf(" -N do not reset the device after uploading to flash\n");
|
|
printf(" by default the device gets reset after upload\n");
|
|
printf(" -? print this help\n");
|
|
printf(" -v print version\n");
|
|
printf(" -V be more verbose\n");
|
|
printf("\n");
|
|
printf("at least -r or -i must be given to be usefull. everything in [] is optional\n");
|
|
printf("examples:\n");
|
|
printf("\n");
|
|
printf("to just load ramtool.bin, starting at 0x40000200, using serial device /dev/ttyS0 :\n");
|
|
printf("lpcload -r\n\n");
|
|
printf("to do the same, but using serial device /dev/ttyS1 instead :\n");
|
|
printf("lpcload -r -d /dev/ttyS1\n\n");
|
|
printf("using the file image.bin as source for the ram, use /dev/ttyS1 as serial device :\n");
|
|
printf("lpcload -r image.bin -d /dev/ttyS1\n");
|
|
}
|
|
|
|
unsigned long parseHex(char *buf)
|
|
{
|
|
unsigned char cnt;
|
|
unsigned long adr;
|
|
|
|
cnt = 0;
|
|
adr = 0;
|
|
|
|
while(buf[cnt])
|
|
{
|
|
adr <<= 4;
|
|
if(buf[cnt] >= '0' && buf[cnt] <= '9')
|
|
{
|
|
adr += (buf[cnt] - '0');
|
|
}
|
|
else if(buf[cnt] >= 'A' && buf[cnt] <= 'F')
|
|
{
|
|
adr += (buf[cnt] - 'A' + 10);
|
|
}
|
|
else if(buf[cnt] >= 'a' && buf[cnt] <= 'f')
|
|
{
|
|
adr += (buf[cnt] - 'a' + 10);
|
|
}
|
|
else if(buf[cnt] == 'x' || buf[cnt] == 'X')
|
|
{
|
|
adr = 0;
|
|
}
|
|
else
|
|
{
|
|
}
|
|
cnt++;
|
|
}
|
|
return adr;
|
|
}
|
|
|
|
const char hval[] = { "0123456789ABCDEF" };
|
|
|
|
void printHexC(unsigned char num)
|
|
{
|
|
printf("%c%c", hval[(num&0xF0)>>4], hval[num&0x0F]);
|
|
}
|
|
|
|
void printHexS(unsigned short num)
|
|
{
|
|
printHexC((num & 0xFF00) >> 8);
|
|
printHexC(num & 0x00FF);
|
|
}
|
|
|
|
void printHexW(unsigned long num)
|
|
{
|
|
printHexS((num & 0xFFFF0000) >> 16);
|
|
printHexS(num & 0x0000FFFF);
|
|
}
|
|
/*
|
|
void enterBootLD(void)
|
|
{
|
|
setDTR(1);
|
|
usleep(10);
|
|
setRTS(1);
|
|
usleep(100);
|
|
setRTS(0);
|
|
usleep(10);
|
|
setDTR(0);
|
|
usleep(100);
|
|
}
|
|
|
|
void resetFB(void)
|
|
{
|
|
setRTS(1);
|
|
usleep(100);
|
|
setRTS(0);
|
|
}
|
|
*/
|
|
void enterBootLD(void)
|
|
{
|
|
setRTS(1);
|
|
usleep(10);
|
|
setDTR(1);
|
|
usleep(100);
|
|
setDTR(0);
|
|
usleep(10);
|
|
setRTS(0);
|
|
usleep(100);
|
|
}
|
|
|
|
void resetFB(void)
|
|
{
|
|
setDTR(1);
|
|
usleep(100);
|
|
setDTR(0);
|
|
}
|
|
|
|
int main(int argc,char **argv)
|
|
{
|
|
char sname[256];
|
|
char rname[256];
|
|
char f0name[256];
|
|
char f1name[256];
|
|
unsigned char i, cmd;
|
|
unsigned int uflags;
|
|
int fd;
|
|
|
|
sprintf(sname,"/dev/ttyS0");
|
|
sprintf(rname,"ramtool.bin");
|
|
sprintf(f0name,"flash0.bin");
|
|
sprintf(f1name,"flash1.bin");
|
|
|
|
verbosity = 0;
|
|
uflags = 0;
|
|
|
|
radr = 0x40000200;
|
|
f0adr = 0x80000000;
|
|
f1adr = 0x82000000;
|
|
gadr = radr;
|
|
|
|
printHeader();
|
|
|
|
for(i=1;i<argc;i++)
|
|
{
|
|
if(argv[i][0] == '-')
|
|
{
|
|
cmd = 0;
|
|
if(argv[i][1] == '-')
|
|
{
|
|
cmd = argv[i][2];
|
|
}
|
|
else
|
|
{
|
|
cmd = argv[i][1];
|
|
}
|
|
|
|
switch(cmd)
|
|
{
|
|
case 'v':
|
|
verbosity = 2;
|
|
break;
|
|
case 'V':
|
|
goto end;
|
|
case 'd':
|
|
if((argc > i+1) && (argv[i+1][0] != '-'))
|
|
{
|
|
strncpy(sname,argv[++i],256);
|
|
printInfoS(1,"using serial device",sname);
|
|
}
|
|
else
|
|
{
|
|
printError("Error in device argument");
|
|
goto bailout;
|
|
}
|
|
break;
|
|
case 'r':
|
|
if((argc > i+1) && (argv[i+1][0] != '-'))
|
|
{
|
|
strncpy(rname,argv[++i],256);
|
|
printInfoS(1,"using ram image",rname);
|
|
}
|
|
uflags |= 0x01;
|
|
break;
|
|
case 'R':
|
|
if((argc > i+1) && (argv[i+1][0] != '-'))
|
|
{
|
|
radr = parseHex(argv[++i]);
|
|
printInfoH(1,"loading ram @",radr);
|
|
}
|
|
else
|
|
printInfoH(1,"used -R but no address given, using default", radr);
|
|
break;
|
|
case 'a':
|
|
if((argc > i+1) && (argv[i+1][0] != '-'))
|
|
{
|
|
strncpy(f0name,argv[++i],256);
|
|
printInfoS(1,"using flash #0 image",f0name);
|
|
}
|
|
uflags |= 0x02;
|
|
break;
|
|
case 'A':
|
|
if((argc > i+1) && (argv[i+1][0] != '-'))
|
|
{
|
|
f0adr = parseHex(argv[++i]);
|
|
printInfoH(1,"setting address for flash #0 @",f0adr);
|
|
}
|
|
else
|
|
printInfoH(1,"used -A but no address given, using default",f0adr);
|
|
break;
|
|
case 'b':
|
|
if((argc > i+1) && (argv[i+1][0] != '-'))
|
|
{
|
|
strncpy(f1name,argv[++i],256);
|
|
printInfoS(1,"using flash #1 image",f1name);
|
|
}
|
|
uflags |= 0x04;
|
|
break;
|
|
case 'B':
|
|
if((argc > i+1) && (argv[i+1][0] != '-'))
|
|
{
|
|
f1adr = parseHex(argv[++i]);
|
|
printInfoH(1,"setting address for flash #1 @",f1adr);
|
|
}
|
|
else
|
|
printInfoH(1,"used -B but no address given, using default",f1adr);
|
|
break;
|
|
case 'X':
|
|
if((argc > i+1) && (argv[i+1][0] != '-'))
|
|
{
|
|
gadr = parseHex(argv[++i]);
|
|
printInfoH(1,"setting ram execute address @",gadr);
|
|
uflags |= 0x08;
|
|
}
|
|
else
|
|
printInfoS(1,"disabling auto-run",0);
|
|
break;
|
|
case 'e':
|
|
printInfoS(1,"erasing flash #0 before write",0);
|
|
uflags |= 0x10;
|
|
break;
|
|
case 'E':
|
|
printInfoS(1,"erasing flash #1 before write",0);
|
|
uflags |= 0x20;
|
|
break;
|
|
case 'S':
|
|
printInfoS(1,"only erasing start sector",0);
|
|
uflags |= 0x40;
|
|
break;
|
|
case 's':
|
|
printInfoS(1,"auto-erasing sectors as needed",0);
|
|
uflags |= 0x80;
|
|
break;
|
|
case 'N':
|
|
printInfoS(1,"dont reset after flash upload is done",0);
|
|
uflags |= 0x100;
|
|
break;
|
|
case 'c':
|
|
printInfoS(1,"using chunk mode for flash #0",0);
|
|
uflags |= 0x200;
|
|
break;
|
|
case 'C':
|
|
printInfoS(1,"using chunk mode for flash #1",0);
|
|
uflags |= 0x400;
|
|
break;
|
|
case 'i':
|
|
uflags |= 0x800;
|
|
break;
|
|
default:
|
|
goto bailout;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
bailout:
|
|
printUsage();
|
|
goto end;
|
|
}
|
|
}
|
|
|
|
if(!uflags)
|
|
{
|
|
printUsage();
|
|
printInfoS(0,"\nnothing to do!",0);
|
|
goto end;
|
|
}
|
|
|
|
printInfoS(2,"opening serial device",sname);
|
|
if(openSerial(sname) <= 0)
|
|
{
|
|
printError("Error opening serial device");
|
|
goto end;
|
|
}
|
|
|
|
if((uflags & 0x01) || (uflags & 0x800))
|
|
{
|
|
if(!(uflags & 0x800))
|
|
{
|
|
printInfoS(2,"opening ram image",rname);
|
|
fd = open(rname,O_RDONLY);
|
|
if(fd < 0)
|
|
{
|
|
printErrorS("cant open",rname);
|
|
goto end;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
fd = 0;
|
|
}
|
|
|
|
printInfoS(2,"reset into bootmode",0);
|
|
enterBootLD();
|
|
|
|
printInfoS(2,"opening bootloader",0);
|
|
if(!openBootLoader(10000))
|
|
{
|
|
printError("Error opening BootLoader");
|
|
goto end;
|
|
}
|
|
|
|
printInfoS(2,"unlocking bootloader",0);
|
|
if(!unlockBootLoader())
|
|
{
|
|
printError("Error unlocking BootLoader");
|
|
goto end;
|
|
}
|
|
if(!(uflags & 0x800))
|
|
{
|
|
printInfoS(1,"uploading ram image",rname);
|
|
}
|
|
else
|
|
{
|
|
printInfoS(1,"uploading compiled-in ram image",0);
|
|
}
|
|
if(uploadRAM(fd, radr))
|
|
{
|
|
printInfoS(1,"ram uploaded",0);
|
|
if(!(uflags&0x08))
|
|
{
|
|
printInfoH(1,"executing code at ram address",gadr);
|
|
if(!goBootLoader(gadr))
|
|
{
|
|
printError("Error starting from ram");
|
|
goto end;
|
|
}
|
|
printInfoH(2,"code execution started",gadr);
|
|
}
|
|
}
|
|
if(fd)
|
|
{
|
|
close(fd);
|
|
}
|
|
}
|
|
|
|
usleep(100000);
|
|
reconfSerial(TOOLBAUD, 0, 5);
|
|
|
|
//while(1)
|
|
{};
|
|
|
|
if(uflags & 0x06)
|
|
{
|
|
printInfoS(2,"opening ram tool",0);
|
|
if(openRamTool())
|
|
printInfoS(2,"opened ramtool",0);
|
|
else
|
|
goto end;
|
|
|
|
if(uflags & 0x02)
|
|
{
|
|
printInfoS(2,"opening flash0 image",f0name);
|
|
fd = open(f0name,O_RDONLY);
|
|
if(fd < 0)
|
|
{
|
|
printErrorS("cant open",f0name);
|
|
goto end;
|
|
}
|
|
printInfoS(1,"uploading flash0 image",f0name);
|
|
if(uflags & 0x200)
|
|
{
|
|
if(uploadChunks(fd, f0adr, (uflags & 0x50)))
|
|
printInfoS(1,"flash #0 uploaded",0);
|
|
else
|
|
goto end;
|
|
}
|
|
else
|
|
{
|
|
if(uploadFlash(fd, f0adr, (uflags & 0x50)))
|
|
printInfoS(1,"flash #0 uploaded",0);
|
|
else
|
|
goto end;
|
|
}
|
|
}
|
|
|
|
close(fd);
|
|
|
|
if(uflags & 0x04)
|
|
{
|
|
printInfoS(2,"opening flash1 image",f1name);
|
|
fd = open(f1name,O_RDONLY);
|
|
if(fd < 0)
|
|
{
|
|
printErrorS("cant open",f1name);
|
|
goto end;
|
|
}
|
|
printInfoS(1,"uploading flash1 image",f1name);
|
|
if(uflags & 0x400)
|
|
{
|
|
if(uploadChunks(fd, f1adr, (uflags & 0x60)))
|
|
printInfoS(1,"flash #1 uploaded",0);
|
|
else
|
|
goto end;
|
|
}
|
|
else
|
|
{
|
|
if(uploadFlash(fd, f1adr, (uflags & 0x60)))
|
|
printInfoS(1,"flash #1 uploaded",0);
|
|
else
|
|
goto end;
|
|
}
|
|
|
|
}
|
|
close(fd);
|
|
if((uflags & 06) && !(uflags & 0x100))
|
|
{
|
|
printInfoS(2,"reset device",0);
|
|
resetFB();
|
|
}
|
|
}
|
|
|
|
end:
|
|
if(fd)
|
|
{
|
|
printInfoS(2,"closing file descriptor",0);
|
|
close(fd);
|
|
}
|
|
printInfoS(2,"closing serial device",sname);
|
|
closeSerial();
|
|
printf("\n");
|
|
return 0;
|
|
}
|