Moved SDO dictionary fetching to master FSMs; added SDO parent kobj.
This commit is contained in:
parent
7642448f62
commit
e33b75b2b5
|
|
@ -111,8 +111,8 @@ int ec_sdo_init(ec_sdo_t *sdo, /**< SDO */
|
|||
memset(&sdo->kobj, 0x00, sizeof(struct kobject));
|
||||
kobject_init(&sdo->kobj);
|
||||
sdo->kobj.ktype = &ktype_ec_sdo;
|
||||
sdo->kobj.parent = &slave->kobj;
|
||||
if (kobject_set_name(&sdo->kobj, "sdo%4X", sdo->index)) {
|
||||
sdo->kobj.parent = &slave->sdo_kobj;
|
||||
if (kobject_set_name(&sdo->kobj, "%4X", sdo->index)) {
|
||||
EC_ERR("Failed to set kobj name.\n");
|
||||
return -1;
|
||||
}
|
||||
|
|
@ -195,7 +195,7 @@ int ec_sdo_entry_init(ec_sdo_entry_t *entry, /**< SDO entry */
|
|||
kobject_init(&entry->kobj);
|
||||
entry->kobj.ktype = &ktype_ec_sdo_entry;
|
||||
entry->kobj.parent = &sdo->kobj;
|
||||
if (kobject_set_name(&entry->kobj, "entry%02X", entry->subindex)) {
|
||||
if (kobject_set_name(&entry->kobj, "%i", entry->subindex)) {
|
||||
EC_ERR("Failed to set kobj name.\n");
|
||||
return -1;
|
||||
}
|
||||
|
|
|
|||
320
master/fsm.c
320
master/fsm.c
|
|
@ -54,6 +54,7 @@ void ec_fsm_master_rewrite_addresses(ec_fsm_t *);
|
|||
void ec_fsm_master_configure_slave(ec_fsm_t *);
|
||||
void ec_fsm_master_scan_slaves(ec_fsm_t *);
|
||||
void ec_fsm_master_write_eeprom(ec_fsm_t *);
|
||||
void ec_fsm_master_sdodict(ec_fsm_t *);
|
||||
|
||||
void ec_fsm_startup_start(ec_fsm_t *);
|
||||
void ec_fsm_startup_broadcast(ec_fsm_t *);
|
||||
|
|
@ -73,9 +74,8 @@ void ec_fsm_slavescan_eeprom_data(ec_fsm_t *);
|
|||
void ec_fsm_slaveconf_init(ec_fsm_t *);
|
||||
void ec_fsm_slaveconf_sync(ec_fsm_t *);
|
||||
void ec_fsm_slaveconf_preop(ec_fsm_t *);
|
||||
void ec_fsm_slaveconf_sdodict(ec_fsm_t *);
|
||||
void ec_fsm_slaveconf_sdoconf(ec_fsm_t *);
|
||||
void ec_fsm_slaveconf_fmmu(ec_fsm_t *);
|
||||
void ec_fsm_slaveconf_sdoconf(ec_fsm_t *);
|
||||
void ec_fsm_slaveconf_saveop(ec_fsm_t *);
|
||||
void ec_fsm_slaveconf_op(ec_fsm_t *);
|
||||
|
||||
|
|
@ -593,6 +593,39 @@ void ec_fsm_master_action_process_states(ec_fsm_t *fsm
|
|||
// Check, if EoE processing has to be started
|
||||
ec_master_eoe_start(master);
|
||||
|
||||
// check, if slaves have an SDO dictionary to read out.
|
||||
list_for_each_entry(slave, &master->slaves, list) {
|
||||
if (!(slave->sii_mailbox_protocols & EC_MBOX_COE)
|
||||
|| slave->sdo_dictionary_fetched
|
||||
|| slave->current_state == EC_SLAVE_STATE_INIT
|
||||
|| jiffies - slave->jiffies_preop < 5 * HZ
|
||||
|| !slave->online
|
||||
|| slave->error_flag) continue;
|
||||
|
||||
if (master->debug_level) {
|
||||
EC_DBG("Fetching SDO dictionary of slave %i.\n",
|
||||
slave->ring_position);
|
||||
}
|
||||
|
||||
if (kobject_add(&slave->sdo_kobj)) {
|
||||
EC_ERR("Failed to add SDO kobj of slave %i.\n",
|
||||
slave->ring_position);
|
||||
slave->error_flag = 1;
|
||||
fsm->master_state = ec_fsm_master_start;
|
||||
fsm->master_state(fsm); // execute immediately
|
||||
return;
|
||||
}
|
||||
|
||||
slave->sdo_dictionary_fetched = 1;
|
||||
|
||||
// start fetching SDO dictionary
|
||||
fsm->slave = slave;
|
||||
fsm->master_state = ec_fsm_master_sdodict;
|
||||
fsm->coe_state = ec_fsm_coe_dict_start;
|
||||
fsm->coe_state(fsm); // execute immediately
|
||||
return;
|
||||
}
|
||||
|
||||
if (master->mode == EC_MASTER_MODE_IDLE) {
|
||||
// nothing to configure. check for pending EEPROM write operations.
|
||||
list_for_each_entry(slave, &master->slaves, list) {
|
||||
|
|
@ -982,7 +1015,39 @@ void ec_fsm_master_write_eeprom(ec_fsm_t *fsm /**< finite state machine */)
|
|||
// restart master state machine.
|
||||
fsm->master_state = ec_fsm_master_start;
|
||||
fsm->master_state(fsm); // execute immediately
|
||||
return;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/**
|
||||
Master state: SDODICT.
|
||||
*/
|
||||
|
||||
void ec_fsm_master_sdodict(ec_fsm_t *fsm /**< finite state machine */)
|
||||
{
|
||||
ec_slave_t *slave = fsm->slave;
|
||||
ec_master_t *master = fsm->master;
|
||||
|
||||
fsm->coe_state(fsm); // execute CoE state machine
|
||||
|
||||
if (fsm->coe_state == ec_fsm_error) {
|
||||
fsm->slave->error_flag = 1;
|
||||
fsm->slave_state = ec_fsm_error;
|
||||
return;
|
||||
}
|
||||
|
||||
if (fsm->coe_state != ec_fsm_end) return;
|
||||
|
||||
// SDO dictionary fetching finished
|
||||
|
||||
if (master->debug_level) {
|
||||
EC_DBG("Finished fetching SDO dictionary of slave %i.\n",
|
||||
slave->ring_position);
|
||||
}
|
||||
|
||||
// restart master state machine.
|
||||
fsm->master_state = ec_fsm_master_start;
|
||||
fsm->master_state(fsm); // execute immediately
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
|
|
@ -1434,139 +1499,12 @@ void ec_fsm_slaveconf_preop(ec_fsm_t *fsm /**< finite state machine */)
|
|||
if (fsm->change_state != ec_fsm_end) return;
|
||||
|
||||
// slave is now in PREOP
|
||||
slave->jiffies_preop = fsm->datagram.jiffies_received;
|
||||
|
||||
if (master->debug_level) {
|
||||
EC_DBG("Slave %i is now in PREOP.\n", slave->ring_position);
|
||||
}
|
||||
|
||||
if (!(slave->sii_mailbox_protocols & EC_MBOX_COE)) {
|
||||
// slave does not support CoE. skip dictionary fetching
|
||||
// and SDO configuration
|
||||
|
||||
if (slave->current_state == slave->requested_state) {
|
||||
fsm->slave_state = ec_fsm_end; // successful
|
||||
if (master->debug_level) {
|
||||
EC_DBG("Finished configuration of slave %i.\n",
|
||||
slave->ring_position);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (!slave->base_fmmu_count) {
|
||||
// slave has no FMMUs. skip configuration and go to SAVEOP
|
||||
fsm->slave_state = ec_fsm_slaveconf_saveop;
|
||||
fsm->change_new = EC_SLAVE_STATE_SAVEOP;
|
||||
fsm->change_state = ec_fsm_change_start;
|
||||
fsm->change_state(fsm); // execute immediately
|
||||
return;
|
||||
}
|
||||
|
||||
// configure FMMUs
|
||||
ec_datagram_npwr(datagram, slave->station_address,
|
||||
0x0600, EC_FMMU_SIZE * slave->base_fmmu_count);
|
||||
memset(datagram->data, 0x00, EC_FMMU_SIZE * slave->base_fmmu_count);
|
||||
for (j = 0; j < slave->fmmu_count; j++) {
|
||||
ec_fmmu_config(&slave->fmmus[j], slave,
|
||||
datagram->data + EC_FMMU_SIZE * j);
|
||||
}
|
||||
|
||||
ec_master_queue_datagram(master, datagram);
|
||||
fsm->slave_state = ec_fsm_slaveconf_fmmu;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!list_empty(&slave->sdo_dictionary)) {
|
||||
// SDO dictionary already fetched
|
||||
|
||||
if (master->debug_level) {
|
||||
EC_DBG("SDO dictionary already present for slave %i.\n",
|
||||
slave->ring_position);
|
||||
}
|
||||
|
||||
if (slave->current_state == slave->requested_state) {
|
||||
fsm->slave_state = ec_fsm_end; // successful
|
||||
if (master->debug_level) {
|
||||
EC_DBG("Finished configuration of slave %i.\n",
|
||||
slave->ring_position);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (list_empty(&slave->sdo_confs)) {
|
||||
// skip SDO configuration
|
||||
|
||||
if (!slave->base_fmmu_count) {
|
||||
// slave has no FMMUs. skip configuration and go to SAVEOP
|
||||
fsm->slave_state = ec_fsm_slaveconf_saveop;
|
||||
fsm->change_new = EC_SLAVE_STATE_SAVEOP;
|
||||
fsm->change_state = ec_fsm_change_start;
|
||||
fsm->change_state(fsm); // execute immediately
|
||||
return;
|
||||
}
|
||||
|
||||
// configure FMMUs
|
||||
ec_datagram_npwr(datagram, slave->station_address,
|
||||
0x0600, EC_FMMU_SIZE * slave->base_fmmu_count);
|
||||
memset(datagram->data, 0x00, EC_FMMU_SIZE * slave->base_fmmu_count);
|
||||
for (j = 0; j < slave->fmmu_count; j++) {
|
||||
ec_fmmu_config(&slave->fmmus[j], slave,
|
||||
datagram->data + EC_FMMU_SIZE * j);
|
||||
}
|
||||
|
||||
ec_master_queue_datagram(master, datagram);
|
||||
fsm->slave_state = ec_fsm_slaveconf_fmmu;
|
||||
return;
|
||||
}
|
||||
|
||||
// start SDO configuration
|
||||
fsm->slave_state = ec_fsm_slaveconf_sdoconf;
|
||||
fsm->coe_sdodata = list_entry(slave->sdo_confs.next, ec_sdo_data_t, list);
|
||||
fsm->coe_state = ec_fsm_coe_down_start;
|
||||
fsm->coe_state(fsm); // execute immediately
|
||||
return;
|
||||
}
|
||||
|
||||
if (master->debug_level) {
|
||||
EC_DBG("Fetching SDO dictionary of slave %i.\n",
|
||||
slave->ring_position);
|
||||
}
|
||||
|
||||
// start fetching SDO dictionary
|
||||
fsm->slave_state = ec_fsm_slaveconf_sdodict;
|
||||
fsm->coe_state = ec_fsm_coe_dict_start;
|
||||
fsm->coe_state(fsm); // execute immediately
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/**
|
||||
Slave configuration state: SDODICT.
|
||||
*/
|
||||
|
||||
void ec_fsm_slaveconf_sdodict(ec_fsm_t *fsm /**< finite state machine */)
|
||||
{
|
||||
ec_slave_t *slave = fsm->slave;
|
||||
ec_datagram_t *datagram = &fsm->datagram;
|
||||
ec_master_t *master = fsm->master;
|
||||
unsigned int j;
|
||||
|
||||
fsm->coe_state(fsm); // execute CoE state machine
|
||||
|
||||
if (fsm->coe_state == ec_fsm_error) {
|
||||
fsm->slave->error_flag = 1;
|
||||
fsm->slave_state = ec_fsm_error;
|
||||
return;
|
||||
}
|
||||
|
||||
if (fsm->coe_state != ec_fsm_end) return;
|
||||
|
||||
// SDO dictionary fetching finished
|
||||
|
||||
if (master->debug_level) {
|
||||
EC_DBG("Finished fetching SDO dictionary of slave %i.\n",
|
||||
slave->ring_position);
|
||||
}
|
||||
|
||||
if (slave->current_state == slave->requested_state) {
|
||||
fsm->slave_state = ec_fsm_end; // successful
|
||||
if (master->debug_level) {
|
||||
|
|
@ -1576,13 +1514,8 @@ void ec_fsm_slaveconf_sdodict(ec_fsm_t *fsm /**< finite state machine */)
|
|||
return;
|
||||
}
|
||||
|
||||
if (list_empty(&slave->sdo_confs)) {
|
||||
// skip SDO configuration
|
||||
|
||||
if (!slave->base_fmmu_count) {
|
||||
// slave has no FMMUs. skip configuration.
|
||||
|
||||
// set state to SAVEOP
|
||||
if (!slave->base_fmmu_count) { // skip FMMU configuration
|
||||
if (list_empty(&slave->sdo_confs)) { // skip SDO configuration
|
||||
fsm->slave_state = ec_fsm_slaveconf_saveop;
|
||||
fsm->change_new = EC_SLAVE_STATE_SAVEOP;
|
||||
fsm->change_state = ec_fsm_change_start;
|
||||
|
|
@ -1590,72 +1523,14 @@ void ec_fsm_slaveconf_sdodict(ec_fsm_t *fsm /**< finite state machine */)
|
|||
return;
|
||||
}
|
||||
|
||||
// configure FMMUs
|
||||
ec_datagram_npwr(datagram, slave->station_address,
|
||||
0x0600, EC_FMMU_SIZE * slave->base_fmmu_count);
|
||||
memset(datagram->data, 0x00, EC_FMMU_SIZE * slave->base_fmmu_count);
|
||||
for (j = 0; j < slave->fmmu_count; j++) {
|
||||
ec_fmmu_config(&slave->fmmus[j], slave,
|
||||
datagram->data + EC_FMMU_SIZE * j);
|
||||
}
|
||||
|
||||
ec_master_queue_datagram(master, datagram);
|
||||
fsm->slave_state = ec_fsm_slaveconf_fmmu;
|
||||
return;
|
||||
}
|
||||
|
||||
// start SDO configuration
|
||||
fsm->slave_state = ec_fsm_slaveconf_sdoconf;
|
||||
fsm->coe_sdodata = list_entry(slave->sdo_confs.next, ec_sdo_data_t, list);
|
||||
fsm->coe_state = ec_fsm_coe_down_start;
|
||||
fsm->coe_state(fsm); // execute immediately
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/**
|
||||
Slave configuration state: SDOCONF.
|
||||
*/
|
||||
|
||||
void ec_fsm_slaveconf_sdoconf(ec_fsm_t *fsm /**< finite state machine */)
|
||||
{
|
||||
ec_slave_t *slave = fsm->slave;
|
||||
ec_datagram_t *datagram = &fsm->datagram;
|
||||
ec_master_t *master = fsm->master;
|
||||
unsigned int j;
|
||||
|
||||
fsm->coe_state(fsm); // execute CoE state machine
|
||||
|
||||
if (fsm->coe_state == ec_fsm_error) {
|
||||
fsm->slave->error_flag = 1;
|
||||
fsm->slave_state = ec_fsm_error;
|
||||
return;
|
||||
}
|
||||
|
||||
if (fsm->coe_state != ec_fsm_end) return;
|
||||
|
||||
// Another SDO to configure?
|
||||
if (fsm->coe_sdodata->list.next != &fsm->slave->sdo_confs) {
|
||||
fsm->coe_sdodata = list_entry(fsm->coe_sdodata->list.next,
|
||||
ec_sdo_data_t, list);
|
||||
// start SDO configuration
|
||||
fsm->slave_state = ec_fsm_slaveconf_sdoconf;
|
||||
fsm->coe_sdodata = list_entry(slave->sdo_confs.next, ec_sdo_data_t, list);
|
||||
fsm->coe_state = ec_fsm_coe_down_start;
|
||||
fsm->coe_state(fsm); // execute immediately
|
||||
return;
|
||||
}
|
||||
|
||||
// All SDOs are now configured.
|
||||
|
||||
if (!slave->base_fmmu_count) {
|
||||
// slave has no FMMUs. skip configuration.
|
||||
|
||||
// set state to SAVEOP
|
||||
fsm->slave_state = ec_fsm_slaveconf_saveop;
|
||||
fsm->change_new = EC_SLAVE_STATE_SAVEOP;
|
||||
fsm->change_state = ec_fsm_change_start;
|
||||
fsm->change_state(fsm); // execute immediately
|
||||
return;
|
||||
}
|
||||
|
||||
// configure FMMUs
|
||||
ec_datagram_npwr(datagram, slave->station_address,
|
||||
0x0600, EC_FMMU_SIZE * slave->base_fmmu_count);
|
||||
|
|
@ -1678,6 +1553,7 @@ void ec_fsm_slaveconf_sdoconf(ec_fsm_t *fsm /**< finite state machine */)
|
|||
void ec_fsm_slaveconf_fmmu(ec_fsm_t *fsm /**< finite state machine */)
|
||||
{
|
||||
ec_datagram_t *datagram = &fsm->datagram;
|
||||
ec_slave_t *slave = fsm->slave;
|
||||
|
||||
if (datagram->state != EC_DATAGRAM_RECEIVED
|
||||
|| datagram->working_counter != 1) {
|
||||
|
|
@ -1688,6 +1564,52 @@ void ec_fsm_slaveconf_fmmu(ec_fsm_t *fsm /**< finite state machine */)
|
|||
return;
|
||||
}
|
||||
|
||||
// No CoE configuration to be applied? Jump to SAVEOP state.
|
||||
if (list_empty(&slave->sdo_confs)) { // skip SDO configuration
|
||||
// set state to SAVEOP
|
||||
fsm->slave_state = ec_fsm_slaveconf_saveop;
|
||||
fsm->change_new = EC_SLAVE_STATE_SAVEOP;
|
||||
fsm->change_state = ec_fsm_change_start;
|
||||
fsm->change_state(fsm); // execute immediately
|
||||
return;
|
||||
}
|
||||
|
||||
// start SDO configuration
|
||||
fsm->slave_state = ec_fsm_slaveconf_sdoconf;
|
||||
fsm->coe_sdodata = list_entry(slave->sdo_confs.next, ec_sdo_data_t, list);
|
||||
fsm->coe_state = ec_fsm_coe_down_start;
|
||||
fsm->coe_state(fsm); // execute immediately
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/**
|
||||
Slave configuration state: SDOCONF.
|
||||
*/
|
||||
|
||||
void ec_fsm_slaveconf_sdoconf(ec_fsm_t *fsm /**< finite state machine */)
|
||||
{
|
||||
fsm->coe_state(fsm); // execute CoE state machine
|
||||
|
||||
if (fsm->coe_state == ec_fsm_error) {
|
||||
fsm->slave->error_flag = 1;
|
||||
fsm->slave_state = ec_fsm_error;
|
||||
return;
|
||||
}
|
||||
|
||||
if (fsm->coe_state != ec_fsm_end) return;
|
||||
|
||||
// Another SDO to configure?
|
||||
if (fsm->coe_sdodata->list.next != &fsm->slave->sdo_confs) {
|
||||
fsm->coe_sdodata = list_entry(fsm->coe_sdodata->list.next,
|
||||
ec_sdo_data_t, list);
|
||||
fsm->coe_state = ec_fsm_coe_down_start;
|
||||
fsm->coe_state(fsm); // execute immediately
|
||||
return;
|
||||
}
|
||||
|
||||
// All SDOs are now configured.
|
||||
|
||||
// set state to SAVEOP
|
||||
fsm->slave_state = ec_fsm_slaveconf_saveop;
|
||||
fsm->change_new = EC_SLAVE_STATE_SAVEOP;
|
||||
|
|
|
|||
|
|
@ -83,6 +83,8 @@ static struct kobj_type ktype_ec_slave = {
|
|||
.default_attrs = def_attrs
|
||||
};
|
||||
|
||||
static struct kobj_type ktype_ec_slave_sdos = {};
|
||||
|
||||
/** \endcond */
|
||||
|
||||
/*****************************************************************************/
|
||||
|
|
@ -114,6 +116,18 @@ int ec_slave_init(ec_slave_t *slave, /**< EtherCAT slave */
|
|||
return -1;
|
||||
}
|
||||
|
||||
// init SDO kobject and add it to the hierarchy
|
||||
memset(&slave->sdo_kobj, 0x00, sizeof(struct kobject));
|
||||
kobject_init(&slave->sdo_kobj);
|
||||
slave->sdo_kobj.ktype = &ktype_ec_slave_sdos;
|
||||
slave->sdo_kobj.parent = &slave->kobj;
|
||||
if (kobject_set_name(&slave->sdo_kobj, "sdos")) {
|
||||
EC_ERR("Failed to set kobject name.\n");
|
||||
kobject_put(&slave->sdo_kobj);
|
||||
kobject_put(&slave->kobj);
|
||||
return -1;
|
||||
}
|
||||
|
||||
slave->master = master;
|
||||
|
||||
slave->requested_state = EC_SLAVE_STATE_UNKNOWN;
|
||||
|
|
@ -158,6 +172,9 @@ int ec_slave_init(ec_slave_t *slave, /**< EtherCAT slave */
|
|||
INIT_LIST_HEAD(&slave->sdo_dictionary);
|
||||
INIT_LIST_HEAD(&slave->sdo_confs);
|
||||
|
||||
slave->sdo_dictionary_fetched = 0;
|
||||
slave->jiffies_preop = 0;
|
||||
|
||||
for (i = 0; i < 4; i++) {
|
||||
slave->dl_link[i] = 0;
|
||||
slave->dl_loop[i] = 0;
|
||||
|
|
@ -225,6 +242,10 @@ void ec_slave_clear(struct kobject *kobj /**< kobject of the slave */)
|
|||
kobject_put(&sdo->kobj);
|
||||
}
|
||||
|
||||
// free SDO kobject
|
||||
if (slave->sdo_dictionary_fetched) kobject_del(&slave->sdo_kobj);
|
||||
kobject_put(&slave->sdo_kobj);
|
||||
|
||||
// free all SDO configurations
|
||||
list_for_each_entry_safe(sdodata, next_sdodata, &slave->sdo_confs, list) {
|
||||
list_del(&sdodata->list);
|
||||
|
|
|
|||
|
|
@ -248,8 +248,11 @@ struct ec_slave
|
|||
ec_fmmu_t fmmus[EC_MAX_FMMUS]; /**< FMMU configurations */
|
||||
uint8_t fmmu_count; /**< number of FMMUs used */
|
||||
|
||||
struct kobject sdo_kobj; /**< kobject for SDOs */
|
||||
struct list_head sdo_dictionary; /**< SDO dictionary list */
|
||||
struct list_head sdo_confs; /**< list of SDO configurations */
|
||||
uint8_t sdo_dictionary_fetched; /**< dictionary has been fetched */
|
||||
unsigned long jiffies_preop; /**< time, the slave went to PREOP */
|
||||
};
|
||||
|
||||
/*****************************************************************************/
|
||||
|
|
|
|||
Loading…
Reference in New Issue