Started freerun state machine development.
--- a/master/master.c Fri May 12 12:40:45 2006 +0000
+++ b/master/master.c Fri May 12 14:48:24 2006 +0000
@@ -45,7 +45,7 @@
/*****************************************************************************/
-void ec_master_freerun(unsigned long);
+void ec_master_freerun(void *);
#ifdef EOE_TIMER
void ec_master_run_eoe(unsigned long);
#else
@@ -54,6 +54,11 @@
ssize_t ec_show_master_attribute(struct kobject *, struct attribute *, char *);
void ec_master_process_watch_command(ec_master_t *);
+// state functions
+void ec_master_state_start(ec_master_t *);
+void ec_master_state_slave(ec_master_t *);
+void ec_master_state_finished(ec_master_t *);
+
/*****************************************************************************/
/** \cond */
@@ -105,10 +110,13 @@
ec_command_init(&master->simple_command);
ec_command_init(&master->watch_command);
- // init freerun timer
- init_timer(&master->freerun_timer);
- master->freerun_timer.function = ec_master_freerun;
- master->freerun_timer.data = (unsigned long) master;
+ if (!(master->workqueue = create_singlethread_workqueue("EoE"))) {
+ EC_ERR("Failed to create master workqueue.\n");
+ goto out_return;
+ }
+
+ // init freerun work
+ INIT_WORK(&master->freerun_work, ec_master_freerun, (void *) master);
// init eoe timer
#ifdef EOE_TIMER
@@ -116,10 +124,6 @@
master->eoe_timer.function = ec_master_run_eoe;
master->eoe_timer.data = (unsigned long) master;
#else
- if (!(master->eoe_workqueue = create_singlethread_workqueue("EoE"))) {
- EC_ERR("Failed to create EoE workqueue.\n");
- goto out_return;
- }
INIT_WORK(&master->eoe_work, ec_master_run_eoe, (void *) master);
#endif
@@ -137,9 +141,7 @@
out_kobj_put:
kobject_put(&master->kobj);
-#ifndef EOE_TIMER
out_return:
-#endif
return -1;
}
@@ -167,9 +169,7 @@
ec_command_clear(&master->simple_command);
ec_command_clear(&master->watch_command);
-#ifndef EOE_TIMER
- if (master->eoe_workqueue) destroy_workqueue(master->eoe_workqueue);
-#endif
+ destroy_workqueue(master->workqueue);
EC_INFO("Master %i cleared.\n", master->index);
}
@@ -193,10 +193,8 @@
#ifdef EOE_TIMER
del_timer_sync(&master->eoe_timer);
#else
- if (master->eoe_workqueue) {
- if (!cancel_delayed_work(&master->eoe_work)) {
- flush_workqueue(master->eoe_workqueue);
- }
+ if (!cancel_delayed_work(&master->eoe_work)) {
+ flush_workqueue(master->eoe_workqueue);
}
#endif
@@ -678,10 +676,11 @@
}
}
- ecrt_master_prepare_async_io(master);
-
- master->freerun_timer.expires = jiffies + 10;
- add_timer(&master->freerun_timer);
+ master->freerun_state = ec_master_state_start;
+
+ ecrt_master_prepare_async_io(master); /** \todo necessary? */
+
+ queue_delayed_work(master->workqueue, &master->freerun_work, HZ);
}
/*****************************************************************************/
@@ -692,11 +691,23 @@
void ec_master_freerun_stop(ec_master_t *master /**< EtherCAT master */)
{
+ ec_slave_t *slave, *next_slave;
+
if (master->mode != EC_MASTER_MODE_FREERUN) return;
EC_INFO("Stopping Free-Run mode.\n");
- del_timer_sync(&master->freerun_timer);
+ if (!cancel_delayed_work(&master->freerun_work)) {
+ flush_workqueue(master->workqueue);
+ }
+
+ // remove slaves
+ list_for_each_entry_safe(slave, next_slave, &master->slaves, list) {
+ list_del(&slave->list);
+ kobject_del(&slave->kobj);
+ kobject_put(&slave->kobj);
+ }
+
master->mode = EC_MASTER_MODE_IDLE;
}
@@ -706,7 +717,7 @@
Free-Run mode function.
*/
-void ec_master_freerun(unsigned long data /**< private timer data = master */)
+void ec_master_freerun(void *data /**< master pointer */)
{
ec_master_t *master = (ec_master_t *) data;
@@ -714,14 +725,101 @@
// watchdog command
ec_master_process_watch_command(master);
+
+ if (master->watch_command.working_counter != master->slave_count) {
+ master->slave_count = master->watch_command.working_counter;
+ EC_INFO("Freerun: Topology change detected.\n");
+ // reset freerun state machine
+ master->freerun_state = ec_master_state_start;
+ }
+
ec_master_queue_command(master, &master->watch_command);
- master->slave_count = master->watch_command.working_counter;
+ // execute freerun state machine
+ master->freerun_state(master);
ecrt_master_async_send(master);
- master->freerun_timer.expires += HZ;
- add_timer(&master->freerun_timer);
+ queue_delayed_work(master->workqueue, &master->freerun_work, HZ);
+}
+
+/*****************************************************************************/
+
+/**
+ Free-Run state: Start.
+ Processes new slave count.
+*/
+
+void ec_master_state_start(ec_master_t *master /**< EtherCAT master*/)
+{
+ ec_slave_t *slave, *next_slave;
+ unsigned int i;
+
+ // remove slaves
+ list_for_each_entry_safe(slave, next_slave, &master->slaves, list) {
+ list_del(&slave->list);
+ kobject_del(&slave->kobj);
+ kobject_put(&slave->kobj);
+ }
+
+ if (!master->slave_count) {
+ // no slaves present -> finish state machine.
+ master->freerun_state = ec_master_state_finished;
+ EC_INFO("Freerun: No slaves found.\n");
+ return;
+ }
+
+ // init slaves
+ for (i = 0; i < master->slave_count; i++) {
+ if (!(slave = (ec_slave_t *) kmalloc(sizeof(ec_slave_t),
+ GFP_KERNEL))) {
+ EC_ERR("Failed to allocate slave %i!\n", i);
+ master->freerun_state = ec_master_state_finished;
+ return;
+ }
+
+ if (ec_slave_init(slave, master, i, i + 1)) {
+ master->freerun_state = ec_master_state_finished;
+ return;
+ }
+
+ if (kobject_add(&slave->kobj)) {
+ EC_ERR("Failed to add kobject.\n");
+ kobject_put(&slave->kobj); // free
+ master->freerun_state = ec_master_state_finished;
+ return;
+ }
+
+ list_add_tail(&slave->list, &master->slaves);
+ }
+
+ // begin scanning of slaves
+ master->freerun_slave = list_entry(master->slaves.next, ec_slave_t, list);
+ master->freerun_state = ec_master_state_slave;
+}
+
+/*****************************************************************************/
+
+/**
+ Free-Run state: Get Slave.
+ Executes the sub-statemachine of a slave.
+*/
+
+void ec_master_state_slave(ec_master_t *master /**< EtherCAT master*/)
+{
+ master->freerun_state = ec_master_state_finished;
+}
+
+/*****************************************************************************/
+
+/**
+ Free-Run state: Finished.
+ End state of the state machine. Does nothing.
+*/
+
+void ec_master_state_finished(ec_master_t *master /**< EtherCAT master*/)
+{
+ return;
}
/*****************************************************************************/
--- a/master/master.h Fri May 12 12:40:45 2006 +0000
+++ b/master/master.h Fri May 12 14:48:24 2006 +0000
@@ -102,7 +102,10 @@
unsigned int timeout; /**< timeout in synchronous IO */
struct list_head eoe_slaves; /**< Ethernet-over-EtherCAT slaves */
unsigned int reserved; /**< true, if the master is reserved for RT */
- struct timer_list freerun_timer; /**< timer object for free run mode */
+ struct workqueue_struct *workqueue; /**< master workqueue */
+ struct work_struct freerun_work; /**< free run work object */
+ void (*freerun_state)(ec_master_t *); /**< freerun state function */
+ ec_slave_t *freerun_slave; /**< current slave in bus scan */
ec_master_mode_t mode; /**< master mode */
int (*request_cb)(void *); /**< lock request callback */
void (*release_cb)(void *); /**< lock release callback */
@@ -110,7 +113,6 @@
#ifdef EOE_TIMER
struct timer_list eoe_timer; /** EoE timer object */
#else
- struct workqueue_struct *eoe_workqueue; /**< EoE workqueue */
struct work_struct eoe_work; /**< work structure for EoE workqueue */
#endif
};