--- 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 */
+ )
+{
+}
+
+/*****************************************************************************/