# HG changeset patch # User Florian Pose # Date 1155631680 0 # Node ID beb0a77d73c0ac8e098338b9d6a3bdae9b06a6ef # Parent 5d8281f1aa2a6ce283711c20c6a2ba9da256eed3 Improved datagram reception in sync_io and frame dequeuing. diff -r 5d8281f1aa2a -r beb0a77d73c0 master/datagram.h --- a/master/datagram.h Tue Aug 15 08:09:18 2006 +0000 +++ b/master/datagram.h Tue Aug 15 08:48:00 2006 +0000 @@ -74,10 +74,10 @@ { 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 -r 5d8281f1aa2a -r beb0a77d73c0 master/master.c --- a/master/master.c Tue Aug 15 08:09:18 2006 +0000 +++ b/master/master.c Tue Aug 15 08:48:00 2006 +0000 @@ -227,8 +227,8 @@ // empty datagram queue list_for_each_entry_safe(datagram, next_c, &master->datagram_queue, queue) { + datagram->state = EC_DATAGRAM_ERROR; list_del_init(&datagram->queue); - datagram->state = EC_DATAGRAM_ERROR; } // clear domains @@ -422,6 +422,10 @@ 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 @@ 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 @@ // 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 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! - - 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++; - } - - 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); + ecrt_master_receive(master); // receive and dequeue datagrams + + // count number of datagrams still waiting for response + datagrams_waiting = 0; + list_for_each_entry(datagram, &master->datagram_queue, queue) { + datagrams_waiting++; + } + + // if there are no more datagrams waiting, abort loop. + if (!datagrams_waiting) break; } } @@ -1328,11 +1311,6 @@ 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) {