2 * lpcload.c - load firmware into ram of lpc2220 via uart0
4 * author: hackbard@hackdaworld.org
12 #include <sys/types.h>
17 #define VERBOSE (1<<0)
18 #define FIRMWARE (1<<1)
20 #define TXRX_TYPE_BAUD 0x01
21 #define TXRX_TYPE_SYNC 0x02
22 #define TXRX_TYPE_CMD 0x03
23 #define TXRX_TYPE_DATA 0x04
24 #define TXRX_TYPE_CKSM 0x05
26 #define CMD_SUCCESS "0\r\n"
27 #define INVALID_COMMAND "1\r\n"
28 #define SRC_ADDR_ERROR "2\r\n"
29 #define DST_ADDR_ERROR "3\r\n"
30 #define SRC_ADDR_NOT_MAPPED "4\r\n"
31 #define DST_ADDR_NOT_MAPPED "5\r\n"
32 #define COUNT_ERROR "6\r\n"
33 #define COMPARE_ERROR "10\r\n"
35 #define PARAM_ERROR "12\r\n"
36 #define ADDR_ERROR "13\r\n"
37 #define ADDR_NOT_MAPPED "14\r\n"
38 #define CMD_LOCKED "15\r\n"
39 #define INVALID_CODE "16\r\n"
40 #define INVALID_BAUD_RATE "17\r\n"
41 #define INVALID_STOP_BIT "18\r\n"
43 #define CRYSTFREQ "10000"
44 #define RAMOFFSET 0x40000200
48 typedef unsigned char u8;
49 typedef unsigned short u16;
50 typedef unsigned int u32;
52 typedef struct s_lpc {
53 int sfd; /* serial fd */
54 char sdev[128]; /* seriel device */
55 int fwfd; /* fimrware fd */
56 char fwfile[128]; /* firmware file */
57 u8 info; /* info/mode */
58 char freq[8]; /* frequency */
59 int partid; /* part id */
60 u8 bcv[2]; /* boot code version */
61 u32 hoff; /* start addr of ihex file */
62 u32 roff; /* ram offset of uc */
67 printf("possible argv:\n");
68 printf(" -d <serial device>\n");
69 printf(" -f <firmware>\n");
70 printf(" -c <crystal freq>\n");
71 printf(" -r <ram offset>\n");
76 int open_serial_device(t_lpc *lpc) {
80 //memset(&term,0,sizeof(struct termios));
82 /* open serial device */
84 lpc->sfd=open(lpc->sdev,O_RDWR);
90 /* configure the serial device */
92 tcgetattr(lpc->sfd,&term);
94 // input/output baudrate
96 cfsetispeed(&term,B9600);
97 cfsetospeed(&term,B9600);
99 // control options -> 8n1
101 term.c_cflag&=~PARENB; // no parity
102 term.c_cflag&=~CSTOPB; // only 1 stop bit
103 term.c_cflag&=~CSIZE; // no bit mask for data bits
104 term.c_cflag|=CS8; // 8 data bits
106 // line options -> raw input
108 term.c_lflag&=~(ICANON|ECHO|ECHOE|ISIG);
110 // input options -> enable flow control
112 //term.c_iflag&=~(IXON|IXOFF|IXANY|INLCR|ICRNL);
113 term.c_iflag&=~(INLCR|ICRNL);
114 term.c_iflag|=(IXON|IXOFF|IXANY);
116 // more control options -> timeout / flow control
119 term.c_cc[VTIME]=10; // 1 second timeout
120 term.c_cc[VSTART]=0x11;
121 term.c_cc[VSTOP]=0x13;
123 tcsetattr(lpc->sfd,TCSANOW,&term);
128 int open_firmware(t_lpc *lpc) {
133 /* open firmware file */
135 lpc->fwfd=open(lpc->fwfile,O_RDONLY);
140 /* read hex file offset */
142 ret=read(lpc->fwfd,buf,7);
144 printf("fw open: not an intel hex file?\n");
147 sscanf(buf+3,"%04x",&(lpc->hoff));
148 lseek(lpc->fwfd,0,SEEK_SET);
153 int txrx(t_lpc *lpc,char *buf,int len,u8 type) {
160 if(lpc->info&VERBOSE)
164 ret=write(lpc->sfd,buf+cnt,len);
166 perror("txrx write");
169 if(lpc->info&VERBOSE)
172 ((buf[cnt+i]>0x19)&(buf[cnt+i]<0x7f))?
177 if(lpc->info&VERBOSE) {
180 printf("%02x ",buf[i]);
181 printf("| (%d)\n",cnt);
184 /* cut the echo if not of type auto baud */
186 if(type!=TXRX_TYPE_BAUD) {
188 ret=read(lpc->sfd,buf,cnt);
190 perror("txrx echo cut");
193 if(type==TXRX_TYPE_CKSM) {
194 printf(" cksm resp: ");
196 printf("%02x ",buf[i]);
201 printf("STOP !!!\n");
207 /* return here if type is data */
209 if(type==TXRX_TYPE_DATA) {
212 ret=read(lpc->sfd,buf,BUFSIZE);
215 printf("FATAL!!!\n");
217 for(j=0;j<ret;j++) printf("%02x ",buf[j]);
225 /* wait, if cksum has to be verified */
227 //if(type==TXRX_TYPE_CKSM)
232 if(lpc->info&VERBOSE)
237 ret=read(lpc->sfd,buf+cnt,BUFSIZE-cnt);
242 if(ret+cnt>BUFSIZE) {
243 printf("txrx read: too small buf size (%d)!\n",BUFSIZE);
246 if(lpc->info&VERBOSE)
249 ((buf[cnt+i]>0x19)&(buf[cnt+i]<0x7f))?
253 if(lpc->info&VERBOSE) {
256 printf("%02x ",buf[i]);
257 printf("| (%d)\n",cnt);
261 /* check/strip return code if type is cmd */
263 if(type==TXRX_TYPE_CMD) {
264 ret=strlen(CMD_SUCCESS);
265 if(!strncmp(buf,CMD_SUCCESS,ret)) {
271 printf("txrx bad return code!\n");
279 int bl_init(t_lpc *lpc) {
284 /* auto baud sequence */
286 txrx(lpc,buf,1,TXRX_TYPE_BAUD);
287 if(strncmp(buf,"Synchronized",12)) {
288 printf("auto baud detection failed\n");
292 /* tell bl that we are synchronized (it's allready in buf) */
293 txrx(lpc,buf,14,TXRX_TYPE_SYNC);
294 if(strncmp(buf,"OK\r\n",4)) {
295 printf("sync failed\n");
299 /* tell bl the crystal frequency */
300 len=strlen(lpc->freq)+2;
301 strncpy(buf,lpc->freq,BUFSIZE);
304 txrx(lpc,buf,len,TXRX_TYPE_SYNC);
305 if(strncmp(buf,"OK\r\n",4)) {
306 printf("freq set failed\n");
313 int read_part_id(t_lpc *lpc) {
317 memcpy(buf,"J\r\n",3);
318 txrx(lpc,buf,3,TXRX_TYPE_CMD);
319 lpc->partid=atoi(buf);
324 int read_bcv(t_lpc *lpc) {
329 memcpy(buf,"K\r\n",3);
330 txrx(lpc,buf,3,TXRX_TYPE_CMD);
331 ptr=strtok(buf,"\r\n");
332 lpc->bcv[0]=strtol(ptr,NULL,16);
333 ptr=strtok(NULL,"\r\n");
334 lpc->bcv[1]=strtol(ptr,NULL,16);
339 int unlock_go(t_lpc *lpc) {
344 memcpy(buf,"U 23130\r\n",9);
345 ret=txrx(lpc,buf,9,TXRX_TYPE_CMD);
355 snprintf(buf,BUFSIZE,"G %d A\r\n",lpc->roff);
357 ret=txrx(lpc,buf,ret,TXRX_TYPE_CMD);
362 int uuencode(char *in,char *out) {
366 out[0]=0x20+((in[0]>>2)&0x3f);
367 out[1]=0x20+(((in[0]<<4)|(in[1]>>4))&0x3f);
368 out[2]=0x20+(((in[1]<<2)|(in[2]>>6))&0x3f);
369 out[3]=0x20+(in[2]&0x3f);
373 printf("%02x ",in[i]);
376 printf("%02x ",out[i]);
382 int write_to_ram(t_lpc *lpc,char *buf,u32 addr,int len) {
386 char txrxbuf[BUFSIZE];
393 printf("ram write: not a multiple of 4\n");
397 /* make it a multiple of 3 (reason: uuencode) */
400 printf("ram write: too much data\n");
403 for(i=len;i<nlen;i++) buf[i]=0;
406 addr+=(lpc->roff-lpc->hoff);
408 /* prepare write command */
409 if(lpc->info&VERBOSE)
410 printf("writing 0x%02x bytes to 0x%08x\n",len,addr);
411 snprintf(txrxbuf,BUFSIZE,"W %d %d\r\n",addr,len);
412 slen=strlen(txrxbuf);
414 /* send command and check return code */
415 txrx(lpc,txrxbuf,slen,TXRX_TYPE_CMD);
416 //if(strncmp(txrxbuf,"OK\r\n",4)) {
417 // printf("ram write: write command failed\n");
428 /* uuencode / prepare data bytes */
429 uuencode(buf+bcnt,txrxbuf);
434 checksum+=(buf[bcnt]+buf[bcnt+1]+buf[bcnt+2]);
435 printf("----> %d %d\n",checksum,bcnt);
437 /* send a data line */
438 txrx(lpc,txrxbuf,6,TXRX_TYPE_DATA);
440 /* increase counters */
446 if((!(lcount%20))|(bcnt==nlen)) {
448 snprintf(txrxbuf,BUFSIZE,"%d\r\n",checksum%0x100);
449 slen=strlen(txrxbuf);
450 txrx(lpc,txrxbuf,slen,TXRX_TYPE_CKSM);
451 if(!strncmp(txrxbuf,"RESEND\r\n",8)) {
452 printf("ram write: resending ...\n");
455 if(strncmp(txrxbuf,"OK\r\n",4)) {
456 printf("ram write: bad response\n");
459 /* reset checksum & counter */
469 int firmware_to_ram(t_lpc *lpc) {
478 ret=read(lpc->fwfd,buf,1);
488 printf("fw to ram: no ihex format\n");
492 ret=read(lpc->fwfd,buf,2);
493 sscanf(buf,"%02x",&len);
495 printf("fw to ram: len not a multiple of 4\n");
499 ret=read(lpc->fwfd,buf,4);
500 sscanf(buf,"%04x",&addr);
502 ret=read(lpc->fwfd,buf,2);
503 sscanf(buf,"%02x",&type);
504 /* successfull return if type is end of file */
508 ret=read(lpc->fwfd,buf,2*len);
510 printf("fw to ram: data missing\n");
514 ret=read(lpc->fwfd,buf,2);
515 /* act according to type */
521 write_to_ram(lpc,buf,addr,len);
524 printf("fw to ram: unknown type %02x\n",type);
532 int main(int argc,char **argv) {
541 memset(&lpc,0,sizeof(t_lpc));
542 strncpy(lpc.freq,CRYSTFREQ,7);
547 for(i=1;i<argc;i++) {
549 if(argv[i][0]!='-') {
556 strncpy(lpc.sdev,argv[++i],127);
559 strncpy(lpc.fwfile,argv[++i],127);
566 strncpy(lpc.freq,argv[++i],7);
575 /* open serial port */
576 if(open_serial_device(&lpc)<0)
579 /* open firmware file */
580 if(open_firmware(&lpc)<0)
583 /* boot loader init */
584 printf("boot loader init ...\n");
590 printf("part id: %d\n",lpc.partid);
592 /* read boot code version */
594 printf("boot code version: %02x %02x\n",lpc.bcv[0],lpc.bcv[1]);
596 /* parse intel hex file and write to ram */
597 firmware_to_ram(&lpc);