diff -r c5d2fb08e43f -r ff37601361a8 master/master.c --- a/master/master.c Mon Oct 16 09:07:49 2006 +0000 +++ b/master/master.c Mon Oct 16 14:38:14 2006 +0000 @@ -311,6 +311,7 @@ list_add_tail(&datagram->queue, &master->datagram_queue); datagram->state = EC_DATAGRAM_QUEUED; + datagram->cycles_queued = get_cycles(); } /*****************************************************************************/ @@ -322,15 +323,18 @@ void ec_master_send_datagrams(ec_master_t *master /**< EtherCAT master */) { - ec_datagram_t *datagram; + ec_datagram_t *datagram, *next; size_t datagram_size; uint8_t *frame_data, *cur_data; void *follows_word; - cycles_t cycles_start, cycles_end; + cycles_t cycles_start, cycles_sent, cycles_end; + unsigned long jiffies_sent; unsigned int frame_count, more_datagrams_waiting; - + struct list_head sent_datagrams; + + cycles_start = get_cycles(); frame_count = 0; - cycles_start = get_cycles(); + INIT_LIST_HEAD(&sent_datagrams); if (unlikely(master->debug_level > 1)) EC_DBG("ec_master_send_datagrams\n"); @@ -354,9 +358,7 @@ break; } - datagram->state = EC_DATAGRAM_SENT; - datagram->cycles_sent = cycles_start; - datagram->check_once_more = 1; + list_add_tail(&datagram->sent, &sent_datagrams); datagram->index = master->datagram_index++; if (unlikely(master->debug_level > 1)) @@ -384,7 +386,7 @@ cur_data += EC_DATAGRAM_FOOTER_SIZE; } - if (cur_data - frame_data == EC_FRAME_HEADER_SIZE) { + if (list_empty(&sent_datagrams)) { if (unlikely(master->debug_level > 1)) EC_DBG("nothing to send.\n"); break; @@ -403,6 +405,17 @@ // send frame ec_device_send(master->device, cur_data - frame_data); + cycles_sent = get_cycles(); + jiffies_sent = jiffies; + + // set datagram states and sending timestamps + list_for_each_entry_safe(datagram, next, &sent_datagrams, sent) { + datagram->state = EC_DATAGRAM_SENT; + datagram->cycles_sent = cycles_sent; + datagram->jiffies_sent = jiffies_sent; + list_del_init(&datagram->sent); // empty list of sent datagrams + } + frame_count++; } while (more_datagrams_waiting); @@ -498,6 +511,8 @@ // dequeue the received datagram datagram->state = EC_DATAGRAM_RECEIVED; + datagram->cycles_received = master->device->cycles_isr; + datagram->jiffies_received = master->device->jiffies_isr; list_del_init(&datagram->queue); } } @@ -1063,8 +1078,7 @@ int ec_master_measure_bus_time(ec_master_t *master) { ec_datagram_t datagram; - cycles_t cycles_start, cycles_end, cycles_timeout; - uint32_t times[100], sum, min, max, i; + uint32_t cur, sum, min, max, i; ec_datagram_init(&datagram); @@ -1074,7 +1088,7 @@ return -1; } - cycles_timeout = (cycles_t) EC_IO_TIMEOUT * (cpu_khz / 1000); + ecrt_master_receive(master); sum = 0; min = 0xFFFFFFFF; @@ -1083,11 +1097,9 @@ for (i = 0; i < 100; i++) { ec_master_queue_datagram(master, &datagram); ecrt_master_send(master); - cycles_start = get_cycles(); - - while (1) { // active waiting - ec_device_call_isr(master->device); - cycles_end = get_cycles(); // take current time + + while (1) { + ecrt_master_receive(master); if (datagram.state == EC_DATAGRAM_RECEIVED) { break; @@ -1096,25 +1108,25 @@ EC_WARN("Failed to measure bus time.\n"); goto error; } - else if (cycles_end - cycles_start >= cycles_timeout) { + else if (datagram.state == EC_DATAGRAM_TIMED_OUT) { EC_WARN("Timeout while measuring bus time.\n"); goto error; } } - times[i] = (unsigned int) (cycles_end - cycles_start) * 1000 / cpu_khz; - sum += times[i]; - if (times[i] > max) max = times[i]; - if (times[i] < min) min = times[i]; - } - - EC_INFO("Bus time is (min/avg/max) %u/%u.%u/%u us.\n", + cur = (unsigned int) (datagram.cycles_received + - datagram.cycles_sent) * 1000 / cpu_khz; + sum += cur; + if (cur > max) max = cur; + if (cur < min) min = cur; + } + + EC_INFO("Bus time is (min/avg/max) %u / %u.%u / %u us.\n", min, sum / 100, sum % 100, max); + ec_datagram_clear(&datagram); return 0; error: - // Dequeue and free datagram - list_del(&datagram.queue); ec_datagram_clear(&datagram); return -1; } @@ -1309,24 +1321,28 @@ void ecrt_master_receive(ec_master_t *master /**< EtherCAT master */) { ec_datagram_t *datagram, *next; - cycles_t cycles_received, cycles_timeout; - + cycles_t cycles_timeout; + + // receive datagrams ec_device_call_isr(master->device); - cycles_received = get_cycles(); - cycles_timeout = EC_IO_TIMEOUT /* us */ * cpu_khz / 1000; + cycles_timeout = (cycles_t) EC_IO_TIMEOUT /* us */ * (cpu_khz / 1000); // dequeue all datagrams that timed out list_for_each_entry_safe(datagram, next, &master->datagram_queue, queue) { switch (datagram->state) { + case EC_DATAGRAM_QUEUED: + if (master->device->cycles_isr + - datagram->cycles_queued > cycles_timeout) { + list_del_init(&datagram->queue); + datagram->state = EC_DATAGRAM_TIMED_OUT; + master->stats.timeouts++; + ec_master_output_stats(master); + } + break; 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; - } + if (master->device->cycles_isr + - datagram->cycles_sent > cycles_timeout) { list_del_init(&datagram->queue); datagram->state = EC_DATAGRAM_TIMED_OUT; master->stats.timeouts++; @@ -1359,11 +1375,12 @@ ecrt_master_send(master); - cycles_start = get_cycles(); // take sending time - cycles_timeout = (cycles_t) EC_IO_TIMEOUT * (cpu_khz / 1000); + cycles_start = get_cycles(); + cycles_timeout = (cycles_t) EC_IO_TIMEOUT /* us */ * (cpu_khz / 1000); // active waiting while (1) { + udelay(100); cycles_end = get_cycles(); if (cycles_end - cycles_start >= cycles_timeout) break; }