master/fsm_slave.c
changeset 1597 491dea6f4fd7
parent 1596 ea8d2b4ee742
child 1598 5ad4eb4963a6
--- a/master/fsm_slave.c	Tue Dec 01 14:24:57 2009 +0100
+++ b/master/fsm_slave.c	Tue Dec 01 16:00:22 2009 +0100
@@ -42,7 +42,10 @@
 /*****************************************************************************/
 
 void ec_fsm_slave_state_idle(ec_fsm_slave_t *);
+int ec_fsm_slave_action_process_sdo(ec_fsm_slave_t *);
+int ec_fsm_slave_action_process_foe(ec_fsm_slave_t *);
 void ec_fsm_slave_state_sdo_request(ec_fsm_slave_t *);
+void ec_fsm_slave_state_foe_request(ec_fsm_slave_t *);
 
 
 /*****************************************************************************/
@@ -62,6 +65,7 @@
 
     // init sub-state-machines
     ec_fsm_coe_init(&fsm->fsm_coe, fsm->datagram);
+    ec_fsm_foe_init(&fsm->fsm_foe, fsm->datagram);
 }
 
 /*****************************************************************************/
@@ -74,6 +78,7 @@
 {
     // clear sub-state machines
     ec_fsm_coe_clear(&fsm->fsm_coe);
+    ec_fsm_foe_clear(&fsm->fsm_foe);
 }
 
 /*****************************************************************************/
@@ -101,20 +106,41 @@
  * Slave state machine
  *****************************************************************************/
 
+/*****************************************************************************/
+
 /** Slave state: IDLE.
  *
- * Check for pending SDO requests and process one.
  *
  */
 void ec_fsm_slave_state_idle(
         ec_fsm_slave_t *fsm /**< Slave state machine. */
         )
 {
+    // Check for pending external SDO requests
+    if (ec_fsm_slave_action_process_sdo(fsm))
+        return;
+    // Check for pending FOE requests
+    if (ec_fsm_slave_action_process_foe(fsm))
+        return;
+
+}
+
+
+/*****************************************************************************/
+
+/** Check for pending SDO requests and process one.
+ *
+ * \return non-zero, if an SDO request is processed.
+ */
+int ec_fsm_slave_action_process_sdo(
+        ec_fsm_slave_t *fsm /**< Slave state machine. */
+        )
+{
     ec_slave_t *slave = fsm->slave;
     ec_master_t *master = slave->master;
     ec_master_sdo_request_t *request, *next;
 
-    // search the first matching external request to be processed
+    // search the first external request to be processed
     list_for_each_entry_safe(request, next, &slave->slave_sdo_requests, list) {
         list_del_init(&request->list); // dequeue
         request->req.state = EC_INT_REQUEST_BUSY;
@@ -137,10 +163,47 @@
         fsm->state = ec_fsm_slave_state_sdo_request;
         ec_fsm_coe_transfer(&fsm->fsm_coe, slave, &request->req);
         ec_fsm_coe_exec(&fsm->fsm_coe); // execute immediately
-        ec_master_queue_sdo_datagram(fsm->slave->master,fsm->datagram);
-        return;
-    }
-}
+        ec_master_queue_external_datagram(fsm->slave->master,fsm->datagram);
+        return 1;
+    }
+    return 0;
+}
+
+
+/*****************************************************************************/
+
+/** Check for pending FOE requests and process one.
+ *
+ * \return non-zero, if an FOE request is processed.
+ */
+int ec_fsm_slave_action_process_foe(
+        ec_fsm_slave_t *fsm /**< Slave state machine. */
+        )
+{
+    ec_slave_t *slave = fsm->slave;
+    ec_master_t *master = slave->master;
+    ec_master_foe_request_t *request, *next;
+
+    // search the first request to be processed
+    list_for_each_entry_safe(request, next, &slave->foe_requests, list) {
+        list_del_init(&request->list); // dequeue
+        request->req.state = EC_INT_REQUEST_BUSY;
+
+        if (master->debug_level)
+            EC_DBG("Processing FoE request for slave %u.\n",
+                    slave->ring_position);
+
+        fsm->foe_request = &request->req;
+        fsm->state = ec_fsm_slave_state_foe_request;
+        ec_fsm_foe_transfer(&fsm->fsm_foe, slave, &request->req);
+        ec_fsm_foe_exec(&fsm->fsm_foe);
+        ec_master_queue_external_datagram(fsm->slave->master,fsm->datagram);
+        return 1;
+    }
+    return 0;
+}
+
+
 
 /*****************************************************************************/
 
@@ -156,7 +219,7 @@
 
     if (ec_fsm_coe_exec(&fsm->fsm_coe))
     {
-        ec_master_queue_sdo_datagram(fsm->slave->master,fsm->datagram);
+        ec_master_queue_external_datagram(fsm->slave->master,fsm->datagram);
         return;
     }
     if (!ec_fsm_coe_success(&fsm->fsm_coe)) {
@@ -169,15 +232,56 @@
         return;
     }
 
+    if (master->debug_level)
+        EC_DBG("Finished SDO request for slave %u.\n",
+                fsm->slave->ring_position);
+
     // SDO request finished
     request->state = EC_INT_REQUEST_SUCCESS;
     wake_up(&slave->sdo_queue);
 
+    fsm->sdo_request = NULL;
+    fsm->state = ec_fsm_slave_state_idle;
+}
+
+
+/*****************************************************************************/
+
+/** Slave state: FOE REQUEST.
+ */
+void ec_fsm_slave_state_foe_request(
+        ec_fsm_slave_t *fsm /**< Slave state machine. */
+        )
+{
+    ec_slave_t *slave = fsm->slave;
+    ec_master_t *master = slave->master;
+    ec_foe_request_t *request = fsm->foe_request;
+
+    if (ec_fsm_foe_exec(&fsm->fsm_foe))
+    {
+        ec_master_queue_external_datagram(fsm->slave->master,fsm->datagram);
+        return;
+    }
+
+    if (!ec_fsm_foe_success(&fsm->fsm_foe)) {
+        EC_ERR("Failed to handle FoE request to slave %u.\n",
+                slave->ring_position);
+        request->state = EC_INT_REQUEST_FAILURE;
+        wake_up(&slave->foe_queue);
+        fsm->foe_request = NULL;
+        fsm->state = ec_fsm_slave_state_idle;
+        return;
+    }
+
+    // finished transferring FoE
     if (master->debug_level)
-        EC_DBG("Finished SDO request for slave %u.\n",
-                fsm->slave->ring_position);
-
-    fsm->sdo_request = NULL;
-    fsm->datagram->data_size = 0;
+        EC_DBG("Successfully transferred %u bytes of FoE data from/to"
+                " slave %u.\n", request->data_size, slave->ring_position);
+
+    request->state = EC_INT_REQUEST_SUCCESS;
+    wake_up(&slave->foe_queue);
+
+    fsm->foe_request = NULL;
     fsm->state = ec_fsm_slave_state_idle;
 }
+