40 #include <boost/foreach.hpp> 41 #include <std_msgs/Int16.h> 48 #include <sr_utilities/sr_math_utils.hpp> 51 using std::stringstream;
61 #include <boost/static_assert.hpp> 72 #define ETHERCAT_CAN_BRIDGE_DATA_SIZE sizeof(ETHERCAT_CAN_BRIDGE_DATA) 75 #define check_for_pthread_mutex_init_error(x) switch (x) \ 78 ROS_ERROR("The system temporarily lacks the resources to create another mutex : %s:%d", __FILE__, __LINE__); \ 82 ROS_ERROR("The value specified as attribute is invalid for mutex init : %s:%d", __FILE__, __LINE__); \ 86 ROS_ERROR("The process cannot allocate enough memory to create another mutex : %s:%d", __FILE__, __LINE__); \ 92 ROS_ERROR("unknown error value, is this POSIX system ? : %s:%d", __FILE__, __LINE__); \ 96 #define unlock(x) switch ( pthread_mutex_unlock(x) ) \ 99 ROS_ERROR("The value specified as a mutex is invalid : %s:%d", __FILE__, __LINE__); \ 103 ROS_ERROR("The current thread does not hold a lock on the mutex : %s:%d", __FILE__, __LINE__); \ 108 #define check_for_trylock_error(x) if (x == EINVAL) \ 110 ROS_ERROR("mutex error %s:%d", __FILE__, __LINE__); \ 122 can_message_sent(true),
123 can_packet_acked(true),
130 res = pthread_mutex_init(&
producing, NULL);
167 void SrEdc::construct(EtherCAT_SlaveHandler *sh,
int &start_address,
unsigned int ethercat_command_data_size,
168 unsigned int ethercat_status_data_size,
unsigned int ethercat_can_bridge_data_size,
169 unsigned int ethercat_command_data_address,
unsigned int ethercat_status_data_address,
170 unsigned int ethercat_can_bridge_data_command_address,
171 unsigned int ethercat_can_bridge_data_status_address)
176 std::string path_to_alias, alias;
177 path_to_alias =
"/hand/mapping/" + boost::lexical_cast<std::string>(sh_->get_serial());
191 if (!nh_priv.
getParam(
"use_ns", use_ns))
192 ROS_INFO_STREAM(
"use_ns not set for " << nh_priv.
getNamespace());
197 ROS_INFO_STREAM(
"Using namespace in sr_edc");
201 ROS_INFO_STREAM(
"Not using namespace in sr_edc");
209 std::string path_to_prefix, prefix;
210 path_to_prefix =
"/hand/joint_prefix/" + boost::lexical_cast<std::string>(sh_->get_serial());
211 ROS_INFO_STREAM(
"Trying to read joint_prefix for: " << path_to_prefix);
223 command_size_ = ethercat_command_data_size + ethercat_can_bridge_data_size;
225 start_address += command_size_;
228 status_size_ = ethercat_status_data_size + ethercat_can_bridge_data_size;
230 start_address += status_size_;
236 ROS_INFO(
"First FMMU (command) : start_address : 0x%08X ; size : %3d bytes ; phy addr : 0x%08X",
command_base_,
238 static_cast<int> (ethercat_command_data_address));
243 ethercat_command_data_address,
256 ROS_INFO(
"Second FMMU (status) : start_address : 0x%08X ; size : %3d bytes ; phy addr : 0x%08X",
status_base_,
258 static_cast<int> (ethercat_status_data_address));
263 ethercat_status_data_address,
270 EtherCAT_FMMU_Config *fmmu =
new EtherCAT_FMMU_Config(2);
272 (*fmmu)[0] = *commandFMMU;
273 (*fmmu)[1] = *statusFMMU;
275 sh->set_fmmu_config(fmmu);
277 EtherCAT_PD_Config *pd =
new EtherCAT_PD_Config(4);
279 (*pd)[0] = EC_SyncMan(ethercat_command_data_address, ethercat_command_data_size, EC_QUEUED, EC_WRITTEN_FROM_MASTER);
280 (*pd)[1] = EC_SyncMan(ethercat_can_bridge_data_command_address, ethercat_can_bridge_data_size, EC_QUEUED,
281 EC_WRITTEN_FROM_MASTER);
282 (*pd)[2] = EC_SyncMan(ethercat_status_data_address, ethercat_status_data_size, EC_QUEUED);
283 (*pd)[3] = EC_SyncMan(ethercat_can_bridge_data_status_address, ethercat_can_bridge_data_size, EC_QUEUED);
285 status_size_ = ethercat_status_data_size + ethercat_can_bridge_data_size;
287 (*pd)[0].ChannelEnable =
true;
288 (*pd)[0].ALEventEnable =
true;
289 (*pd)[0].WriteEvent =
true;
291 (*pd)[1].ChannelEnable =
true;
292 (*pd)[1].ALEventEnable =
true;
293 (*pd)[1].WriteEvent =
true;
295 (*pd)[2].ChannelEnable =
true;
296 (*pd)[3].ChannelEnable =
true;
298 sh->set_pd_config(pd);
300 ROS_INFO(
"status_size_ : %d ; command_size_ : %d", status_size_, command_size_);
310 unsigned char cmd_sent;
311 unsigned int wait_time;
312 bool timedout =
true;
313 unsigned int timeout;
323 if (!(err = pthread_mutex_trylock(&
producing)))
344 if (wait_time > timeout)
354 ROS_ERROR(
"ERASE command timedout, resending it !");
377 unsigned int cmd_sent;
379 unsigned int wait_time;
381 unsigned int timeout;
385 if (!(err = pthread_mutex_trylock(&
producing)))
387 ROS_DEBUG(
"Sending READ data ... position : %03x",
pos);
410 if (wait_time > timeout)
459 sr_robot_msgs::SimpleMotorFlasher::Response &res)
462 unsigned int base_addr;
463 unsigned int smallest_start_address = 0x7fff;
464 unsigned int biggest_end_address = 0;
465 unsigned int total_size = 0;
466 bool timedout =
true;
480 fd = bfd_openr(req.firmware.c_str(), NULL);
484 res.value = res.FAIL;
490 if (!bfd_check_format(fd, bfd_object))
492 if (bfd_get_error() != bfd_error_file_ambiguously_recognized)
495 res.value = res.FAIL;
509 int8u magic_packet[] = {0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA};
515 ROS_WARN(
"First magic CAN packet timedout");
516 ROS_WARN(
"Sending another magic CAN packet to put the motor in bootloading mode");
521 ROS_ERROR(
"None of the magic packets were ACKed, didn't bootload the motor.");
522 res.value = res.FAIL;
538 total_size = biggest_end_address - smallest_start_address;
539 base_addr = smallest_start_address;
544 binary_content =
reinterpret_cast<bfd_byte *
>(malloc(total_size + 8));
547 ROS_ERROR(
"Error allocating memory for binary_content");
548 res.value = res.FAIL;
563 res.value = res.FAIL;
575 res.value = res.FAIL;
586 res.value = res.FAIL;
595 ROS_INFO(
"Resetting microcontroller.");
607 res.value = res.SUCCESS;
621 if (!(res = pthread_mutex_trylock(&
producing)))
625 ROS_DEBUG(
"We're sending a CAN message for flashing.");
630 "Sending : SID : 0x%04X ; bus : 0x%02X ; length : 0x%02X ;" 631 " data : 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X",
634 message->message_length,
635 message->message_data[0],
636 message->message_data[1],
637 message->message_data[2],
638 message->message_data[3],
639 message->message_data[4],
640 message->message_data[5],
641 message->message_data[6],
642 message->message_data[7]);
648 ROS_ERROR(
"Mutex is locked, we don't send any CAN message !");
655 message->message_id = 0x00;
656 message->message_length = 0;
672 if (packet->message_id == 0)
678 ROS_DEBUG(
"ack sid : %04X", packet->message_id);
683 ROS_DEBUG(
"READ reply %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x", packet->message_data[0],
684 packet->message_data[1],
685 packet->message_data[2],
686 packet->message_data[3],
687 packet->message_data[4],
688 packet->message_data[5],
689 packet->message_data[6],
690 packet->message_data[7]);
712 if (packet->message_length !=
can_message_.message_length)
714 ROS_DEBUG(
"Length is bad: %d", packet->message_length);
720 for (i = 0; i < packet->message_length; ++i)
723 packet->message_data[i]);
724 if (packet->message_data[i] !=
can_message_.message_data[i])
731 if (!(0x0010 & packet->message_id))
738 if ((packet->message_id & 0b0000000111101111) != (
can_message_.message_id & 0b0000000111101111))
746 ROS_DEBUG(
"Everything is OK, this is our ACK !");
753 unsigned char cmd_sent;
759 if (!(err = pthread_mutex_trylock(&
producing)))
765 if (msg_data != NULL)
767 for (
unsigned int i = 0; i < msg_length; i++)
789 if (wait_time > timeout)
807 while (
pos < total_size)
809 bool timedout =
true;
822 ROS_ERROR(
"Too much retry for READ back, try flashing again");
833 unsigned int section_size = 0;
834 unsigned int section_addr = 0;
845 for (s = fd->sections; s; s = s->next)
848 if (bfd_get_section_flags(fd, s) & (SEC_LOAD))
852 if (bfd_section_lma(fd, s) == bfd_section_vma(fd, s))
854 section_addr = (
unsigned int) bfd_section_lma(fd, s);
855 if (section_addr >= 0x7fff)
859 section_size = (
unsigned int) bfd_section_size(fd, s);
860 *smallest_start_address = std::min(section_addr, *smallest_start_address);
861 *biggest_end_address = std::max(*biggest_end_address, section_addr + section_size);
870 unsigned int section_size = 0;
871 unsigned int section_addr = 0;
873 for (s = fd->sections; s; s = s->next)
876 if (bfd_get_section_flags(fd, s) & (SEC_LOAD))
880 if (bfd_section_lma(fd, s) == bfd_section_vma(fd, s))
882 section_addr = (
unsigned int) bfd_section_lma(fd, s);
886 if (section_addr >= 0x7fff)
890 section_size = (
unsigned int) bfd_section_size(fd, s);
891 bfd_get_section_contents(fd, s, content + (section_addr - base_addr), 0, section_size);
909 unsigned char cmd_sent;
910 int wait_time, timeout;
913 unsigned int packet = 0;
914 ROS_INFO(
"Sending the firmware data");
915 while (
pos < ((total_size % 32) == 0 ? total_size : (total_size + 32 - (total_size % 32))))
917 bool timedout =
true;
930 if (!(err = pthread_mutex_trylock(&
producing)))
956 if (wait_time > timeout)
972 if (!(err = pthread_mutex_trylock(&
producing)))
979 for (
unsigned char j = 0; j < 8; ++j)
1002 if (wait_time > timeout)
1011 ROS_ERROR(
"A WRITE data packet has been lost at pos=%u, resending the 32 bytes block at pos=%u !",
pos,
1012 (
pos - packet * 8));
unsigned int motor_being_flashed
ros::NodeHandle nh_tilde_
bfd_byte * binary_content
bool simple_motor_flasher(sr_robot_msgs::SimpleMotorFlasher::Request &req, sr_robot_msgs::SimpleMotorFlasher::Response &res)
ROS Service that flashes a new firmware into a SimpleMotor board.
static const unsigned int max_retry
ServiceServer advertiseService(const std::string &service, bool(T::*srv_func)(MReq &, MRes &), T *obj)
#define check_for_pthread_mutex_init_error(x)
bool read_flash(unsigned int offset, unsigned int baddr)
Function that reads back 8 bytes from PIC18F program memory.
virtual void reinitialize_boards()=0
This function will call the reinitialization function for the boards attached to the CAN bus...
BOOST_STATIC_ASSERT(sizeof(EDC_COMMAND)==4)
pthread_mutex_t producing
virtual void construct(EtherCAT_SlaveHandler *sh, int &start_address, unsigned int ethercat_command_data_size, unsigned int ethercat_status_data_size, unsigned int ethercat_can_bridge_data_size, unsigned int ethercat_command_data_address, unsigned int ethercat_status_data_address, unsigned int ethercat_can_bridge_data_command_address, unsigned int ethercat_can_bridge_data_status_address)
Construct function, run at startup to set SyncManagers and FMMUs.
ETHERCAT_CAN_BRIDGE_DATA can_message_
virtual void get_board_id_and_can_bus(int board_id, int *can_bus, unsigned int *board_can_id)=0
ROSCPP_DECL bool get(const std::string &key, std::string &s)
bool getParam(const std::string &key, std::string &s) const
bool write_flash_data(unsigned int base_addr, unsigned int total_size)
ros::NodeHandle nodehandle_
void send_CAN_msg(int8u can_bus, int16u msg_id, int8u msg_length, int8u msg_data[], int timeout, bool *timedout)
void erase_flash()
Erase the PIC18F Flash memory.
void build_CAN_message(ETHERCAT_CAN_BRIDGE_DATA *message)
SrEdc()
Constructor of the SrEdc driver.
#define ROS_WARN_STREAM(args)
#define ROS_DEBUG_STREAM(args)
bool can_data_is_ack(ETHERCAT_CAN_BRIDGE_DATA *packet)
This function checks if the can packet in the unpackState() this_buffer is an ACK.
bool read_content_from_object_file(bfd *fd, bfd_byte *content, unsigned int base_addr)
#define ROS_INFO_STREAM(args)
const std::string & getNamespace() const
#define check_for_trylock_error(x)
static std::string get_filename(std::string full_path)
std::string device_joint_prefix_
This is a parent class for the ROS drivers for any Shadow Robot EtherCAT Dual CAN Slave...
void find_address_range(bfd *fd, unsigned int *smallest_start_address, unsigned int *biggest_end_address)
ros::ServiceServer serviceServer
WRITE_FLASH_ADDRESS_COMMAND
#define ETHERCAT_CAN_BRIDGE_DATA_SIZE
bool read_back_and_check_flash(unsigned int baddr, unsigned int total_size)