master/fsm_sii.c
branchstable-1.3
changeset 1746 72e7507b3f1b
parent 1745 07fd94c5119d
--- a/master/fsm_sii.c	Thu Sep 13 11:08:46 2007 +0000
+++ b/master/fsm_sii.c	Wed Oct 03 08:58:01 2007 +0000
@@ -43,16 +43,28 @@
 #include "master.h"
 #include "fsm_sii.h"
 
-/*****************************************************************************/
-
-void ec_fsm_sii_start_reading(ec_fsm_sii_t *);
-void ec_fsm_sii_read_check(ec_fsm_sii_t *);
-void ec_fsm_sii_read_fetch(ec_fsm_sii_t *);
-void ec_fsm_sii_start_writing(ec_fsm_sii_t *);
-void ec_fsm_sii_write_check(ec_fsm_sii_t *);
-void ec_fsm_sii_write_check2(ec_fsm_sii_t *);
-void ec_fsm_sii_end(ec_fsm_sii_t *);
-void ec_fsm_sii_error(ec_fsm_sii_t *);
+/**
+ * Read/Write timeout. [ms]
+ */
+#define EEPROM_TIMEOUT 10
+
+/**
+ * Time before evaluating answer at writing. [ms]
+ */
+#define EEPROM_INHIBIT  5
+
+//#define SII_DEBUG
+
+/*****************************************************************************/
+
+void ec_fsm_sii_state_start_reading(ec_fsm_sii_t *);
+void ec_fsm_sii_state_read_check(ec_fsm_sii_t *);
+void ec_fsm_sii_state_read_fetch(ec_fsm_sii_t *);
+void ec_fsm_sii_state_start_writing(ec_fsm_sii_t *);
+void ec_fsm_sii_state_write_check(ec_fsm_sii_t *);
+void ec_fsm_sii_state_write_check2(ec_fsm_sii_t *);
+void ec_fsm_sii_state_end(ec_fsm_sii_t *);
+void ec_fsm_sii_state_error(ec_fsm_sii_t *);
 
 /*****************************************************************************/
 
@@ -86,13 +98,13 @@
 
 void ec_fsm_sii_read(ec_fsm_sii_t *fsm, /**< finite state machine */
                      ec_slave_t *slave, /**< slave to read from */
-                     uint16_t offset, /**< offset to read from */
+                     uint16_t word_offset, /**< offset to read from */
                      ec_fsm_sii_addressing_t mode /**< addressing scheme */
                      )
 {
-    fsm->state = ec_fsm_sii_start_reading;
+    fsm->state = ec_fsm_sii_state_start_reading;
     fsm->slave = slave;
-    fsm->offset = offset;
+    fsm->word_offset = word_offset;
     fsm->mode = mode;
 }
 
@@ -104,14 +116,14 @@
 
 void ec_fsm_sii_write(ec_fsm_sii_t *fsm, /**< finite state machine */
                       ec_slave_t *slave, /**< slave to read from */
-                      uint16_t offset, /**< offset to read from */
-                      const uint16_t *value, /**< pointer to 2 bytes of data */
+                      uint16_t word_offset, /**< offset to read from */
+                      const uint8_t *value, /**< pointer to 2 bytes of data */
                       ec_fsm_sii_addressing_t mode /**< addressing scheme */
                       )
 {
-    fsm->state = ec_fsm_sii_start_writing;
+    fsm->state = ec_fsm_sii_state_start_writing;
     fsm->slave = slave;
-    fsm->offset = offset;
+    fsm->word_offset = word_offset;
     fsm->mode = mode;
     memcpy(fsm->value, value, 2);
 }
@@ -127,7 +139,8 @@
 {
     fsm->state(fsm);
 
-    return fsm->state != ec_fsm_sii_end && fsm->state != ec_fsm_sii_error;
+    return fsm->state != ec_fsm_sii_state_end
+		&& fsm->state != ec_fsm_sii_state_error;
 }
 
 /*****************************************************************************/
@@ -139,11 +152,11 @@
 
 int ec_fsm_sii_success(ec_fsm_sii_t *fsm /**< Finite state machine */)
 {
-    return fsm->state == ec_fsm_sii_end;
+    return fsm->state == ec_fsm_sii_state_end;
 }
 
 /******************************************************************************
- *  SII state machine
+ * state functions
  *****************************************************************************/
 
 /**
@@ -151,7 +164,9 @@
    Starts reading the slave information interface.
 */
 
