X-Git-Url: https://hackdaworld.org/gitweb/?a=blobdiff_plain;f=betty%2Flpcload.c;h=905ebbdcb2e29a0544989d05c0fcce4092cb5c85;hb=c085074294f2852dbe03000d077c9a44b0d7d888;hp=8bd853010f225979c073ad24a3d5aaa630b693f6;hpb=e98e1b46f919aaa0eadb3a74ada0e4f6220a589c;p=my-code%2Farm.git diff --git a/betty/lpcload.c b/betty/lpcload.c index 8bd8530..905ebbd 100644 --- a/betty/lpcload.c +++ b/betty/lpcload.c @@ -19,7 +19,9 @@ #define TXRX_TYPE_BAUD 0x01 #define TXRX_TYPE_SYNC 0x02 -#define TXRX_TYPE_DATA 0x03 +#define TXRX_TYPE_CMD 0x03 +#define TXRX_TYPE_DATA 0x04 +#define TXRX_TYPE_CKSM 0x05 #define CMD_SUCCESS "0\r\n" #define INVALID_COMMAND "1\r\n" @@ -39,10 +41,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 */ @@ -53,6 +58,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) { @@ -61,6 +68,7 @@ void usage(void) { printf(" -d \n"); printf(" -f \n"); printf(" -c \n"); + printf(" -r \n"); printf(" -v\n"); } @@ -99,14 +107,18 @@ int open_serial_device(t_lpc *lpc) { term.c_lflag&=~(ICANON|ECHO|ECHOE|ISIG); - // input options -> disable flow control + // input options -> enable flow control - term.c_iflag&=~(IXON|IXOFF|IXANY); + //term.c_iflag&=~(IXON|IXOFF|IXANY|INLCR|ICRNL); + term.c_iflag&=~(INLCR|ICRNL); + term.c_iflag|=(IXON|IXOFF|IXANY); - // more control options -> timeout + // more control options -> timeout / flow control term.c_cc[VMIN]=0; term.c_cc[VTIME]=10; // 1 second timeout + term.c_cc[VSTART]=0x11; + term.c_cc[VSTOP]=0x13; tcsetattr(lpc->sfd,TCSANOW,&term); @@ -115,6 +127,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); @@ -122,6 +137,16 @@ 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; } @@ -149,29 +174,66 @@ int txrx(t_lpc *lpc,char *buf,int len,u8 type) { len-=ret; cnt+=ret; } - if(lpc->info&VERBOSE) - printf(" (%d)\n",cnt); + if(lpc->info&VERBOSE) { + printf(" | "); + for(i=0;i0) { ret=read(lpc->sfd,buf,cnt); if(ret<0) { perror("txrx echo cut"); return ret; } + if(type==TXRX_TYPE_CKSM) { + printf(" cksm resp: "); + for(i=0;isfd,buf,BUFSIZE); + for(i=0;iinfo&VERBOSE) printf(" << "); ret=1; cnt=0; - while(ret>0) { + while(ret) { ret=read(lpc->sfd,buf+cnt,BUFSIZE-cnt); if(ret<0) { perror("txrx read"); @@ -188,14 +250,17 @@ int txrx(t_lpc *lpc,char *buf,int len,u8 type) { buf[cnt+i]:'.'); cnt+=ret; } - if(lpc->info&VERBOSE) - printf(" (%d)\n",cnt); - len=cnt; + if(lpc->info&VERBOSE) { + printf(" | "); + for(i=0;ipartid=atoi(buf); return lpc->partid; @@ -262,7 +327,7 @@ int read_bcv(t_lpc *lpc) { char *ptr; memcpy(buf,"K\r\n",3); - txrx(lpc,buf,3,TXRX_TYPE_DATA); + txrx(lpc,buf,3,TXRX_TYPE_CMD); ptr=strtok(buf,"\r\n"); lpc->bcv[0]=strtol(ptr,NULL,16); ptr=strtok(NULL,"\r\n"); @@ -271,37 +336,131 @@ int read_bcv(t_lpc *lpc) { return 0; } +int unlock_go(t_lpc *lpc) { + + char buf[BUFSIZE]; + int ret; + + memcpy(buf,"U 23130\r\n",9); + ret=txrx(lpc,buf,9,TXRX_TYPE_CMD); + + return ret; +} + +int go(t_lpc *lpc) { + + char buf[BUFSIZE]; + int ret,len; + + snprintf(buf,BUFSIZE,"G %d A\r\n",lpc->roff); + len=strlen(buf); + ret=txrx(lpc,buf,ret,TXRX_TYPE_CMD); + + return ret; +} + int uuencode(char *in,char *out) { + int i; + out[0]=0x20+((in[0]>>2)&0x3f); out[1]=0x20+(((in[0]<<4)|(in[1]>>4))&0x3f); out[2]=0x20+(((in[1]<<2)|(in[2]>>6))&0x3f); out[3]=0x20+(in[2]&0x3f); + printf(" enc: "); + for(i=0;i<3;i++) + printf("%02x ",in[i]); + printf("-> "); + for(i=0;i<4;i++) + printf("%02x ",out[i]); + printf("\n"); + return 0; } -int write_to_ram(t_lpc *lpc,char *buf,int addr,int len) { +int write_to_ram(t_lpc *lpc,char *buf,u32 addr,int len) { int lcount; - u8 checksum; + u32 checksum; + char txrxbuf[BUFSIZE]; + int count,bcnt; + int nlen,slen; + int i; + /* check length */ if(len%4) { printf("ram write: not a multiple of 4\n"); return -1; } - while(1) { - if(!(lcount%20)) { + /* make it a multiple of 3 (reason: uuencode) */ + nlen=(len/3+1)*3; + if(nlen>BUFSIZE) { + printf("ram write: too much data\n"); + return -1; + } + for(i=len;iroff-lpc->hoff); + + /* prepare write command */ + if(lpc->info&VERBOSE) + printf("writing 0x%02x bytes to 0x%08x\n",len,addr); + snprintf(txrxbuf,BUFSIZE,"W %d %d\r\n",addr,len); + slen=strlen(txrxbuf); + + /* send command and check return code */ + txrx(lpc,txrxbuf,slen,TXRX_TYPE_CMD); + //if(strncmp(txrxbuf,"OK\r\n",4)) { + // printf("ram write: write command failed\n"); + // return -1; + //} + + /* send data */ + lcount=0; + bcnt=0; + count=0; + checksum=0; + while(bcnt %d %d\n",checksum,bcnt); + + /* send a data line */ + txrx(lpc,txrxbuf,6,TXRX_TYPE_DATA); + + /* increase counters */ + lcount+=1; + bcnt+=3; + count+=3; + + /* checksum */ + if((!(lcount%20))|(bcnt==nlen)) { /* send checksum */ - if(lcount!=0) { - + snprintf(txrxbuf,BUFSIZE,"%d\r\n",checksum%0x100); + slen=strlen(txrxbuf); + txrx(lpc,txrxbuf,slen,TXRX_TYPE_CKSM); + if(!strncmp(txrxbuf,"RESEND\r\n",8)) { + printf("ram write: resending ...\n"); + bcnt-=count; + } + if(strncmp(txrxbuf,"OK\r\n",4)) { + printf("ram write: bad response\n"); + return -1; } - /* reset checksum */ + /* reset checksum & counter */ checksum=0; + count=0; } - lcount+=1; } return 0; @@ -309,7 +468,63 @@ int write_to_ram(t_lpc *lpc,char *buf,int addr,int len) { int firmware_to_ram(t_lpc *lpc) { - + char buf[BUFSIZE]; + u32 addr,len,type; + int ret; + + /* read a line */ + while(ret) { + /* 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; + } + /* 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 */ + ret=read(lpc->fwfd,buf,2); + /* act according to type */ + switch(type) { + case 0x03: + /* get cs and ip */ + break; + case 0x00: + write_to_ram(lpc,buf,addr,len); + break; + default: + printf("fw to ram: unknown type %02x\n",type); + return -1; + } + } return 0; } @@ -325,6 +540,7 @@ int main(int argc,char **argv) { memset(&lpc,0,sizeof(t_lpc)); strncpy(lpc.freq,CRYSTFREQ,7); + lpc.roff=RAMOFFSET; /* parse argv */ @@ -360,9 +576,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); @@ -372,11 +593,15 @@ int main(int argc,char **argv) { read_bcv(&lpc); 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; + /* parse intel hex file and write to ram */ firmware_to_ram(&lpc); + /* unlock go cmd */ + unlock_go(&lpc); + + /* go! */ + go(&lpc); + end: close(lpc.sfd); close(lpc.fwfd);