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