diff --git a/master/ethernet.c b/master/ethernet.c index 53edc5055768adc4a28368db7690c335ee5dfd4b..9f6d08cad81952f62e9dba380d282ca68edb2902 100644 --- a/master/ethernet.c +++ b/master/ethernet.c @@ -317,7 +317,8 @@ int ec_eoe_active(const ec_eoe_t *eoe /**< EoE handler */) void ec_eoe_state_rx_start(ec_eoe_t *eoe /**< EoE handler */) { - if (!eoe->slave->online || !eoe->slave->master->main_device.link_state) + if (eoe->slave->online_state == EC_SLAVE_OFFLINE || + !eoe->slave->master->main_device.link_state) return; ec_slave_mbox_prepare_check(eoe->slave, &eoe->datagram); @@ -518,7 +519,8 @@ void ec_eoe_state_tx_start(ec_eoe_t *eoe /**< EoE handler */) unsigned int wakeup = 0; #endif - if (!eoe->slave->online || !eoe->slave->master->main_device.link_state) + if (eoe->slave->online_state == EC_SLAVE_OFFLINE || + !eoe->slave->master->main_device.link_state) return; spin_lock_bh(&eoe->tx_queue_lock); diff --git a/master/fsm_master.c b/master/fsm_master.c index 4f9104bbe8b889dec1de15173f51f2c48ffe8192..e4068552d6535257fdc9fbfc59a2cfeaa21c4a73 100644 --- a/master/fsm_master.c +++ b/master/fsm_master.c @@ -185,7 +185,7 @@ void ec_fsm_master_state_broadcast(ec_fsm_master_t *fsm /**< master state machin // link is down fsm->slaves_responding = 0; list_for_each_entry(slave, &master->slaves, list) { - slave->online = 0; + ec_slave_set_online_state(slave, EC_SLAVE_OFFLINE); } fsm->state = ec_fsm_master_state_error; return; @@ -302,7 +302,7 @@ int ec_fsm_master_action_process_eeprom( up(&master->eeprom_sem); slave = request->slave; - if (!slave->online || slave->error_flag) { + if (slave->online_state == EC_SLAVE_OFFLINE || slave->error_flag) { EC_ERR("Discarding EEPROM data, slave %i not ready.\n", slave->ring_position); request->state = EC_EEPROM_REQ_ERROR; @@ -344,7 +344,7 @@ void ec_fsm_master_action_process_states(ec_fsm_master_t *fsm // check if any slaves are not in the state, they're supposed to be list_for_each_entry(slave, &master->slaves, list) { if (slave->error_flag - || !slave->online + || slave->online_state == EC_SLAVE_OFFLINE || slave->requested_state == EC_SLAVE_STATE_UNKNOWN || (slave->current_state == slave->requested_state && slave->self_configured)) continue; @@ -380,7 +380,7 @@ void ec_fsm_master_action_process_states(ec_fsm_master_t *fsm EC_DBG("Processing SDO request...\n"); slave = master->sdo_request->sdo->slave; if (slave->current_state == EC_SLAVE_STATE_INIT - || !slave->online) { + || slave->online_state == EC_SLAVE_OFFLINE) { EC_ERR("Failed to process SDO request, slave %i not ready.\n", slave->ring_position); master->sdo_request->return_code = -1; @@ -403,7 +403,7 @@ void ec_fsm_master_action_process_states(ec_fsm_master_t *fsm || slave->sdo_dictionary_fetched || slave->current_state == EC_SLAVE_STATE_INIT || jiffies - slave->jiffies_preop < EC_WAIT_SDO_DICT * HZ - || !slave->online + || slave->online_state == EC_SLAVE_OFFLINE || slave->error_flag) continue; if (master->debug_level) { @@ -459,7 +459,7 @@ void ec_fsm_master_action_next_slave_state(ec_fsm_master_t *fsm if (fsm->validate) { fsm->validate = 0; list_for_each_entry(slave, &master->slaves, list) { - if (slave->online) continue; + if (slave->online_state == EC_SLAVE_ONLINE) continue; // At least one slave is offline. validate! EC_INFO("Validating bus.\n"); @@ -485,7 +485,6 @@ void ec_fsm_master_state_read_states(ec_fsm_master_t *fsm /**< master state mach { ec_slave_t *slave = fsm->slave; ec_datagram_t *datagram = fsm->datagram; - uint8_t new_state; if (datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--) { ec_master_queue_datagram(fsm->master, fsm->datagram); @@ -501,39 +500,14 @@ void ec_fsm_master_state_read_states(ec_fsm_master_t *fsm /**< master state mach // did the slave not respond to its station address? if (datagram->working_counter != 1) { - if (slave->online) { - slave->online = 0; - if (slave->master->debug_level) - EC_DBG("Slave %i: offline.\n", slave->ring_position); - } + ec_slave_set_online_state(slave, EC_SLAVE_OFFLINE); ec_fsm_master_action_next_slave_state(fsm); return; } // slave responded - new_state = EC_READ_U8(datagram->data); - if (!slave->online) { // slave was offline before - slave->online = 1; - slave->error_flag = 0; // clear error flag - slave->current_state = new_state; - if (slave->master->debug_level) { - char cur_state[EC_STATE_STRING_SIZE]; - ec_state_string(slave->current_state, cur_state); - EC_DBG("Slave %i: online (%s).\n", - slave->ring_position, cur_state); - } - } - else if (new_state != slave->current_state) { - if (slave->master->debug_level) { - char old_state[EC_STATE_STRING_SIZE], - cur_state[EC_STATE_STRING_SIZE]; - ec_state_string(slave->current_state, old_state); - ec_state_string(new_state, cur_state); - EC_DBG("Slave %i: %s -> %s.\n", - slave->ring_position, old_state, cur_state); - } - slave->current_state = new_state; - } + ec_slave_set_state(slave, EC_READ_U8(datagram->data)); // set app state first + ec_slave_set_online_state(slave, EC_SLAVE_ONLINE); // check, if new slave state has to be acknowledged if (slave->current_state & EC_SLAVE_STATE_ACK_ERR && !slave->error_flag) { @@ -614,7 +588,7 @@ void ec_fsm_master_action_addresses(ec_fsm_master_t *fsm /**< master state machi { ec_datagram_t *datagram = fsm->datagram; - while (fsm->slave->online) { + while (fsm->slave->online_state == EC_SLAVE_ONLINE) { if (fsm->slave->list.next == &fsm->master->slaves) { // last slave? fsm->state = ec_fsm_master_state_start; fsm->state(fsm); // execute immediately diff --git a/master/master.c b/master/master.c index cd70315ae3dbda00c02f711029229f8cda88acdf..cdd601b75921abef690e44694e8d3d3989a9da7f 100644 --- a/master/master.c +++ b/master/master.c @@ -528,7 +528,7 @@ void ec_master_leave_operation_mode(ec_master_t *master // don't try to set PREOP for slaves that don't respond, // because of 3 second timeout. - if (!slave->online) { + if (slave->online_state == EC_SLAVE_OFFLINE) { if (master->debug_level) EC_DBG("Skipping to configure offline slave %i.\n", slave->ring_position); diff --git a/master/slave.c b/master/slave.c index ea7aef9116c4fbd0d200d6a55526ad6b835147ae..0679c32a954cd988f397bff2586ffd1d015e478f 100644 --- a/master/slave.c +++ b/master/slave.c @@ -116,7 +116,7 @@ int ec_slave_init(ec_slave_t *slave, /**< EtherCAT slave */ slave->current_state = EC_SLAVE_STATE_UNKNOWN; slave->self_configured = 0; slave->error_flag = 0; - slave->online = 1; + slave->online_state = EC_SLAVE_ONLINE; slave->fmmu_count = 0; slave->coupler_index = 0; @@ -328,6 +328,58 @@ void ec_slave_reset(ec_slave_t *slave /**< EtherCAT slave */) /*****************************************************************************/ +/** + * Sets the application state of a slave. + */ + +void ec_slave_set_state(ec_slave_t *slave, /**< EtherCAT slave */ + ec_slave_state_t new_state /**< new application state */ + ) +{ + if (new_state != slave->current_state) { + if (slave->master->debug_level) { + char old_state[EC_STATE_STRING_SIZE], + cur_state[EC_STATE_STRING_SIZE]; + ec_state_string(slave->current_state, old_state); + ec_state_string(new_state, cur_state); + EC_DBG("Slave %i: %s -> %s.\n", + slave->ring_position, old_state, cur_state); + } + slave->current_state = new_state; + } +} + +/*****************************************************************************/ + +/** + * Sets the online state of a slave. + */ + +void ec_slave_set_online_state(ec_slave_t *slave, /**< EtherCAT slave */ + ec_slave_online_state_t new_state /**< new online state */ + ) +{ + if (new_state == EC_SLAVE_OFFLINE && + slave->online_state == EC_SLAVE_ONLINE) { + if (slave->master->debug_level) + EC_DBG("Slave %i: offline.\n", slave->ring_position); + } + else if (new_state == EC_SLAVE_ONLINE && + slave->online_state == EC_SLAVE_OFFLINE) { + slave->error_flag = 0; // clear error flag + if (slave->master->debug_level) { + char cur_state[EC_STATE_STRING_SIZE]; + ec_state_string(slave->current_state, cur_state); + EC_DBG("Slave %i: online (%s).\n", + slave->ring_position, cur_state); + } + } + + slave->online_state = new_state; +} + +/*****************************************************************************/ + /** */ @@ -636,8 +688,8 @@ size_t ec_slave_info(const ec_slave_t *slave, /**< EtherCAT slave */ off += sprintf(buffer + off, " ("); off += ec_state_string(slave->requested_state, buffer + off); off += sprintf(buffer + off, ")\nFlags: %s, %s\n", - slave->online ? "online" : "OFFLINE", - slave->error_flag ? "ERROR" : "ok"); + slave->online_state == EC_SLAVE_ONLINE ? "online" : "OFFLINE", + slave->error_flag ? "ERROR" : "ok"); off += sprintf(buffer + off, "Ring position: %i\n", slave->ring_position); off += sprintf(buffer + off, "Advanced position: %i:%i\n", diff --git a/master/slave.h b/master/slave.h index cd6f9fb773ef97df85120b43702a383eb363bbb2..6654422a18879c7166324e32c58384d5e280ccf5 100644 --- a/master/slave.h +++ b/master/slave.h @@ -72,6 +72,12 @@ typedef enum } ec_slave_state_t; +typedef enum { + EC_SLAVE_OFFLINE, + EC_SLAVE_ONLINE +} +ec_slave_online_state_t; + /*****************************************************************************/ /** @@ -195,11 +201,11 @@ struct ec_slave struct kobject kobj; /**< kobject */ ec_master_t *master; /**< master owning the slave */ - ec_slave_state_t requested_state; /**< requested slave state */ - ec_slave_state_t current_state; /**< current slave state */ + ec_slave_state_t requested_state; /**< requested application state */ + ec_slave_state_t current_state; /**< current application state */ unsigned int self_configured; /**< slave was configured by this master */ unsigned int error_flag; /**< stop processing after an error */ - unsigned int online; /**< non-zero, if the slave responds. */ + unsigned int online_state; /**< online state */ // addresses uint16_t ring_position; /**< ring position */ @@ -266,6 +272,8 @@ int ec_slave_prepare_fmmu(ec_slave_t *, const ec_domain_t *, const ec_sii_sync_t *); void ec_slave_request_state(ec_slave_t *, ec_slave_state_t); +void ec_slave_set_state(ec_slave_t *, ec_slave_state_t); +void ec_slave_set_online_state(ec_slave_t *, ec_slave_online_state_t); // SII categories int ec_slave_fetch_strings(ec_slave_t *, const uint8_t *);