From 9537c567f88252d657a935961519982cf54d8e33 Mon Sep 17 00:00:00 2001 From: Florian Pose Date: Wed, 6 Feb 2013 17:25:08 +0100 Subject: [PATCH] Introduced --enable-sii-assign. --- NEWS | 5 ++ TODO | 1 - configure.ac | 24 +++++++ master/fsm_slave_config.c | 134 +++++++++++++++++++++++++++++++++++++- master/fsm_slave_scan.c | 100 +++++++++++++++++++++++++--- 5 files changed, 251 insertions(+), 13 deletions(-) diff --git a/NEWS b/NEWS index 2be66a46..050a70eb 100644 --- a/NEWS +++ b/NEWS @@ -6,6 +6,11 @@ vim: spelllang=en spell ------------------------------------------------------------------------------- +Changes since 1.5.1: + +* Introduced --enable-sii-assign to switch on assigning the SII to PDI and + back to EtherCAT during configuration. + Changes in 1.5.1: * Fixed reset of allow_scanning flag if ecrt_master_activate() was not called. diff --git a/TODO b/TODO index 1a091860..d16b0777 100644 --- a/TODO +++ b/TODO @@ -12,7 +12,6 @@ Version 1.5.2: • Document --with-devices. • Document RTDM interface. -• Allow PDI access to EEPROM during INIT->PREOP transition. Future issues: diff --git a/configure.ac b/configure.ac index 9512a16f..de057d31 100644 --- a/configure.ac +++ b/configure.ac @@ -830,6 +830,30 @@ fi AC_DEFINE_UNQUOTED([EC_MAX_NUM_DEVICES], $devices, [Max. number of Ethernet devices per master]) +#------------------------------------------------------------------------------ +# SII assignment +#------------------------------------------------------------------------------ + +AC_ARG_ENABLE([sii-assign], + AS_HELP_STRING([--enable-sii-assign], + [Enable SII assignment to PDI (default: no)]), + [ + case "${enableval}" in + yes) siiassign=1 + ;; + no) siiassign=0 + ;; + *) AC_MSG_ERROR([Invalid value for --enable-sii-assign]) + ;; + esac + ], + [siiassign=0] +) + +if test "x${siiassign}" = "x1"; then + AC_DEFINE([EC_SII_ASSIGN], [1], [Assign SII to PDI]) +fi + #------------------------------------------------------------------------------ AC_CONFIG_FILES([ diff --git a/master/fsm_slave_config.c b/master/fsm_slave_config.c index 51349b02..2ca63f0c 100644 --- a/master/fsm_slave_config.c +++ b/master/fsm_slave_config.c @@ -67,7 +67,13 @@ void ec_fsm_slave_config_state_clear_fmmus(ec_fsm_slave_config_t *); void ec_fsm_slave_config_state_clear_sync(ec_fsm_slave_config_t *); void ec_fsm_slave_config_state_dc_clear_assign(ec_fsm_slave_config_t *); void ec_fsm_slave_config_state_mbox_sync(ec_fsm_slave_config_t *); +#ifdef EC_SII_ASSIGN +void ec_fsm_slave_config_state_assign_pdi(ec_fsm_slave_config_t *); +#endif void ec_fsm_slave_config_state_boot_preop(ec_fsm_slave_config_t *); +#ifdef EC_SII_ASSIGN +void ec_fsm_slave_config_state_assign_ethercat(ec_fsm_slave_config_t *); +#endif void ec_fsm_slave_config_state_sdo_conf(ec_fsm_slave_config_t *); void ec_fsm_slave_config_state_soe_conf_preop(ec_fsm_slave_config_t *); void ec_fsm_slave_config_state_watchdog_divider(ec_fsm_slave_config_t *); @@ -87,6 +93,9 @@ void ec_fsm_slave_config_enter_init(ec_fsm_slave_config_t *); void ec_fsm_slave_config_enter_clear_sync(ec_fsm_slave_config_t *); void ec_fsm_slave_config_enter_dc_clear_assign(ec_fsm_slave_config_t *); void ec_fsm_slave_config_enter_mbox_sync(ec_fsm_slave_config_t *); +#ifdef EC_SII_ASSIGN +void ec_fsm_slave_config_enter_assign_pdi(ec_fsm_slave_config_t *); +#endif void ec_fsm_slave_config_enter_boot_preop(ec_fsm_slave_config_t *); void ec_fsm_slave_config_enter_sdo_conf(ec_fsm_slave_config_t *); void ec_fsm_slave_config_enter_soe_conf_preop(ec_fsm_slave_config_t *); @@ -432,7 +441,11 @@ void ec_fsm_slave_config_enter_mbox_sync( // no mailbox protocols supported EC_SLAVE_DBG(slave, 1, "Slave does not support" " mailbox communication.\n"); +#ifdef EC_SII_ASSIGN + ec_fsm_slave_config_enter_assign_pdi(fsm); +#else ec_fsm_slave_config_enter_boot_preop(fsm); +#endif return; } @@ -595,9 +608,71 @@ void ec_fsm_slave_config_state_mbox_sync( return; } +#ifdef EC_SII_ASSIGN + ec_fsm_slave_config_enter_assign_pdi(fsm); +#else + ec_fsm_slave_config_enter_boot_preop(fsm); +#endif +} + +/*****************************************************************************/ + +#ifdef EC_SII_ASSIGN + +/** Assign SII to PDI. + */ +void ec_fsm_slave_config_enter_assign_pdi( + ec_fsm_slave_config_t *fsm /**< slave state machine */ + ) +{ + ec_datagram_t *datagram = fsm->datagram; + ec_slave_t *slave = fsm->slave; + + if (fsm->slave->requested_state != EC_SLAVE_STATE_BOOT) { + EC_SLAVE_DBG(slave, 1, "Assigning SII access to PDI.\n"); + + ec_datagram_fpwr(datagram, slave->station_address, 0x0500, 0x01); + EC_WRITE_U8(datagram->data, 0x01); // PDI + fsm->retries = EC_FSM_RETRIES; + fsm->state = ec_fsm_slave_config_state_assign_pdi; + } + else { + ec_fsm_slave_config_enter_boot_preop(fsm); + } +} + +/*****************************************************************************/ + +/** Slave configuration state: ASSIGN_PDI. + */ +void ec_fsm_slave_config_state_assign_pdi( + ec_fsm_slave_config_t *fsm /**< slave state machine */ + ) +{ + ec_datagram_t *datagram = fsm->datagram; + ec_slave_t *slave = fsm->slave; + + if (datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--) { + return; + } + + if (datagram->state != EC_DATAGRAM_RECEIVED) { + EC_SLAVE_WARN(slave, "Failed receive SII assignment datagram: "); + ec_datagram_print_state(datagram); + goto cont_preop; + } + + if (datagram->working_counter != 1) { + EC_SLAVE_WARN(slave, "Failed to assign SII to PDI: "); + ec_datagram_print_wc_error(datagram); + } + +cont_preop: ec_fsm_slave_config_enter_boot_preop(fsm); } +#endif + /*****************************************************************************/ /** Request PREOP state. @@ -609,9 +684,11 @@ void ec_fsm_slave_config_enter_boot_preop( fsm->state = ec_fsm_slave_config_state_boot_preop; if (fsm->slave->requested_state != EC_SLAVE_STATE_BOOT) { - ec_fsm_change_start(fsm->fsm_change, fsm->slave, EC_SLAVE_STATE_PREOP); + ec_fsm_change_start(fsm->fsm_change, + fsm->slave, EC_SLAVE_STATE_PREOP); } else { // BOOT - ec_fsm_change_start(fsm->fsm_change, fsm->slave, EC_SLAVE_STATE_BOOT); + ec_fsm_change_start(fsm->fsm_change, + fsm->slave, EC_SLAVE_STATE_BOOT); } ec_fsm_change_exec(fsm->fsm_change); // execute immediately @@ -627,7 +704,9 @@ void ec_fsm_slave_config_state_boot_preop( { ec_slave_t *slave = fsm->slave; - if (ec_fsm_change_exec(fsm->fsm_change)) return; + if (ec_fsm_change_exec(fsm->fsm_change)) { + return; + } if (!ec_fsm_change_success(fsm->fsm_change)) { if (!fsm->fsm_change->spontaneous_change) @@ -642,6 +721,53 @@ void ec_fsm_slave_config_state_boot_preop( EC_SLAVE_DBG(slave, 1, "Now in %s.\n", slave->requested_state != EC_SLAVE_STATE_BOOT ? "PREOP" : "BOOT"); +#ifdef EC_SII_ASSIGN + EC_SLAVE_DBG(slave, 1, "Assigning SII access back to EtherCAT.\n"); + + ec_datagram_fpwr(fsm->datagram, slave->station_address, 0x0500, 0x01); + EC_WRITE_U8(fsm->datagram->data, 0x00); // EtherCAT + fsm->retries = EC_FSM_RETRIES; + fsm->state = ec_fsm_slave_config_state_assign_ethercat; +#else + if (slave->current_state == slave->requested_state) { + fsm->state = ec_fsm_slave_config_state_end; // successful + EC_SLAVE_DBG(slave, 1, "Finished configuration.\n"); + return; + } + + ec_fsm_slave_config_enter_sdo_conf(fsm); +#endif +} + +/*****************************************************************************/ + +#ifdef EC_SII_ASSIGN + +/** Slave configuration state: ASSIGN_ETHERCAT. + */ +void ec_fsm_slave_config_state_assign_ethercat( + ec_fsm_slave_config_t *fsm /**< slave state machine */ + ) +{ + ec_datagram_t *datagram = fsm->datagram; + ec_slave_t *slave = fsm->slave; + + if (datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--) { + return; + } + + if (datagram->state != EC_DATAGRAM_RECEIVED) { + EC_SLAVE_WARN(slave, "Failed receive SII assignment datagram: "); + ec_datagram_print_state(datagram); + goto cont_sdo_conf; + } + + if (datagram->working_counter != 1) { + EC_SLAVE_WARN(slave, "Failed to assign SII back to EtherCAT: "); + ec_datagram_print_wc_error(datagram); + } + +cont_sdo_conf: if (slave->current_state == slave->requested_state) { fsm->state = ec_fsm_slave_config_state_end; // successful EC_SLAVE_DBG(slave, 1, "Finished configuration.\n"); @@ -651,6 +777,8 @@ void ec_fsm_slave_config_state_boot_preop( ec_fsm_slave_config_enter_sdo_conf(fsm); } +#endif + /*****************************************************************************/ /** Check for SDO configurations to be applied. diff --git a/master/fsm_slave_scan.c b/master/fsm_slave_scan.c index 623707de..d75ab83d 100644 --- a/master/fsm_slave_scan.c +++ b/master/fsm_slave_scan.c @@ -50,6 +50,9 @@ void ec_fsm_slave_scan_state_base(ec_fsm_slave_scan_t *); void ec_fsm_slave_scan_state_dc_cap(ec_fsm_slave_scan_t *); void ec_fsm_slave_scan_state_dc_times(ec_fsm_slave_scan_t *); void ec_fsm_slave_scan_state_datalink(ec_fsm_slave_scan_t *); +#ifdef EC_SII_ASSIGN +void ec_fsm_slave_scan_state_assign_sii(ec_fsm_slave_scan_t *); +#endif void ec_fsm_slave_scan_state_sii_size(ec_fsm_slave_scan_t *); void ec_fsm_slave_scan_state_sii_data(ec_fsm_slave_scan_t *); #ifdef EC_REGALIAS @@ -439,11 +442,52 @@ void ec_fsm_slave_scan_enter_datalink( /*****************************************************************************/ +/** Enter slave scan state SII_SIZE. + */ +void ec_fsm_slave_scan_enter_sii_size( + ec_fsm_slave_scan_t *fsm /**< slave state machine */ + ) +{ + // Start fetching SII size + + fsm->sii_offset = EC_FIRST_SII_CATEGORY_OFFSET; // first category header + ec_fsm_sii_read(&fsm->fsm_sii, fsm->slave, fsm->sii_offset, + EC_FSM_SII_USE_CONFIGURED_ADDRESS); + fsm->state = ec_fsm_slave_scan_state_sii_size; + fsm->state(fsm); // execute state immediately +} + +/*****************************************************************************/ + +#ifdef EC_SII_ASSIGN + +/** Enter slave scan state ASSIGN_SII. + */ +void ec_fsm_slave_scan_enter_assign_sii( + ec_fsm_slave_scan_t *fsm /**< slave state machine */ + ) +{ + ec_datagram_t *datagram = fsm->datagram; + ec_slave_t *slave = fsm->slave; + + // assign SII to ECAT + ec_datagram_fpwr(datagram, slave->station_address, 0x0500, 1); + EC_WRITE_U8(datagram->data, 0x00); // EtherCAT + fsm->retries = EC_FSM_RETRIES; + fsm->state = ec_fsm_slave_scan_state_assign_sii; +} + +#endif + +/*****************************************************************************/ + /** Slave scan state: DATALINK. */ -void ec_fsm_slave_scan_state_datalink(ec_fsm_slave_scan_t *fsm /**< slave state machine */) +void ec_fsm_slave_scan_state_datalink( + ec_fsm_slave_scan_t *fsm /**< slave state machine */ + ) { ec_datagram_t *datagram = fsm->datagram; ec_slave_t *slave = fsm->slave; @@ -478,22 +522,60 @@ void ec_fsm_slave_scan_state_datalink(ec_fsm_slave_scan_t *fsm /**< slave state dl_status & (1 << (9 + i * 2)) ? 1 : 0; } - // Start fetching SII size - - fsm->sii_offset = EC_FIRST_SII_CATEGORY_OFFSET; // first category header - ec_fsm_sii_read(&fsm->fsm_sii, slave, fsm->sii_offset, - EC_FSM_SII_USE_CONFIGURED_ADDRESS); - fsm->state = ec_fsm_slave_scan_state_sii_size; - fsm->state(fsm); // execute state immediately +#ifdef EC_SII_ASSIGN + ec_fsm_slave_scan_enter_assign_sii(fsm); +#else + ec_fsm_slave_scan_enter_sii_size(fsm); +#endif } /*****************************************************************************/ +#ifdef EC_SII_ASSIGN + +/** + Slave scan state: ASSIGN_SII. +*/ + +void ec_fsm_slave_scan_state_assign_sii( + ec_fsm_slave_scan_t *fsm /**< slave state machine */ + ) +{ + ec_datagram_t *datagram = fsm->datagram; + ec_slave_t *slave = fsm->slave; + + if (datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--) { + return; + } + + if (datagram->state != EC_DATAGRAM_RECEIVED) { + EC_SLAVE_WARN(slave, "Failed to receive SII assignment datagram: "); + ec_datagram_print_state(datagram); + // Try to go on, probably assignment is correct + goto continue_with_sii_size; + } + + if (datagram->working_counter != 1) { + EC_SLAVE_WARN(slave, "Failed to assign SII to EtherCAT: "); + ec_datagram_print_wc_error(datagram); + // Try to go on, probably assignment is correct + } + +continue_with_sii_size: + ec_fsm_slave_scan_enter_sii_size(fsm); +} + +#endif + +/*****************************************************************************/ + /** Slave scan state: SII SIZE. */ -void ec_fsm_slave_scan_state_sii_size(ec_fsm_slave_scan_t *fsm /**< slave state machine */) +void ec_fsm_slave_scan_state_sii_size( + ec_fsm_slave_scan_t *fsm /**< slave state machine */ + ) { ec_slave_t *slave = fsm->slave; uint16_t cat_type, cat_size;