37 #include "dll/ethercat_device_addressed_telegram.h"    44 #define ERR_MODE "\033[41m"    45 #define STD_MODE "\033[0m"    46 #define WARN_MODE "\033[43m"    47 #define GOOD_MODE "\033[42m"    48 #define INFO_MODE "\033[44m"    50 #define ERROR_HDR "\033[41mERROR\033[0m"    51 #define WARN_HDR "\033[43mERROR\033[0m"    93     if (length > MBX_DATA_SIZE) 
    95       fprintf(stderr, 
"size of %d is too large for write\n", length);
   102     if (length > (MBX_SIZE-1))
   104       fprintf(stderr, 
"size of %d is too large for read\n", length);
   109     assert(0 && 
"invalid MbxCmdType");
   128   if (!this->
hdr_.build(address, length, type, seqnum))
   135     memcpy(
data_, data, length);
   139     memset(
data_, 0, length);
   167   int timediff_ms = (current.tv_sec-start.tv_sec)*1000 
   168     + (current.tv_nsec-start.tv_nsec)/1000000; 
   182   int result = clock_gettime(clk_id, time);
   185     fprintf(stderr, 
"safe_clock_gettime : %s\n", strerror(error));
   201   assert(usec<1000000);
   204   struct timespec req, rem;
   206   req.tv_nsec = usec*1000;
   207   while (nanosleep(&req, &rem)!=0) { 
   209     fprintf(stderr,
"%s : Error : %s\n", __func__, strerror(error));    
   210     if (error != EINTR) {
   223   tg->set_idx(logic->get_idx());
   224   tg->set_wkc(logic->get_wkc());
   232     ROS_ERROR(
"WG0X : init mailbox mutex :%s", strerror(error));
   245   EC_State state = 
sh_->get_state();
   246   if ((state != EC_SAFEOP_STATE) && (state != EC_OP_STATE)) {
   248             "cannot do mailbox read in current device state = %d\n", __func__, state);
   283   EC_Logic *logic = EC_Logic::instance();    
   284   EC_UINT station_addr = 
sh_->get_station_address();  
   289   unsigned char unused[1] = {0};
   290   NPRD_Telegram read_start(
   297   NPRD_Telegram read_end(  
   304   read_start.attach(&read_end);
   305   EC_Ethernet_Frame frame(&read_start);
   310   static const unsigned MAX_DROPS = 15;
   311   for (
unsigned tries=0; tries<MAX_DROPS; ++tries) {
   322             " too much packet loss\n", __func__);   
   328   if (read_start.get_wkc() != read_end.get_wkc()) {
   330             "read mbx working counters are inconsistant, %d, %d\n",
   331             __func__, read_start.get_wkc(), read_end.get_wkc());
   334   if (read_start.get_wkc() > 1) {
   336             "more than one device (%d) responded \n", __func__, read_start.get_wkc());
   339   if (read_start.get_wkc() == 1)  {
   341             " read mbx contained garbage data\n", __func__);
   362   static const int MAX_WAIT_TIME_MS = 100;
   364   unsigned good_results=0;
   367   struct timespec start_time, current_time;
   378       const uint8_t MailboxStatusMask = (1<<3);
   379       if (SyncManStatus & MailboxStatusMask) {
   388   } 
while (timediff < MAX_WAIT_TIME_MS);
   390   if (good_results == 0) {
   392             " error reading from device\n", __func__);          
   395             " error read mbx not full after %d ms\n", __func__, timediff);      
   414   static const int MAX_WAIT_TIME_MS = 100;
   416   unsigned good_results=0;
   419   struct timespec start_time, current_time;
   430       const uint8_t MailboxStatusMask = (1<<3);
   431       if ( !(SyncManStatus & MailboxStatusMask) ) {
   440   } 
while (timediff < MAX_WAIT_TIME_MS);
   442   if (good_results == 0) {
   444             " error reading from device\n", __func__);          
   447             " error write mbx not empty after %d ms\n", __func__, timediff);      
   478   EC_Logic *logic = EC_Logic::instance();    
   479   EC_UINT station_addr = 
sh_->get_station_address();
   485   static const unsigned TELEGRAM_OVERHEAD = 50;
   498     unsigned char unused[1] = {0};
   499     NPWR_Telegram write_start(
   505                               (
const unsigned char*) data);
   515       write_start.attach(&write_end);
   518     EC_Ethernet_Frame frame(&write_start);
   523     for (
unsigned tries=0; (tries<10) && !success; ++tries) {
   544               " too much packet loss\n", __func__);   
   549     if (split_write && (write_start.get_wkc() != write_end.get_wkc())) {
   551               " write mbx working counters are inconsistant\n", __func__);
   555     if (write_start.get_wkc() > 1) 
   558               " multiple (%d) devices responded to mailbox write\n", __func__, write_start.get_wkc());
   561     else if (write_start.get_wkc() != 1)
   567                 " initial mailbox write refused\n", __func__);
   574                 " repeated mailbox write refused\n", __func__);
   599             " could not read status mailbox syncman (1)\n", __func__);
   606             " syncman repeat request and ack do not match\n", __func__);
   615             " could not write syncman repeat request\n", __func__);
   621   static const int MAX_WAIT_TIME_MS = 100;
   624   struct timespec start_time, current_time;
   632               " could not read status mailbox syncman (2)\n", __func__);
   640                 " got repeat response, but read mailbox is still empty\n", __func__);
   649               " syncman repeat request was changed while waiting for response\n", __func__);
   661   } 
