X-Git-Url: https://hackdaworld.org/gitweb/?a=blobdiff_plain;f=betty%2Flpcload.c;h=f7911a89e2730f0ccc0f51b825f1a85cd37713d3;hb=d24fd4a34d026918724fad1ddbb0da1de9d28c63;hp=a1dd97f044ce5bd9b5963a7e9fbebb769ed3c288;hpb=4474a24ed63502f06e217a30350155b7b8ae6a80;p=my-code%2Farm.git diff --git a/betty/lpcload.c b/betty/lpcload.c index a1dd97f..f7911a8 100644 --- a/betty/lpcload.c +++ b/betty/lpcload.c @@ -1,8 +1,10 @@ /* * lpcload.c - load firmware into ram of lpc2220 via uart0 * - * author: hackbard@hackdaworld.org + * author: hackbard@hackdaworld.org, rolf.anders@physik.uni-augsburg.de * + * build: make + * usage: sudo ./lpcload -d /dev/ttyS0 -f firmware.hex [-v] */ #include @@ -16,11 +18,24 @@ #define VERBOSE (1<<0) #define FIRMWARE (1<<1) +#define BANK0 (1<<2) +#define BANK2 (1<<3) +#define BL (1<<4) +#define BANK0_ADDR 0x80000000 +#define BANK2_ADDR 0x82000000 +#define BANK_SIZE 0x00100000 +#define BL_ADDR 0x7fffe000 +#define BL_SIZE 0x00000800 + +#define CMD_READ 'R' // stay compatible to fwflash! + +#define TXRX_TYPE_SYNC 0x00 +#define TXRX_TYPE_CKSM 0x00 #define TXRX_TYPE_BAUD 0x01 -#define TXRX_TYPE_SYNC 0x02 -#define TXRX_TYPE_CMD 0x03 -#define TXRX_TYPE_DATA 0x04 +#define TXRX_TYPE_CMD 0x02 +#define TXRX_TYPE_DATA 0x03 +#define TXRX_TYPE_GO 0x04 #define CMD_SUCCESS "0\r\n" #define INVALID_COMMAND "1\r\n" @@ -55,19 +70,24 @@ typedef struct s_lpc { char fwfile[128]; /* firmware file */ u8 info; /* info/mode */ char freq[8]; /* frequency */ - int partid; /* part id */ - u8 bcv[2]; /* boot code version */ - u32 hoff; /* start addr of ihex file */ + char bank0[127]; /* flash dump bank0 */ + int b0fd; /* dumpfile fd bank0 */ + char bank2[127]; /* flash dump bank2 */ + int b2fd; /* dumpfile fd bank0 */ + char bl[127]; /* flash dump bootloader */ + int blfd; /* dumpfile fd bootloader */ u32 roff; /* ram offset of uc */ + u32 jaddr; /* addr for the jump */ } t_lpc; void usage(void) { printf("possible argv:\n"); - printf(" -d \n"); - printf(" -f \n"); - printf(" -c \n"); - printf(" -r \n"); + printf(" -d \n"); + printf(" -f \n"); + printf(" -c \n"); + printf(" -Dx \n"); + printf(" x=0: bank0, x=2: bank2, x=b: bootloader\n"); printf(" -v\n"); } @@ -92,8 +112,8 @@ int open_serial_device(t_lpc *lpc) { // input/output baudrate - cfsetispeed(&term,B9600); - cfsetospeed(&term,B9600); + cfsetispeed(&term,B38400); + cfsetospeed(&term,B38400); // control options -> 8n1 @@ -106,14 +126,22 @@ 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|IXANY); + term.c_iflag|=(IXON|IXOFF); + + // output options + + term.c_oflag=0; - // 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); @@ -122,9 +150,6 @@ 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); @@ -132,19 +157,40 @@ int open_firmware(t_lpc *lpc) { if(lpc->fwfd<0) perror("fw open"); - /* read hex file offset */ + return lpc->fwfd; +} - ret=read(lpc->fwfd,buf,7); - if(buf[0]!=':') { - printf("fw open: not an intel hex file?\n"); - return -1; +int open_dumpfiles(t_lpc *lpc) { + + /* open dumpfiles */ + + if(lpc->info&BANK0) { + lpc->b0fd=open(lpc->bank0,O_WRONLY|O_CREAT); + if(lpc->b0fd<0) { + perror("bank0 dump file open"); + return lpc->b0fd; + } } - sscanf(buf+3,"%04x",&(lpc->hoff)); - lseek(lpc->fwfd,0,SEEK_SET); - return lpc->fwfd; -} + if(lpc->info&BANK2) { + lpc->b2fd=open(lpc->bank2,O_WRONLY|O_CREAT); + if(lpc->b2fd<0) { + perror("bank2 dump file open"); + return lpc->b2fd; + } + } + + if(lpc->info&BL) { + lpc->blfd=open(lpc->bl,O_WRONLY|O_CREAT); + if(lpc->blfd<0) { + perror("bootloader dump file open"); + return lpc->blfd; + } + } + + return 0; +} int txrx(t_lpc *lpc,char *buf,int len,u8 type) { int ret,cnt; @@ -169,8 +215,14 @@ 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;iinfo&VERBOSE) - printf(" << "); + ret=read(lpc->sfd,buf,1); + if(ret<0) { + perror("txrx read (first byte)"); + return ret; + } + + switch(buf[0]) { + case 'S': + cnt=13; + break; + case 'O': + cnt=3; + break; + case 'R': + cnt=7; + break; + case '0': + cnt=2; + break; + default: + printf("txrx read: bad return byte '%02x'\n",buf[0]); + break; + } + ret=1; - cnt=0; - while(ret>0) { - ret=read(lpc->sfd,buf+cnt,BUFSIZE-cnt); + i=cnt; + while(i) { + ret=read(lpc->sfd,buf+1+cnt-i,i); if(ret<0) { - perror("txrx read"); + perror("txrx read (next bytes)"); return ret; } - if(ret+cnt>BUFSIZE) { - printf("txrx read: too small buf size (%d)!\n",BUFSIZE); - return -1; - } - if(lpc->info&VERBOSE) - for(i=0;i0x19)&(buf[cnt+i]<0x7f))? - buf[cnt+i]:'.'); - cnt+=ret; + i-=ret; } - if(lpc->info&VERBOSE) - printf(" (%d)\n",cnt); - buf[cnt]='\0'; + if(lpc->info&VERBOSE) { + printf(" << "); + for(i=0;i0x19)&(buf[i]<0x7f))? + buf[i]:'.'); + printf(" | "); + for(i=0;ipartid=atoi(buf); + memcpy(buf,"U 23130\r\n",9); + ret=txrx(lpc,buf,9,TXRX_TYPE_CMD); - return lpc->partid; + return ret; } -int read_bcv(t_lpc *lpc) { +int go(t_lpc *lpc) { char buf[BUFSIZE]; - char *ptr; + int ret,len; - memcpy(buf,"K\r\n",3); - txrx(lpc,buf,3,TXRX_TYPE_CMD); - ptr=strtok(buf,"\r\n"); - lpc->bcv[0]=strtol(ptr,NULL,16); - ptr=strtok(NULL,"\r\n"); - lpc->bcv[1]=strtol(ptr,NULL,16); + snprintf(buf,BUFSIZE,"G %d A\r\n",lpc->jaddr); + len=strlen(buf); + ret=txrx(lpc,buf,len,TXRX_TYPE_GO); - return 0; + return ret; } -int uuencode(u8 *in,char *out) { +int uuencode(u8 *in,u8 *out,int len) { - 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); + out[0]=0x20+len; + out[1]=0x20+((in[0]>>2)&0x3f); + out[2]=0x20+(((in[0]<<4)|(in[1]>>4))&0x3f); + out[3]=0x20+(((in[1]<<2)|(in[2]>>6))&0x3f); + out[4]=0x20+(in[2]&0x3f); return 0; } -int write_to_ram(t_lpc *lpc,u8 *buf,u32 addr,int len) { +int write_to_ram(t_lpc *lpc,char *buf,u32 addr,int len) { int lcount; u32 checksum; @@ -321,7 +397,7 @@ int write_to_ram(t_lpc *lpc,u8 *buf,u32 addr,int len) { } /* make it a multiple of 3 (reason: uuencode) */ - nlen=(len/3+1)*3; + nlen=(!(len%3))?len:((len/3+1)*3); if(nlen>BUFSIZE) { printf("ram write: too much data\n"); return -1; @@ -329,20 +405,16 @@ int write_to_ram(t_lpc *lpc,u8 *buf,u32 addr,int len) { for(i=len;iroff-lpc->hoff); + addr+=lpc->roff; /* prepare write command */ if(lpc->info&VERBOSE) - printf("writing %02x bytes to %08x\n",len,addr); + 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; @@ -352,15 +424,16 @@ int write_to_ram(t_lpc *lpc,u8 *buf,u32 addr,int len) { while(bcntsfd,txrxbuf+4,4); printf("ram write: resending ...\n"); bcnt-=count; } @@ -394,12 +471,11 @@ int write_to_ram(t_lpc *lpc,u8 *buf,u32 addr,int len) { int firmware_to_ram(t_lpc *lpc) { char buf[BUFSIZE]; - u8 data[BUFSIZE]; - u32 addr,len,type,val; - u8 cksum; - int ret,i; + u32 addr,len,type; + int ret,temp; /* read a line */ + ret=1; while(ret) { /* sync line */ ret=read(lpc->fwfd,buf,1); @@ -418,10 +494,6 @@ int firmware_to_ram(t_lpc *lpc) { /* 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); @@ -431,32 +503,34 @@ int firmware_to_ram(t_lpc *lpc) { /* 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)) { + /* read data (and cksum) */ + ret=read(lpc->fwfd,buf,2*(len+1)); + if(ret!=(2*(len+1))) { 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; + for(ret=0;retroff=((buf[0]<<24)|(buf[1]<<16)); + break; + case 0x05: + lpc->jaddr=((buf[0]<<24)|(buf[1]<<16)); + lpc->jaddr|=((buf[2]<<8)|buf[3]); break; default: printf("fw to ram: unknown type %02x\n",type); @@ -467,10 +541,90 @@ int firmware_to_ram(t_lpc *lpc) { return 0; } +int lpc_txbuf_flush(t_lpc *lpc) { + + int i,ret; + u8 buf[16]; + + ret=1; + printf("flushing lpc tx buffer: "); + while(ret) { + ret=read(lpc->sfd,buf,16); + for(i=0;i>24)&0xff; + buf[2]=(addr>>16)&0xff; + buf[3]=(addr>>8)&0xff; + buf[4]=addr&0xff; + buf[5]=(len>>24)&0xff; + buf[6]=(len>>16)&0xff; + buf[7]=(len>>8)&0xff; + buf[8]=len&0xff; + printf(" sending cmd: "); + while(size) { + ret=write(sfd,buf+cnt,size); + for(i=cnt;i aborting\n"); + goto end; + } + + /* open firmware file */ + if(open_firmware(&lpc)<0) + goto end; - /* read boot code version */ - read_bcv(&lpc); - printf("boot code version: %02x %02x\n",lpc.bcv[0],lpc.bcv[1]); + /* open dump files */ + if(open_dumpfiles(&lpc)<0) + goto end; - // to be continued ... (parsing fw file and poking it to ram) + /* parse intel hex file and write to ram */ + printf("write firmware to ram ...\n"); firmware_to_ram(&lpc); + /* unlock go cmd */ + printf("unlock go command ...\n"); + unlock_go(&lpc); + + /* go! */ + printf("go ...\n"); + ret=go(&lpc); + + /* flush the lpc2220 tx buf */ + lpc_txbuf_flush(&lpc); + + /* download flash/bootloader content */ + if(lpc.info&BANK0) + dump_files(lpc.sfd,lpc.b0fd,BANK0_ADDR,BANK_SIZE); + if(lpc.info&BANK2) + dump_files(lpc.sfd,lpc.b2fd,BANK2_ADDR,BANK_SIZE); + if(lpc.info&BL) + dump_files(lpc.sfd,lpc.blfd,BL_ADDR,BL_SIZE); + end: - close(lpc.sfd); - close(lpc.fwfd); + if(lpc.sfd) + close(lpc.sfd); + if(lpc.fwfd) + close(lpc.fwfd); + if(lpc.b0fd) + close(lpc.b0fd); + if(lpc.b2fd) + close(lpc.b2fd); + if(lpc.blfd) + close(lpc.blfd); return 0; }