diff --git a/master/datagram.c b/master/datagram.c index 54ce5af876d3e16610999e421a259953128d7f6f..c94d03f3b4f37037085feb54dd5940a066358719 100644 --- a/master/datagram.c +++ b/master/datagram.c @@ -78,6 +78,7 @@ void ec_datagram_init(ec_datagram_t *datagram /**< EtherCAT datagram */) datagram->working_counter = 0x00; datagram->state = EC_DATAGRAM_INIT; datagram->cycles_sent = 0; + datagram->check_once_more = 0; } /*****************************************************************************/ diff --git a/master/datagram.h b/master/datagram.h index b0de0a89f2208cc0d6e4745e5c6d55e4626c11b0..1228f96638729dfc433a9b9ff4f275d7063e373d 100644 --- a/master/datagram.h +++ b/master/datagram.h @@ -119,6 +119,7 @@ typedef struct uint16_t working_counter; /**< working counter */ ec_datagram_state_t state; /**< datagram state */ cycles_t cycles_sent; /**< time, the datagram was sent */ + uint8_t check_once_more; /**< one more try in case of timeout */ } ec_datagram_t; diff --git a/master/fsm.c b/master/fsm.c index bb49ea7a1d24b3627df5503fb1fba47e8da98fdb..e5779954783a6b86bb3e83cf739041f0027f9251 100644 --- a/master/fsm.c +++ b/master/fsm.c @@ -265,7 +265,7 @@ void ec_fsm_startup_broadcast(ec_fsm_t *fsm /**< finite state machine */) ec_master_t *master = fsm->master; if (datagram->state != EC_DATAGRAM_RECEIVED) { - EC_ERR("Failed tor receive broadcast datagram.\n"); + EC_ERR("Failed to receive broadcast datagram.\n"); fsm->master_state = ec_fsm_error; return; } @@ -1613,6 +1613,7 @@ void ec_fsm_sii_read_check(ec_fsm_t *fsm /**< finite state machine */) return; } + fsm->sii_check_once_more = 1; fsm->sii_start = get_cycles(); // issue check/fetch datagram @@ -1649,16 +1650,19 @@ void ec_fsm_sii_read_fetch(ec_fsm_t *fsm /**< finite state machine */) if (EC_READ_U8(datagram->data + 1) & 0x81) { // still busy... timeout? if (get_cycles() - fsm->sii_start >= (cycles_t) 10 * cpu_khz) { - EC_ERR("SII: Read timeout.\n"); - fsm->sii_state = ec_fsm_error; + if (!fsm->sii_check_once_more) { + EC_ERR("SII: Read timeout.\n"); + fsm->sii_state = ec_fsm_error; #if 0 - EC_DBG("SII busy: %02X %02X %02X %02X\n", - EC_READ_U8(datagram->data + 0), - EC_READ_U8(datagram->data + 1), - EC_READ_U8(datagram->data + 2), - EC_READ_U8(datagram->data + 3)); + EC_DBG("SII busy: %02X %02X %02X %02X\n", + EC_READ_U8(datagram->data + 0), + EC_READ_U8(datagram->data + 1), + EC_READ_U8(datagram->data + 2), + EC_READ_U8(datagram->data + 3)); #endif - return; + return; + } + fsm->sii_check_once_more = 0; } // issue check/fetch datagram again diff --git a/master/fsm.h b/master/fsm.h index c111b275e41e94d23d06ad59bfa8e9a42f8fd3ba..97754f2faacdc70d3205aa167fb3e341e11ecb7e 100644 --- a/master/fsm.h +++ b/master/fsm.h @@ -72,6 +72,7 @@ struct ec_fsm unsigned int sii_mode; /**< SII reading done by APRD (0) or NPRD (1) */ uint8_t sii_value[4]; /**< raw SII value (32bit) */ cycles_t sii_start; /**< sii start */ + uint8_t sii_check_once_more; /**< do one more check in case of timeout */ void (*change_state)(ec_fsm_t *); /**< slave state change state function */ ec_slave_state_t change_new; /**< input: new state */ diff --git a/master/master.c b/master/master.c index d92b60d0abb188ebe30e277906f5ec1a52b4ab85..bae5e431fa96db3db769a9062bbe885e662a96af 100644 --- a/master/master.c +++ b/master/master.c @@ -356,6 +356,7 @@ void ec_master_send_datagrams(ec_master_t *master /**< EtherCAT master */) datagram->state = EC_DATAGRAM_SENT; datagram->cycles_sent = cycles_start; + datagram->check_once_more = 1; datagram->index = master->datagram_index++; if (unlikely(master->debug_level > 1)) @@ -1313,7 +1314,7 @@ void ecrt_master_receive(ec_master_t *master /**< EtherCAT master */) ec_device_call_isr(master->device); cycles_received = get_cycles(); - cycles_timeout = EC_IO_TIMEOUT * cpu_khz / 1000; + cycles_timeout = EC_IO_TIMEOUT /* us */ * cpu_khz / 1000; // dequeue all datagrams that timed out list_for_each_entry_safe(datagram, next, &master->datagram_queue, queue) { @@ -1321,6 +1322,11 @@ void ecrt_master_receive(ec_master_t *master /**< EtherCAT master */) case EC_DATAGRAM_SENT: case EC_DATAGRAM_QUEUED: if (cycles_received - datagram->cycles_sent > cycles_timeout) { + if (datagram->state == EC_DATAGRAM_SENT + && datagram->check_once_more) { + datagram->check_once_more = 0; + break; + } list_del_init(&datagram->queue); datagram->state = EC_DATAGRAM_TIMED_OUT; master->stats.timeouts++;