Introduced idle flag in master state machine.
authorFlorian Pose <fp@igh-essen.com>
Mon, 12 Mar 2007 12:11:43 +0000
changeset 650 c68995623e94
parent 649 a4d3fffdaed7
child 651 8c11399cc911
Introduced idle flag in master state machine.
NEWS
TODO
master/fsm_master.c
master/fsm_master.h
master/master.c
--- a/NEWS	Mon Mar 12 11:02:05 2007 +0000
+++ b/NEWS	Mon Mar 12 12:11:43 2007 +0000
@@ -37,6 +37,8 @@
 * Implemented setting of secondary slave address (alias) via sysfs.
 * Implemented SDO reading in operation mode via sysfs.
 * Removed annoying eeprom_write_enable file. EEPROM writing always enabled.
+* Master state machine scheduled with timeout if idle, otherwise is executed
+  as fast as possible (with schedule()).
 * Removed EtherCAT line comments from 8139too drivers.
 
 -------------------------------------------------------------------------------
--- a/TODO	Mon Mar 12 11:02:05 2007 +0000
+++ b/TODO	Mon Mar 12 12:11:43 2007 +0000
@@ -26,7 +26,6 @@
   - Evaluate EEPROM contents after writing.
   - SDO dictionary fetching in operation mode.
   - SDO write access in sysfs.
-  - Speed up IDLE state machine through fast mode with schedule().
   - Configure slave ports to automatically open on link detection.
   - Calculate cycle time of operation state machine.
 
--- a/master/fsm_master.c	Mon Mar 12 11:02:05 2007 +0000
+++ b/master/fsm_master.c	Mon Mar 12 12:11:43 2007 +0000
@@ -74,6 +74,7 @@
     fsm->master = master;
     fsm->datagram = datagram;
     fsm->state = ec_fsm_master_state_start;
+    fsm->idle = 0;
     fsm->slaves_responding = 0;
     fsm->topology_change_pending = 0;
     fsm->slave_states = EC_SLAVE_STATE_UNKNOWN;
@@ -126,15 +127,30 @@
 /*****************************************************************************/
 
 /**
-   \return false, if state machine has terminated
-*/
-
-int ec_fsm_master_running(ec_fsm_master_t *fsm /**< master state machine */)
+ * \return false, if state machine has terminated
+ */
+
+int ec_fsm_master_running(
+        const ec_fsm_master_t *fsm /**< master state machine */
+        )
 {
     return fsm->state != ec_fsm_master_state_end
         && fsm->state != ec_fsm_master_state_error;
 }
 
+/*****************************************************************************/
+
+/**
+ * \return true, if the state machine is in an idle phase
+ */
+
+int ec_fsm_master_idle(
+        const ec_fsm_master_t *fsm /**< master state machine */
+        )
+{
+    return fsm->idle;
+}
+
 /******************************************************************************
  *  master state machine
  *****************************************************************************/
@@ -146,6 +162,7 @@
 
 void ec_fsm_master_state_start(ec_fsm_master_t *fsm)
 {
+    fsm->idle = 1;
     ec_datagram_brd(fsm->datagram, 0x0130, 2);
     fsm->state = ec_fsm_master_state_broadcast;
 }
@@ -167,8 +184,7 @@
     if (datagram->state == EC_DATAGRAM_TIMED_OUT)
         return; // always retry
 
-    if (datagram->state != EC_DATAGRAM_RECEIVED) { // EC_DATAGRAM_ERROR
-        // link is down
+    if (datagram->state != EC_DATAGRAM_RECEIVED) { // link is down
         fsm->slaves_responding = 0;
         list_for_each_entry(slave, &master->slaves, list) {
             ec_slave_set_online_state(slave, EC_SLAVE_OFFLINE);
@@ -210,6 +226,7 @@
             master->mode == EC_MASTER_MODE_IDLE) {
         fsm->topology_change_pending = 0;
         fsm->tainted = 0;
+        fsm->idle = 0;
 
         ec_master_eoe_stop(master);
         ec_master_destroy_slaves(master);
@@ -359,6 +376,7 @@
                     slave->ring_position);
 
         // start uploading SDO
+        fsm->idle = 0;
         fsm->slave = slave;
         fsm->sdo_request = request;
         fsm->state = ec_fsm_master_state_sdo_request;
@@ -406,6 +424,7 @@
             }
         }
 
