From a55ad1e9e2bb15d803cf3232b740bcba99be3e09 Mon Sep 17 00:00:00 2001 From: Florian Pose <fp@igh-essen.com> Date: Tue, 15 Aug 2006 08:48:00 +0000 Subject: [PATCH] Improved datagram reception in sync_io and frame dequeuing. --- master/datagram.h | 8 +++--- master/master.c | 64 ++++++++++++++++------------------------------- 2 files changed, 25 insertions(+), 47 deletions(-) diff --git a/master/datagram.h b/master/datagram.h index 011d5ec9..b0de0a89 100644 --- a/master/datagram.h +++ b/master/datagram.h @@ -74,10 +74,10 @@ typedef enum { EC_DATAGRAM_INIT, /**< new datagram */ EC_DATAGRAM_QUEUED, /**< datagram queued by master */ - EC_DATAGRAM_SENT, /**< datagram has been sent */ - EC_DATAGRAM_RECEIVED, /**< datagram has been received */ - EC_DATAGRAM_TIMED_OUT, /**< datagram timed out */ - EC_DATAGRAM_ERROR /**< error while sending/receiving */ + EC_DATAGRAM_SENT, /**< datagram has been sent and still in the queue */ + EC_DATAGRAM_RECEIVED, /**< datagram has been received and dequeued */ + EC_DATAGRAM_TIMED_OUT, /**< datagram timed out and was dequeued */ + EC_DATAGRAM_ERROR /**< error while sending/receiving, datagram dequeued */ } ec_datagram_state_t; diff --git a/master/master.c b/master/master.c index 6e4832d2..aae21d65 100644 --- a/master/master.c +++ b/master/master.c @@ -227,8 +227,8 @@ void ec_master_reset(ec_master_t *master /**< EtherCAT master */) // empty datagram queue list_for_each_entry_safe(datagram, next_c, &master->datagram_queue, queue) { - list_del_init(&datagram->queue); datagram->state = EC_DATAGRAM_ERROR; + list_del_init(&datagram->queue); } // clear domains @@ -422,6 +422,10 @@ void ec_master_receive_datagrams(ec_master_t *master, /**< EtherCAT master */ unsigned int cmd_follows, matched; const uint8_t *cur_data; ec_datagram_t *datagram; + cycles_t cycles_received, cycles_timeout; + + cycles_received = get_cycles(); + cycles_timeout = EC_IO_TIMEOUT * cpu_khz / 1000; if (unlikely(size < EC_FRAME_HEADER_SIZE)) { master->stats.corrupted++; @@ -477,7 +481,7 @@ void ec_master_receive_datagrams(ec_master_t *master, /**< EtherCAT master */ continue; } - // copy received data in the datagram memory + // copy received data into the datagram memory memcpy(datagram->data, cur_data, data_size); cur_data += data_size; @@ -488,6 +492,12 @@ void ec_master_receive_datagrams(ec_master_t *master, /**< EtherCAT master */ // dequeue the received datagram datagram->state = EC_DATAGRAM_RECEIVED; list_del_init(&datagram->queue); + + // was the datagram reception delayed? + if (cycles_received - datagram->cycles_sent > cycles_timeout) { + master->stats.delayed++; + ec_master_output_stats(master); + } } } @@ -1237,50 +1247,23 @@ void ecrt_master_deactivate(ec_master_t *master /**< EtherCAT master */) void ec_master_sync_io(ec_master_t *master /**< EtherCAT master */) { - ec_datagram_t *datagram, *n; - unsigned int datagrams_sent; - cycles_t cycles_start, cycles_end, cycles_timeout; + ec_datagram_t *datagram; + unsigned int datagrams_waiting; // send datagrams ecrt_master_send(master); - cycles_start = get_cycles(); // measure io time - cycles_timeout = (cycles_t) EC_IO_TIMEOUT * (cpu_khz / 1000); - while (1) { // active waiting - ec_device_call_isr(master->device); - - cycles_end = get_cycles(); // take current time - if (cycles_end - cycles_start >= cycles_timeout) break; // timeout! + ecrt_master_receive(master); // receive and dequeue datagrams - datagrams_sent = 0; - list_for_each_entry_safe(datagram, n, &master->datagram_queue, queue) { - if (datagram->state == EC_DATAGRAM_RECEIVED) - list_del_init(&datagram->queue); - else if (datagram->state == EC_DATAGRAM_SENT) - datagrams_sent++; + // count number of datagrams still waiting for response + datagrams_waiting = 0; + list_for_each_entry(datagram, &master->datagram_queue, queue) { + datagrams_waiting++; } - if (!datagrams_sent) break; - } - - // timeout; dequeue all datagrams - list_for_each_entry_safe(datagram, n, &master->datagram_queue, queue) { - switch (datagram->state) { - case EC_DATAGRAM_SENT: - case EC_DATAGRAM_QUEUED: - datagram->state = EC_DATAGRAM_TIMED_OUT; - master->stats.timeouts++; - ec_master_output_stats(master); - break; - case EC_DATAGRAM_RECEIVED: - master->stats.delayed++; - ec_master_output_stats(master); - break; - default: - break; - } - list_del_init(&datagram->queue); + // if there are no more datagrams waiting, abort loop. + if (!datagrams_waiting) break; } } @@ -1328,11 +1311,6 @@ void ecrt_master_receive(ec_master_t *master /**< EtherCAT master */) cycles_received = get_cycles(); cycles_timeout = EC_IO_TIMEOUT * cpu_khz / 1000; - // dequeue all received datagrams - list_for_each_entry_safe(datagram, next, &master->datagram_queue, queue) - if (datagram->state == EC_DATAGRAM_RECEIVED) - list_del_init(&datagram->queue); - // dequeue all datagrams that timed out list_for_each_entry_safe(datagram, next, &master->datagram_queue, queue) { switch (datagram->state) { -- GitLab