-void ec_fsm_sii_start_reading(ec_fsm_sii_t *fsm /**< finite state machine */)
+void ec_fsm_sii_state_start_reading(
+		ec_fsm_sii_t *fsm /**< finite state machine */
+		)
 {
     ec_datagram_t *datagram = fsm->datagram;
 
@@ -165,11 +180,17 @@
             break;
     }
 
-    EC_WRITE_U8 (datagram->data,     0x00); // read-only access
+    EC_WRITE_U8 (datagram->data,     0x80); // two address octets
     EC_WRITE_U8 (datagram->data + 1, 0x01); // request read operation
-    EC_WRITE_U16(datagram->data + 2, fsm->offset);
+    EC_WRITE_U16(datagram->data + 2, fsm->word_offset);
+
+#ifdef SII_DEBUG
+	EC_DBG("reading SII data:\n");
+	ec_print_data(datagram->data, 4);
+#endif
+
     fsm->retries = EC_FSM_RETRIES;
-    fsm->state = ec_fsm_sii_read_check;
+    fsm->state = ec_fsm_sii_state_read_check;
 }
 
 /*****************************************************************************/
@@ -179,7 +200,9 @@
    Checks, if the SII-read-datagram has been sent and issues a fetch datagram.
 */
 
-void ec_fsm_sii_read_check(ec_fsm_sii_t *fsm /**< finite state machine */)
+void ec_fsm_sii_state_read_check(
+		ec_fsm_sii_t *fsm /**< finite state machine */
+		)
 {
     ec_datagram_t *datagram = fsm->datagram;
 
@@ -187,7 +210,7 @@
         return;
 
     if (datagram->state != EC_DATAGRAM_RECEIVED) {
-        fsm->state = ec_fsm_sii_error;
+        fsm->state = ec_fsm_sii_state_error;
         EC_ERR("Failed to receive SII read datagram from slave %i"
                 " (datagram state %i).\n",
                fsm->slave->ring_position, datagram->state);
@@ -195,7 +218,7 @@
     }
 
     if (datagram->working_counter != 1) {
-        fsm->state = ec_fsm_sii_error;
+        fsm->state = ec_fsm_sii_state_error;
         EC_ERR("Reception of SII read datagram failed on slave %i: ",
                 fsm->slave->ring_position);
         ec_datagram_print_wc_error(datagram);
@@ -216,7 +239,7 @@
     }
 
     fsm->retries = EC_FSM_RETRIES;
-    fsm->state = ec_fsm_sii_read_fetch;
+    fsm->state = ec_fsm_sii_state_read_fetch;
 }
 
 /*****************************************************************************/
@@ -226,7 +249,9 @@
    Fetches the result of an SII-read datagram.
 */
 
