# HG changeset patch # User Florian Pose # Date 1161608382 0 # Node ID 100f51f28cf2b86cd70f3c50989ffe16a406f625 # Parent 5e883e0ef95f10231c72cc24568a00bbade5454d Layed out SII state machine. diff -r 5e883e0ef95f -r 100f51f28cf2 master/Kbuild --- a/master/Kbuild Fri Oct 20 15:35:15 2006 +0000 +++ b/master/Kbuild Mon Oct 23 12:59:42 2006 +0000 @@ -38,7 +38,8 @@ obj-m := ec_master.o ec_master-objs := module.o master.o device.o slave.o datagram.o \ - domain.o mailbox.o canopen.o ethernet.o fsm.o xmldev.o + domain.o mailbox.o canopen.o ethernet.o \ + fsm_sii.o fsm.o xmldev.o ifeq ($(EC_DBG_IF),1) ec_master-objs += debug.o diff -r 5e883e0ef95f -r 100f51f28cf2 master/Makefile.am --- a/master/Makefile.am Fri Oct 20 15:35:15 2006 +0000 +++ b/master/Makefile.am Mon Oct 23 12:59:42 2006 +0000 @@ -40,6 +40,7 @@ domain.c domain.h \ doxygen.c \ ethernet.c ethernet.h \ + fsm_sii.c fsm_sii.h \ fsm.c fsm.h \ globals.h \ mailbox.c mailbox.h \ diff -r 5e883e0ef95f -r 100f51f28cf2 master/fsm.c --- a/master/fsm.c Fri Oct 20 15:35:15 2006 +0000 +++ b/master/fsm.c Mon Oct 23 12:59:42 2006 +0000 @@ -80,13 +80,6 @@ void ec_fsm_slaveconf_saveop(ec_fsm_t *); void ec_fsm_slaveconf_op(ec_fsm_t *); -void ec_fsm_sii_start_reading(ec_fsm_t *); -void ec_fsm_sii_read_check(ec_fsm_t *); -void ec_fsm_sii_read_fetch(ec_fsm_t *); -void ec_fsm_sii_start_writing(ec_fsm_t *); -void ec_fsm_sii_write_check(ec_fsm_t *); -void ec_fsm_sii_write_check2(ec_fsm_t *); - void ec_fsm_change_start(ec_fsm_t *); void ec_fsm_change_check(ec_fsm_t *); void ec_fsm_change_status(ec_fsm_t *); @@ -145,6 +138,8 @@ return -1; } + ec_fsm_sii_init(&fsm->fsm_sii, &fsm->datagram); + return 0; } @@ -156,6 +151,8 @@ void ec_fsm_clear(ec_fsm_t *fsm /**< finite state machine */) { + ec_fsm_sii_clear(&fsm->fsm_sii); + ec_datagram_clear(&fsm->datagram); } @@ -688,10 +685,8 @@ // found pending EEPROM write operation. execute it! EC_INFO("Writing EEPROM of slave %i...\n", slave->ring_position); fsm->sii_offset = 0x0000; - memcpy(fsm->sii_value, slave->new_eeprom_data, 2); - fsm->sii_mode = 1; - fsm->sii_state = ec_fsm_sii_start_writing; - fsm->slave = slave; + ec_fsm_sii_write(&fsm->fsm_sii, slave, fsm->sii_offset, + slave->new_eeprom_data, EC_FSM_SII_NODE); fsm->master_state = ec_fsm_master_write_eeprom; fsm->master_state(fsm); // execute immediately return; @@ -738,10 +733,8 @@ EC_INFO("Validating bus.\n"); fsm->slave = list_entry(master->slaves.next, ec_slave_t, list); fsm->master_state = ec_fsm_master_validate_vendor; - fsm->sii_offset = 0x0008; // vendor ID - fsm->sii_mode = 0; - fsm->sii_state = ec_fsm_sii_start_reading; - fsm->sii_state(fsm); // execute immediately + ec_fsm_sii_read(&fsm->fsm_sii, slave, 0x0008, EC_FSM_SII_POSITION); + ec_fsm_sii_exec(&fsm->fsm_sii); // execute immediately return; } } @@ -811,9 +804,11 @@ { ec_slave_t *slave = fsm->slave; - fsm->sii_state(fsm); // execute SII state machine - - if (fsm->sii_state == ec_fsm_error) { + ec_fsm_sii_exec(&fsm->fsm_sii); // execute SII state machine + + if (ec_fsm_sii_running(&fsm->fsm_sii)) return; + + if (!ec_fsm_sii_success(&fsm->fsm_sii)) { fsm->slave->error_flag = 1; EC_ERR("Failed to validate vendor ID of slave %i.\n", slave->ring_position); @@ -822,9 +817,7 @@ return; } - if (fsm->sii_state != ec_fsm_end) return; - - if (EC_READ_U32(fsm->sii_value) != slave->sii_vendor_id) { + if (EC_READ_U32(fsm->fsm_sii.value) != slave->sii_vendor_id) { EC_ERR("Slave %i: invalid vendor ID!\n", slave->ring_position); fsm->master_state = ec_fsm_master_start; fsm->master_state(fsm); // execute immediately @@ -833,10 +826,8 @@ // vendor ID is ok. check product code. fsm->master_state = ec_fsm_master_validate_product; - fsm->sii_offset = 0x000A; // product code - fsm->sii_mode = 0; - fsm->sii_state = ec_fsm_sii_start_reading; - fsm->sii_state(fsm); // execute immediately + ec_fsm_sii_read(&fsm->fsm_sii, slave, 0x000A, EC_FSM_SII_POSITION); + ec_fsm_sii_exec(&fsm->fsm_sii); // execute immediately } /*****************************************************************************/ @@ -881,9 +872,11 @@ { ec_slave_t *slave = fsm->slave; - fsm->sii_state(fsm); // execute SII state machine - - if (fsm->sii_state == ec_fsm_error) { + ec_fsm_sii_exec(&fsm->fsm_sii); // execute SII state machine + + if (ec_fsm_sii_running(&fsm->fsm_sii)) return; + + if (!ec_fsm_sii_success(&fsm->fsm_sii)) { fsm->slave->error_flag = 1; EC_ERR("Failed to validate product code of slave %i.\n", slave->ring_position); @@ -892,12 +885,10 @@ return; } - if (fsm->sii_state != ec_fsm_end) return; - - if (EC_READ_U32(fsm->sii_value) != slave->sii_product_code) { + if (EC_READ_U32(fsm->fsm_sii.value) != slave->sii_product_code) { EC_ERR("Slave %i: invalid product code!\n", slave->ring_position); EC_ERR("expected 0x%08X, got 0x%08X.\n", slave->sii_product_code, - EC_READ_U32(fsm->sii_value)); + EC_READ_U32(fsm->fsm_sii.value)); fsm->master_state = ec_fsm_master_start; fsm->master_state(fsm); // execute immediately return; @@ -914,10 +905,8 @@ // validate next slave fsm->slave = list_entry(fsm->slave->list.next, ec_slave_t, list); fsm->master_state = ec_fsm_master_validate_vendor; - fsm->sii_offset = 0x0008; // vendor ID - fsm->sii_mode = 0; - fsm->sii_state = ec_fsm_sii_start_reading; - fsm->sii_state(fsm); // execute immediately + ec_fsm_sii_read(&fsm->fsm_sii, slave, 0x0008, EC_FSM_SII_POSITION); + ec_fsm_sii_exec(&fsm->fsm_sii); // execute immediately } /*****************************************************************************/ @@ -1020,9 +1009,11 @@ { ec_slave_t *slave = fsm->slave; - fsm->sii_state(fsm); // execute SII state machine - - if (fsm->sii_state == ec_fsm_error) { + ec_fsm_sii_exec(&fsm->fsm_sii); // execute SII state machine + + if (ec_fsm_sii_running(&fsm->fsm_sii)) return; + + if (!ec_fsm_sii_success(&fsm->fsm_sii)) { fsm->slave->error_flag = 1; EC_ERR("Failed to write EEPROM contents to slave %i.\n", slave->ring_position); @@ -1033,13 +1024,12 @@ return; } - if (fsm->sii_state != ec_fsm_end) return; - fsm->sii_offset++; if (fsm->sii_offset < slave->new_eeprom_size) { - memcpy(fsm->sii_value, slave->new_eeprom_data + fsm->sii_offset, 2); - fsm->sii_state = ec_fsm_sii_start_writing; - fsm->sii_state(fsm); // execute immediately + ec_fsm_sii_write(&fsm->fsm_sii, slave, fsm->sii_offset, + slave->new_eeprom_data + fsm->sii_offset, + EC_FSM_SII_NODE); + ec_fsm_sii_exec(&fsm->fsm_sii); // execute immediately return; } @@ -1268,8 +1258,7 @@ // Start fetching EEPROM size fsm->sii_offset = 0x0040; // first category header - fsm->sii_mode = 1; - fsm->sii_state = ec_fsm_sii_start_reading; + ec_fsm_sii_read(&fsm->fsm_sii, slave, fsm->sii_offset, EC_FSM_SII_NODE); fsm->slave_state = ec_fsm_slavescan_eeprom_size; fsm->slave_state(fsm); // execute state immediately } @@ -1286,9 +1275,11 @@ uint16_t cat_type, cat_size; // execute SII state machine - fsm->sii_state(fsm); - - if (fsm->sii_state == ec_fsm_error) { + ec_fsm_sii_exec(&fsm->fsm_sii); + + if (ec_fsm_sii_running(&fsm->fsm_sii)) return; + + if (!ec_fsm_sii_success(&fsm->fsm_sii)) { fsm->slave->error_flag = 1; fsm->slave_state = ec_fsm_error; EC_ERR("Failed to read EEPROM size of slave %i.\n", @@ -1296,15 +1287,14 @@ return; } - if (fsm->sii_state != ec_fsm_end) return; - - cat_type = EC_READ_U16(fsm->sii_value); - cat_size = EC_READ_U16(fsm->sii_value + 2); + cat_type = EC_READ_U16(fsm->fsm_sii.value); + cat_size = EC_READ_U16(fsm->fsm_sii.value + 2); if (cat_type != 0xFFFF) { // not the last category fsm->sii_offset += cat_size + 2; - fsm->sii_state = ec_fsm_sii_start_reading; - fsm->sii_state(fsm); // execute state immediately + ec_fsm_sii_read(&fsm->fsm_sii, slave, fsm->sii_offset, + EC_FSM_SII_NODE); + ec_fsm_sii_exec(&fsm->fsm_sii); // execute state immediately return; } @@ -1327,11 +1317,10 @@ // Start fetching EEPROM contents + fsm->slave_state = ec_fsm_slavescan_eeprom_data; fsm->sii_offset = 0x0000; - fsm->sii_mode = 1; - fsm->sii_state = ec_fsm_sii_start_reading; - fsm->slave_state = ec_fsm_slavescan_eeprom_data; - fsm->slave_state(fsm); // execute state immediately + ec_fsm_sii_read(&fsm->fsm_sii, slave, fsm->sii_offset, EC_FSM_SII_NODE); + ec_fsm_sii_exec(&fsm->fsm_sii); // execute state immediately } /*****************************************************************************/ @@ -1346,9 +1335,11 @@ uint16_t *cat_word, cat_type, cat_size; // execute SII state machine - fsm->sii_state(fsm); - - if (fsm->sii_state == ec_fsm_error) { + ec_fsm_sii_exec(&fsm->fsm_sii); + + if (ec_fsm_sii_running(&fsm->fsm_sii)) return; + + if (!ec_fsm_sii_success(&fsm->fsm_sii)) { fsm->slave->error_flag = 1; fsm->slave_state = ec_fsm_error; EC_ERR("Failed to fetch EEPROM contents of slave %i.\n", @@ -1356,22 +1347,23 @@ return; } - if (fsm->sii_state != ec_fsm_end) return; - // 2 words fetched if (fsm->sii_offset + 2 <= slave->eeprom_size / 2) { // 2 words fit - memcpy(slave->eeprom_data + fsm->sii_offset * 2, fsm->sii_value, 4); + memcpy(slave->eeprom_data + fsm->sii_offset * 2, + fsm->fsm_sii.value, 4); } else { // copy the last word - memcpy(slave->eeprom_data + fsm->sii_offset * 2, fsm->sii_value, 2); + memcpy(slave->eeprom_data + fsm->sii_offset * 2, + fsm->fsm_sii.value, 2); } if (fsm->sii_offset + 2 < slave->eeprom_size / 2) { // fetch the next 2 words fsm->sii_offset += 2; - fsm->sii_state = ec_fsm_sii_start_reading; - fsm->sii_state(fsm); // execute state immediately + ec_fsm_sii_read(&fsm->fsm_sii, slave, fsm->sii_offset, + EC_FSM_SII_NODE); + ec_fsm_sii_exec(&fsm->fsm_sii); // execute state immediately return; } @@ -1793,220 +1785,6 @@ } /****************************************************************************** - * SII state machine - *****************************************************************************/ - -/** - SII state: START READING. - Starts reading the slave information interface. -*/ - -void ec_fsm_sii_start_reading(ec_fsm_t *fsm /**< finite state machine */) -{ - ec_datagram_t *datagram = &fsm->datagram; - - // initiate read operation - if (fsm->sii_mode) { - ec_datagram_npwr(datagram, fsm->slave->station_address, 0x502, 4); - } - else { - ec_datagram_apwr(datagram, fsm->slave->ring_position, 0x502, 4); - } - - EC_WRITE_U8 (datagram->data, 0x00); // read-only access - EC_WRITE_U8 (datagram->data + 1, 0x01); // request read operation - EC_WRITE_U16(datagram->data + 2, fsm->sii_offset); - ec_master_queue_datagram(fsm->master, datagram); - fsm->sii_state = ec_fsm_sii_read_check; -} - -/*****************************************************************************/ - -/** - SII state: READ CHECK. - Checks, if the SII-read-datagram has been sent and issues a fetch datagram. -*/ - -void ec_fsm_sii_read_check(ec_fsm_t *fsm /**< finite state machine */) -{ - ec_datagram_t *datagram = &fsm->datagram; - - if (datagram->state != EC_DATAGRAM_RECEIVED - || datagram->working_counter != 1) { - EC_ERR("SII: Reception of read datagram failed.\n"); - fsm->sii_state = ec_fsm_error; - return; - } - - fsm->sii_start = datagram->cycles_sent; - fsm->sii_check_once_more = 1; - - // issue check/fetch datagram - if (fsm->sii_mode) { - ec_datagram_nprd(datagram, fsm->slave->station_address, 0x502, 10); - } - else { - ec_datagram_aprd(datagram, fsm->slave->ring_position, 0x502, 10); - } - - ec_master_queue_datagram(fsm->master, datagram); - fsm->sii_state = ec_fsm_sii_read_fetch; -} - -/*****************************************************************************/ - -/** - SII state: READ FETCH. - Fetches the result of an SII-read datagram. -*/ - -void ec_fsm_sii_read_fetch(ec_fsm_t *fsm /**< finite state machine */) -{ - ec_datagram_t *datagram = &fsm->datagram; - - if (datagram->state != EC_DATAGRAM_RECEIVED - || datagram->working_counter != 1) { - EC_ERR("SII: Reception of check/fetch datagram failed.\n"); - fsm->sii_state = ec_fsm_error; - return; - } - - // check "busy bit" - if (EC_READ_U8(datagram->data + 1) & 0x81) { - // still busy... timeout? - if (datagram->cycles_received - - fsm->sii_start >= (cycles_t) 10 * cpu_khz) { - 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)); -#endif - return; - } - fsm->sii_check_once_more = 0; - } - - // issue check/fetch datagram again - if (fsm->sii_mode) { - ec_datagram_nprd(datagram, fsm->slave->station_address, 0x502, 10); - } - else { - ec_datagram_aprd(datagram, fsm->slave->ring_position, 0x502, 10); - } - ec_master_queue_datagram(fsm->master, datagram); - 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->sii_value, datagram->data + 6, 4); - fsm->sii_state = ec_fsm_end; -} - -/*****************************************************************************/ - -/** - SII state: START WRITING. - Starts reading the slave information interface. -*/ - -void ec_fsm_sii_start_writing(ec_fsm_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 + 1, 0x02); // request write operation - EC_WRITE_U32(datagram->data + 2, fsm->sii_offset); - memcpy(datagram->data + 6, fsm->sii_value, 2); - ec_master_queue_datagram(fsm->master, datagram); - fsm->sii_state = ec_fsm_sii_write_check; -} - -/*****************************************************************************/ - -/** - SII state: WRITE CHECK. -*/ - -void ec_fsm_sii_write_check(ec_fsm_t *fsm /**< finite state machine */) -{ - ec_datagram_t *datagram = &fsm->datagram; - - if (datagram->state != EC_DATAGRAM_RECEIVED - || datagram->working_counter != 1) { - EC_ERR("SII: Reception of write datagram failed.\n"); - fsm->sii_state = ec_fsm_error; - return; - } - - fsm->sii_start = datagram->cycles_sent; - fsm->sii_check_once_more = 1; - - // issue check/fetch datagram - ec_datagram_nprd(datagram, fsm->slave->station_address, 0x502, 2); - ec_master_queue_datagram(fsm->master, datagram); - fsm->sii_state = ec_fsm_sii_write_check2; -} - -/*****************************************************************************/ - -/** - SII state: WRITE CHECK 2. -*/ - -void ec_fsm_sii_write_check2(ec_fsm_t *fsm /**< finite state machine */) -{ - ec_datagram_t *datagram = &fsm->datagram; - - if (datagram->state != EC_DATAGRAM_RECEIVED - || datagram->working_counter != 1) { - EC_ERR("SII: Reception of write check datagram failed.\n"); - fsm->sii_state = ec_fsm_error; - return; - } - - if (EC_READ_U8(datagram->data + 1) & 0x82) { - // still busy... timeout? - if (datagram->cycles_received - - fsm->sii_start >= (cycles_t) 10 * cpu_khz) { - if (!fsm->sii_check_once_more) { - EC_ERR("SII: Write timeout.\n"); - fsm->sii_state = ec_fsm_error; - return; - } - fsm->sii_check_once_more = 0; - } - - // issue check/fetch datagram again - ec_master_queue_datagram(fsm->master, datagram); - return; - } - - if (EC_READ_U8(datagram->data + 1) & 0x40) { - EC_ERR("SII: Write operation failed!\n"); - fsm->sii_state = ec_fsm_error; - return; - } - - // success - fsm->sii_state = ec_fsm_end; -} - -/****************************************************************************** * state change state machine *****************************************************************************/ diff -r 5e883e0ef95f -r 100f51f28cf2 master/fsm.h --- a/master/fsm.h Fri Oct 20 15:35:15 2006 +0000 +++ b/master/fsm.h Mon Oct 23 12:59:42 2006 +0000 @@ -47,6 +47,8 @@ #include "slave.h" #include "canopen.h" +#include "fsm_sii.h" + /*****************************************************************************/ typedef struct ec_fsm ec_fsm_t; /**< \see ec_fsm */ @@ -65,15 +67,11 @@ unsigned int master_slaves_responding; /**< number of responding slaves */ ec_slave_state_t master_slave_states; /**< states of responding slaves */ unsigned int master_validation; /**< non-zero, if validation to do */ + uint16_t sii_offset; /**< current offset for SII access */ void (*slave_state)(ec_fsm_t *); /**< slave state function */ - void (*sii_state)(ec_fsm_t *); /**< SII state function */ - uint16_t sii_offset; /**< input: offset in SII */ - 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; /**< one more try after timeout */ + ec_fsm_sii_t fsm_sii; /**< SII state machine */ void (*change_state)(ec_fsm_t *); /**< slave state change state function */ ec_slave_state_t change_new; /**< input: new state */ diff -r 5e883e0ef95f -r 100f51f28cf2 master/fsm_sii.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/master/fsm_sii.c Mon Oct 23 12:59:42 2006 +0000 @@ -0,0 +1,393 @@ +/****************************************************************************** + * + * $Id$ + * + * Copyright (C) 2006 Florian Pose, Ingenieurgemeinschaft IgH + * + * This file is part of the IgH EtherCAT Master. + * + * The IgH EtherCAT Master is free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * The IgH EtherCAT Master is distributed in the hope that it will be + * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with the IgH EtherCAT Master; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + * The right to use EtherCAT Technology is granted and comes free of + * charge under condition of compatibility of product made by + * Licensee. People intending to distribute/sell products based on the + * code, have to sign an agreement to guarantee that products using + * software based on IgH EtherCAT master stay compatible with the actual + * EtherCAT specification (which are released themselves as an open + * standard) as the (only) precondition to have the right to use EtherCAT + * Technology, IP and trade marks. + * + *****************************************************************************/ + +/** + \file + EtherCAT slave information interface FSM. +*/ + +/*****************************************************************************/ + +#include "globals.h" +#include "mailbox.h" +#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 *); + +/*****************************************************************************/ + +/** + Constructor. +*/ + +void ec_fsm_sii_init(ec_fsm_sii_t *fsm, /**< finite state machine */ + ec_datagram_t *datagram /**< datagram structure to use */ + ) +{ + fsm->state = NULL; + fsm->datagram = datagram; +} + +/*****************************************************************************/ + +/** + Destructor. +*/ + +void ec_fsm_sii_clear(ec_fsm_sii_t *fsm /**< finite state machine */) +{ +} + +/*****************************************************************************/ + +/** + Initializes the SII read state machine. +*/ + +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 */ + ec_fsm_sii_addressing_t mode /**< addressing scheme */ + ) +{ + fsm->state = ec_fsm_sii_start_reading; + fsm->slave = slave; + fsm->offset = offset; + fsm->mode = mode; +} + +/*****************************************************************************/ + +/** + Initializes the SII write state machine. +*/ + +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 */ + uint16_t *value, /**< pointer to 2 bytes of data */ + ec_fsm_sii_addressing_t mode /**< addressing scheme */ + ) +{ + fsm->state = ec_fsm_sii_start_writing; + fsm->slave = slave; + fsm->offset = offset; + fsm->mode = mode; + memcpy(fsm->value, value, 2); +} + +/*****************************************************************************/ + +/** + Executes the SII state machine. +*/ + +void ec_fsm_sii_exec(ec_fsm_sii_t *fsm /**< finite state machine */) +{ + fsm->state(fsm); +} + +/*****************************************************************************/ + +/** + Returns the running state of the master startup state machine. + \return non-zero if not terminated yet. +*/ + +int ec_fsm_sii_running(ec_fsm_sii_t *fsm /**< Finite state machine */) +{ + return fsm->state != ec_fsm_sii_end && fsm->state != ec_fsm_sii_error; +} + +/*****************************************************************************/ + +/** + Returns, if the master startup state machine terminated with success. + \return non-zero if successful. +*/ + +int ec_fsm_sii_success(ec_fsm_sii_t *fsm /**< Finite state machine */) +{ + return fsm->state == ec_fsm_sii_end; +} + +/****************************************************************************** + * SII state machine + *****************************************************************************/ + +/** + SII state: START READING. + Starts reading the slave information interface. +*/ + +void ec_fsm_sii_start_reading(ec_fsm_sii_t *fsm /**< finite state machine */) +{ + ec_datagram_t *datagram = fsm->datagram; + + // initiate read operation + switch (fsm->mode) { + case EC_FSM_SII_POSITION: + ec_datagram_apwr(datagram, fsm->slave->ring_position, 0x502, 4); + break; + case EC_FSM_SII_NODE: + ec_datagram_npwr(datagram, fsm->slave->station_address, 0x502, 4); + break; + } + + EC_WRITE_U8 (datagram->data, 0x00); // read-only access + EC_WRITE_U8 (datagram->data + 1, 0x01); // request read operation + EC_WRITE_U16(datagram->data + 2, fsm->offset); + ec_master_queue_datagram(fsm->slave->master, datagram); + fsm->state = ec_fsm_sii_read_check; +} + +/*****************************************************************************/ + +/** + SII state: READ CHECK. + 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 */) +{ + ec_datagram_t *datagram = fsm->datagram; + + if (datagram->state != EC_DATAGRAM_RECEIVED + || datagram->working_counter != 1) { + EC_ERR("SII: Reception of read datagram failed.\n"); + fsm->state = ec_fsm_sii_error; + return; + } + + fsm->cycles_start = datagram->cycles_sent; + fsm->check_once_more = 1; + + // issue check/fetch datagram + 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; + } + ec_master_queue_datagram(fsm->slave->master, datagram); + fsm->state = ec_fsm_sii_read_fetch; +} + +/*****************************************************************************/ + +/** + SII state: READ FETCH. + Fetches the result of an SII-read datagram. +*/ + +void ec_fsm_sii_read_fetch(ec_fsm_sii_t *fsm /**< finite state machine */) +{ + ec_datagram_t *datagram = fsm->datagram; + + if (datagram->state != EC_DATAGRAM_RECEIVED + || datagram->working_counter != 1) { + EC_ERR("SII: Reception of check/fetch datagram failed.\n"); + fsm->state = ec_fsm_sii_error; + return; + } + + // check "busy bit" + if (EC_READ_U8(datagram->data + 1) & 0x81) { + // still busy... timeout? + if (datagram->cycles_received + - fsm->cycles_start >= (cycles_t) 10 * cpu_khz) { + if (!fsm->check_once_more) { + 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 + 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; + } + ec_master_queue_datagram(fsm->slave->master, datagram); + 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; +} + +/*****************************************************************************/ + +/** + SII state: START WRITING. + Starts reading the slave information interface. +*/ + +void ec_fsm_sii_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 + 1, 0x02); // request write operation + EC_WRITE_U32(datagram->data + 2, fsm->offset); + memcpy(datagram->data + 6, fsm->value, 2); + ec_master_queue_datagram(fsm->slave->master, datagram); + fsm->state = ec_fsm_sii_write_check; +} + +/*****************************************************************************/ + +/** + SII state: WRITE CHECK. +*/ + +void ec_fsm_sii_write_check(ec_fsm_sii_t *fsm /**< finite state machine */) +{ + ec_datagram_t *datagram = fsm->datagram; + + if (datagram->state != EC_DATAGRAM_RECEIVED + || datagram->working_counter != 1) { + EC_ERR("SII: Reception of write datagram failed.\n"); + fsm->state = ec_fsm_sii_error; + return; + } + + fsm->cycles_start = datagram->cycles_sent; + fsm->check_once_more = 1; + + // issue check/fetch datagram + ec_datagram_nprd(datagram, fsm->slave->station_address, 0x502, 2); + ec_master_queue_datagram(fsm->slave->master, datagram); + fsm->state = ec_fsm_sii_write_check2; +} + +/*****************************************************************************/ + +/** + SII state: WRITE CHECK 2. +*/ + +void ec_fsm_sii_write_check2(ec_fsm_sii_t *fsm /**< finite state machine */) +{ + ec_datagram_t *datagram = fsm->datagram; + + if (datagram->state != EC_DATAGRAM_RECEIVED + || datagram->working_counter != 1) { + EC_ERR("SII: Reception of write check datagram failed.\n"); + fsm->state = ec_fsm_sii_error; + return; + } + + if (EC_READ_U8(datagram->data + 1) & 0x82) { + // still busy... timeout? + if (datagram->cycles_received + - fsm->cycles_start >= (cycles_t) 10 * cpu_khz) { + if (!fsm->check_once_more) { + EC_ERR("SII: Write timeout.\n"); + fsm->state = ec_fsm_sii_error; + return; + } + fsm->check_once_more = 0; + } + + // issue check/fetch datagram again + ec_master_queue_datagram(fsm->slave->master, datagram); + return; + } + + if (EC_READ_U8(datagram->data + 1) & 0x40) { + EC_ERR("SII: Write operation failed!\n"); + fsm->state = ec_fsm_sii_error; + return; + } + + // success + fsm->state = ec_fsm_sii_end; +} + +/*****************************************************************************/ + +/** + State: ERROR. +*/ + +void ec_fsm_sii_error(ec_fsm_sii_t *fsm /**< finite state machine */) +{ +} + +/*****************************************************************************/ + +/** + State: END. +*/ + +void ec_fsm_sii_end(ec_fsm_sii_t *fsm /**< finite state machine */) +{ +} + +/*****************************************************************************/ diff -r 5e883e0ef95f -r 100f51f28cf2 master/fsm_sii.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/master/fsm_sii.h Mon Oct 23 12:59:42 2006 +0000 @@ -0,0 +1,95 @@ +/****************************************************************************** + * + * $Id$ + * + * Copyright (C) 2006 Florian Pose, Ingenieurgemeinschaft IgH + * + * This file is part of the IgH EtherCAT Master. + * + * The IgH EtherCAT Master is free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * The IgH EtherCAT Master is distributed in the hope that it will be + * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with the IgH EtherCAT Master; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + * The right to use EtherCAT Technology is granted and comes free of + * charge under condition of compatibility of product made by + * Licensee. People intending to distribute/sell products based on the + * code, have to sign an agreement to guarantee that products using + * software based on IgH EtherCAT master stay compatible with the actual + * EtherCAT specification (which are released themselves as an open + * standard) as the (only) precondition to have the right to use EtherCAT + * Technology, IP and trade marks. + * + *****************************************************************************/ + +/** + \file + EtherCAT slave information interface FSM structure. +*/ + +/*****************************************************************************/ + +#ifndef __EC_FSM_SII__ +#define __EC_FSM_SII__ + +#include "globals.h" +#include "../include/ecrt.h" +#include "datagram.h" +#include "slave.h" + +/*****************************************************************************/ + +typedef enum +{ + EC_FSM_SII_POSITION, + EC_FSM_SII_NODE +} +ec_fsm_sii_addressing_t; + +/*****************************************************************************/ + +typedef struct ec_fsm_sii ec_fsm_sii_t; /**< \see ec_fsm_sii */ + +/** + Slave information interface FSM. +*/ + +struct ec_fsm_sii +{ + ec_slave_t *slave; /**< slave the FSM runs on */ + ec_datagram_t *datagram; /**< datagram used in the state machine */ + + void (*state)(ec_fsm_sii_t *); /**< SII state function */ + uint16_t offset; /**< input: offset in SII */ + ec_fsm_sii_addressing_t mode; /**< reading via APRD or NPRD */ + uint8_t value[4]; /**< raw SII value (32bit) */ + cycles_t cycles_start; /**< start timestamp */ + uint8_t check_once_more; /**< one more try after timeout */ +}; + +/*****************************************************************************/ + +void ec_fsm_sii_init(ec_fsm_sii_t *, ec_datagram_t *); +void ec_fsm_sii_clear(ec_fsm_sii_t *); + +void ec_fsm_sii_read(ec_fsm_sii_t *, ec_slave_t *, + uint16_t, ec_fsm_sii_addressing_t); +void ec_fsm_sii_write(ec_fsm_sii_t *, ec_slave_t *, uint16_t, uint16_t *, + ec_fsm_sii_addressing_t); + +void ec_fsm_sii_exec(ec_fsm_sii_t *); +int ec_fsm_sii_running(ec_fsm_sii_t *); +int ec_fsm_sii_success(ec_fsm_sii_t *); + +/*****************************************************************************/ + +#endif