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)
bool writeData(EthercatCom *com, EtherCAT_SlaveHandler *sh, EthercatDevice::AddrMode addrMode, unsigned num) const
Write data to Sync Manager Activation register.
union ethercat_hardware::WG0XMbxHdr::@63 __attribute__
bool waitForReadMailboxReady(EthercatCom *com)
Waits until read mailbox is full or timeout.
pthread_mutex_t mailbox_lock_
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]
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
bool verifyChecksum(void) const
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)