#include <fcntl.h>
#include <termios.h>
-#define VERBOSE (1<<0)
-#define FIRMWARE (1<<1)
-
-#define CRYSTFREQ "10000"
-
-#define BUFSIZE 64
+#define VERBOSE (1<<0)
+#define FIRMWARE (1<<1)
+
+#define TXRX_TYPE_BAUD 0x01
+#define TXRX_TYPE_SYNC 0x02
+#define TXRX_TYPE_DATA 0x03
+
+#define CMD_SUCCESS "0\r\n"
+#define INVALID_COMMAND "1\r\n"
+#define SRC_ADDR_ERROR "2\r\n"
+#define DST_ADDR_ERROR "3\r\n"
+#define SRC_ADDR_NOT_MAPPED "4\r\n"
+#define DST_ADDR_NOT_MAPPED "5\r\n"
+#define COUNT_ERROR "6\r\n"
+#define COMPARE_ERROR "10\r\n"
+#define BUSY "11\r\n"
+#define PARAM_ERROR "12\r\n"
+#define ADDR_ERROR "13\r\n"
+#define ADDR_NOT_MAPPED "14\r\n"
+#define CMD_LOCKED "15\r\n"
+#define INVALID_CODE "16\r\n"
+#define INVALID_BAUD_RATE "17\r\n"
+#define INVALID_STOP_BIT "18\r\n"
+
+#define CRYSTFREQ "10000"
+
+#define BUFSIZE 64
+
+typedef unsigned char u8;
+
+typedef struct s_lpc {
+ int sfd; /* serial fd */
+ char sdev[128]; /* seriel device */
+ int fwfd; /* fimrware fd */
+ char fwfile[128]; /* firmware file */
+ u8 info; /* info/mode */
+ char freq[8]; /* frequency */
+ int partid; /* part id */
+ u8 bcv[2]; /* boot code version */
+} t_lpc;
void usage(void) {
}
-int txrx(int fd,char *buf,int *len,unsigned char v) {
+int open_serial_device(t_lpc *lpc) {
+
+ struct termios term;
+
+ //memset(&term,0,sizeof(struct termios));
+
+ /* open serial device */
+
+ lpc->sfd=open(lpc->sdev,O_RDWR);
+ if(lpc->sfd<0) {
+ perror("tts open");
+ return lpc->sfd;
+ }
+
+ /* configure the serial device */
+
+ tcgetattr(lpc->sfd,&term);
+
+ // input/output baudrate
+
+ cfsetispeed(&term,B9600);
+ cfsetospeed(&term,B9600);
+
+ // control options -> 8n1
+
+ term.c_cflag&=~PARENB; // no parity
+ term.c_cflag&=~CSTOPB; // only 1 stop bit
+ term.c_cflag&=~CSIZE; // no bit mask for data bits
+ term.c_cflag|=CS8; // 8 data bits
+
+ // line options -> raw input
+
+ term.c_lflag&=~(ICANON|ECHO|ECHOE|ISIG);
+
+ // input options -> disable flow control
+
+ term.c_iflag&=~(IXON|IXOFF|IXANY);
+
+ // more control options -> timeout
+
+ term.c_cc[VMIN]=0;
+ term.c_cc[VTIME]=10; // 1 second timeout
+
+ tcsetattr(lpc->sfd,TCSANOW,&term);
+
+ return lpc->sfd;
+}
+
+int open_firmware(t_lpc *lpc) {
+
+ /* open firmware file */
+
+ lpc->fwfd=open(lpc->fwfile,O_RDONLY);
+
+ if(lpc->fwfd<0)
+ perror("fw open");
+
+ return lpc->fwfd;
+}
+
+int txrx(t_lpc *lpc,char *buf,int len,u8 type) {
int ret,cnt;
int i;
/* write */
- if(v&VERBOSE)
+ if(lpc->info&VERBOSE)
printf(" >> ");
cnt=0;
- while(*len) {
- ret=write(fd,buf+cnt,*len);
+ while(len) {
+ ret=write(lpc->sfd,buf+cnt,len);
if(ret<0) {
perror("txrx write");
return ret;
}
- if(v&VERBOSE)
+ if(lpc->info&VERBOSE)
for(i=0;i<ret;i++)
printf("%c",
((buf[cnt+i]>0x19)&(buf[cnt+i]<0x7f))?
buf[cnt+i]:'.');
- *len-=ret;
+ len-=ret;
cnt+=ret;
}
- if(v&VERBOSE)
+ if(lpc->info&VERBOSE)
printf(" (%d)\n",cnt);
- /* cut the echo */
- // add more checking here!
- while(cnt)
- cnt-=read(fd,buf,cnt);
+ /* cut the echo if not of type auto baud */
+
+ if(type!=TXRX_TYPE_BAUD) {
+ while(cnt) {
+ ret=read(lpc->sfd,buf,cnt);
+ if(ret<0) {
+ perror("txrx echo cut");
+ return ret;
+ }
+ cnt-=ret;
+ }
+ }
/* read */
- if(v&VERBOSE)
+ if(lpc->info&VERBOSE)
printf(" << ");
ret=1;
cnt=0;
while(ret>0) {
- ret=read(fd,buf+cnt,BUFSIZE-cnt);
+ ret=read(lpc->sfd,buf+cnt,BUFSIZE-cnt);
if(ret<0) {
perror("txrx read");
return ret;
printf("txrx read: too small buf size (%d)!\n",BUFSIZE);
return -1;
}
- if(v&VERBOSE)
+ if(lpc->info&VERBOSE)
for(i=0;i<ret;i++)
printf("%c",
((buf[cnt+i]>0x19)&(buf[cnt+i]<0x7f))?
buf[cnt+i]:'.');
cnt+=ret;
}
- if(v&VERBOSE)
+ if(lpc->info&VERBOSE)
printf(" (%d)\n",cnt);
- *len=cnt;
+ len=cnt;
+ buf[cnt]='\0';
+
+ /* check/strip return code if type is data */
+
+ if(type==TXRX_TYPE_DATA) {
+ ret=strlen(CMD_SUCCESS);
+ if(!strncmp(buf,CMD_SUCCESS,ret)) {
+ for(i=ret;i<cnt;i++)
+ buf[i-ret]=buf[i];
+ buf[cnt]='\0';
+ }
+ else {
+ printf("txrx bad return code!\n");
+ return -1;
+ }
+ }
return cnt;
}
-int main(int argc,char **argv) {
+int bl_init(t_lpc *lpc) {
- int i;
- char tts[128];
- int tts_fd;
- char fw[128];
- int fw_fd;
- unsigned char info;
- struct termios term;
- char cfreq[8];
+ char buf[BUFSIZE];
int len;
+
+ /* auto baud sequence */
+ buf[0]='?';
+ txrx(lpc,buf,1,TXRX_TYPE_BAUD);
+ if(strncmp(buf,"Synchronized\r\n",14)) {
+ printf("auto baud detection failed\n");
+ return -1;
+ }
+
+ /* tell bl that we are synchronized (it's allready in buf) */
+ txrx(lpc,buf,14,TXRX_TYPE_SYNC);
+ if(strncmp(buf,"OK\r\n",4)) {
+ printf("sync failed\n");
+ return -1;
+ }
+
+ /* tell bl the crystal frequency */
+ len=strlen(lpc->freq)+2;
+ strncpy(buf,lpc->freq,BUFSIZE);
+ buf[len-2]='\r';
+ buf[len-1]='\n';
+ txrx(lpc,buf,len,TXRX_TYPE_SYNC);
+ if(strncmp(buf,"OK\r\n",4)) {
+ printf("freq set failed\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+int read_part_id(t_lpc *lpc) {
+
char buf[BUFSIZE];
+ memcpy(buf,"J\r\n",3);
+ txrx(lpc,buf,3,TXRX_TYPE_DATA);
+ lpc->partid=atoi(buf);
+
+ return lpc->partid;
+}
+
+int read_bcv(t_lpc *lpc) {
+
+ char buf[BUFSIZE];
+ char *ptr;
+
+ memcpy(buf,"K\r\n",3);
+ txrx(lpc,buf,3,TXRX_TYPE_DATA);
+ ptr=strtok(buf,"\r\n");
+ lpc->bcv[0]=strtol(ptr,NULL,16);
+ ptr=strtok(NULL,"\r\n");
+ lpc->bcv[1]=strtol(ptr,NULL,16);
+
+ return 0;
+}
+
+int main(int argc,char **argv) {
+
+ t_lpc lpc;
+ int i;
+
/*
* initial ...
*/
- info=0;
- memset(&term,0,sizeof(struct termios));
- strncpy(cfreq,CRYSTFREQ,7);
+ memset(&lpc,0,sizeof(t_lpc));
+ strncpy(lpc.freq,CRYSTFREQ,7);
/* parse argv */
switch(argv[i][1]) {
case 'd':
- strncpy(tts,argv[++i],127);
+ strncpy(lpc.sdev,argv[++i],127);
break;
case 'f':
- strncpy(fw,argv[++i],127);
- info|=FIRMWARE;
+ strncpy(lpc.fwfile,argv[++i],127);
+ lpc.info|=FIRMWARE;
break;
case 'v':
- info|=VERBOSE;
+ lpc.info|=VERBOSE;
break;
case 'c':
- strncpy(cfreq,argv[++i],7);
+ strncpy(lpc.freq,argv[++i],7);
break;
default:
usage();
}
- /*
- * open serial device
- */
+ /* open serial port */
+ open_serial_device(&lpc);
- tts_fd=open(tts,O_RDWR);
- if(tts_fd<0) {
- perror("tts open");
- return tts_fd;
- }
-
- /*
- * configure serial device
- */
-
- tcgetattr(tts_fd,&term);
-
- // input/output baudrate
-
- cfsetispeed(&term,B9600);
- cfsetospeed(&term,B9600);
-
- // control options -> 8n1
-
- term.c_cflag&=~PARENB; // no parity
- term.c_cflag&=~CSTOPB; // only 1 stop bit
- term.c_cflag&=~CSIZE; // no bit mask for data bits
- term.c_cflag|=CS8; // 8 data bits
-
- // line options -> raw input
-
- term.c_lflag&=~(ICANON|ECHO|ECHOE|ISIG);
-
- // input options -> disable flow control
-
- term.c_iflag&=~(IXON|IXOFF|IXANY);
-
- // more control options -> timeout
-
- term.c_cc[VMIN]=0;
- term.c_cc[VTIME]=10; // 1 second timeout
-
- tcsetattr(tts_fd,TCSANOW,&term);
-
- /* auto baud sequence */
-
- printf("auto baud sequence ...\n");
- write(tts_fd,"?",1);
- len=0;
- txrx(tts_fd,buf,&len,info);
- if(strncmp(buf,"Synchronized\r\n",14)) {
- printf("auto baud detection failed\n");
- return -1;
- }
-
- /* tell bl that we are synchronized (it's allready in buf) */
-
- printf("sync sequence ...\n");
- len=14;
- txrx(tts_fd,buf,&len,info);
- if(strncmp(buf,"OK\r\n",4)) {
- printf("sync failed\n");
- return -1;
- }
-
- /* tell bl the crystal frequency */
-
- printf("frequency setting sequence ...\n");
- len=strlen(cfreq)+2;
- strncpy(buf,cfreq,BUFSIZE);
- buf[len-2]='\r';
- buf[len-1]='\n';
- txrx(tts_fd,buf,&len,info);
- if(strncmp(buf,"OK\r\n",4)) {
- printf("freq set failed\n");
- return -1;
- }
+ /* boot loader init */
+ printf("boot loader init ...\n");
+ bl_init(&lpc);
/* read part id */
- printf("read part id ...\n");
- len=3;
- memcpy(buf,"J\r\n",3);
- txrx(tts_fd,buf,&len,info);
- buf[len]='\0';
- printf("part id: %d (0x%x)\n",atoi(buf),atoi(buf+3));
+ read_part_id(&lpc);
+ printf("part id: %d\n",lpc.partid);
/* read boot code version */
- printf("read boot code version ...\n");
- len=3;
- memcpy(buf,"K\r\n",3);
- txrx(tts_fd,buf,&len,info);
- buf[len]='\0';
- printf("boot code version: %c %c\n",(buf),atoi(buf));
-
-
-
+ 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)
-end:
- close(tts_fd);
+//end:
+ close(lpc.sfd);
return 0;
}