SDO uploading via Sysfs without master FSM calling wake_up().
This commit is contained in:
parent
459841ea00
commit
5ae68fa1db
|
|
@ -295,18 +295,31 @@ ssize_t ec_sdo_entry_read_value(ec_sdo_entry_t *entry, /**< SDO entry */
|
||||||
off_t off = 0;
|
off_t off = 0;
|
||||||
ec_sdo_request_t request;
|
ec_sdo_request_t request;
|
||||||
|
|
||||||
ec_sdo_request_init_read(&request, sdo, entry);
|
if (down_interruptible(&master->sdo_sem)) {
|
||||||
list_add_tail(&request.queue, &master->sdo_requests);
|
|
||||||
if (wait_event_interruptible(master->sdo_wait_queue,
|
|
||||||
request.return_code)) {
|
|
||||||
// interrupted by signal
|
// interrupted by signal
|
||||||
list_del_init(&request.queue);
|
return -ERESTARTSYS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ec_sdo_request_init_read(&request, sdo, entry);
|
||||||
|
|
||||||
|
// 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) {
|
if (request.return_code == 1 && request.data) {
|
||||||
off += ec_sdo_entry_format_data(entry, &request, buffer);
|
off += ec_sdo_entry_format_data(entry, &request, buffer);
|
||||||
}
|
}
|
||||||
else if (request.return_code < 0) {
|
else {
|
||||||
off = -EINVAL;
|
off = -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
42
master/fsm.c
42
master/fsm.c
|
|
@ -523,7 +523,6 @@ void ec_fsm_master_action_process_states(ec_fsm_t *fsm
|
||||||
ec_master_t *master = fsm->master;
|
ec_master_t *master = fsm->master;
|
||||||
ec_slave_t *slave;
|
ec_slave_t *slave;
|
||||||
char old_state[EC_STATE_STRING_SIZE], new_state[EC_STATE_STRING_SIZE];
|
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
|
// check if any slaves are not in the state, they're supposed to be
|
||||||
list_for_each_entry(slave, &master->slaves, list) {
|
list_for_each_entry(slave, &master->slaves, list) {
|
||||||
|
|
@ -558,29 +557,28 @@ void ec_fsm_master_action_process_states(ec_fsm_t *fsm
|
||||||
// Check, if EoE processing has to be started
|
// Check, if EoE processing has to be started
|
||||||
ec_master_eoe_start(master);
|
ec_master_eoe_start(master);
|
||||||
|
|
||||||
// check, if there are pending SDO requests
|
// Check for a pending SDO request
|
||||||
list_for_each_entry_safe(request, next_request,
|
if (master->sdo_seq_master != master->sdo_seq_user) {
|
||||||
&master->sdo_requests, queue) {
|
if (master->debug_level)
|
||||||
// TODO: critical section!
|
EC_DBG("Processing SDO request...\n");
|
||||||
list_del_init(&request->queue);
|
slave = master->sdo_request->sdo->slave;
|
||||||
|
|
||||||
slave = request->sdo->slave;
|
|
||||||
|
|
||||||
if (slave->current_state == EC_SLAVE_STATE_INIT
|
if (slave->current_state == EC_SLAVE_STATE_INIT
|
||||||
|| !slave->online
|
|| !slave->online
|
||||||
|| slave->error_flag) {
|
|| slave->error_flag) {
|
||||||
request->return_code = -1;
|
EC_ERR("Failed to process SDO request, slave %i not ready.\n",
|
||||||
wake_up_interruptible(&master->sdo_wait_queue);
|
slave->ring_position);
|
||||||
continue;
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// check, if slaves have an SDO dictionary to read out.
|
// check, if slaves have an SDO dictionary to read out.
|
||||||
|
|
@ -1034,7 +1032,7 @@ void ec_fsm_master_sdo_request(ec_fsm_t *fsm /**< finite state machine */)
|
||||||
|
|
||||||
if (!ec_fsm_coe_success(&fsm->fsm_coe)) {
|
if (!ec_fsm_coe_success(&fsm->fsm_coe)) {
|
||||||
request->return_code = -1;
|
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 = ec_fsm_master_start;
|
||||||
fsm->master_state(fsm); // execute immediately
|
fsm->master_state(fsm); // execute immediately
|
||||||
return;
|
return;
|
||||||
|
|
@ -1043,7 +1041,7 @@ void ec_fsm_master_sdo_request(ec_fsm_t *fsm /**< finite state machine */)
|
||||||
// SDO dictionary fetching finished
|
// SDO dictionary fetching finished
|
||||||
|
|
||||||
request->return_code = 1;
|
request->return_code = 1;
|
||||||
wake_up_interruptible(&master->sdo_wait_queue);
|
master->sdo_seq_master++;
|
||||||
|
|
||||||
// restart master state machine.
|
// restart master state machine.
|
||||||
fsm->master_state = ec_fsm_master_start;
|
fsm->master_state = ec_fsm_master_start;
|
||||||
|
|
|
||||||
|
|
@ -58,6 +58,7 @@ void ec_master_clear(struct kobject *);
|
||||||
void ec_master_sync_io(ec_master_t *);
|
void ec_master_sync_io(ec_master_t *);
|
||||||
void ec_master_idle_run(void *);
|
void ec_master_idle_run(void *);
|
||||||
void ec_master_eoe_run(unsigned long);
|
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_show_master_attribute(struct kobject *, struct attribute *, char *);
|
||||||
ssize_t ec_store_master_attribute(struct kobject *, struct attribute *,
|
ssize_t ec_store_master_attribute(struct kobject *, struct attribute *,
|
||||||
const char *, size_t);
|
const char *, size_t);
|
||||||
|
|
@ -130,8 +131,11 @@ int ec_master_init(ec_master_t *master, /**< EtherCAT master */
|
||||||
master->idle_cycle_time_pos = 0;
|
master->idle_cycle_time_pos = 0;
|
||||||
master->eoe_cycle_time_pos = 0;
|
master->eoe_cycle_time_pos = 0;
|
||||||
master->debug_level = 0;
|
master->debug_level = 0;
|
||||||
INIT_LIST_HEAD(&master->sdo_requests);
|
init_MUTEX(&master->sdo_sem);
|
||||||
init_waitqueue_head(&master->sdo_wait_queue);
|
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
|
// create workqueue
|
||||||
if (!(master->workqueue = create_singlethread_workqueue("EtherCAT"))) {
|
if (!(master->workqueue = create_singlethread_workqueue("EtherCAT"))) {
|
||||||
|
|
@ -301,14 +305,11 @@ void ec_master_clear_slaves(ec_master_t *master)
|
||||||
|
|
||||||
void ec_master_flush_sdo_requests(ec_master_t *master)
|
void ec_master_flush_sdo_requests(ec_master_t *master)
|
||||||
{
|
{
|
||||||
ec_sdo_request_t *req, *next_req;
|
del_timer_sync(&master->sdo_timer);
|
||||||
|
complete(&master->sdo_complete);
|
||||||
list_for_each_entry_safe(req, next_req, &master->sdo_requests, queue) {
|
master->sdo_request = NULL;
|
||||||
list_del_init(&req->queue);
|
master->sdo_seq_user = 0;
|
||||||
req->return_code = -1;
|
master->sdo_seq_master = 0;
|
||||||
}
|
|
||||||
|
|
||||||
wake_up_interruptible(&master->sdo_wait_queue);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
|
@ -1004,6 +1005,7 @@ void ec_master_eoe_stop(ec_master_t *master /**< EtherCAT master */)
|
||||||
}
|
}
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Does the Ethernet-over-EtherCAT processing.
|
Does the Ethernet-over-EtherCAT processing.
|
||||||
*/
|
*/
|
||||||
|
|
@ -1066,6 +1068,25 @@ void ec_master_eoe_run(unsigned long data /**< master pointer */)
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
|
||||||
|
/**
|
||||||
|
*/
|
||||||
|
|
||||||
|
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.
|
Calculates Advanced Position Adresses.
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -44,7 +44,6 @@
|
||||||
#include <linux/list.h>
|
#include <linux/list.h>
|
||||||
#include <linux/sysfs.h>
|
#include <linux/sysfs.h>
|
||||||
#include <linux/timer.h>
|
#include <linux/timer.h>
|
||||||
#include <linux/wait.h>
|
|
||||||
#include <asm/atomic.h>
|
#include <asm/atomic.h>
|
||||||
#include <asm/semaphore.h>
|
#include <asm/semaphore.h>
|
||||||
|
|
||||||
|
|
@ -139,8 +138,12 @@ struct ec_master
|
||||||
|
|
||||||
uint8_t eeprom_write_enable; /**< allow write operations to EEPROMs */
|
uint8_t eeprom_write_enable; /**< allow write operations to EEPROMs */
|
||||||
|
|
||||||
struct list_head sdo_requests; /**< list of SDO read/write requests */
|
ec_sdo_request_t *sdo_request; /**< pointer to the current SDO request */
|
||||||
wait_queue_head_t sdo_wait_queue; /**< wait queue for SDO access */
|
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 */
|
||||||
};
|
};
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue