# HG changeset patch # User Florian Pose # Date 1147445304 0 # Node ID 34d7ce41e9db4bf1213c34427b571e19d93c1b71 # Parent f973808540a679af701e0f2513492aa91e87440e Started freerun state machine development. diff -r f973808540a6 -r 34d7ce41e9db master/master.c --- 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; } /*****************************************************************************/ diff -r f973808540a6 -r 34d7ce41e9db master/master.h --- 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 };