Skip to content
Snippets Groups Projects
Commit c649cd5b authored by Sergi Hernandez's avatar Sergi Hernandez
Browse files

Improved version of the firmware downloader tool for the robotis devices.

Improved download speed.
Addes support for more devices.
parent 3c43253d
No related branches found
No related tags found
No related merge requests found
...@@ -18,3 +18,9 @@ ADD_EXECUTABLE(fw_downloader ${sources}) ...@@ -18,3 +18,9 @@ ADD_EXECUTABLE(fw_downloader ${sources})
# link necessary libraries # link necessary libraries
TARGET_LINK_LIBRARIES(fw_downloader ${iriutils_LIBRARY}) TARGET_LINK_LIBRARIES(fw_downloader ${iriutils_LIBRARY})
TARGET_LINK_LIBRARIES(fw_downloader ${comm_LIBRARY}) TARGET_LINK_LIBRARIES(fw_downloader ${comm_LIBRARY})
INSTALL(TARGETS fw_downloader
RUNTIME DESTINATION bin
LIBRARY DESTINATION lib/iridrivers
ARCHIVE DESTINATION lib/iridrivers)
...@@ -10,11 +10,26 @@ ...@@ -10,11 +10,26 @@
#include <iostream> #include <iostream>
const unsigned char bootloader_ping='#'; const unsigned char bootloader_ping='#';
const unsigned char bootloader_ack[]="\n"; const unsigned char bootloader_ack='\n';
//const unsigned char bootloader_load_hex[]="l 0x08003000\n"; const unsigned char bootloader_load='l';
const unsigned char bootloader_load_hex[]="l"; const unsigned char bootloader_go='g';
const unsigned char bootloader_load_motion[]="l 0x08060000\n";
const unsigned char bootloader_go[]="\ngo\n"; 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[]) int main(int argc,char *argv[])
{ {
...@@ -25,34 +40,19 @@ int main(int argc,char *argv[]) ...@@ -25,34 +40,19 @@ int main(int argc,char *argv[])
TRS232_config serial_config; TRS232_config serial_config;
long int num_data=0,i=0; long int num_data=0,i=0;
bool end=false; bool end=false;
// input arguments parser variables int option;
static struct option long_options[] = {{"h", no_argument, 0, 0},// display help message std::string opt_device,opt_fw_file;
{"help", no_argument, 0, 0}, protocol_t protocol;
{"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;
// binary file variables // binary file variables
unsigned char binary_file[MEMORY_MAXSIZE]; 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 start_address=0;
long int binary_size=0; long int binary_size=0;
int block_size=0,count=0,small_block_size=0; int block_size=0,count=0;
// bootloader variables // bootloader variables
unsigned char bootloader_data[MEMORY_MAXSIZE]; unsigned char bootloader_data[MEMORY_MAXSIZE];
bool bootloader_connected=false,error=false; bool bootloader_connected=false;
unsigned char checksum=0x00; unsigned char checksum=0x00;
char load_hex_address[32];
// motion file variables
FILE *motion_fd;
// configuration information for the serial device // configuration information for the serial device
serial_config.baud=57600; serial_config.baud=57600;
...@@ -60,58 +60,47 @@ int main(int argc,char *argv[]) ...@@ -60,58 +60,47 @@ int main(int argc,char *argv[])
serial_config.parity=none; serial_config.parity=none;
serial_config.stop_bits=1; serial_config.stop_bits=1;
for(i=0;i<MEMORY_MAXSIZE;i++) memset(binary_file,0xFF,MEMORY_MAXSIZE);
binary_file[i]=0xFF;
// parse the input arguments // parse the input arguments
do{ while((option = getopt(argc, argv, "hd:f:p:")) != -1)
opt_status=getopt_long_only(argc,argv,"",long_options,&opt_index); {
if(opt_status!=-1) switch(option)
{ {
if(opt_status=='?')// option not recognized or argument missing case 'h':// show help message
{ show_help(argv[0]);
printf("Unknown option \n"); break;
return 0; case 'd':// select serial device
/* handle the error and exit */ std::cout << "Output device: " << optarg << std::endl;
} opt_device=std::string(optarg);
else// process the argument break;
{ case 'f':// select firmware file
switch(opt_index) 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: std::cout << "Unsupported protocol" << std::endl;
case 1: /* display the help information and exit */ show_help(argv[0]);
break; return 0;
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;
} }
} break;
} }
}while(opt_status!=-1); }
// check that the two arguments have been entered // check that the two arguments have been entered
if(opt_device.size()!=0) if(opt_device.size()!=0)
{ {
if(opt_fw_file.size()!=0 && opt_motion_file.size()!=0) if(opt_fw_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)
{ {
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; return 0;
} }
else else
...@@ -129,77 +118,55 @@ int main(int argc,char *argv[]) ...@@ -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) if(hex2bin((char *)opt_fw_file.c_str(), binary_file, &start_address, &binary_size) == false)
{ {
serial_port.close(); serial_port.close();
printf("Error converting the firmware hex file.\n"); std::cout << "Error converting the firmware hex file" << std::endl;
return 0; 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 try{
motion_fd = fopen(opt_motion_file.c_str(), "r"); event_server->wait_all(events,20);
if (!motion_fd) num_data=serial_port.get_num_data();
{ serial_port.read((unsigned char *)bootloader_data,num_data);
printf("Can not find file!\n"); bootloader_data[num_data]='\0';
return 0; printf("%s",bootloader_data);
} fflush(stdout);
fseek(motion_fd, 0, SEEK_END ); for(i=0;i<num_data;i++)
if(ftell(motion_fd)!=(long)(MEMORY_MAXSIZE/2)) {
{ if(protocol==new_protocol)
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++)
{ {
if(servo_model=="mx28") if(bootloader_data[i]=='#')
{ {
if(bootloader_data[i]=='#') count++;
{ if(count==5)
count++; bootloader_connected=true;
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)
count++; bootloader_connected=true;
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) while(!end)
{ {
try{ try{
event_server->wait_all(events,3000); event_server->wait_all(events,300);
num_data=serial_port.get_num_data(); num_data=serial_port.get_num_data();
serial_port.read(bootloader_data,num_data); serial_port.read(bootloader_data,num_data);
bootloader_data[num_data]='\0'; bootloader_data[num_data]='\0';
...@@ -210,15 +177,16 @@ int main(int argc,char *argv[]) ...@@ -210,15 +177,16 @@ int main(int argc,char *argv[])
end=true; end=true;
} }
} }
end=false;
} }
sleep(1);
end=false;
// start the download // 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) while(!end)
{ {
try{ try{
event_server->wait_all(events,3000); event_server->wait_all(events,300);
num_data=serial_port.get_num_data(); num_data=serial_port.get_num_data();
serial_port.read(bootloader_data,num_data); serial_port.read(bootloader_data,num_data);
bootloader_data[num_data]='\0'; bootloader_data[num_data]='\0';
...@@ -229,126 +197,6 @@ int main(int argc,char *argv[]) ...@@ -229,126 +197,6 @@ int main(int argc,char *argv[])
end=true; 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 // compute the binary file checksum
for(i=0;i<binary_size;i++) for(i=0;i<binary_size;i++)
checksum+=binary_file[start_address+i]; checksum+=binary_file[start_address+i];
...@@ -356,31 +204,22 @@ int main(int argc,char *argv[]) ...@@ -356,31 +204,22 @@ int main(int argc,char *argv[])
while(downloaded_size < binary_size) while(downloaded_size < binary_size)
{ {
usleep(1000); 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; block_size=binary_size-downloaded_size;
// if(block_size>64) if(block_size>64)
// block_size=64; block_size=64;
block_size=binary_size;
serial_port.write(&binary_file[start_address+downloaded_size],block_size); serial_port.write(&binary_file[start_address+downloaded_size],block_size);
downloaded_size+=block_size; downloaded_size+=block_size;
printf("\rDownloading Firmware (%ld/%ld byte)", downloaded_size, binary_size); printf("\rDownloading Firmware (%ld/%ld byte)", downloaded_size, binary_size);
sync(); fflush(stdout);
} }
// send the checksum // send the checksum
serial_port.write(&checksum,1); serial_port.write(&checksum,1);
sleep(1); std::cout << std::endl << "Download complete" << std::endl;
printf("\nDownload complete\n");
end=false; end=false;
/* while(!end) while(!end)
{ {
try{ try{
event_server->wait_all(events,3000); event_server->wait_all(events,300);
// there has been an error // there has been an error
num_data=serial_port.get_num_data(); num_data=serial_port.get_num_data();
serial_port.read(bootloader_data,num_data); serial_port.read(bootloader_data,num_data);
...@@ -390,37 +229,36 @@ int main(int argc,char *argv[]) ...@@ -390,37 +229,36 @@ int main(int argc,char *argv[])
// no error to report // no error to report
end=true; end=true;
} }
}*/ }
return 0; // start the loaded program
if(opt_fw_file.size()!=0) 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 try{
serial_port.write((unsigned char *)bootloader_go,4); event_server->wait_all(events,300);
end=false; // there has been an error
while(!end) num_data=serial_port.get_num_data();
{ serial_port.read(bootloader_data,num_data);
try{ bootloader_data[num_data]='\0';
event_server->wait_all(events,1000); printf("%s",bootloader_data);
// there has been an error }catch(CEventTimeoutException &e){
num_data=serial_port.get_num_data(); // no error to report
serial_port.read(bootloader_data,num_data); end=true;
bootloader_data[num_data]='\0';
printf("%s",bootloader_data);
}catch(CEventTimeoutException &e){
// no error to report
end=true;
}
} }
} }
serial_port.close(); serial_port.close();
}catch(CException &e){ }catch(CException &e){
/* handle exceptions */ /* handle exceptions */
printf("%s\n",e.what().c_str()); std::cout << e.what() << std::endl;
} }
} }
} }
else else
{ {
/* display the help information and exit */ std::cout << "No serial device specified" << std::endl;
show_help(argv[0]);
} }
} }
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment