# HG changeset patch # User Florian Pose # Date 1161702865 0 # Node ID ffa13db95e10e80cb5ee27093cc23f6ec247c0c0 # Parent 16fddae16c94f04ad28de2de9bc26c19727387f3 SDO uploading via Sysfs without master FSM calling wake_up(). diff -r 16fddae16c94 -r ffa13db95e10 master/canopen.c --- a/master/canopen.c Tue Oct 24 12:06:59 2006 +0000 +++ b/master/canopen.c Tue Oct 24 15:14:25 2006 +0000 @@ -295,18 +295,31 @@ off_t off = 0; ec_sdo_request_t request; + if (down_interruptible(&master->sdo_sem)) { + // interrupted by signal + return -ERESTARTSYS; + } + ec_sdo_request_init_read(&request, sdo, entry); - list_add_tail(&request.queue, &master->sdo_requests); - if (wait_event_interruptible(master->sdo_wait_queue, - request.return_code)) { - // interrupted by signal - list_del_init(&request.queue); - } + + // this is necessary, because the completion object + // is completed by the ec_master_flush_sdo_requests() function. + INIT_COMPLETION(master->sdo_complete); + + master->sdo_request = &request; + master->sdo_seq_user++; + master->sdo_timer.expires = jiffies + 10; + add_timer(&master->sdo_timer); + + wait_for_completion(&master->sdo_complete); + + master->sdo_request = NULL; + up(&master->sdo_sem); if (request.return_code == 1 && request.data) { off += ec_sdo_entry_format_data(entry, &request, buffer); } - else if (request.return_code < 0) { + else { off = -EINVAL; } diff -r 16fddae16c94 -r ffa13db95e10 master/fsm.c --- a/master/fsm.c Tue Oct 24 12:06:59 2006 +0000 +++ b/master/fsm.c Tue Oct 24 15:14:25 2006 +0000 @@ -523,7 +523,6 @@ ec_master_t *master = fsm->master; ec_slave_t *slave; char old_state[EC_STATE_STRING_SIZE], new_state[EC_STATE_STRING_SIZE]; - ec_sdo_request_t *request, *next_request; // check if any slaves are not in the state, they're supposed to be list_for_each_entry(slave, &master->slaves, list) { @@ -558,29 +557,28 @@ // Check, if EoE processing has to be started ec_master_eoe_start(master); - // check, if there are pending SDO requests - list_for_each_entry_safe(request, next_request, - &master->sdo_requests, queue) { - // TODO: critical section! - list_del_init(&request->queue); - - slave = request->sdo->slave; - + // Check for a pending SDO request + if (master->sdo_seq_master != master->sdo_seq_user) { + if (master->debug_level) + EC_DBG("Processing SDO request...\n"); + slave = master->sdo_request->sdo->slave; if (slave->current_state == EC_SLAVE_STATE_INIT || !slave->online || slave->error_flag) { - request->return_code = -1; - wake_up_interruptible(&master->sdo_wait_queue); - continue; - } - - // start uploading SDO - fsm->slave = slave; - fsm->master_state = ec_fsm_master_sdo_request; - fsm->sdo_request = request; - ec_fsm_coe_upload(&fsm->fsm_coe, slave, request); - ec_fsm_coe_exec(&fsm->fsm_coe); // execute immediately - return; + EC_ERR("Failed to process SDO request, slave %i not ready.\n", + slave->ring_position); + master->sdo_request->return_code = -1; + master->sdo_seq_master++; + } + else { + // start uploading SDO + fsm->slave = slave; + fsm->master_state = ec_fsm_master_sdo_request; + fsm->sdo_request = master->sdo_request; + ec_fsm_coe_upload(&fsm->fsm_coe, slave, fsm->sdo_request); + ec_fsm_coe_exec(&fsm->fsm_coe); // execute immediately + return; + } } // check, if slaves have an SDO dictionary to read out. @@ -1034,7 +1032,7 @@ if (!ec_fsm_coe_success(&fsm->fsm_coe)) { request->return_code = -1; - wake_up_interruptible(&master->sdo_wait_queue); + master->sdo_seq_master++; fsm->master_state = ec_fsm_master_start; fsm->master_state(fsm); // execute immediately return; @@ -1043,7 +1041,7 @@ // SDO dictionary fetching finished request->return_code = 1; - wake_up_interruptible(&master->sdo_wait_queue); + master->sdo_seq_master++; // restart master state machine. fsm->master_state = ec_fsm_master_start; diff -r 16fddae16c94 -r ffa13db95e10 master/master.c --- a/master/master.c Tue Oct 24 12:06:59 2006 +0000 +++ b/master/master.c Tue Oct 24 15:14:25 2006 +0000 @@ -58,6 +58,7 @@ void ec_master_sync_io(ec_master_t *); void ec_master_idle_run(void *); void ec_master_eoe_run(unsigned long); +void ec_master_check_sdo(unsigned long); ssize_t ec_show_master_attribute(struct kobject *, struct attribute *, char *); ssize_t ec_store_master_attribute(struct kobject *, struct attribute *, const char *, size_t); @@ -130,8 +131,11 @@ master->idle_cycle_time_pos = 0; master->eoe_cycle_time_pos = 0; master->debug_level = 0; - INIT_LIST_HEAD(&master->sdo_requests); - init_waitqueue_head(&master->sdo_wait_queue); + init_MUTEX(&master->sdo_sem); + init_timer(&master->sdo_timer); + master->sdo_timer.function = ec_master_check_sdo; + master->sdo_timer.data = (unsigned long) master; + init_completion(&master->sdo_complete); // create workqueue if (!(master->workqueue = create_singlethread_workqueue("EtherCAT"))) { @@ -301,14 +305,11 @@ void ec_master_flush_sdo_requests(ec_master_t *master) { - ec_sdo_request_t *req, *next_req; - - list_for_each_entry_safe(req, next_req, &master->sdo_requests, queue) { - list_del_init(&req->queue); - req->return_code = -1; - } - - wake_up_interruptible(&master->sdo_wait_queue); + del_timer_sync(&master->sdo_timer); + complete(&master->sdo_complete); + master->sdo_request = NULL; + master->sdo_seq_user = 0; + master->sdo_seq_master = 0; } /*****************************************************************************/ @@ -1004,6 +1005,7 @@ } /*****************************************************************************/ + /** Does the Ethernet-over-EtherCAT processing. */ @@ -1067,6 +1069,25 @@ /*****************************************************************************/ /** +*/ + +void ec_master_check_sdo(unsigned long data /**< master pointer */) +{ + ec_master_t *master = (ec_master_t *) data; + + if (master->sdo_seq_master != master->sdo_seq_user) { + master->sdo_timer.expires = jiffies + 10; + add_timer(&master->sdo_timer); + return; + } + + // master has processed the request + complete(&master->sdo_complete); +} + +/*****************************************************************************/ + +/** Calculates Advanced Position Adresses. */ diff -r 16fddae16c94 -r ffa13db95e10 master/master.h --- a/master/master.h Tue Oct 24 12:06:59 2006 +0000 +++ b/master/master.h Tue Oct 24 15:14:25 2006 +0000 @@ -44,7 +44,6 @@ #include #include #include -#include #include #include @@ -139,8 +138,12 @@ uint8_t eeprom_write_enable; /**< allow write operations to EEPROMs */ - struct list_head sdo_requests; /**< list of SDO read/write requests */ - wait_queue_head_t sdo_wait_queue; /**< wait queue for SDO access */ + ec_sdo_request_t *sdo_request; /**< pointer to the current SDO request */ + unsigned int sdo_seq_user; /**< sequence number for user space */ + unsigned int sdo_seq_master; /**< sequence number for master */ + struct semaphore sdo_sem; /**< SDO semaphore */ + struct timer_list sdo_timer; /**< timer for polling sdo processing */ + struct completion sdo_complete; /**< SDO request completion object */ }; /*****************************************************************************/