+        fsm->idle = 0;
         fsm->slave = slave;
         fsm->state = ec_fsm_master_state_configure_slave;
         ec_fsm_slave_start_conf(&fsm->fsm_slave, slave);
@@ -439,6 +458,7 @@
             slave->sdo_dictionary_fetched = 1;
 
             // start fetching SDO dictionary
+            fsm->idle = 0;
             fsm->slave = slave;
             fsm->state = ec_fsm_master_state_sdodict;
             ec_fsm_coe_dictionary(&fsm->fsm_coe, slave);
@@ -469,6 +489,7 @@
     // is there another slave to query?
     if (slave->list.next != &master->slaves) {
         // process next slave
+        fsm->idle = 1;
         fsm->slave = list_entry(slave->list.next, ec_slave_t, list);
         ec_datagram_nprd(fsm->datagram, fsm->slave->station_address,
                          0x0130, 2);
@@ -487,6 +508,7 @@
 
             // At least one slave is offline. validate!
             EC_INFO("Validating bus.\n");
+            fsm->idle = 0;
             fsm->slave = list_entry(master->slaves.next, ec_slave_t, list);
             fsm->state = ec_fsm_master_state_validate_vendor;
             ec_fsm_sii_read(&fsm->fsm_sii, slave, 0x0008, EC_FSM_SII_POSITION);
@@ -533,6 +555,7 @@
 
     // check, if new slave state has to be acknowledged
     if (slave->current_state & EC_SLAVE_STATE_ACK_ERR && !slave->error_flag) {
+        fsm->idle = 0;
         fsm->state = ec_fsm_master_state_acknowledge;
         ec_fsm_change_ack(&fsm->fsm_change, slave);
         ec_fsm_change_exec(&fsm->fsm_change);
--- a/master/fsm_master.h	Mon Mar 12 11:02:05 2007 +0000
+++ b/master/fsm_master.h	Mon Mar 12 12:11:43 2007 +0000
@@ -81,6 +81,7 @@
     unsigned int retries; /**< retries on datagram timeout. */
 
     void (*state)(ec_fsm_master_t *); /**< master state function */
+    int idle; /**< state machine is in idle phase */
     unsigned int slaves_responding; /**< number of responding slaves */
     unsigned int topology_change_pending; /**< bus topology changed */
     ec_slave_state_t slave_states; /**< states of responding slaves */
@@ -104,7 +105,8 @@
 void ec_fsm_master_clear(ec_fsm_master_t *);
 
 int ec_fsm_master_exec(ec_fsm_master_t *);
-int ec_fsm_master_running(ec_fsm_master_t *);
+int ec_fsm_master_running(const ec_fsm_master_t *);
+int ec_fsm_master_idle(const ec_fsm_master_t *);
 
 /*****************************************************************************/
 
--- a/master/master.c	Mon Mar 12 11:02:05 2007 +0000
+++ b/master/master.c	Mon Mar 12 12:11:43 2007 +0000
@@ -836,8 +836,13 @@
         master->idle_cycle_time_pos++;
         master->idle_cycle_time_pos %= HZ;
 
-        set_current_state(TASK_INTERRUPTIBLE);
-        schedule_timeout(1);
+        if (ec_fsm_master_idle(&master->fsm)) {
+            set_current_state(TASK_INTERRUPTIBLE);
+            schedule_timeout(1);
+        }
+        else {
+            schedule();
+        }
     }
     
     master->thread_id = 0;
@@ -883,8 +888,13 @@
         master->idle_cycle_time_pos %= HZ;
 
 schedule:
-        set_current_state(TASK_INTERRUPTIBLE);
-        schedule_timeout(1);
+        if (ec_fsm_master_idle(&master->fsm)) {
+            set_current_state(TASK_INTERRUPTIBLE);
+            schedule_timeout(1);
+        }
+        else {
+            schedule();
+        }
     }
     
     master->thread_id = 0;