--- a/examples/mini/mini.c Wed May 10 11:33:10 2006 +0000
+++ b/examples/mini/mini.c Wed May 10 11:51:05 2006 +0000
@@ -108,21 +108,15 @@
int request_lock(void *data)
{
- unsigned int tries = 0;
- while (1) {
- if (spin_trylock(&master_lock)) {
- if (tries) printk(KERN_INFO "lock: %i tries needed.\n", tries);
- return 1;
- }
- tries++;
- }
+ spin_lock_bh(&master_lock);
+ return 0; // access allowed
}
/*****************************************************************************/
void release_lock(void *data)
{
- spin_unlock(&master_lock);
+ spin_unlock_bh(&master_lock);
}
/*****************************************************************************/
--- a/master/master.c Wed May 10 11:33:10 2006 +0000
+++ b/master/master.c Wed May 10 11:51:05 2006 +0000
@@ -46,7 +46,11 @@
/*****************************************************************************/
void ec_master_freerun(unsigned long);
+#ifdef EOE_TIMER
void ec_master_run_eoe(unsigned long);
+#else
+void ec_master_run_eoe(void *);
+#endif
ssize_t ec_show_master_attribute(struct kobject *, struct attribute *, char *);
void ec_master_process_watch_command(ec_master_t *);
@@ -98,31 +102,45 @@
INIT_LIST_HEAD(&master->domains);
INIT_LIST_HEAD(&master->eoe_slaves);
+ 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;
+
+ // init eoe timer
+#ifdef EOE_TIMER
+ init_timer(&master->eoe_timer);
+ 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
+
// init kobject and add it to the hierarchy
memset(&master->kobj, 0x00, sizeof(struct kobject));
kobject_init(&master->kobj);
master->kobj.ktype = &ktype_ec_master;
if (kobject_set_name(&master->kobj, "ethercat%i", index)) {
EC_ERR("Failed to set kobj name.\n");
- kobject_put(&master->kobj);
- return -1;
- }
-
- // init freerun timer
- init_timer(&master->freerun_timer);
- master->freerun_timer.function = ec_master_freerun;
- master->freerun_timer.data = (unsigned long) master;
-
- // init eoe timer
- init_timer(&master->eoe_timer);
- master->eoe_timer.function = ec_master_run_eoe;
- master->eoe_timer.data = (unsigned long) master;
-
- ec_command_init(&master->simple_command);
- ec_command_init(&master->watch_command);
+ goto out_kobj_put;
+ }
ec_master_reset(master);
return 0;
+
+ out_kobj_put:
+ kobject_put(&master->kobj);
+#ifndef EOE_TIMER
+ out_return:
+#endif
+ return -1;
}
/*****************************************************************************/
@@ -139,9 +157,6 @@
EC_INFO("Clearing master %i...\n", master->index);
- del_timer_sync(&master->eoe_timer);
- del_timer_sync(&master->freerun_timer);
-
ec_master_reset(master);
if (master->device) {
@@ -152,6 +167,10 @@
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
+
EC_INFO("Master %i cleared.\n", master->index);
}
@@ -171,7 +190,15 @@
ec_eoe_t *eoe, *next_eoe;
// stop EoE processing
+#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);
+ }
+ }
+#endif
// stop free-run mode
ec_master_freerun_stop(master);
@@ -839,12 +866,17 @@
Does the Ethernet-over-EtherCAT processing.
*/
+#ifdef EOE_TIMER
void ec_master_run_eoe(unsigned long data /**< master pointer */)
+#else
+void ec_master_run_eoe(void *data /**< master pointer */)
+#endif
{
ec_master_t *master = (ec_master_t *) data;
ec_eoe_t *eoe;
- if (!master->request_cb(master->cb_data)) goto restart_timer;
+ // request_cb must return 0, if the lock has been aquired!
+ if (master->request_cb(master->cb_data)) goto queue;
ecrt_master_async_receive(master);
list_for_each_entry(eoe, &master->eoe_slaves, list) {
@@ -854,9 +886,13 @@
master->release_cb(master->cb_data);
- restart_timer:
+ queue:
+#ifdef EOE_TIMER
master->eoe_timer.expires += HZ / 1000;
add_timer(&master->eoe_timer);
+#else
+ queue_delayed_work(master->eoe_workqueue, &master->eoe_work, HZ / 1000);
+#endif
}
/******************************************************************************
@@ -1420,6 +1456,9 @@
/**
Sets the locking callbacks.
+ The request_cb function must return zero, to allow another instance
+ (the EoE process for example) to access the master. Non-zero means,
+ that access is forbidden at this time.
\ingroup RealtimeInterface
*/
@@ -1472,8 +1511,12 @@
}
// start EoE processing
+#ifdef EOE_TIMER
master->eoe_timer.expires = jiffies + 10;
add_timer(&master->eoe_timer);
+#else
+ queue_work(master->eoe_workqueue, &master->eoe_work);
+#endif
return 0;
}
--- a/master/master.h Wed May 10 11:33:10 2006 +0000
+++ b/master/master.h Wed May 10 11:51:05 2006 +0000
@@ -40,6 +40,14 @@
/*****************************************************************************/
+// Uncomment this to do EoE within a kernel timer. Otherwise, it will be
+// done in a working queue.
+
+//#define EOE_TIMER
+
+
+/*****************************************************************************/
+
/**
EtherCAT master mode.
*/
@@ -100,7 +108,12 @@
int (*request_cb)(void *); /**< lock request callback */
void (*release_cb)(void *); /**< lock release callback */
void *cb_data; /**< data parameter of locking callbacks */
+#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
};
/*****************************************************************************/