X-Git-Url: https://hackdaworld.org/gitweb/?a=blobdiff_plain;f=betty%2Flpcload.c;h=0d2f9c85ddd9bfd9f5394c556a38ee666d707aa8;hb=feece393fb07514608a7ad21eaa376ea3375e945;hp=0bf3006aa7dd262c3ce0872bd309cd7e4c1626ed;hpb=f549db2020c9e68e37e89f3cb7a921e5a7f75954;p=my-code%2Farm.git diff --git a/betty/lpcload.c b/betty/lpcload.c index 0bf3006..0d2f9c8 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 @@ -21,6 +23,7 @@ #define TXRX_TYPE_SYNC 0x02 #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" @@ -40,10 +43,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 */ @@ -52,8 +58,8 @@ 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 */ + u32 roff; /* ram offset of uc */ } t_lpc; void usage(void) { @@ -62,6 +68,7 @@ void usage(void) { printf(" -d \n"); printf(" -f \n"); printf(" -c \n"); + printf(" -r \n"); printf(" -v\n"); } @@ -100,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|IXANY); + term.c_iflag|=(IXON|IXOFF); - // 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); @@ -116,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); @@ -123,10 +137,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; @@ -150,8 +174,12 @@ int txrx(t_lpc *lpc,u8 *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) { - u8 buf[BUFSIZE]; - char *ptr; + char buf[BUFSIZE]; + 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->roff); + len=strlen(buf); + ret=txrx(lpc,buf,len,TXRX_TYPE_CMD); - return 0; + return ret; } -int uuencode(u8 *in,u8 *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,int addr,int len) { +int write_to_ram(t_lpc *lpc,char *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; @@ -302,26 +349,24 @@ int write_to_ram(t_lpc *lpc,u8 *buf,int 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; } for(i=len;iroff-lpc->hoff); + /* prepare write command */ - snprintf(txrxbuf,BUFSIZE,"W %d %d",addr,len); + 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); - txrxbuf[slen]='\r'; - txrxbuf[slen+1]='\0'; - slen+=2; /* 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; @@ -331,15 +376,16 @@ int write_to_ram(t_lpc *lpc,u8 *buf,int addr,int len) { while(bcntsfd,txrxbuf+4,4); printf("ram write: resending ...\n"); bcnt-=count; } @@ -371,25 +422,64 @@ 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]; + u32 addr,len,type; + int ret,temp; - /* read file */ + /* read a line */ + ret=1; 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 (and cksum) */ + ret=read(lpc->fwfd,buf,2*(len+1)); + if(ret!=(2*(len+1))) { + printf("fw to ram: data missing\n"); + return -1; + } + for(ret=0;ret