/************************************************* * * * SiTCP Bus Control Protocol * * Test program * * * * 2006/03/01 Tomohisa Uchida * * 2006/07/25 modified, J.L. Raaf * *************************************************/ #define USE_READLINE #include "bcp.h" #include #include #include #include //#include #include #ifdef USE_READLINE #include #include #endif #define ERROR -1 #define OK 0 #define maxLineLength 200 // command table typedef struct { char *name; int nargs; } a_cmd; // positions in table correspond to switch() constants below! static a_cmd cmds[] = { "help", 0, "write", 2, "read", 2, "program", 3, "test",0, "quit", 0 }; #define N_CMD (sizeof(cmds)/sizeof(a_cmd)) int rd(int sock, struct sockaddr_in sitcpAddr, unsigned int addr); int wr(int sock, struct sockaddr_in sitcpAddr, unsigned int addr, unsigned int data); int FLASHburn(int sock, struct sockaddr_in sitcpAddr, char *Filename, int backup, int check); int parse_command( char *pb, char *tok[], unsigned int tokn[], int maxt); static FILE *fp = NULL; // script input int new_fw = 1; char *rl_gets (); int main(int argc, char* argv[]){ struct timeval timeout; fd_set setSelect; char* sitcpIpAddr; unsigned int sitcpPort = 0x1234; unsigned int tokn[16]; // numeric conversion of tokens char line[maxLineLength]; int nt; // number of tokens in input char *pb, *tp; // buffer pointer, token pointer char *tok[16]; // tokens in input commands int i,j,k,rdata; /* Get IP address and port # of SiTCP */ if(argc > 1) sitcpIpAddr = argv[1]; else sitcpIpAddr = "192.168.11.44\0"; if(argc > 2) sitcpPort = atoi(argv[2]); /* Create a Socket */ puts("\nCreating UDP socket...\n"); int sock; sock = socket(AF_INET, SOCK_DGRAM, 0); struct sockaddr_in sitcpAddr; sitcpAddr.sin_family = AF_INET; sitcpAddr.sin_port = htons(sitcpPort); sitcpAddr.sin_addr.s_addr = inet_addr(sitcpIpAddr); struct bcp_header sndHeader; unsigned char sndBuf[2048]; unsigned char sndData[256]; int sndDataLen = 0; rdata = rd(sock,sitcpAddr,0x100); wr(sock,sitcpAddr,0x100,0); if(rd(sock,sitcpAddr,0x100)) new_fw = 0; else{ wr(sock,sitcpAddr,0x100,0xaaaa); if(rd(sock,sitcpAddr,0x100) != 0xaaaa) new_fw = 0; } wr(sock,sitcpAddr,0x100,rdata); // Set some of the BCP header values (those that don't change right now) sndHeader.type = (unsigned char) 0xff; sndHeader.id = (unsigned char) 1; while( (pb = rl_gets()) != NULL) { nt = parse_command( pb, tok, tokn, 15); if (nt) { for (i = 0; i < N_CMD; i++) { if(!strncasecmp( tok[0], cmds[i].name, strlen(tok[0]))) { sndHeader.address = htonl(tokn[1]); switch( i) { case 0 : // help printf("help\n"); printf("write address data : write two bytes of data to udp adddress\n"); printf("read address : read two bytes from udp address\n"); printf("quit : quit\n"); break; case 1 : //write wr(sock,sitcpAddr,tokn[1],tokn[2]); break; case 2 : //read if(nt == 2) tokn[2] = 2; for(j=0;j < tokn[2]; j += 2){ rdata = rd(sock,sitcpAddr,tokn[1]+j); printf("adddress : 0x%08x data = 0x%04x\n",tokn[1]+j,rdata); } break; case 3 : //program wr(sock,sitcpAddr,0,0); //exit any test modes new_fw = 1; rdata = rd(sock,sitcpAddr,0x100); wr(sock,sitcpAddr,0x100,0); if(rd(sock,sitcpAddr,0x100)) new_fw = 0; else{ wr(sock,sitcpAddr,0x100,0xaaaa); if(rd(sock,sitcpAddr,0x100) != 0xaaaa) new_fw = 0; } wr(sock,sitcpAddr,0x100,rdata); if(nt < 3) tokn[2] = 0; if(nt < 4) FLASHburn(sock,sitcpAddr,tok[1],tokn[2],0); FLASHburn(sock,sitcpAddr,tok[1],tokn[2],1); break; case 4://test firmware version new_fw = 1; rdata = rd(sock,sitcpAddr,0x100); wr(sock,sitcpAddr,0x100,0); if(rd(sock,sitcpAddr,0x100)) new_fw = 0; else{ wr(sock,sitcpAddr,0x100,0xaaaa); if(rd(sock,sitcpAddr,0x100) != 0xaaaa) new_fw = 0; } wr(sock,sitcpAddr,0x100,rdata); break; case 5 : //quit return OK; break; } } } } } puts("\nClosing socket."); close(sock); }//end main() ; int rd(int sock, struct sockaddr_in sitcpAddr, unsigned int addr) { unsigned char sndBuf[16]; unsigned char recvBuf[16]; int recvVal = 1; int recvBytes; int data; struct timeval timeout; fd_set setSelect; sndBuf[0] = 0xff; sndBuf[1] = 0xc0; sndBuf[2] = 0x01; sndBuf[3] = 0x02; sndBuf[4] = (addr & 0xff000000) >> 24; sndBuf[5] = (addr & 0xff0000) >> 16; sndBuf[6] = (addr & 0xff00) >> 8; sndBuf[7] = (addr & 0xff); // Send UDP packet int jj = sendto(sock, sndBuf, 8, 0, (struct sockaddr *)&sitcpAddr, sizeof(sitcpAddr)); if (jj == -1) printf("Error sending packet.\n"); // Receive packet back from SiTCP while (recvVal) { FD_ZERO(&setSelect); FD_SET(sock, &setSelect); timeout.tv_sec = 3; timeout.tv_usec = 0; if(select(sock+1, &setSelect, NULL, NULL,&timeout)==0){ // timeout occurred recvVal = 0; printf("***** rd Timed out! ***** addr = 0x%08x\n",addr); return ERROR; // exit(1); } else { if (FD_ISSET(sock, &setSelect)) { recvBytes = recvfrom(sock,recvBuf, 16, 0, NULL, NULL); if(new_fw) data = (recvBuf[8] << 8) + recvBuf[9]; else data = (recvBuf[9] << 8) + recvBuf[8]; recvVal = 0; } } } return data; } int wr(int sock, struct sockaddr_in sitcpAddr, unsigned int addr, unsigned int data) { unsigned char sndBuf[16]; unsigned char recvBuf[16]; int recvVal = 1; int recvBytes; struct timeval timeout; fd_set setSelect; sndBuf[0] = 0xff; sndBuf[1] = 0x80; sndBuf[2] = 0x01; sndBuf[3] = 0x02; sndBuf[4] = (addr & 0xff000000) >> 24; sndBuf[5] = (addr & 0xff0000) >> 16; sndBuf[6] = (addr & 0xff00) >> 8; sndBuf[7] = (addr & 0xff); if(new_fw){ sndBuf[9] = (data & 0xff); sndBuf[8] = (data & 0xff00) >> 8; } else{ sndBuf[8] = (data & 0xff); sndBuf[9] = (data & 0xff00) >> 8; } // Send UDP packet int jj = sendto(sock, sndBuf, 10, 0, (struct sockaddr *)&sitcpAddr, sizeof(sitcpAddr)); if (jj == -1) printf("Error sending packet.\n"); // Receive packet back from SiTCP while (recvVal) { FD_ZERO(&setSelect); FD_SET(sock, &setSelect); timeout.tv_sec = 3; timeout.tv_usec = 0; if(select(sock+1, &setSelect, NULL, NULL,&timeout)==0){ // timeout occurred recvVal = 0; printf("\n***** wr Timed out! ***** addr = 0x%08x data = 0x%04x\n",addr,data); return ERROR; // exit(1); } else { if (FD_ISSET(sock, &setSelect)) { recvBytes = recvfrom(sock,recvBuf, 16, 0, NULL, NULL); recvVal = 0; } } } return OK; } int FLASHburn(int sock, struct sockaddr_in sitcpAddr, char *Filename, int backup, int check) { FILE *f; int ln = 0, v2; char line[maxLineLength]; unsigned buf; int addr; int i,rdata; // open mcs file f = fopen(Filename,"r"); if (!f) { printf("FLASHburn: Cannot open file %s\n",Filename); return ERROR; } // check device ID while(wr(sock,sitcpAddr,0x400,0x9f) < 0); while(wr(sock,sitcpAddr,2,3) < 0); while((rdata = rd(sock,sitcpAddr,0x404-(new_fw << 1))) < 0); v2 = 0; if((rdata & 0xff) == 0x15){ v2 = 1; printf("This is a version 2 board\n"); } else if((rdata & 0xff) == 0x16) printf("This is a old version board\n"); else{ printf("Wrong FLASH ID : 0x%02x found\n",rdata & 0xff); return ERROR; } if(!check){ //sector erase for(i = (2-v2)*16*backup; i < (2-v2)*16*(1+backup); i++){ //enable write while(wr(sock,sitcpAddr,0x400,6) < 0); while(wr(sock,sitcpAddr,2,0) < 0); //waiting for write enable rdata = 1; while(rdata & 0x1){ while(wr(sock,sitcpAddr,0x400,5) < 0); while(wr(sock,sitcpAddr,2,2) < 0); while((rdata = rd(sock,sitcpAddr,0x402-(new_fw << 1))) < 0); } //execute erase while(wr(sock,sitcpAddr,0x400,0xd8+(i << 8)) < 0); while(wr(sock,sitcpAddr,0x402,0x0) < 0); while(wr(sock,sitcpAddr,2,3) < 0); printf("\rerase secotr%d command sent!",i); fflush(stdout); //waiting for bulk erase to end rdata = 1; while(rdata & 0x1){ while(wr(sock,sitcpAddr,0x400,5) < 0); while(wr(sock,sitcpAddr,2,2) < 0); while((rdata = rd(sock,sitcpAddr,0x402-(new_fw << 1))) < 0); } } printf("\nerase done!\n"); } addr = backup << (21-v2); // loop over record in the file and read them in the array "line" while ( fgets(line, maxLineLength, f) != NULL) { char c1[3],c2[5]; unsigned char data[200]; int byte_count,address,address_bias,rec_type,total; ln++; if(ln%0x1000 == 0){ // printf("\rcurrent line: 0x%x",ln); // fflush(stdout); printf("current line: 0x%x\n",ln); } // check that the record has more than 9 characters if ( strlen(line) < 9 ) { printf("FLASHburn: Error while reading " "line %d: it has less than 9 characters\n",ln); return ERROR; } // number of bytes in the record (first two hex numbers) strncpy(c1,line+1,2); c1[2] = '\0'; sscanf(c1,"%x",&byte_count); // address (hex numbers 3-6) strncpy(c2,line+3,4); c2[4] = '\0'; sscanf(c2,"%x",&address); // record type (hex numbers 7-8) strncpy(c1,line+7,2); c1[2] = '\0'; sscanf(c1,"%x",&rec_type); // calculate checksum total = byte_count+address/256+address%256+rec_type; // loop over the rest of the characters in the record and // convert them to int for (i=0; i<(byte_count+1);i++) { strncpy(c1,line+2*i+9,2); c1[2] = '\0'; data[i] = strtol(c1,NULL,16); total = total + data[i]; } // check the checksum for the record if (total%256 != 0) { printf("programChip: Error while reading line " "%d - a checksum error is found\n",ln); return ERROR; } //byte count must be even if(byte_count%2 == 1)byte_count++; // only data records are written if (rec_type == 0 && byte_count != 0) { for (i=0; i> 8)) < 0); while(wr(sock,sitcpAddr,0x402,(addr & 0xff00) >> 8) < 0); while(wr(sock,sitcpAddr,2,0x103) < 0); } else{ //enable write while(wr(sock,sitcpAddr,0x400,6) < 0); while(wr(sock,sitcpAddr,2,0) < 0); //page program command and address buf = 2 + ((addr & 0xff0000) >> 8); while(wr(sock,sitcpAddr,0x400,buf) < 0); buf = (addr & 0xff00) >> 8; while(wr(sock,sitcpAddr,0x402,buf) < 0); } } buf = data[i] + (data[i+1] << 8); if(check){ while((rdata = rd(sock,sitcpAddr,0x605-5*new_fw+(addr & 0xff))) < 0); if(rdata != buf){ printf("FLASH error addr = 0x%06x expected data : 0x%04x real data : 0x%04x\n",addr,buf,rdata); return ERROR; } } else while(wr(sock,sitcpAddr,0x604+(addr & 0xff),buf) < 0); addr += 2; //256 bytes of data in buffer, start page write if (addr%256 == 0 && check == 0) { //execute page write while(wr(sock,sitcpAddr,2,0x103) < 0); //waiting for page write end rdata = 1; while(rdata & 0x1){ while(wr(sock,sitcpAddr,0x400,5) < 0); while(wr(sock,sitcpAddr,2,2) < 0); while((rdata = rd(sock,sitcpAddr,0x402-(new_fw << 1))) < 0); } // printf("page written addr = 0x%08x\n",addr-256); } } // loop over bytes in the line } // rec_type equal to 0 } // loop over lines // close mcs file //if there are unwritten data in the buffer if (addr%256 != 0 && check == 0) { //fill buffer with 0xffff for(i = (addr & 0xff); i < 256; i += 2) while(wr(sock,sitcpAddr,0x604+i,0xffff) < 0); //execute page write while(wr(sock,sitcpAddr,2,0x103) < 0); //waiting for page write end rdata = 1; while(rdata & 0x1){ while(wr(sock,sitcpAddr,0x400,5) < 0); while(wr(sock,sitcpAddr,2,2) < 0); while((rdata = rd(sock,sitcpAddr,0x402-(new_fw << 1))) < 0); } } fclose(f); if(check) printf("FLASH content is the same as the file %s\n",Filename); return OK; } // // parse input line into blank-separated tokens // ignore trailing comments (start with "#") // convert obvious numbers // int parse_command( char *pb, char *tok[], unsigned int tokn[], int maxt) { int nt = 0; char *tp, *p, *p2; int ct; // type: 1 = digits 2 = hex 4 = other while( (tp = strsep( &pb, " \t\n")) != NULL) { if( *tp != '\0') { tok[nt] = tp; // see what kind of chars are in there ct = 0; // special case for leading '0x' if( !strncasecmp( "0x", tp, 2)) { ct = 2; p2 = tp+2; } else p2 = tp; for( p=p2; *p && *p != '#'; ++p) { if( isdigit( *p) && ct==0){ ct = 1; if(maxt == 16) ct = 2; } else if( isxdigit( *p) && !isdigit( *p) && (ct!=4)) ct = 2; else if( !isxdigit( *p)) ct = 4; } switch( ct) { case 1: sscanf( p2, "%d", &tokn[nt]); break; case 2: sscanf( p2, "%x", &tokn[nt]); break; default: tokn[nt] = 0; } if( ++nt >= maxt) goto toomany; } } toomany: return nt; } /* A static variable for holding the line. */ static char *line_read = (char *)NULL; static char file_buf[256]; // // read a line from fp if non-null // or terminal using readline // keep a history // char *rl_gets () { int n; static char last_line[2048]; if( fp != NULL) { if( fgets( file_buf, 255, fp) == NULL){ //after file ends, using terminal input fclose(fp); fp = NULL; goto din; } else { if( (n = strlen( file_buf)) > 1) file_buf[n-1] = '\0'; return file_buf; } } din: #ifdef USE_READLINE /* If the buffer has already been allocated, return the memory to the free pool. */ if (line_read) { free (line_read); line_read = (char *)NULL; } /* Get a line from the user. */ line_read = readline ("tcpip> "); /* If the line has any text in it, save it on the history. */ if (line_read && *line_read) if (strcasecmp(line_read, last_line)) { strcpy(last_line, line_read); add_history(line_read); } return (line_read); #else printf( "tcpipp> "); if( fgets( file_buf, 255, stdin) == NULL) return NULL; else { if( (n = strlen( file_buf)) > 1) file_buf[n-1] = '\0'; return file_buf; } #endif }