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})
# 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)
......@@ -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]);
}
}
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