-void ec_fsm_sii_read_fetch(ec_fsm_sii_t *fsm /**< finite state machine */)
+void ec_fsm_sii_state_read_fetch(
+		ec_fsm_sii_t *fsm /**< finite state machine */
+		)
 {
     ec_datagram_t *datagram = fsm->datagram;
 
@@ -234,7 +259,7 @@
         return;
 
     if (datagram->state != EC_DATAGRAM_RECEIVED) {
-        fsm->state = ec_fsm_sii_error;
+        fsm->state = ec_fsm_sii_state_error;
         EC_ERR("Failed to receive SII check/fetch datagram from slave %i"
                 " (datagram state %i).\n",
                fsm->slave->ring_position, datagram->state);
@@ -242,79 +267,78 @@
     }
 
     if (datagram->working_counter != 1) {
-        fsm->state = ec_fsm_sii_error;
+        fsm->state = ec_fsm_sii_state_error;
         EC_ERR("Reception of SII check/fetch datagram failed on slave %i: ",
                 fsm->slave->ring_position);
         ec_datagram_print_wc_error(datagram);
         return;
     }
 
+#ifdef SII_DEBUG
+	EC_DBG("checking SII read state:\n");
+	ec_print_data(datagram->data, 10);
+#endif
+
+    if (EC_READ_U8(datagram->data + 1) & 0x20) {
+        EC_ERR("SII: Error on last SII command!\n");
+        fsm->state = ec_fsm_sii_state_error;
+        return;
+    }
+
     // check "busy bit"
-    if (EC_READ_U8(datagram->data + 1) & 0x81) {
+    if (EC_READ_U8(datagram->data + 1) & 0x81) { // busy bit or
+												 // read operation busy
         // still busy... timeout?
         if (datagram->cycles_received
-            - fsm->cycles_start >= (cycles_t) 10 * cpu_khz) {
-            if (!fsm->check_once_more) {
+            - fsm->cycles_start >= (cycles_t) EEPROM_TIMEOUT * cpu_khz) {
+            if (fsm->check_once_more) {
+				fsm->check_once_more = 0;
+			} else {
                 EC_ERR("SII: Read timeout.\n");
-                fsm->state = ec_fsm_sii_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));
-#endif
+                fsm->state = ec_fsm_sii_state_error;
                 return;
             }
-            fsm->check_once_more = 0;
         }
 
         // issue check/fetch datagram again
-        switch (fsm->mode) {
-            case EC_FSM_SII_POSITION:
-                ec_datagram_aprd(datagram, fsm->slave->ring_position, 0x502, 10);
-                break;
-            case EC_FSM_SII_NODE:
-                ec_datagram_nprd(datagram, fsm->slave->station_address, 0x502, 10);
-                break;
-        }
         fsm->retries = EC_FSM_RETRIES;
         return;
     }
 
-#if 0
-    EC_DBG("SII rec: %02X %02X %02X %02X - %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_READ_U8(datagram->data + 6), EC_READ_U8(datagram->data + 7),
-           EC_READ_U8(datagram->data + 8), EC_READ_U8(datagram->data + 9));
-#endif
-
     // SII value received.
     memcpy(fsm->value, datagram->data + 6, 4);
-    fsm->state = ec_fsm_sii_end;
+    fsm->state = ec_fsm_sii_state_end;
 }
 
 /*****************************************************************************/
 
 /**
    SII state: START WRITING.
-   Starts reading the slave information interface.
-*/
-
-void ec_fsm_sii_start_writing(ec_fsm_sii_t *fsm /**< finite state machine */)
+   Starts writing a word through the slave information interface.
+*/
+
+void ec_fsm_sii_state_start_writing(
+		ec_fsm_sii_t *fsm /**< finite state machine */
+		)
 {
     ec_datagram_t *datagram = fsm->datagram;
 
     // initiate write operation
     ec_datagram_npwr(datagram, fsm->slave->station_address, 0x502, 8);
-    EC_WRITE_U8 (datagram->data,     0x01); // enable write access
+    EC_WRITE_U8 (datagram->data,     0x81); // two address octets
+											// + enable write access
     EC_WRITE_U8 (datagram->data + 1, 0x02); // request write operation
-    EC_WRITE_U32(datagram->data + 2, fsm->offset);
+    EC_WRITE_U16(datagram->data + 2, fsm->word_offset);
+	memset(datagram->data + 4, 0x00, 2);
     memcpy(datagram->data + 6, fsm->value, 2);
 
+#ifdef SII_DEBUG
+	EC_DBG("writing SII data:\n");
+	ec_print_data(datagram->data, 8);
+#endif
+
     fsm->retries = EC_FSM_RETRIES;
-    fsm->state = ec_fsm_sii_write_check;
+    fsm->state = ec_fsm_sii_state_write_check;
 }
 
 /*****************************************************************************/
@@ -323,7 +347,9 @@
    SII state: WRITE CHECK.
 */
 
