diff --git a/src/fw_downloader/fw_downloader.cpp b/src/fw_downloader/fw_downloader.cpp index 2c08f8bed5fb1bc2ee5c12432f64fd38d0baa377..61f96dcbf7e8a8d8f9aca3e6f134d3e763ce2640 100755 --- a/src/fw_downloader/fw_downloader.cpp +++ b/src/fw_downloader/fw_downloader.cpp @@ -8,11 +8,14 @@ #include <string.h> #include <stdio.h> #include <iostream> +#include <fstream> const unsigned char bootloader_ping='#'; const unsigned char bootloader_ack='\n'; const unsigned char bootloader_load='l'; const unsigned char bootloader_go='g'; +const unsigned char bootloader_dump='d'; +const unsigned char bootloader_clear='c'; typedef enum {original_protocol=0,new_protocol=1} protocol_t; @@ -28,6 +31,8 @@ void show_help(char *name) std::cout << " devices supported by the new protocol:" << std::endl; std::cout << " - cm510" << std::endl; std::cout << " - mx servo family" << std::endl; + std::cout << " -c clear eeprom memory" << std::endl; + std::cout << " -r eeprom_file read eeprom memory to file" << std::endl; std::cout << " -h shows this help" << std::endl; } @@ -41,7 +46,7 @@ int main(int argc,char *argv[]) long int num_data=0,i=0; bool end=false; int option; - std::string opt_device,opt_fw_file; + std::string opt_device,opt_fw_file,eeprom_file; protocol_t protocol; // binary file variables unsigned char binary_file[MEMORY_MAXSIZE]; @@ -52,7 +57,11 @@ int main(int argc,char *argv[]) // bootloader variables unsigned char bootloader_data[MEMORY_MAXSIZE]; bool bootloader_connected=false; + bool write_fw=false; unsigned char checksum=0x00; + // eeprom variables + std::ofstream ee_file; + bool read_eeprom=false,clear_eeprom=false; // configuration information for the serial device serial_config.baud=57600; @@ -63,7 +72,7 @@ int main(int argc,char *argv[]) memset(binary_file,0xFF,MEMORY_MAXSIZE); // parse the input arguments - while((option = getopt(argc, argv, "hd:f:p:")) != -1) + while((option = getopt(argc, argv, "hd:f:p:cr:")) != -1) { switch(option) { @@ -76,6 +85,9 @@ int main(int argc,char *argv[]) break; case 'f':// select firmware file std::cout << "Firmware file: " << optarg << std::endl; + write_fw=true; + read_eeprom=false; + clear_eeprom=false; opt_fw_file=std::string(optarg); break; case 'p':// select protocol @@ -91,79 +103,115 @@ int main(int argc,char *argv[]) return 0; } break; + case 'c': + write_fw=false; + read_eeprom=false; + clear_eeprom=true; + break; + case 'r':// read eeprom memory + write_fw=false; + read_eeprom=true; + clear_eeprom=false; + eeprom_file=std::string(optarg); + break; } } // check that the two arguments have been entered if(opt_device.size()!=0) { - if(opt_fw_file.size()==0) - { - std::cout << "No firmware file has been specified" << std::endl; - show_help(argv[0]); - return 0; - } - else - { - try{ - // open the serial port - serial_port.open((void *)&opt_device); - // configure the serial port - serial_port.config(&serial_config); - // get the recevice event - events.push_back(serial_port.get_rx_event_id()); - // convert the hex file to a binary file - if(opt_fw_file.size()!=0) - { - if(hex2bin((char *)opt_fw_file.c_str(), binary_file, &start_address, &binary_size) == false) + try{ + // open the serial port + serial_port.open((void *)&opt_device); + // configure the serial port + serial_port.config(&serial_config); + // get the recevice event + events.push_back(serial_port.get_rx_event_id()); + // connect to the bootloader + std::cout << "Switch off device power and turn it on" << std::endl; + while(!bootloader_connected) + { + try{ + if((num_data=serial_port.get_num_data()==0)) + event_server->wait_all(events,100); + num_data=serial_port.get_num_data(); + serial_port.read((unsigned char *)bootloader_data,num_data); + bootloader_data[num_data]='\0'; + printf("%s",bootloader_data); + fflush(stdout); + for(i=0;i<num_data;i++) { - serial_port.close(); - std::cout << "Error converting the firmware hex file" << std::endl; - return 0; + if(protocol==new_protocol) + { + if(bootloader_data[i]=='#') + { + count++; + if(count==5) + bootloader_connected=true; + } + } + else + { + if(bootloader_data[i]=='*') + { + count++; + if(count==5) + bootloader_connected=true; + } + } } + }catch(CEventTimeoutException &e){ + // do nothing and retry + serial_port.write((unsigned char *)&bootloader_ping, 1); } - std::cout << "Switch off device power and turn it on" << std::endl; - // ping the device - while(!bootloader_connected) + } + // ping the device + if(protocol==new_protocol) + { + /* send acknowledgment to the device*/ + serial_port.write((unsigned char *)&bootloader_ack, 1); + end=false; + while(!end) { try{ if((num_data=serial_port.get_num_data()==0)) - event_server->wait_all(events,20); + event_server->wait_all(events,300); num_data=serial_port.get_num_data(); - serial_port.read((unsigned char *)bootloader_data,num_data); + serial_port.read(bootloader_data,num_data); bootloader_data[num_data]='\0'; printf("%s",bootloader_data); fflush(stdout); - for(i=0;i<num_data;i++) - { - if(protocol==new_protocol) - { - if(bootloader_data[i]=='#') - { - count++; - if(count==5) - bootloader_connected=true; - } - } - else - { - if(bootloader_data[i]=='*') - { - count++; - if(count==5) - bootloader_connected=true; - } - } - } }catch(CEventTimeoutException &e){ - // do nothing and retry - serial_port.write((unsigned char *)&bootloader_ping, 1); + end=true; } } - if(protocol==new_protocol) + } + sleep(1); + // convert the hex file to a binary file + if(write_fw) + { + if(opt_fw_file.size()==0) + { + std::cout << "No firmware file has been specified" << std::endl; + show_help(argv[0]); + return 0; + } + else { - /* send acknowledgment to the device*/ - serial_port.write((unsigned char *)&bootloader_ack, 1); + if(opt_fw_file.size()!=0) + { + if(hex2bin((char *)opt_fw_file.c_str(), binary_file, &start_address, &binary_size) == false) + { + serial_port.close(); + std::cout << "Error converting the firmware hex file" << std::endl; + return 0; + } + } + // start the download + serial_port.write((unsigned char *)&bootloader_load,1); + if(protocol==new_protocol) + serial_port.write((unsigned char *)&bootloader_ack,1); + end=false; while(!end) { try{ @@ -175,17 +223,91 @@ int main(int argc,char *argv[]) printf("%s",bootloader_data); fflush(stdout); }catch(CEventTimeoutException &e){ - // the flash has been properly erased end=true; } } + // compute the binary file checksum + for(i=0;i<binary_size;i++) + checksum+=binary_file[start_address+i]; + // send the binary file in 64 byte segments + while(downloaded_size < binary_size) + { + usleep(1000); + block_size=binary_size-downloaded_size; + if(block_size>64) + block_size=64; + serial_port.write(&binary_file[start_address+downloaded_size],block_size); + downloaded_size+=block_size; + printf("\rDownloading Firmware (%ld/%ld byte)", downloaded_size, binary_size); + fflush(stdout); + } + usleep(1000); + // send the checksum + serial_port.write(&checksum,1); + std::cout << std::endl << "Download complete" << std::endl; end=false; + while(!end) + { + try{ + if((num_data=serial_port.get_num_data()==0)) + event_server->wait_all(events,300); + // there has been an error + num_data=serial_port.get_num_data(); + serial_port.read(bootloader_data,num_data); + bootloader_data[num_data]='\0'; + printf("%s",bootloader_data); + }catch(CEventTimeoutException &e){ + // no error to report + end=true; + } + } + } + } + else if(read_eeprom) + { + if(eeprom_file.size()==0) + { + std::cout << "No file has been specified" << std::endl; + show_help(argv[0]); + return 0; } - sleep(1); - // start the download - serial_port.write((unsigned char *)&bootloader_load,1); + else + { + ee_file.open (eeprom_file.c_str(), std::ofstream::out | std::ofstream::trunc); + if(ee_file.fail()) + { + std::cout << "Imposible to create eeprom file" << std::endl; + return 0; + } + else + { + serial_port.write((unsigned char *)&bootloader_dump,1); + if(protocol==new_protocol) + serial_port.write((unsigned char *)&bootloader_ack,1); + end=false; + while(!end) + { + try{ + if((num_data=serial_port.get_num_data()==0)) + event_server->wait_all(events,1000); + num_data=serial_port.get_num_data(); + serial_port.read(bootloader_data,num_data); + ee_file.write((char *)bootloader_data,num_data); + }catch(CEventTimeoutException &e){ + end=true; + } + } + ee_file.close(); + } + } + } + else if(clear_eeprom) + { + serial_port.write((unsigned char *)&bootloader_clear,1); if(protocol==new_protocol) serial_port.write((unsigned char *)&bootloader_ack,1); + // wait for the command ack + end=false; while(!end) { try{ @@ -197,69 +319,67 @@ int main(int argc,char *argv[]) printf("%s",bootloader_data); fflush(stdout); }catch(CEventTimeoutException &e){ - // the flash has been properly erased end=true; } } - // compute the binary file checksum - for(i=0;i<binary_size;i++) - checksum+=binary_file[start_address+i]; - // send the binary file in 64 byte segments - while(downloaded_size < binary_size) - { - usleep(1000); - block_size=binary_size-downloaded_size; - if(block_size>64) - block_size=64; - serial_port.write(&binary_file[start_address+downloaded_size],block_size); - downloaded_size+=block_size; - printf("\rDownloading Firmware (%ld/%ld byte)", downloaded_size, binary_size); - fflush(stdout); - } - usleep(1000); - // send the checksum - serial_port.write(&checksum,1); - std::cout << std::endl << "Download complete" << std::endl; + // wait for the command to end end=false; while(!end) { try{ if((num_data=serial_port.get_num_data()==0)) - event_server->wait_all(events,300); - // there has been an error + event_server->wait_all(events,5000); num_data=serial_port.get_num_data(); serial_port.read(bootloader_data,num_data); bootloader_data[num_data]='\0'; printf("%s",bootloader_data); + fflush(stdout); + end=true; }catch(CEventTimeoutException &e){ - // no error to report + std::cout << "Erase operation did not finish in time" << std::endl; end=true; } } - // start the loaded program - serial_port.write((unsigned char *)&bootloader_go,1); - if(protocol==new_protocol) - serial_port.write((unsigned char *)&bootloader_ack,1); + // read any remaining data end=false; while(!end) { try{ - event_server->wait_all(events,300); - // there has been an error + if((num_data=serial_port.get_num_data()==0)) + event_server->wait_all(events,300); num_data=serial_port.get_num_data(); serial_port.read(bootloader_data,num_data); bootloader_data[num_data]='\0'; printf("%s",bootloader_data); + fflush(stdout); }catch(CEventTimeoutException &e){ - // no error to report end=true; } } - serial_port.close(); - }catch(CException &e){ - /* handle exceptions */ - std::cout << e.what() << std::endl; } + // start the loaded program + serial_port.write((unsigned char *)&bootloader_go,1); + if(protocol==new_protocol) + serial_port.write((unsigned char *)&bootloader_ack,1); + end=false; + while(!end) + { + try{ + event_server->wait_all(events,300); + // there has been an error + num_data=serial_port.get_num_data(); + serial_port.read(bootloader_data,num_data); + bootloader_data[num_data]='\0'; + printf("%s",bootloader_data); + }catch(CEventTimeoutException &e){ + // no error to report + end=true; + } + } + serial_port.close(); + }catch(CException &e){ + /* handle exceptions */ + std::cout << e.what() << std::endl; } } else