EoE in Free-Run mode; Finished slave configuration state machine.
This commit is contained in:
parent
c821aa3f6d
commit
4ea2816432
|
|
@ -70,17 +70,15 @@ struct net_device_stats *ec_eoedev_stats(struct net_device *);
|
|||
|
||||
/**
|
||||
EoE constructor.
|
||||
Initializes the EoE object, creates a net_device and registeres it.
|
||||
Initializes the EoE handler, creates a net_device and registeres it.
|
||||
*/
|
||||
|
||||
int ec_eoe_init(ec_eoe_t *eoe, /**< EoE object */
|
||||
ec_slave_t *slave /**< assigned slave */
|
||||
)
|
||||
int ec_eoe_init(ec_eoe_t *eoe /**< EoE handler */)
|
||||
{
|
||||
ec_eoe_t **priv;
|
||||
int result, i;
|
||||
|
||||
eoe->slave = slave;
|
||||
eoe->slave = NULL;
|
||||
eoe->state = ec_eoe_state_rx_start;
|
||||
eoe->opened = 0;
|
||||
eoe->rx_skb = NULL;
|
||||
|
|
@ -95,7 +93,7 @@ int ec_eoe_init(ec_eoe_t *eoe, /**< EoE object */
|
|||
|
||||
if (!(eoe->dev =
|
||||
alloc_netdev(sizeof(ec_eoe_t *), "eoe%d", ether_setup))) {
|
||||
EC_ERR("Unable to allocate net_device for EoE object!\n");
|
||||
EC_ERR("Unable to allocate net_device for EoE handler!\n");
|
||||
goto out_return;
|
||||
}
|
||||
|
||||
|
|
@ -145,7 +143,7 @@ int ec_eoe_init(ec_eoe_t *eoe, /**< EoE object */
|
|||
Unregisteres the net_device and frees allocated memory.
|
||||
*/
|
||||
|
||||
void ec_eoe_clear(ec_eoe_t *eoe /**< EoE object */)
|
||||
void ec_eoe_clear(ec_eoe_t *eoe /**< EoE handler */)
|
||||
{
|
||||
if (eoe->dev) {
|
||||
unregister_netdev(eoe->dev);
|
||||
|
|
@ -169,7 +167,7 @@ void ec_eoe_clear(ec_eoe_t *eoe /**< EoE object */)
|
|||
Empties the transmit queue.
|
||||
*/
|
||||
|
||||
void ec_eoe_flush(ec_eoe_t *eoe /**< EoE object */)
|
||||
void ec_eoe_flush(ec_eoe_t *eoe /**< EoE handler */)
|
||||
{
|
||||
ec_eoe_frame_t *frame, *next;
|
||||
|
||||
|
|
@ -191,7 +189,7 @@ void ec_eoe_flush(ec_eoe_t *eoe /**< EoE object */)
|
|||
Sends a frame or the next fragment.
|
||||
*/
|
||||
|
||||
int ec_eoe_send(ec_eoe_t *eoe /**< EoE object */)
|
||||
int ec_eoe_send(ec_eoe_t *eoe /**< EoE handler */)
|
||||
{
|
||||
size_t remaining_size, current_size, complete_offset;
|
||||
unsigned int last_fragment;
|
||||
|
|
@ -262,7 +260,7 @@ int ec_eoe_send(ec_eoe_t *eoe /**< EoE object */)
|
|||
Runs the EoE state machine.
|
||||
*/
|
||||
|
||||
void ec_eoe_run(ec_eoe_t *eoe /**< EoE object */)
|
||||
void ec_eoe_run(ec_eoe_t *eoe /**< EoE handler */)
|
||||
{
|
||||
if (!eoe->opened) return;
|
||||
|
||||
|
|
@ -277,22 +275,25 @@ void ec_eoe_run(ec_eoe_t *eoe /**< EoE object */)
|
|||
\return 1 if the device is "up", 0 if it is "down"
|
||||
*/
|
||||
|
||||
unsigned int ec_eoe_active(const ec_eoe_t *eoe /**< EoE object */)
|
||||
unsigned int ec_eoe_active(const ec_eoe_t *eoe /**< EoE handler */)
|
||||
{
|
||||
return eoe->opened;
|
||||
return eoe->slave && eoe->opened;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/**
|
||||
Prints EoE object information.
|
||||
Prints EoE handler information.
|
||||
*/
|
||||
|
||||
void ec_eoe_print(const ec_eoe_t *eoe /**< EoE object */)
|
||||
void ec_eoe_print(const ec_eoe_t *eoe /**< EoE handler */)
|
||||
{
|
||||
EC_INFO(" EoE slave %i\n", eoe->slave->ring_position);
|
||||
EC_INFO(" Assigned device: %s (%s)\n", eoe->dev->name,
|
||||
eoe->opened ? "opened" : "closed");
|
||||
EC_INFO(" EoE handler %s\n", eoe->dev->name);
|
||||
EC_INFO(" State: %s\n", eoe->opened ? "opened" : "closed");
|
||||
if (eoe->slave)
|
||||
EC_INFO(" Coupled to slave %i.\n", eoe->slave->ring_position);
|
||||
else
|
||||
EC_INFO(" Not coupled.\n");
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
|
|
@ -305,7 +306,7 @@ void ec_eoe_print(const ec_eoe_t *eoe /**< EoE object */)
|
|||
slave's mailbox for a new command.
|
||||
*/
|
||||
|
||||
void ec_eoe_state_rx_start(ec_eoe_t *eoe /**< EoE object */)
|
||||
void ec_eoe_state_rx_start(ec_eoe_t *eoe /**< EoE handler */)
|
||||
{
|
||||
ec_slave_mbox_prepare_check(eoe->slave);
|
||||
ec_master_queue_command(eoe->slave->master, &eoe->slave->mbox_command);
|
||||
|
|
@ -320,7 +321,7 @@ void ec_eoe_state_rx_start(ec_eoe_t *eoe /**< EoE object */)
|
|||
command, if new data is available.
|
||||
*/
|
||||
|
||||
void ec_eoe_state_rx_check(ec_eoe_t *eoe /**< EoE object */)
|
||||
void ec_eoe_state_rx_check(ec_eoe_t *eoe /**< EoE handler */)
|
||||
{
|
||||
if (eoe->slave->mbox_command.state != EC_CMD_RECEIVED) {
|
||||
eoe->stats.rx_errors++;
|
||||
|
|
@ -346,7 +347,7 @@ void ec_eoe_state_rx_check(ec_eoe_t *eoe /**< EoE object */)
|
|||
EoE command.
|
||||
*/
|
||||
|
||||
void ec_eoe_state_rx_fetch(ec_eoe_t *eoe /**< EoE object */)
|
||||
void ec_eoe_state_rx_fetch(ec_eoe_t *eoe /**< EoE handler */)
|
||||
{
|
||||
size_t rec_size, data_size;
|
||||
uint8_t *data, frame_type, last_fragment, time_appended;
|
||||
|
|
@ -486,7 +487,7 @@ void ec_eoe_state_rx_fetch(ec_eoe_t *eoe /**< EoE object */)
|
|||
sequence is started instead.
|
||||
*/
|
||||
|
||||
void ec_eoe_state_tx_start(ec_eoe_t *eoe /**< EoE object */)
|
||||
void ec_eoe_state_tx_start(ec_eoe_t *eoe /**< EoE handler */)
|
||||
{
|
||||
#if EOE_DEBUG_LEVEL > 0
|
||||
unsigned int wakeup;
|
||||
|
|
@ -546,7 +547,7 @@ void ec_eoe_state_tx_start(ec_eoe_t *eoe /**< EoE object */)
|
|||
fragment, if necessary.
|
||||
*/
|
||||
|
||||
void ec_eoe_state_tx_sent(ec_eoe_t *eoe /**< EoE object */)
|
||||
void ec_eoe_state_tx_sent(ec_eoe_t *eoe /**< EoE handler */)
|
||||
{
|
||||
if (eoe->slave->mbox_command.state != EC_CMD_RECEIVED) {
|
||||
eoe->stats.tx_errors++;
|
||||
|
|
@ -595,7 +596,12 @@ int ec_eoedev_open(struct net_device *dev /**< EoE net_device */)
|
|||
eoe->opened = 1;
|
||||
netif_start_queue(dev);
|
||||
eoe->tx_queue_active = 1;
|
||||
EC_INFO("%s (slave %i) opened.\n", dev->name, eoe->slave->ring_position);
|
||||
EC_INFO("%s opened.\n", dev->name);
|
||||
if (!eoe->slave)
|
||||
EC_WARN("device %s is not coupled to any EoE slave!\n", dev->name);
|
||||
else {
|
||||
eoe->slave->requested_state = EC_SLAVE_STATE_OP;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -612,7 +618,12 @@ int ec_eoedev_stop(struct net_device *dev /**< EoE net_device */)
|
|||
eoe->tx_queue_active = 0;
|
||||
eoe->opened = 0;
|
||||
ec_eoe_flush(eoe);
|
||||
EC_INFO("%s (slave %i) stopped.\n", dev->name, eoe->slave->ring_position);
|
||||
EC_INFO("%s stopped.\n", dev->name);
|
||||
if (!eoe->slave)
|
||||
EC_WARN("device %s is not coupled to any EoE slave!\n", dev->name);
|
||||
else {
|
||||
eoe->slave->requested_state = EC_SLAVE_STATE_INIT;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -64,7 +64,7 @@ ec_eoe_frame_t;
|
|||
typedef struct ec_eoe ec_eoe_t;
|
||||
|
||||
/**
|
||||
Ethernet-over-EtherCAT (EoE) Object.
|
||||
Ethernet-over-EtherCAT (EoE) handler.
|
||||
The master creates one of these objects for each slave that supports the
|
||||
EoE protocol.
|
||||
*/
|
||||
|
|
@ -93,7 +93,7 @@ struct ec_eoe
|
|||
|
||||
/*****************************************************************************/
|
||||
|
||||
int ec_eoe_init(ec_eoe_t *, ec_slave_t *);
|
||||
int ec_eoe_init(ec_eoe_t *);
|
||||
void ec_eoe_clear(ec_eoe_t *);
|
||||
void ec_eoe_run(ec_eoe_t *);
|
||||
unsigned int ec_eoe_active(const ec_eoe_t *);
|
||||
|
|
|
|||
871
master/fsm.c
871
master/fsm.c
File diff suppressed because it is too large
Load Diff
|
|
@ -76,6 +76,9 @@ struct ec_fsm
|
|||
void (*sii_state)(ec_fsm_t *); /**< SII state function */
|
||||
uint16_t sii_offset; /**< input: offset in SII */
|
||||
uint32_t sii_result; /**< output: read SII value (32bit) */
|
||||
|
||||
void (*change_state)(ec_fsm_t *); /**< slave state change state function */
|
||||
uint8_t change_new; /**< input: new state */
|
||||
};
|
||||
|
||||
/*****************************************************************************/
|
||||
|
|
@ -84,7 +87,6 @@ int ec_fsm_init(ec_fsm_t *, ec_master_t *);
|
|||
void ec_fsm_clear(ec_fsm_t *);
|
||||
void ec_fsm_reset(ec_fsm_t *);
|
||||
void ec_fsm_execute(ec_fsm_t *);
|
||||
int ec_fsm_idle(const ec_fsm_t *);
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
|
|
|
|||
|
|
@ -115,6 +115,7 @@
|
|||
|
||||
extern void ec_print_data(const uint8_t *, size_t);
|
||||
extern void ec_print_data_diff(const uint8_t *, const uint8_t *, size_t);
|
||||
extern void ec_print_states(uint8_t);
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
|
|
|
|||
237
master/master.c
237
master/master.c
|
|
@ -56,7 +56,7 @@
|
|||
/*****************************************************************************/
|
||||
|
||||
void ec_master_freerun(void *);
|
||||
void ec_master_run_eoe(unsigned long);
|
||||
void ec_master_eoe_run(unsigned long);
|
||||
ssize_t ec_show_master_attribute(struct kobject *, struct attribute *, char *);
|
||||
void ec_master_process_watch_command(ec_master_t *);
|
||||
|
||||
|
|
@ -94,30 +94,51 @@ static struct kobj_type ktype_ec_master = {
|
|||
*/
|
||||
|
||||
int ec_master_init(ec_master_t *master, /**< EtherCAT master */
|
||||
unsigned int index /**< master index */
|
||||
unsigned int index, /**< master index */
|
||||
unsigned int eoe_devices /**< number of EoE devices */
|
||||
)
|
||||
{
|
||||
ec_eoe_t *eoe, *next_eoe;
|
||||
unsigned int i;
|
||||
|
||||
EC_INFO("Initializing master %i.\n", index);
|
||||
|
||||
if (!(master->workqueue = create_singlethread_workqueue("EoE"))) {
|
||||
EC_ERR("Failed to create master workqueue.\n");
|
||||
goto out_return;
|
||||
}
|
||||
|
||||
if (ec_fsm_init(&master->fsm, master)) goto out_free_wq;
|
||||
|
||||
master->index = index;
|
||||
master->device = NULL;
|
||||
master->reserved = 0;
|
||||
INIT_LIST_HEAD(&master->slaves);
|
||||
INIT_LIST_HEAD(&master->command_queue);
|
||||
INIT_LIST_HEAD(&master->domains);
|
||||
INIT_LIST_HEAD(&master->eoe_slaves);
|
||||
INIT_LIST_HEAD(&master->eoe_handlers);
|
||||
ec_command_init(&master->simple_command);
|
||||
INIT_WORK(&master->freerun_work, ec_master_freerun, (void *) master);
|
||||
init_timer(&master->eoe_timer);
|
||||
master->eoe_timer.function = ec_master_run_eoe;
|
||||
master->eoe_timer.function = ec_master_eoe_run;
|
||||
master->eoe_timer.data = (unsigned long) master;
|
||||
master->internal_lock = SPIN_LOCK_UNLOCKED;
|
||||
master->eoe_running = 0;
|
||||
|
||||
// create workqueue
|
||||
if (!(master->workqueue = create_singlethread_workqueue("EtherCAT"))) {
|
||||
EC_ERR("Failed to create master workqueue.\n");
|
||||
goto out_return;
|
||||
}
|
||||
|
||||
// create EoE handlers
|
||||
for (i = 0; i < eoe_devices; i++) {
|
||||
if (!(eoe = (ec_eoe_t *) kmalloc(sizeof(ec_eoe_t), GFP_KERNEL))) {
|
||||
EC_ERR("Failed to allocate EoE-Object.\n");
|
||||
goto out_clear_eoe;
|
||||
}
|
||||
if (ec_eoe_init(eoe)) {
|
||||
kfree(eoe);
|
||||
goto out_clear_eoe;
|
||||
}
|
||||
list_add_tail(&eoe->list, &master->eoe_handlers);
|
||||
}
|
||||
|
||||
// create state machine object
|
||||
if (ec_fsm_init(&master->fsm, master)) goto out_clear_eoe;
|
||||
|
||||
// init kobject and add it to the hierarchy
|
||||
memset(&master->kobj, 0x00, sizeof(struct kobject));
|
||||
|
|
@ -132,7 +153,12 @@ int ec_master_init(ec_master_t *master, /**< EtherCAT master */
|
|||
ec_master_reset(master);
|
||||
return 0;
|
||||
|
||||
out_free_wq:
|
||||
out_clear_eoe:
|
||||
list_for_each_entry_safe(eoe, next_eoe, &master->eoe_handlers, list) {
|
||||
list_del(&eoe->list);
|
||||
ec_eoe_clear(eoe);
|
||||
kfree(eoe);
|
||||
}
|
||||
destroy_workqueue(master->workqueue);
|
||||
out_return:
|
||||
return -1;
|
||||
|
|
@ -149,6 +175,7 @@ int ec_master_init(ec_master_t *master, /**< EtherCAT master */
|
|||
void ec_master_clear(struct kobject *kobj /**< kobject of the master */)
|
||||
{
|
||||
ec_master_t *master = container_of(kobj, ec_master_t, kobj);
|
||||
ec_eoe_t *eoe, *next_eoe;
|
||||
|
||||
EC_INFO("Clearing master %i...\n", master->index);
|
||||
|
||||
|
|
@ -157,6 +184,13 @@ void ec_master_clear(struct kobject *kobj /**< kobject of the master */)
|
|||
ec_command_clear(&master->simple_command);
|
||||
destroy_workqueue(master->workqueue);
|
||||
|
||||
// clear EoE objects
|
||||
list_for_each_entry_safe(eoe, next_eoe, &master->eoe_handlers, list) {
|
||||
list_del(&eoe->list);
|
||||
ec_eoe_clear(eoe);
|
||||
kfree(eoe);
|
||||
}
|
||||
|
||||
if (master->device) {
|
||||
ec_device_clear(master->device);
|
||||
kfree(master->device);
|
||||
|
|
@ -177,14 +211,9 @@ void ec_master_reset(ec_master_t *master /**< EtherCAT master */)
|
|||
{
|
||||
ec_command_t *command, *next_c;
|
||||
ec_domain_t *domain, *next_d;
|
||||
ec_eoe_t *eoe, *next_eoe;
|
||||
|
||||
// stop EoE processing
|
||||
del_timer_sync(&master->eoe_timer);
|
||||
|
||||
// stop free-run mode
|
||||
ec_master_eoe_stop(master);
|
||||
ec_master_freerun_stop(master);
|
||||
|
||||
ec_master_clear_slaves(master);
|
||||
|
||||
// empty command queue
|
||||
|
|
@ -200,13 +229,6 @@ void ec_master_reset(ec_master_t *master /**< EtherCAT master */)
|
|||
kobject_put(&domain->kobj);
|
||||
}
|
||||
|
||||
// clear EoE objects
|
||||
list_for_each_entry_safe(eoe, next_eoe, &master->eoe_slaves, list) {
|
||||
list_del(&eoe->list);
|
||||
ec_eoe_clear(eoe);
|
||||
kfree(eoe);
|
||||
}
|
||||
|
||||
master->command_index = 0;
|
||||
master->debug_level = 0;
|
||||
master->timeout = 500; // 500us
|
||||
|
|
@ -674,6 +696,8 @@ void ec_master_freerun_stop(ec_master_t *master /**< EtherCAT master */)
|
|||
{
|
||||
if (master->mode != EC_MASTER_MODE_FREERUN) return;
|
||||
|
||||
ec_master_eoe_stop(master);
|
||||
|
||||
EC_INFO("Stopping Free-Run mode.\n");
|
||||
|
||||
if (!cancel_delayed_work(&master->freerun_work)) {
|
||||
|
|
@ -693,18 +717,21 @@ void ec_master_freerun_stop(ec_master_t *master /**< EtherCAT master */)
|
|||
void ec_master_freerun(void *data /**< master pointer */)
|
||||
{
|
||||
ec_master_t *master = (ec_master_t *) data;
|
||||
unsigned long delay;
|
||||
|
||||
// aquire master lock
|
||||
spin_lock_bh(&master->internal_lock);
|
||||
|
||||
ecrt_master_async_receive(master);
|
||||
|
||||
// execute freerun state machine
|
||||
// execute master state machine
|
||||
ec_fsm_execute(&master->fsm);
|
||||
|
||||
ecrt_master_async_send(master);
|
||||
|
||||
delay = HZ / 100;
|
||||
if (ec_fsm_idle(&master->fsm)) delay = HZ;
|
||||
queue_delayed_work(master->workqueue, &master->freerun_work, delay);
|
||||
// release master lock
|
||||
spin_unlock_bh(&master->internal_lock);
|
||||
|
||||
queue_delayed_work(master->workqueue, &master->freerun_work, HZ / 100);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
|
@ -798,32 +825,131 @@ ssize_t ec_show_master_attribute(struct kobject *kobj, /**< kobject */
|
|||
|
||||
/*****************************************************************************/
|
||||
|
||||
/**
|
||||
Starts Ethernet-over-EtherCAT processing for all EoE-capable slaves.
|
||||
*/
|
||||
|
||||
void ec_master_eoe_start(ec_master_t *master /**< EtherCAT master */)
|
||||
{
|
||||
ec_eoe_t *eoe;
|
||||
ec_slave_t *slave;
|
||||
unsigned int coupled, found;
|
||||
|
||||
if (master->eoe_running) return;
|
||||
|
||||
// decouple all EoE handlers
|
||||
list_for_each_entry(eoe, &master->eoe_handlers, list)
|
||||
eoe->slave = NULL;
|
||||
coupled = 0;
|
||||
|
||||
// couple a free EoE handler to every EoE-capable slave
|
||||
list_for_each_entry(slave, &master->slaves, list) {
|
||||
if (!(slave->sii_mailbox_protocols & EC_MBOX_EOE)) continue;
|
||||
|
||||
found = 0;
|
||||
list_for_each_entry(eoe, &master->eoe_handlers, list) {
|
||||
if (eoe->slave) continue;
|
||||
eoe->slave = slave;
|
||||
found = 1;
|
||||
coupled++;
|
||||
EC_INFO("Coupling device %s to slave %i.\n",
|
||||
eoe->dev->name, slave->ring_position);
|
||||
if (eoe->opened)
|
||||
slave->requested_state = EC_SLAVE_STATE_OP;
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
EC_WARN("No EoE handler for slave %i!\n", slave->ring_position);
|
||||
slave->requested_state = EC_SLAVE_STATE_INIT;
|
||||
}
|
||||
}
|
||||
|
||||
if (!coupled) {
|
||||
EC_INFO("No EoE handlers coupled.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
EC_INFO("Starting EoE processing.\n");
|
||||
master->eoe_running = 1;
|
||||
|
||||
// start EoE processing
|
||||
master->eoe_timer.expires = jiffies + 10;
|
||||
add_timer(&master->eoe_timer);
|
||||
return;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/**
|
||||
Stops the Ethernet-over-EtherCAT processing.
|
||||
*/
|
||||
|
||||
void ec_master_eoe_stop(ec_master_t *master /**< EtherCAT master */)
|
||||
{
|
||||
ec_eoe_t *eoe;
|
||||
|
||||
if (!master->eoe_running) return;
|
||||
|
||||
EC_INFO("Stopping EoE processing.\n");
|
||||
|
||||
del_timer_sync(&master->eoe_timer);
|
||||
|
||||
// decouple all EoE handlers
|
||||
list_for_each_entry(eoe, &master->eoe_handlers, list) {
|
||||
if (eoe->slave) {
|
||||
eoe->slave->requested_state = EC_SLAVE_STATE_INIT;
|
||||
eoe->slave = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
master->eoe_running = 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/**
|
||||
Does the Ethernet-over-EtherCAT processing.
|
||||
*/
|
||||
|
||||
void ec_master_run_eoe(unsigned long data /**< master pointer */)
|
||||
void ec_master_eoe_run(unsigned long data /**< master pointer */)
|
||||
{
|
||||
ec_master_t *master = (ec_master_t *) data;
|
||||
ec_eoe_t *eoe;
|
||||
unsigned int active = 0;
|
||||
|
||||
list_for_each_entry(eoe, &master->eoe_slaves, list) {
|
||||
list_for_each_entry(eoe, &master->eoe_handlers, list) {
|
||||
if (ec_eoe_active(eoe)) active++;
|
||||
}
|
||||
if (!active) goto queue_timer;
|
||||
|
||||
// request_cb must return 0, if the lock has been aquired!
|
||||
if (active && !master->request_cb(master->cb_data))
|
||||
{
|
||||
ecrt_master_async_receive(master);
|
||||
list_for_each_entry(eoe, &master->eoe_slaves, list) {
|
||||
ec_eoe_run(eoe);
|
||||
}
|
||||
ecrt_master_async_send(master);
|
||||
// aquire master lock...
|
||||
if (master->mode == EC_MASTER_MODE_RUNNING) {
|
||||
// request_cb must return 0, if the lock has been aquired!
|
||||
if (master->request_cb(master->cb_data))
|
||||
goto queue_timer;
|
||||
}
|
||||
else if (master->mode == EC_MASTER_MODE_FREERUN) {
|
||||
spin_lock(&master->internal_lock);
|
||||
}
|
||||
else
|
||||
goto queue_timer;
|
||||
|
||||
// actual EoE stuff
|
||||
ecrt_master_async_receive(master);
|
||||
list_for_each_entry(eoe, &master->eoe_handlers, list) {
|
||||
ec_eoe_run(eoe);
|
||||
}
|
||||
ecrt_master_async_send(master);
|
||||
|
||||
// release lock...
|
||||
if (master->mode == EC_MASTER_MODE_RUNNING) {
|
||||
master->release_cb(master->cb_data);
|
||||
}
|
||||
else if (master->mode == EC_MASTER_MODE_FREERUN) {
|
||||
spin_unlock(&master->internal_lock);
|
||||
}
|
||||
|
||||
queue_timer:
|
||||
master->eoe_timer.expires += HZ / EC_EOE_FREQUENCY;
|
||||
add_timer(&master->eoe_timer);
|
||||
}
|
||||
|
|
@ -1404,37 +1530,12 @@ void ecrt_master_callbacks(ec_master_t *master, /**< EtherCAT master */
|
|||
|
||||
int ecrt_master_start_eoe(ec_master_t *master /**< EtherCAT master */)
|
||||
{
|
||||
ec_eoe_t *eoe;
|
||||
ec_slave_t *slave;
|
||||
|
||||
if (!master->request_cb || !master->release_cb) {
|
||||
EC_ERR("EoE requires master callbacks to be set!\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
list_for_each_entry(slave, &master->slaves, list) {
|
||||
// does the slave support EoE?
|
||||
if (!(slave->sii_mailbox_protocols & EC_MBOX_EOE)) continue;
|
||||
|
||||
if (!(eoe = (ec_eoe_t *) kmalloc(sizeof(ec_eoe_t), GFP_KERNEL))) {
|
||||
EC_ERR("Failed to allocate EoE-Object.\n");
|
||||
return -1;
|
||||
}
|
||||
if (ec_eoe_init(eoe, slave)) {
|
||||
kfree(eoe);
|
||||
return -1;
|
||||
}
|
||||
list_add_tail(&eoe->list, &master->eoe_slaves);
|
||||
}
|
||||
|
||||
if (list_empty(&master->eoe_slaves)) {
|
||||
EC_WARN("start_eoe: no EoE-capable slaves present.\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
// start EoE processing
|
||||
master->eoe_timer.expires = jiffies + 10;
|
||||
add_timer(&master->eoe_timer);
|
||||
ec_master_eoe_start(master);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -1482,9 +1583,9 @@ void ecrt_master_print(const ec_master_t *master, /**< EtherCAT master */
|
|||
list_for_each_entry(slave, &master->slaves, list)
|
||||
ec_slave_print(slave, verbosity);
|
||||
}
|
||||
if (!list_empty(&master->eoe_slaves)) {
|
||||
if (!list_empty(&master->eoe_handlers)) {
|
||||
EC_INFO("Ethernet-over-EtherCAT (EoE) objects:\n");
|
||||
list_for_each_entry(eoe, &master->eoe_slaves, list) {
|
||||
list_for_each_entry(eoe, &master->eoe_handlers, list) {
|
||||
ec_eoe_print(eoe);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -116,7 +116,9 @@ struct ec_master
|
|||
ec_master_mode_t mode; /**< master mode */
|
||||
|
||||
struct timer_list eoe_timer; /** EoE timer object */
|
||||
struct list_head eoe_slaves; /**< Ethernet-over-EtherCAT slaves */
|
||||
unsigned int eoe_running; /**< non-zero, if EoE processing is active. */
|
||||
struct list_head eoe_handlers; /**< Ethernet-over-EtherCAT handlers */
|
||||
spinlock_t internal_lock; /**< spinlock used in freerun mode */
|
||||
int (*request_cb)(void *); /**< lock request callback */
|
||||
void (*release_cb)(void *); /**< lock release callback */
|
||||
void *cb_data; /**< data parameter of locking callbacks */
|
||||
|
|
@ -125,7 +127,7 @@ struct ec_master
|
|||
/*****************************************************************************/
|
||||
|
||||
// master creation and deletion
|
||||
int ec_master_init(ec_master_t *, unsigned int);
|
||||
int ec_master_init(ec_master_t *, unsigned int, unsigned int);
|
||||
void ec_master_clear(struct kobject *);
|
||||
void ec_master_reset(ec_master_t *);
|
||||
|
||||
|
|
@ -133,6 +135,10 @@ void ec_master_reset(ec_master_t *);
|
|||
void ec_master_freerun_start(ec_master_t *);
|
||||
void ec_master_freerun_stop(ec_master_t *);
|
||||
|
||||
// EoE
|
||||
void ec_master_eoe_start(ec_master_t *);
|
||||
void ec_master_eoe_stop(ec_master_t *);
|
||||
|
||||
// IO
|
||||
void ec_master_receive(ec_master_t *, const uint8_t *, size_t);
|
||||
void ec_master_queue_command(ec_master_t *, ec_command_t *);
|
||||
|
|
@ -143,6 +149,9 @@ int ec_master_bus_scan(ec_master_t *);
|
|||
|
||||
// misc.
|
||||
void ec_master_clear_slaves(ec_master_t *);
|
||||
void ec_sync_config(const ec_sync_t *, uint8_t *);
|
||||
void ec_eeprom_sync_config(const ec_eeprom_sync_t *, uint8_t *);
|
||||
void ec_fmmu_config(const ec_fmmu_t *, uint8_t *);
|
||||
void ec_master_output_stats(ec_master_t *);
|
||||
|
||||
/*****************************************************************************/
|
||||
|
|
|
|||
|
|
@ -67,19 +67,22 @@ void __exit ec_cleanup_module(void);
|
|||
/*****************************************************************************/
|
||||
|
||||
static int ec_master_count = 1;
|
||||
static int ec_eoe_devices = 0;
|
||||
static struct list_head ec_masters;
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/** \cond */
|
||||
|
||||
MODULE_AUTHOR ("Florian Pose <fp@igh-essen.com>");
|
||||
MODULE_DESCRIPTION ("EtherCAT master driver module");
|
||||
module_param(ec_master_count, int, S_IRUGO);
|
||||
module_param(ec_eoe_devices, int, S_IRUGO);
|
||||
|
||||
MODULE_AUTHOR("Florian Pose <fp@igh-essen.com>");
|
||||
MODULE_DESCRIPTION("EtherCAT master driver module");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_VERSION(COMPILE_INFO);
|
||||
|
||||
module_param(ec_master_count, int, 1);
|
||||
MODULE_PARM_DESC(ec_master_count, "number of EtherCAT masters to initialize");
|
||||
MODULE_PARM_DESC(ec_eoe_devices, "number of EoE devices per master");
|
||||
|
||||
/** \endcond */
|
||||
|
||||
|
|
@ -114,7 +117,7 @@ int __init ec_init_module(void)
|
|||
goto out_free;
|
||||
}
|
||||
|
||||
if (ec_master_init(master, i)) // kobject_put is done inside...
|
||||
if (ec_master_init(master, i, ec_eoe_devices))
|
||||
goto out_free;
|
||||
|
||||
if (kobject_add(&master->kobj)) {
|
||||
|
|
@ -228,6 +231,41 @@ void ec_print_data_diff(const uint8_t *d1, /**< first data */
|
|||
printk("\n");
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/**
|
||||
Prints slave states in clear text.
|
||||
*/
|
||||
|
||||
void ec_print_states(const uint8_t states /**< slave states */)
|
||||
{
|
||||
unsigned int first = 1;
|
||||
|
||||
if (!states) {
|
||||
printk("(unknown)");
|
||||
return;
|
||||
}
|
||||
|
||||
if (states & EC_SLAVE_STATE_INIT) {
|
||||
printk("INIT");
|
||||
first = 0;
|
||||
}
|
||||
if (states & EC_SLAVE_STATE_PREOP) {
|
||||
if (!first) printk(", ");
|
||||
printk("PREOP");
|
||||
first = 0;
|
||||
}
|
||||
if (states & EC_SLAVE_STATE_SAVEOP) {
|
||||
if (!first) printk(", ");
|
||||
printk("SAVEOP");
|
||||
first = 0;
|
||||
}
|
||||
if (states & EC_SLAVE_STATE_OP) {
|
||||
if (!first) printk(", ");
|
||||
printk("OP");
|
||||
}
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* Device interface
|
||||
*****************************************************************************/
|
||||
|
|
|
|||
|
|
@ -48,6 +48,10 @@
|
|||
|
||||
/*****************************************************************************/
|
||||
|
||||
extern const ec_code_msg_t al_status_messages[];
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
int ec_slave_fetch_categories(ec_slave_t *);
|
||||
ssize_t ec_show_slave_attribute(struct kobject *, struct attribute *, char *);
|
||||
|
||||
|
|
@ -89,10 +93,6 @@ static struct kobj_type ktype_ec_slave = {
|
|||
|
||||
/*****************************************************************************/
|
||||
|
||||
const ec_code_msg_t al_status_messages[];
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/**
|
||||
Slave constructor.
|
||||
\return 0 in case of success, else < 0
|
||||
|
|
@ -144,6 +144,9 @@ int ec_slave_init(ec_slave_t *slave, /**< EtherCAT slave */
|
|||
slave->eeprom_name = NULL;
|
||||
slave->eeprom_group = NULL;
|
||||
slave->eeprom_desc = NULL;
|
||||
slave->requested_state = EC_SLAVE_STATE_UNKNOWN;
|
||||
slave->current_state = EC_SLAVE_STATE_UNKNOWN;
|
||||
slave->state_error = 0;
|
||||
|
||||
ec_command_init(&slave->mbox_command);
|
||||
|
||||
|
|
@ -1261,32 +1264,6 @@ ssize_t ec_show_slave_attribute(struct kobject *kobj, /**< slave's kobject */
|
|||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/**
|
||||
Application layer status messages.
|
||||
*/
|
||||
|
||||
const ec_code_msg_t al_status_messages[] = {
|
||||
{0x0001, "Unspecified error"},
|
||||
{0x0011, "Invalud requested state change"},
|
||||
{0x0012, "Unknown requested state"},
|
||||
{0x0013, "Bootstrap not supported"},
|
||||
{0x0014, "No valid firmware"},
|
||||
{0x0015, "Invalid mailbox configuration"},
|
||||
{0x0016, "Invalid mailbox configuration"},
|
||||
{0x0017, "Invalid sync manager configuration"},
|
||||
{0x0018, "No valid inputs available"},
|
||||
{0x0019, "No valid outputs"},
|
||||
{0x001A, "Synchronisation error"},
|
||||
{0x001B, "Sync manager watchdog"},
|
||||
{0x0020, "Slave needs cold start"},
|
||||
{0x0021, "Slave needs INIT"},
|
||||
{0x0022, "Slave needs PREOP"},
|
||||
{0x0023, "Slave needs SAVEOP"},
|
||||
{}
|
||||
};
|
||||
|
||||
/******************************************************************************
|
||||
* Realtime interface
|
||||
*****************************************************************************/
|
||||
|
|
|
|||
|
|
@ -272,6 +272,10 @@ struct ec_slave
|
|||
struct list_head sdo_dictionary; /**< SDO directory list */
|
||||
|
||||
ec_command_t mbox_command; /**< mailbox command */
|
||||
|
||||
ec_slave_state_t requested_state; /**< requested slave state */
|
||||
ec_slave_state_t current_state; /**< current slave state */
|
||||
unsigned int state_error; /**< a state error has happened */
|
||||
};
|
||||
|
||||
/*****************************************************************************/
|
||||
|
|
|
|||
|
|
@ -73,6 +73,10 @@ case "$1" in
|
|||
rc_exit
|
||||
fi
|
||||
|
||||
if [ ! $EOE_DEVICES ]; then
|
||||
EOE_DEVICES=0
|
||||
fi
|
||||
|
||||
for mod in 8139too 8139cp; do
|
||||
if lsmod | grep "^$mod " > /dev/null; then
|
||||
if ! rmmod $mod; then
|
||||
|
|
@ -83,7 +87,17 @@ case "$1" in
|
|||
fi
|
||||
done
|
||||
|
||||
modprobe ec_8139too ec_device_index=$DEVICE_INDEX
|
||||
if ! modprobe ec_master ec_eoe_devices=$EOE_DEVICES; then
|
||||
/bin/false
|
||||
rc_status -v
|
||||
rc_exit
|
||||
fi
|
||||
|
||||
if ! modprobe ec_8139too ec_device_index=$DEVICE_INDEX; then
|
||||
/bin/false
|
||||
rc_status -v
|
||||
rc_exit
|
||||
fi
|
||||
|
||||
rc_status -v
|
||||
;;
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@
|
|||
#DEVICE_INDEX=99
|
||||
|
||||
#
|
||||
# Number of Ethernet-over-EtherCAT devices the master shall create
|
||||
# Number of Ethernet-over-EtherCAT devices every master shall create
|
||||
# on startup. Default is 0.
|
||||
#
|
||||
#EOE_DEVICES=0
|
||||
|
|
|
|||
Loading…
Reference in New Issue