-void ec_fsm_sii_write_check(ec_fsm_sii_t *fsm /**< finite state machine */)
+void ec_fsm_sii_state_write_check(
+		ec_fsm_sii_t *fsm /**< finite state machine */
+		)
 {
     ec_datagram_t *datagram = fsm->datagram;
 
@@ -331,7 +357,7 @@
         return;
 
     if (datagram->state != EC_DATAGRAM_RECEIVED) {
-        fsm->state = ec_fsm_sii_error;
+        fsm->state = ec_fsm_sii_state_error;
         EC_ERR("Failed to receive SII write datagram for slave %i"
                 " (datagram state %i).\n",
                fsm->slave->ring_position, datagram->state);
@@ -339,7 +365,7 @@
     }
 
     if (datagram->working_counter != 1) {
-        fsm->state = ec_fsm_sii_error;
+        fsm->state = ec_fsm_sii_state_error;
         EC_ERR("Reception of SII write datagram failed on slave %i: ",
                 fsm->slave->ring_position);
         ec_datagram_print_wc_error(datagram);
@@ -349,10 +375,10 @@
     fsm->cycles_start = datagram->cycles_sent;
     fsm->check_once_more = 1;
 
-    // issue check/fetch datagram
+    // issue check datagram
     ec_datagram_nprd(datagram, fsm->slave->station_address, 0x502, 2);
     fsm->retries = EC_FSM_RETRIES;
-    fsm->state = ec_fsm_sii_write_check2;
+    fsm->state = ec_fsm_sii_state_write_check2;
 }
 
 /*****************************************************************************/
@@ -361,7 +387,9 @@
    SII state: WRITE CHECK 2.
 */
 
-void ec_fsm_sii_write_check2(ec_fsm_sii_t *fsm /**< finite state machine */)
+void ec_fsm_sii_state_write_check2(
+		ec_fsm_sii_t *fsm /**< finite state machine */
+		)
 {
     ec_datagram_t *datagram = fsm->datagram;
 
@@ -369,7 +397,7 @@
         return;
 
     if (datagram->state != EC_DATAGRAM_RECEIVED) {
-        fsm->state = ec_fsm_sii_error;
+        fsm->state = ec_fsm_sii_state_error;
         EC_ERR("Failed to receive SII write check datagram from slave %i"
                 " (datagram state %i).\n",
                fsm->slave->ring_position, datagram->state);
@@ -377,38 +405,63 @@
     }
 
     if (datagram->working_counter != 1) {
-        fsm->state = ec_fsm_sii_error;
+        fsm->state = ec_fsm_sii_state_error;
         EC_ERR("Reception of SII write check datagram failed on slave %i: ",
                 fsm->slave->ring_position);
         ec_datagram_print_wc_error(datagram);
         return;
     }
 
-    if (EC_READ_U8(datagram->data + 1) & 0x82) {
+#ifdef SII_DEBUG
+	EC_DBG("checking SII write state:\n");
+	ec_print_data(datagram->data, 2);
+#endif
+
+    if (EC_READ_U8(datagram->data + 1) & 0x20) {
+        EC_ERR("SII: Error on last SII command!\n");
+        fsm->state = ec_fsm_sii_state_error;
+        return;
+    }
+
+	/* FIXME: some slaves never answer with the busy flag set...
+	 * wait a few ms for the write operation to complete. */
+	if (datagram->cycles_received - fsm->cycles_start
+			< (cycles_t) EEPROM_INHIBIT * cpu_khz) {
+#ifdef SII_DEBUG
+		EC_DBG("too early.\n");
+#endif
+        // issue check datagram again
+        fsm->retries = EC_FSM_RETRIES;
+        return;
+	}
+
+    if (EC_READ_U8(datagram->data + 1) & 0x82) { // busy bit or
+												 // write operation busy bit
         // still busy... timeout?
         if (datagram->cycles_received
-            - fsm->cycles_start >= (cycles_t) 10 * cpu_khz) {
-            if (!fsm->check_once_more) {
+            - fsm->cycles_start >= (cycles_t) EEPROM_TIMEOUT * cpu_khz) {
+            if (fsm->check_once_more) {
+				fsm->check_once_more = 0;
+			} else {
                 EC_ERR("SII: Write timeout.\n");
-                fsm->state = ec_fsm_sii_error;
+                fsm->state = ec_fsm_sii_state_error;
                 return;
             }
-            fsm->check_once_more = 0;
         }
 
-        // issue check/fetch datagram again
+        // issue check datagram again
         fsm->retries = EC_FSM_RETRIES;
         return;
     }
 
     if (EC_READ_U8(datagram->data + 1) & 0x40) {
         EC_ERR("SII: Write operation failed!\n");
-        fsm->state = ec_fsm_sii_error;
+        fsm->state = ec_fsm_sii_state_error;
         return;
     }
 
     // success
-    fsm->state = ec_fsm_sii_end;
+    fsm->state = ec_fsm_sii_state_end;
 }
 
 /*****************************************************************************/
@@ -417,7 +470,9 @@
    State: ERROR.
 */
 
-void ec_fsm_sii_error(ec_fsm_sii_t *fsm /**< finite state machine */)
+void ec_fsm_sii_state_error(
+		ec_fsm_sii_t *fsm /**< finite state machine */
+		)
 {
 }
 
@@ -427,8 +482,10 @@
    State: END.
 */
 
-void ec_fsm_sii_end(ec_fsm_sii_t *fsm /**< finite state machine */)
-{
-}
-
-/*****************************************************************************/
+void ec_fsm_sii_state_end(
+		ec_fsm_sii_t *fsm /**< finite state machine */
+		)
+{
+}
+
+/*****************************************************************************/