master/fsm.c
changeset 419 cf724fc82a00
parent 411 42d239bab6ae
child 420 0ae52c37179b
--- a/master/fsm.c	Thu Oct 19 14:05:56 2006 +0000
+++ b/master/fsm.c	Thu Oct 19 14:23:24 2006 +0000
@@ -54,6 +54,7 @@
 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_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_fmmu(ec_fsm_t *);
 void ec_fsm_slaveconf_sdoconf(ec_fsm_t *);
-void ec_fsm_slaveconf_fmmu(ec_fsm_t *);
 void ec_fsm_slaveconf_saveop(ec_fsm_t *);
 void ec_fsm_slaveconf_op(ec_fsm_t *);
 
@@ -593,6 +593,39 @@
     // 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 @@
     // 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,26 +1499,23 @@
     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
+    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) { // 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;
@@ -1461,63 +1523,6 @@
             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);
@@ -1526,136 +1531,6 @@
         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) {
-            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.
-
-            // 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);
-        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);
-        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_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 @@
         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;