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
25 #define CMD_SUCCESS "0\r\n"
26 #define INVALID_COMMAND "1\r\n"
27 #define SRC_ADDR_ERROR "2\r\n"
28 #define DST_ADDR_ERROR "3\r\n"
29 #define SRC_ADDR_NOT_MAPPED "4\r\n"
30 #define DST_ADDR_NOT_MAPPED "5\r\n"
31 #define COUNT_ERROR "6\r\n"
32 #define COMPARE_ERROR "10\r\n"
34 #define PARAM_ERROR "12\r\n"
35 #define ADDR_ERROR "13\r\n"
36 #define ADDR_NOT_MAPPED "14\r\n"
37 #define CMD_LOCKED "15\r\n"
38 #define INVALID_CODE "16\r\n"
39 #define INVALID_BAUD_RATE "17\r\n"
40 #define INVALID_STOP_BIT "18\r\n"
42 #define CRYSTFREQ "10000"
43 #define RAMOFFSET 0x40000200
47 typedef unsigned char u8;
48 typedef unsigned short u16;
49 typedef unsigned int u32;
51 typedef struct s_lpc {
52 int sfd; /* serial fd */
53 char sdev[128]; /* seriel device */
54 int fwfd; /* fimrware fd */
55 char fwfile[128]; /* firmware file */
56 u8 info; /* info/mode */
57 char freq[8]; /* frequency */
58 int partid; /* part id */
59 u8 bcv[2]; /* boot code version */
60 u32 hoff; /* start addr of ihex file */
61 u32 roff; /* ram offset of uc */
66 printf("possible argv:\n");
67 printf(" -d <serial device>\n");
68 printf(" -f <firmware>\n");
69 printf(" -c <crystal freq>\n");
70 printf(" -r <ram offset>\n");
75 int open_serial_device(t_lpc *lpc) {
79 //memset(&term,0,sizeof(struct termios));
81 /* open serial device */
83 lpc->sfd=open(lpc->sdev,O_RDWR);
89 /* configure the serial device */
91 tcgetattr(lpc->sfd,&term);
93 // input/output baudrate
95 cfsetispeed(&term,B9600);
96 cfsetospeed(&term,B9600);
98 // control options -> 8n1
100 term.c_cflag&=~PARENB; // no parity
101 term.c_cflag&=~CSTOPB; // only 1 stop bit
102 term.c_cflag&=~CSIZE; // no bit mask for data bits
103 term.c_cflag|=CS8; // 8 data bits
105 // line options -> raw input
107 term.c_lflag&=~(ICANON|ECHO|ECHOE|ISIG);
109 // input options -> disable flow control
111 term.c_iflag&=~(IXON|IXOFF|IXANY);
113 // more control options -> timeout
116 term.c_cc[VTIME]=10; // 1 second timeout
118 tcsetattr(lpc->sfd,TCSANOW,&term);
123 int open_firmware(t_lpc *lpc) {
128 /* open firmware file */
130 lpc->fwfd=open(lpc->fwfile,O_RDONLY);
135 /* read hex file offset */
137 ret=read(lpc->fwfd,buf,7);
139 printf("fw open: not an intel hex file?\n");
142 sscanf(buf+3,"%04x",&(lpc->hoff));
143 lseek(lpc->fwfd,0,SEEK_SET);
148 int txrx(t_lpc *lpc,char *buf,int len,u8 type) {
155 if(lpc->info&VERBOSE)
159 ret=write(lpc->sfd,buf+cnt,len);
161 perror("txrx write");
164 if(lpc->info&VERBOSE)
167 ((buf[cnt+i]>0x19)&(buf[cnt+i]<0x7f))?
172 if(lpc->info&VERBOSE)
173 printf(" (%d)\n",cnt);
175 /* cut the echo if not of type auto baud */
177 if(type!=TXRX_TYPE_BAUD) {
179 ret=read(lpc->sfd,buf,cnt);
181 perror("txrx echo cut");
188 /* return here if type is data */
190 if(type==TXRX_TYPE_DATA)
195 if(lpc->info&VERBOSE)
200 ret=read(lpc->sfd,buf+cnt,BUFSIZE-cnt);
205 if(ret+cnt>BUFSIZE) {
206 printf("txrx read: too small buf size (%d)!\n",BUFSIZE);
209 if(lpc->info&VERBOSE)
212 ((buf[cnt+i]>0x19)&(buf[cnt+i]<0x7f))?
216 if(lpc->info&VERBOSE)
217 printf(" (%d)\n",cnt);
220 /* check/strip return code if type is data */
222 if(type==TXRX_TYPE_CMD) {
223 ret=strlen(CMD_SUCCESS);
224 if(!strncmp(buf,CMD_SUCCESS,ret)) {
230 printf("txrx bad return code!\n");
238 int bl_init(t_lpc *lpc) {
243 /* auto baud sequence */
245 txrx(lpc,buf,1,TXRX_TYPE_BAUD);
246 if(strncmp(buf,"Synchronized\r\n",14)) {
247 printf("auto baud detection failed\n");
251 /* tell bl that we are synchronized (it's allready in buf) */
252 txrx(lpc,buf,14,TXRX_TYPE_SYNC);
253 if(strncmp(buf,"OK\r\n",4)) {
254 printf("sync failed\n");
258 /* tell bl the crystal frequency */
259 len=strlen(lpc->freq)+2;
260 strncpy(buf,lpc->freq,BUFSIZE);
263 txrx(lpc,buf,len,TXRX_TYPE_SYNC);
264 if(strncmp(buf,"OK\r\n",4)) {
265 printf("freq set failed\n");
272 int read_part_id(t_lpc *lpc) {
276 memcpy(buf,"J\r\n",3);
277 txrx(lpc,buf,3,TXRX_TYPE_CMD);
278 lpc->partid=atoi(buf);
283 int read_bcv(t_lpc *lpc) {
288 memcpy(buf,"K\r\n",3);
289 txrx(lpc,buf,3,TXRX_TYPE_CMD);
290 ptr=strtok(buf,"\r\n");
291 lpc->bcv[0]=strtol(ptr,NULL,16);
292 ptr=strtok(NULL,"\r\n");
293 lpc->bcv[1]=strtol(ptr,NULL,16);
298 int uuencode(u8 *in,char *out) {
300 out[0]=0x20+((in[0]>>2)&0x3f);
301 out[1]=0x20+(((in[0]<<4)|(in[1]>>4))&0x3f);
302 out[2]=0x20+(((in[1]<<2)|(in[2]>>6))&0x3f);
303 out[3]=0x20+(in[2]&0x3f);
308 int write_to_ram(t_lpc *lpc,u8 *buf,u32 addr,int len) {
312 char txrxbuf[BUFSIZE];
319 printf("ram write: not a multiple of 4\n");
323 /* make it a multiple of 3 (reason: uuencode) */
326 printf("ram write: too much data\n");
329 for(i=len;i<nlen;i++) buf[i]=0;
332 addr+=(lpc->roff-lpc->hoff);
334 /* prepare write command */
335 if(lpc->info&VERBOSE)
336 printf("writing %02x bytes to %08x\n",len,addr);
337 snprintf(txrxbuf,BUFSIZE,"W %d %d\r\n",addr,len);
338 slen=strlen(txrxbuf);
340 /* send command and check return code */
341 txrx(lpc,txrxbuf,slen,TXRX_TYPE_CMD);
342 if(strncmp(txrxbuf,"OK\r\n",4)) {
343 printf("ram write: write command failed\n");
354 /* uuencode / prepare data bytes */
355 uuencode(buf+bcnt,txrxbuf);
360 checksum+=(buf[0]+buf[1]+buf[2]);
362 /* send a data line */
363 txrx(lpc,txrxbuf,6,TXRX_TYPE_DATA);
365 /* increase counters */
371 if((!(lcount%20))|(bcnt==nlen)) {
373 snprintf(txrxbuf,BUFSIZE,"%d\r\n",checksum);
374 slen=strlen(txrxbuf);
375 txrx(lpc,txrxbuf,slen,TXRX_TYPE_CMD);
376 if(!strncmp(txrxbuf,"RESEND\r\n",8)) {
377 printf("ram write: resending ...\n");
380 if(strncmp(txrxbuf,"OK\r\n",4)) {
381 printf("ram write: bad response\n");
384 /* reset checksum & counter */
394 int firmware_to_ram(t_lpc *lpc) {
398 u32 addr,len,type,val;
405 ret=read(lpc->fwfd,buf,1);
415 printf("fw to ram: no ihex format\n");
419 ret=read(lpc->fwfd,buf,2);
420 sscanf(buf,"%02x",&len);
422 printf("fw to ram: len not a multiple of 4\n");
426 ret=read(lpc->fwfd,buf,4);
427 sscanf(buf,"%04x",&addr);
429 ret=read(lpc->fwfd,buf,2);
430 sscanf(buf,"%02x",&type);
431 /* successfull return if type is end of file */
435 ret=read(lpc->fwfd,buf,2*len);
437 printf("fw to ram: data missing\n");
443 sscanf(buf+2*i,"%02x",&val);
447 ret=read(lpc->fwfd,buf,2);
448 sscanf(buf,"%02x",&val);
449 if(val+cksum!=0x100) {
450 printf("fw to ram: wrong checksum\n");
453 /* act according to type */
459 write_to_ram(lpc,data,addr,len);
462 printf("fw to ram: unknown type %02x\n",type);
470 int main(int argc,char **argv) {
479 memset(&lpc,0,sizeof(t_lpc));
480 strncpy(lpc.freq,CRYSTFREQ,7);
485 for(i=1;i<argc;i++) {
487 if(argv[i][0]!='-') {
494 strncpy(lpc.sdev,argv[++i],127);
497 strncpy(lpc.fwfile,argv[++i],127);
504 strncpy(lpc.freq,argv[++i],7);
513 /* open serial port */
514 if(open_serial_device(&lpc)<0)
517 /* open firmware file */
518 if(open_firmware(&lpc)<0)
521 /* boot loader init */
522 printf("boot loader init ...\n");
528 printf("part id: %d\n",lpc.partid);
530 /* read boot code version */
532 printf("boot code version: %02x %02x\n",lpc.bcv[0],lpc.bcv[1]);
534 // to be continued ... (parsing fw file and poking it to ram)
535 firmware_to_ram(&lpc);