diff -r 07fd94c5119d -r 72e7507b3f1b master/fsm_sii.c --- 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 */ + ) +{ +} + +/*****************************************************************************/