while (timediff < MAX_WAIT_TIME_MS);
   664           " error repeat request not acknowledged after %d ms\n", __func__, timediff);    
   683   static const unsigned MAX_TRIES = 10;
   684   static const unsigned MAX_DROPPED = 10;
   696   EC_Logic *logic = EC_Logic::instance();    
   697   EC_UINT station_addr = 
sh_->get_station_address();
   703   static const unsigned TELEGRAM_OVERHEAD = 50;
   711   unsigned char unused[1] = {0};
   712   NPRD_Telegram read_start(
   718                            (
unsigned char*) data);
   719   NPRD_Telegram read_end(  
   728     read_start.attach(&read_end);
   731   EC_Ethernet_Frame frame(&read_start);
   734   unsigned total_dropped =0;
   735   for (tries=0; tries<MAX_TRIES; ++tries) {      
   739     for (dropped=0; dropped<MAX_DROPPED; ++dropped) {
   748     if (dropped>=MAX_DROPPED) {
   750               " too many dropped packets : %d\n", __func__, dropped);
   753     if (split_read && (read_start.get_wkc() != read_end.get_wkc())) {
   755               "read mbx working counters are inconsistant\n", __func__);
   759     if (read_start.get_wkc() == 0) {
   762                 " inconsistancy : got wkc=%d with no dropped packets\n", 
   763                 __func__, read_start.get_wkc()); 
   764         fprintf(stderr, 
"total dropped = %d\n", total_dropped);
   770                 " asking for read repeat after dropping %d packets\n", __func__, dropped);
   776     } 
else if (read_start.get_wkc() == 1) {
   781               " invalid wkc for read : %d\n", __func__, read_start.get_wkc());   
   787   if (tries >= MAX_TRIES) {
   789             " could not get responce from device after %d retries, %d total dropped packets\n",
   790             __func__, tries, total_dropped);
   842             " clearing read mbx\n", __func__);
   852               " builing mbx header\n", __func__);
   858       fprintf(stderr, 
"%s : " ERROR_HDR " write of cmd failed\n", __func__);
   867             "waiting for read mailbox\n", __func__);
   883     memset(&stat,0,
sizeof(stat));
   887       fprintf(stderr, 
"%s : " ERROR_HDR " read failed\n", __func__);
   894               "checksum error reading mailbox data\n", __func__);
   895       fprintf(stderr, 
"length = %d\n", length);
   898     memcpy(data, &stat, length);
   910     fprintf(stderr, 
"%s : " ERROR_HDR " getting mbx lock\n", __func__);
   921     fprintf(stderr, 
"%s : " ERROR_HDR " freeing mbx lock\n", __func__);
   970       fprintf(stderr, 
"%s : " ERROR_HDR " builing mbx header\n", __func__);
   974     unsigned write_length = 
