X-Git-Url: https://hackdaworld.org/gitweb/?a=blobdiff_plain;f=betty%2Flpcload.c;h=a1dd97f044ce5bd9b5963a7e9fbebb769ed3c288;hb=4474a24ed63502f06e217a30350155b7b8ae6a80;hp=0bf3006aa7dd262c3ce0872bd309cd7e4c1626ed;hpb=f549db2020c9e68e37e89f3cb7a921e5a7f75954;p=my-code%2Farm.git diff --git a/betty/lpcload.c b/betty/lpcload.c index 0bf3006..a1dd97f 100644 --- a/betty/lpcload.c +++ b/betty/lpcload.c @@ -40,10 +40,13 @@ #define INVALID_STOP_BIT "18\r\n" #define CRYSTFREQ "10000" +#define RAMOFFSET 0x40000200 -#define BUFSIZE 64 +#define BUFSIZE 128 typedef unsigned char u8; +typedef unsigned short u16; +typedef unsigned int u32; typedef struct s_lpc { int sfd; /* serial fd */ @@ -54,6 +57,8 @@ typedef struct s_lpc { char freq[8]; /* frequency */ int partid; /* part id */ u8 bcv[2]; /* boot code version */ + u32 hoff; /* start addr of ihex file */ + u32 roff; /* ram offset of uc */ } t_lpc; void usage(void) { @@ -62,6 +67,7 @@ void usage(void) { printf(" -d \n"); printf(" -f \n"); printf(" -c \n"); + printf(" -r \n"); printf(" -v\n"); } @@ -116,6 +122,9 @@ int open_serial_device(t_lpc *lpc) { int open_firmware(t_lpc *lpc) { + int ret; + char buf[BUFSIZE]; + /* open firmware file */ lpc->fwfd=open(lpc->fwfile,O_RDONLY); @@ -123,10 +132,20 @@ int open_firmware(t_lpc *lpc) { if(lpc->fwfd<0) perror("fw open"); + /* read hex file offset */ + + ret=read(lpc->fwfd,buf,7); + if(buf[0]!=':') { + printf("fw open: not an intel hex file?\n"); + return -1; + } + sscanf(buf+3,"%04x",&(lpc->hoff)); + lseek(lpc->fwfd,0,SEEK_SET); + return lpc->fwfd; } -int txrx(t_lpc *lpc,u8 *buf,int len,u8 type) { +int txrx(t_lpc *lpc,char *buf,int len,u8 type) { int ret,cnt; int i; @@ -218,7 +237,7 @@ int txrx(t_lpc *lpc,u8 *buf,int len,u8 type) { int bl_init(t_lpc *lpc) { - u8 buf[BUFSIZE]; + char buf[BUFSIZE]; int len; /* auto baud sequence */ @@ -252,7 +271,7 @@ int bl_init(t_lpc *lpc) { int read_part_id(t_lpc *lpc) { - u8 buf[BUFSIZE]; + char buf[BUFSIZE]; memcpy(buf,"J\r\n",3); txrx(lpc,buf,3,TXRX_TYPE_CMD); @@ -263,7 +282,7 @@ int read_part_id(t_lpc *lpc) { int read_bcv(t_lpc *lpc) { - u8 buf[BUFSIZE]; + char buf[BUFSIZE]; char *ptr; memcpy(buf,"K\r\n",3); @@ -276,7 +295,7 @@ int read_bcv(t_lpc *lpc) { return 0; } -int uuencode(u8 *in,u8 *out) { +int uuencode(u8 *in,char *out) { out[0]=0x20+((in[0]>>2)&0x3f); out[1]=0x20+(((in[0]<<4)|(in[1]>>4))&0x3f); @@ -286,11 +305,11 @@ int uuencode(u8 *in,u8 *out) { return 0; } -int write_to_ram(t_lpc *lpc,u8 *buf,int addr,int len) { +int write_to_ram(t_lpc *lpc,u8 *buf,u32 addr,int len) { int lcount; - u8 checksum; - u8 txrxbuf[BUFSIZE]; + u32 checksum; + char txrxbuf[BUFSIZE]; int count,bcnt; int nlen,slen; int i; @@ -309,12 +328,14 @@ int write_to_ram(t_lpc *lpc,u8 *buf,int addr,int len) { } for(i=len;iroff-lpc->hoff); + /* prepare write command */ - snprintf(txrxbuf,BUFSIZE,"W %d %d",addr,len); + if(lpc->info&VERBOSE) + printf("writing %02x bytes to %08x\n",len,addr); + snprintf(txrxbuf,BUFSIZE,"W %d %d\r\n",addr,len); slen=strlen(txrxbuf); - txrxbuf[slen]='\r'; - txrxbuf[slen+1]='\0'; - slen+=2; /* send command and check return code */ txrx(lpc,txrxbuf,slen,TXRX_TYPE_CMD); @@ -347,10 +368,11 @@ int write_to_ram(t_lpc *lpc,u8 *buf,int addr,int len) { count+=3; /* checksum */ - if(!(lcount%20)) { + if((!(lcount%20))|(bcnt==nlen)) { /* send checksum */ - txrxbuf[0]=checksum; - txrx(lpc,txrxbuf,1,TXRX_TYPE_CMD); + snprintf(txrxbuf,BUFSIZE,"%d\r\n",checksum); + slen=strlen(txrxbuf); + txrx(lpc,txrxbuf,slen,TXRX_TYPE_CMD); if(!strncmp(txrxbuf,"RESEND\r\n",8)) { printf("ram write: resending ...\n"); bcnt-=count; @@ -371,25 +393,74 @@ int write_to_ram(t_lpc *lpc,u8 *buf,int addr,int len) { int firmware_to_ram(t_lpc *lpc) { - char line[BUFSIZE]; char buf[BUFSIZE]; + u8 data[BUFSIZE]; + u32 addr,len,type,val; + u8 cksum; + int ret,i; - /* read file */ + /* read a line */ while(ret) { - /* read line */ - while(ret) { - ret=read(lpc->fwfd,line,1); - if(line[0]!=':') { + /* sync line */ + ret=read(lpc->fwfd,buf,1); + switch(buf[0]) { + case '\r': + continue; + case '\n': + continue; + case ':': + /* start code */ + break; + default: printf("fw to ram: no ihex format\n"); return -1; - } - ret=read(lpc->fwfd,line+1,2); - line[3]='\0'; - len=atoi(line+1); - ret=read(lpc->fwfd,line+3,4); - line[7]='\0'; - addr=strtol(line+3); - + } + /* read len */ + ret=read(lpc->fwfd,buf,2); + sscanf(buf,"%02x",&len); + if(len%4) { + printf("fw to ram: len not a multiple of 4\n"); + return -1; + } + /* read addr */ + ret=read(lpc->fwfd,buf,4); + sscanf(buf,"%04x",&addr); + /* read type */ + ret=read(lpc->fwfd,buf,2); + sscanf(buf,"%02x",&type); + /* successfull return if type is end of file */ + if(type==0x01) + return 0; + /* read data */ + ret=read(lpc->fwfd,buf,2*len); + if(ret!=(2*len)) { + printf("fw to ram: data missing\n"); + return -1; + } + /* checksum */ + cksum=0; + for(i=0;ifwfd,buf,2); + sscanf(buf,"%02x",&val); + if(val+cksum!=0x100) { + printf("fw to ram: wrong checksum\n"); + return -1; + } + /* act according to type */ + switch(type) { + case 0x03: + /* get cs and ip */ + break; + case 0x00: + write_to_ram(lpc,data,addr,len); + break; + default: + printf("fw to ram: unknown type %02x\n",type); + return -1; } } @@ -407,6 +478,7 @@ int main(int argc,char **argv) { memset(&lpc,0,sizeof(t_lpc)); strncpy(lpc.freq,CRYSTFREQ,7); + lpc.roff=RAMOFFSET; /* parse argv */ @@ -442,9 +514,14 @@ int main(int argc,char **argv) { if(open_serial_device(&lpc)<0) goto end; + /* open firmware file */ + if(open_firmware(&lpc)<0) + goto end; + /* boot loader init */ printf("boot loader init ...\n"); - bl_init(&lpc); + if(bl_init(&lpc)<0) + return -1; /* read part id */ read_part_id(&lpc); @@ -455,8 +532,6 @@ int main(int argc,char **argv) { printf("boot code version: %02x %02x\n",lpc.bcv[0],lpc.bcv[1]); // to be continued ... (parsing fw file and poking it to ram) - if(open_firmware(&lpc)<0) - goto end; firmware_to_ram(&lpc); end: