Serveral changes to avoid timeouts under high CPU load.
authorFlorian Pose <fp@igh-essen.com>
Mon, 16 Oct 2006 09:07:49 +0000
changeset 397 c5d2fb08e43f
parent 396 189909f92019
child 398 ff37601361a8
Serveral changes to avoid timeouts under high CPU load.
master/datagram.c
master/datagram.h
master/fsm.c
master/fsm.h
master/master.c
--- a/master/datagram.c	Mon Oct 16 08:03:28 2006 +0000
+++ b/master/datagram.c	Mon Oct 16 09:07:49 2006 +0000
@@ -78,6 +78,7 @@
     datagram->working_counter = 0x00;
     datagram->state = EC_DATAGRAM_INIT;
     datagram->cycles_sent = 0;
+    datagram->check_once_more = 0;
 }
 
 /*****************************************************************************/
--- a/master/datagram.h	Mon Oct 16 08:03:28 2006 +0000
+++ b/master/datagram.h	Mon Oct 16 09:07:49 2006 +0000
@@ -119,6 +119,7 @@
     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;
 
--- a/master/fsm.c	Mon Oct 16 08:03:28 2006 +0000
+++ b/master/fsm.c	Mon Oct 16 09:07:49 2006 +0000
@@ -265,7 +265,7 @@
     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 @@
         return;
     }
 
+    fsm->sii_check_once_more = 1;
     fsm->sii_start = get_cycles();
 
     // issue check/fetch datagram
@@ -1649,16 +1650,19 @@
     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
--- a/master/fsm.h	Mon Oct 16 08:03:28 2006 +0000
+++ b/master/fsm.h	Mon Oct 16 09:07:49 2006 +0000
@@ -72,6 +72,7 @@
     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 */
--- a/master/master.c	Mon Oct 16 08:03:28 2006 +0000
+++ b/master/master.c	Mon Oct 16 09:07:49 2006 +0000
@@ -356,6 +356,7 @@
 
             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 @@
     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 @@
             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++;