sizeof(cmd.hdr_)+length+
sizeof(cmd.checksum_);
   976       fprintf(stderr, 
"%s : " ERROR_HDR " write failed\n", __func__);
   986             "write mailbox\n", __func__);
 
static const unsigned MBX_STATUS_PHY_ADDR
 
static const unsigned MBX_COMMAND_PHY_ADDR
 
int readMailbox_(EthercatCom *com, unsigned address, void *data, unsigned length)
Internal function. 
 
void publishMailboxDiagnostics(diagnostic_updater::DiagnosticStatusWrapper &d)
 
union ethercat_hardware::WG0XMbxHdr::@63 __attribute__
 
bool waitForReadMailboxReady(EthercatCom *com)
Waits until read mailbox is full or timeout. 
 
pthread_mutex_t mailbox_lock_
 
bool writeData(EthercatCom *com, EtherCAT_SlaveHandler *sh, EthercatDevice::AddrMode addrMode, unsigned num) const 
Write data to Sync Manager Activation register. 
 
unsigned computeChecksum(void const *data, unsigned length)
 
static const unsigned MBX_SIZE
 
bool readMailboxInternal(EthercatCom *com, void *data, unsigned length)
Reads data from read mailbox. 
 
MbxDiagnostics mailbox_publish_diagnostics_
 
void addf(const std::string &key, const char *format,...)
 
SyncManPDIControl pdi_control
 
unsigned int rotateRight8(unsigned in)
 
int timediff_ms(const timespec ¤t, const timespec &start)
Find difference between two timespec values. 
 
bool clearReadMailbox(EthercatCom *com)
Clears read mailbox by reading first and last byte. 
 
int safe_clock_gettime(clockid_t clk_id, timespec *time)
error checking wrapper around clock_gettime 
 
int writeMailbox(EthercatCom *com, unsigned address, void const *data, unsigned length)
Write data to WG0X local bus using mailbox communication. 
 
static const unsigned MBX_STATUS_SIZE
 
int writeMailbox_(EthercatCom *com, unsigned address, void const *data, unsigned length)
Internal function. 
 
bool initialize(EtherCAT_SlaveHandler *sh)
 
void diagnoseMailboxError(EthercatCom *com)
Runs diagnostic on read and write mailboxes. 
 
bool _readMailboxRepeatRequest(EthercatCom *com)
 
static const unsigned MBX_COMMAND_SIZE
 
bool writeMailboxInternal(EthercatCom *com, void const *data, unsigned length)
Writes data to mailbox. 
 
virtual bool txandrx_once(struct EtherCAT_Frame *frame)=0
 
uint8_t data_[MBX_DATA_SIZE]
 
bool verifyChecksum(void) const 
 
static const unsigned MBX_DATA_SIZE
 
bool readData(EthercatCom *com, EtherCAT_SlaveHandler *sh, EthercatDevice::AddrMode addrMode, unsigned num)
Read data from Sync Manager. 
 
bool waitForWriteMailboxReady(EthercatCom *com)
Waits until write mailbox is empty or timeout. 
 
static int readData(EthercatCom *com, EtherCAT_SlaveHandler *sh, EC_UINT address, void *buffer, EC_UINT length, AddrMode addrMode)
Read data from device ESC. 
 
int readMailbox(EthercatCom *com, unsigned address, void *data, unsigned length)
Read data from WG0X local bus using mailbox communication. 
 
bool build(unsigned address, unsigned length, MbxCmdType type, unsigned seqnum, void const *data)
 
void updateIndexAndWkc(EC_Telegram *tg, EC_Logic *logic)
 
static const unsigned MBX_STATUS_SYNCMAN_NUM
 
bool readMailboxRepeatRequest(EthercatCom *com)
 
MbxDiagnostics mailbox_diagnostics_
 
static const unsigned MBX_COMMAND_SYNCMAN_NUM
 
EtherCAT_SlaveHandler * sh_
 
void safe_usleep(uint32_t usec)
safe version of usleep. 
 
bool verifyDeviceStateForMailboxOperation()
 
bool build(unsigned address, unsigned length, MbxCmdType type, unsigned seqnum)