diff -r ea8d2b4ee742 -r 491dea6f4fd7 master/fsm_slave.c --- 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; } +