diff --git a/src/fw_downloader/CMakeLists.txt b/src/fw_downloader/CMakeLists.txt index 969571b2a1ea8a07471304992d780861da89a94c..cab8f0f4fe5be61c790ce05b0d51fc5c0f24edf0 100755 --- a/src/fw_downloader/CMakeLists.txt +++ b/src/fw_downloader/CMakeLists.txt @@ -18,3 +18,9 @@ ADD_EXECUTABLE(fw_downloader ${sources}) # link necessary libraries TARGET_LINK_LIBRARIES(fw_downloader ${iriutils_LIBRARY}) TARGET_LINK_LIBRARIES(fw_downloader ${comm_LIBRARY}) + +INSTALL(TARGETS fw_downloader + RUNTIME DESTINATION bin + LIBRARY DESTINATION lib/iridrivers + ARCHIVE DESTINATION lib/iridrivers) + diff --git a/src/fw_downloader/fw_downloader.cpp b/src/fw_downloader/fw_downloader.cpp index f41efc83e46febd1b57c24bac8db40c97e385400..633665f1968f1274f43fbc717f5020c7f1d5799f 100755 --- a/src/fw_downloader/fw_downloader.cpp +++ b/src/fw_downloader/fw_downloader.cpp @@ -10,11 +10,26 @@ #include <iostream> const unsigned char bootloader_ping='#'; -const unsigned char bootloader_ack[]="\n"; -//const unsigned char bootloader_load_hex[]="l 0x08003000\n"; -const unsigned char bootloader_load_hex[]="l"; -const unsigned char bootloader_load_motion[]="l 0x08060000\n"; -const unsigned char bootloader_go[]="\ngo\n"; +const unsigned char bootloader_ack='\n'; +const unsigned char bootloader_load='l'; +const unsigned char bootloader_go='g'; + +typedef enum {original_protocol=0,new_protocol=1} protocol_t; + +void show_help(char *name) +{ + std::cout << "Usage: " << name << "-d <serial device> -f <firmware file> -p <protocol> [-h]" << std::endl; + std::cout << " -d serial_device Linux serial device used to communicate" << std::endl; + std::cout << " -f firmware_file desired firmware file in Intel Hex format" << std::endl; + std::cout << " -p protocol Communication protocol to be used (original or new)" << std::endl; + std::cout << " devices supported by the original protocol:" << std::endl; + std::cout << " - ax servo family" << std::endl; + std::cout << " - rx servo family" << std::endl; + std::cout << " devices supported by the new protocol:" << std::endl; + std::cout << " - cm510" << std::endl; + std::cout << " - mx servo family" << std::endl; + std::cout << " -h shows this help" << std::endl; +} int main(int argc,char *argv[]) { @@ -25,34 +40,19 @@ int main(int argc,char *argv[]) TRS232_config serial_config; long int num_data=0,i=0; bool end=false; - // input arguments parser variables - static struct option long_options[] = {{"h", no_argument, 0, 0},// display help message - {"help", no_argument, 0, 0}, - {"d", required_argument, 0, 0},// select the desired output device - {"device", required_argument, 0, 0}, - {"f", required_argument, 0, 0},// select the desired firmware file - {"firmware", required_argument, 0, 0}, - {"m", required_argument, 0, 0},// select the desired motion file - {"motion", required_argument, 0, 0}, - {"s", required_argument, 0, 0},// select the desired servo model - {"servo", required_argument, 0, 0}, - {0, 0, 0, 0} - }; - int opt_status,opt_index; - std::string opt_device,opt_fw_file,opt_motion_file,servo_model; + int option; + std::string opt_device,opt_fw_file; + protocol_t protocol; // binary file variables unsigned char binary_file[MEMORY_MAXSIZE]; - long int downloaded_size=0,downloaded_block_size=0; + long int downloaded_size=0; long int start_address=0; long int binary_size=0; - int block_size=0,count=0,small_block_size=0; + int block_size=0,count=0; // bootloader variables unsigned char bootloader_data[MEMORY_MAXSIZE]; - bool bootloader_connected=false,error=false; + bool bootloader_connected=false; unsigned char checksum=0x00; - char load_hex_address[32]; - // motion file variables - FILE *motion_fd; // configuration information for the serial device serial_config.baud=57600; @@ -60,58 +60,47 @@ int main(int argc,char *argv[]) serial_config.parity=none; serial_config.stop_bits=1; - for(i=0;i<MEMORY_MAXSIZE;i++) - binary_file[i]=0xFF; + memset(binary_file,0xFF,MEMORY_MAXSIZE); // parse the input arguments - do{ - opt_status=getopt_long_only(argc,argv,"",long_options,&opt_index); - if(opt_status!=-1) + while((option = getopt(argc, argv, "hd:f:p:")) != -1) + { + switch(option) { - if(opt_status=='?')// option not recognized or argument missing - { - printf("Unknown option \n"); - return 0; - /* handle the error and exit */ - } - else// process the argument - { - switch(opt_index) + case 'h':// show help message + show_help(argv[0]); + break; + case 'd':// select serial device + std::cout << "Output device: " << optarg << std::endl; + opt_device=std::string(optarg); + break; + case 'f':// select firmware file + std::cout << "Firmware file: " << optarg << std::endl; + opt_fw_file=std::string(optarg); + break; + case 'p':// select protocol + std::cout << "Selected protocol: " << optarg << std::endl; + if(std::string(optarg)=="original") + protocol=original_protocol; + else if(std::string(optarg)=="new") + protocol=new_protocol; + else { - case 0: - case 1: /* display the help information and exit */ - break; - case 2: - case 3: printf("output device: %s\n",optarg); - opt_device=std::string(optarg); - break; - case 4: - case 5: printf("Hex file: %s\n", optarg); - opt_fw_file=std::string(optarg); - break; - case 6: - case 7: printf("Motion file: %s\n",optarg); - opt_motion_file=std::string(optarg); - break; - case 8: - case 9: printf("servo model: %s\n",optarg); - servo_model=std::string(optarg); - break; + std::cout << "Unsupported protocol" << std::endl; + show_help(argv[0]); + return 0; } - } + break; } - }while(opt_status!=-1); + } + // check that the two arguments have been entered if(opt_device.size()!=0) { - if(opt_fw_file.size()!=0 && opt_motion_file.size()!=0) - { - printf("Only one file can be download at a time.\n"); - return 0; - } - else if(opt_fw_file.size()==0 && opt_motion_file.size()==0) + if(opt_fw_file.size()==0) { - printf("At least one file have to be specified.\n"); + std::cout << "No firmware file has been specified" << std::endl; + show_help(argv[0]); return 0; } else @@ -129,77 +118,55 @@ int main(int argc,char *argv[]) if(hex2bin((char *)opt_fw_file.c_str(), binary_file, &start_address, &binary_size) == false) { serial_port.close(); - printf("Error converting the firmware hex file.\n"); + std::cout << "Error converting the firmware hex file" << std::endl; return 0; - /* throw an exception */ } } - else + std::cout << "Switch off device power and turn it on" << std::endl; + // ping the device + while(!bootloader_connected) { - // the motion file is already a binary file - motion_fd = fopen(opt_motion_file.c_str(), "r"); - if (!motion_fd) - { - printf("Can not find file!\n"); - return 0; - } - fseek(motion_fd, 0, SEEK_END ); - if(ftell(motion_fd)!=(long)(MEMORY_MAXSIZE/2)) - { - printf("The motion file is too short or too large.\n"); - return 0; - } - rewind(motion_fd); - // read the contents of the file - fread(binary_file,1,MEMORY_MAXSIZE/2,motion_fd); - start_address=0; - binary_size=MEMORY_MAXSIZE/2; - // close the file - fclose(motion_fd); - } - printf("Press DARwIn-OP's Reset button to start...\n"); - if(servo_model!="cm9") - { - while(!bootloader_connected) - { - try{ - event_server->wait_all(events,20); - 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++) + try{ + event_server->wait_all(events,20); + 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++) + { + if(protocol==new_protocol) { - if(servo_model=="mx28") + if(bootloader_data[i]=='#') { - if(bootloader_data[i]=='#') - { - count++; - if(count==5) - bootloader_connected=true; - } + count++; + if(count==5) + bootloader_connected=true; } - else if(servo_model=="ax12" || servo_model=="rx28") + } + else + { + if(bootloader_data[i]=='*') { - if(bootloader_data[i]=='*') - { - count++; - if(count==5) - bootloader_connected=true; - } + count++; + if(count==5) + bootloader_connected=true; } } - }catch(CEventTimeoutException &e){ - // do nothing and retry - serial_port.write((unsigned char *)&bootloader_ping, 1); } + }catch(CEventTimeoutException &e){ + // do nothing and retry + serial_port.write((unsigned char *)&bootloader_ping, 1); } - serial_port.write((unsigned char *)bootloader_ack, 1); + } + if(protocol==new_protocol) + { + /* send acknowledgment to the device*/ + serial_port.write((unsigned char *)&bootloader_ack, 1); while(!end) { try{ - event_server->wait_all(events,3000); + 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'; @@ -210,15 +177,16 @@ int main(int argc,char *argv[]) end=true; } } + end=false; } - sleep(1); - end=false; // start the download - serial_port.write((unsigned char *)bootloader_load_hex,1); + serial_port.write((unsigned char *)&bootloader_load,1); + if(protocol==new_protocol) + serial_port.write((unsigned char *)&bootloader_ack,1); while(!end) { try{ - event_server->wait_all(events,3000); + 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'; @@ -229,126 +197,6 @@ int main(int argc,char *argv[]) end=true; } } - sleep(1); -/* if(servo_model=="mx28") - { - end=false; - serial_port.write((unsigned char *)bootloader_ack, 1); - while(!end) - { - try{ - event_server->wait_all(events,3000); - 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){ - // the flash has been properly erased - end=true; - } - } - sleep(1); - }*/ -/* end=false; - while(downloaded_size < binary_size) - { - sleep(1); - end=false; - sprintf(load_hex_address,"l 0x%08x\n",(int)(0x08000000+start_address+downloaded_size)); - serial_port.write((unsigned char *)load_hex_address, strlen(load_hex_address)); - while(!end) - { - try{ - event_server->wait_all(events,1000); - error=true; - 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){ - // the flash has been properly erased - if(error) - { - serial_port.close(); - return 0; - } - else - end=true; - } - } - sleep(1); - if(servo_model=="mx28") - { - error=false; - end=false; - serial_port.write((unsigned char *)bootloader_ack, 1); - while(!end) - { - try{ - event_server->wait_all(events,3000); - 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){ - // the flash has been properly erased - if(error) - { - serial_port.close(); - return 0; - } - else - end=true; - } - } - sleep(1); - } - block_size=binary_size-downloaded_size; - if(block_size>64*1024) - block_size=64*1024; - // compute the binary file checksum - checksum=0; - for(i=0;i<block_size;i++) - checksum+=binary_file[start_address+downloaded_size+i]; - downloaded_block_size=0; - while(downloaded_block_size < block_size) - { - usleep(1000); - small_block_size=block_size-downloaded_block_size; - if(small_block_size>64) - small_block_size=64; - serial_port.write(&binary_file[start_address+downloaded_size+downloaded_block_size],small_block_size); - downloaded_block_size+=small_block_size; - printf("\rDownloading Firmware (%ld/%ld byte)", downloaded_block_size, block_size); - } - downloaded_size+=block_size; - serial_port.write(&checksum,1); - sleep(1); - end=false; - while(!end) - { - try{ - event_server->wait_all(events,3000); - // 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 - if(error) - { - serial_port.close(); - return 0; - } - else - end=true; - } - } - }*/ // compute the binary file checksum for(i=0;i<binary_size;i++) checksum+=binary_file[start_address+i]; @@ -356,31 +204,22 @@ int main(int argc,char *argv[]) while(downloaded_size < binary_size) { usleep(1000); - if((num_data=serial_port.get_num_data())!=0) - { - serial_port.read(bootloader_data,num_data); - bootloader_data[num_data]='\0'; - printf("%s",bootloader_data); - return 0; - } block_size=binary_size-downloaded_size; -// if(block_size>64) -// block_size=64; - block_size=binary_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); - sync(); + fflush(stdout); } // send the checksum serial_port.write(&checksum,1); - sleep(1); - printf("\nDownload complete\n"); + std::cout << std::endl << "Download complete" << std::endl; end=false; -/* while(!end) + while(!end) { try{ - event_server->wait_all(events,3000); + 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); @@ -390,37 +229,36 @@ int main(int argc,char *argv[]) // no error to report end=true; } - }*/ - return 0; - if(opt_fw_file.size()!=0) + } + // 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) { - // start the loaded program - serial_port.write((unsigned char *)bootloader_go,4); - end=false; - while(!end) - { - try{ - event_server->wait_all(events,1000); - // 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; - } + 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 */ - printf("%s\n",e.what().c_str()); + std::cout << e.what() << std::endl; } } } else { - /* display the help information and exit */ + std::cout << "No serial device specified" << std::endl; + show_help(argv[0]); } }