From 0b33a62cd349ee14189caa051b14fd3831222101 Mon Sep 17 00:00:00 2001 From: Florian Pose <fp@igh-essen.com> Date: Wed, 26 Apr 2006 10:15:02 +0000 Subject: [PATCH] command timeout, EoE processing with kernel timer. --- master/command.c | 1 + master/command.h | 2 ++ master/ethernet.c | 4 --- master/master.c | 72 +++++++++++++++++++++++++---------------------- master/master.h | 3 +- mini/mini.c | 31 ++++++++++++++------ 6 files changed, 65 insertions(+), 48 deletions(-) diff --git a/master/command.c b/master/command.c index a308274e..675afa0b 100644 --- a/master/command.c +++ b/master/command.c @@ -68,6 +68,7 @@ void ec_command_init(ec_command_t *command /**< EtherCAT command */) command->index = 0x00; command->working_counter = 0x00; command->state = EC_CMD_INIT; + command->t_sent = 0; } /*****************************************************************************/ diff --git a/master/command.h b/master/command.h index 39ad579e..a0712b11 100644 --- a/master/command.h +++ b/master/command.h @@ -32,6 +32,7 @@ #define _EC_COMMAND_H_ #include <linux/list.h> +#include <linux/timex.h> #include "globals.h" @@ -106,6 +107,7 @@ typedef struct uint8_t index; /**< command index (set by master) */ uint16_t working_counter; /**< working counter */ ec_command_state_t state; /**< command state */ + cycles_t t_sent; /**< time, the commands was sent */ } ec_command_t; diff --git a/master/ethernet.c b/master/ethernet.c index 1bcc9bf8..86715e75 100644 --- a/master/ethernet.c +++ b/master/ethernet.c @@ -120,13 +120,11 @@ void ec_eoe_run(ec_eoe_t *eoe) uint8_t *data; ec_master_t *master; size_t rec_size; -#if 0 unsigned int i; uint8_t fragment_number; uint8_t complete_size; uint8_t frame_number; uint8_t last_fragment; -#endif master = eoe->slave->master; @@ -165,7 +163,6 @@ void ec_eoe_run(ec_eoe_t *eoe) return; } -#if 0 fragment_number = EC_READ_U16(data + 2) & 0x003F; complete_size = (EC_READ_U16(data + 2) >> 6) & 0x003F; frame_number = (EC_READ_U16(data + 2) >> 12) & 0x0003; @@ -185,7 +182,6 @@ void ec_eoe_run(ec_eoe_t *eoe) } } printk("\n"); -#endif eoe->rx_state = EC_EOE_IDLE; return; diff --git a/master/master.c b/master/master.c index 467669c1..d3740480 100644 --- a/master/master.c +++ b/master/master.c @@ -46,7 +46,7 @@ /*****************************************************************************/ void ec_master_freerun(unsigned long); -void ec_master_run_eoe(void *); +void ec_master_run_eoe(unsigned long); ssize_t ec_show_master_attribute(struct kobject *, struct attribute *, char *); void ec_master_process_watch_command(ec_master_t *); @@ -113,8 +113,10 @@ int ec_master_init(ec_master_t *master, /**< EtherCAT master */ master->freerun_timer.function = ec_master_freerun; master->freerun_timer.data = (unsigned long) master; - master->eoe_wq = NULL; - INIT_WORK(&master->eoe_work, ec_master_run_eoe, 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); @@ -137,6 +139,7 @@ void ec_master_clear(struct kobject *kobj /**< kobject of the master */) EC_INFO("Clearing master %i...\n", master->index); + del_timer_sync(&master->eoe_timer); del_timer_sync(&master->freerun_timer); ec_master_reset(master); @@ -149,8 +152,6 @@ void ec_master_clear(struct kobject *kobj /**< kobject of the master */) ec_command_clear(&master->simple_command); ec_command_clear(&master->watch_command); - if (master->eoe_wq) destroy_workqueue(master->eoe_wq); - EC_INFO("Master %i cleared.\n", master->index); } @@ -170,10 +171,9 @@ void ec_master_reset(ec_master_t *master /**< EtherCAT master */) ec_eoe_t *eoe, *next_eoe; // stop EoE processing - if (master->eoe_wq && !cancel_delayed_work(&master->eoe_work)) { - flush_workqueue(master->eoe_wq); - } + del_timer_sync(&master->eoe_timer); + // stop free-run mode ec_master_freerun_stop(master); // remove all slaves @@ -264,15 +264,14 @@ void ec_master_send_commands(ec_master_t *master /**< EtherCAT master */) size_t command_size; uint8_t *frame_data, *cur_data; void *follows_word; - cycles_t start = 0, end; + cycles_t t_start, t_end; unsigned int frame_count, more_commands_waiting; frame_count = 0; + t_start = get_cycles(); - if (unlikely(master->debug_level > 0)) { + if (unlikely(master->debug_level > 0)) EC_DBG("ec_master_send_commands\n"); - start = get_cycles(); - } do { // fetch pointer to transmit socket buffer @@ -294,6 +293,7 @@ void ec_master_send_commands(ec_master_t *master /**< EtherCAT master */) } command->state = EC_CMD_SENT; + command->t_sent = t_start; command->index = master->command_index++; if (unlikely(master->debug_level > 0)) @@ -345,9 +345,9 @@ void ec_master_send_commands(ec_master_t *master /**< EtherCAT master */) while (more_commands_waiting); if (unlikely(master->debug_level > 0)) { - end = get_cycles(); + t_end = get_cycles(); EC_DBG("ec_master_send_commands sent %i frames in %ius.\n", - frame_count, (u32) (end - start) * 1000 / cpu_khz); + frame_count, (u32) (t_end - t_start) * 1000 / cpu_khz); } } @@ -844,19 +844,24 @@ void ec_master_process_watch_command(ec_master_t *master Does the Ethernet-over-EtherCAT processing. */ -void ec_master_run_eoe(void *data /**< work data (= master pointer) */) +void ec_master_run_eoe(unsigned long data /**< master pointer */) { ec_master_t *master = (ec_master_t *) data; - -#if 0 ec_eoe_t *eoe; + if (!master->request_cb(master->cb_data)) goto restart_timer; + + ecrt_master_async_receive(master); list_for_each_entry(eoe, &master->eoe_slaves, list) { - ec_eoe_run(eoe); + ec_eoe_run(eoe); } -#endif + ecrt_master_async_send(master); - queue_delayed_work(master->eoe_wq, &master->eoe_work, HZ); + master->release_cb(master->cb_data); + + restart_timer: + master->eoe_timer.expires += HZ / 4; + add_timer(&master->eoe_timer); } /****************************************************************************** @@ -1232,26 +1237,32 @@ void ecrt_master_async_send(ec_master_t *master /**< EtherCAT master */) void ecrt_master_async_receive(ec_master_t *master /**< EtherCAT master */) { ec_command_t *command, *next; + cycles_t t_received, t_timeout; ec_device_call_isr(master->device); + t_received = get_cycles(); + t_timeout = (cycles_t) master->timeout * (cpu_khz / 1000); + // dequeue all received commands list_for_each_entry_safe(command, next, &master->command_queue, queue) if (command->state == EC_CMD_RECEIVED) list_del_init(&command->queue); - // dequeue all remaining commands + // dequeue all commands that timed out list_for_each_entry_safe(command, next, &master->command_queue, queue) { switch (command->state) { case EC_CMD_SENT: case EC_CMD_QUEUED: - command->state = EC_CMD_TIMEOUT; - master->stats.timeouts++; - ec_master_output_stats(master); + if (t_received - command->t_sent > t_timeout) { + list_del_init(&command->queue); + command->state = EC_CMD_TIMEOUT; + master->stats.timeouts++; + ec_master_output_stats(master); + } break; default: break; } - list_del_init(&command->queue); } } @@ -1465,16 +1476,9 @@ int ecrt_master_start_eoe(ec_master_t *master /**< EtherCAT master */) return 0; } - // create the EoE workqueue, if necessary - if (!master->eoe_wq) { - if (!(master->eoe_wq = create_singlethread_workqueue("eoework"))) { - EC_ERR("Failed to create EoE workqueue!\n"); - return -1; - } - } - // start EoE processing - queue_work(master->eoe_wq, &master->eoe_work); + master->eoe_timer.expires = jiffies + 10; + add_timer(&master->eoe_timer); return 0; } diff --git a/master/master.h b/master/master.h index f9f4532a..1af3096f 100644 --- a/master/master.h +++ b/master/master.h @@ -101,8 +101,7 @@ struct ec_master int (*request_cb)(void *); /**< lock request callback */ void (*release_cb)(void *); /**< lock release callback */ void *cb_data; /**< data parameter of locking callbacks */ - struct workqueue_struct *eoe_wq; /**< work queue for EoE processing */ - struct work_struct eoe_work; /**< EoE work object */ + struct timer_list eoe_timer; /** EoE timer object */ }; /*****************************************************************************/ diff --git a/mini/mini.c b/mini/mini.c index 67cc2da5..6f09ae6f 100644 --- a/mini/mini.c +++ b/mini/mini.c @@ -28,6 +28,8 @@ #include <linux/module.h> #include <linux/delay.h> #include <linux/timer.h> +#include <linux/spinlock.h> +#include <linux/interrupt.h> #include "../include/ecrt.h" // EtherCAT realtime interface @@ -41,6 +43,7 @@ struct timer_list timer; // EtherCAT ec_master_t *master = NULL; ec_domain_t *domain1 = NULL; +spinlock_t master_lock = SPIN_LOCK_UNLOCKED; // data fields //void *r_ssi_input, *r_ssi_status, *r_4102[3]; @@ -61,6 +64,8 @@ void run(unsigned long data) { static unsigned int counter = 0; + spin_lock(&master_lock); + #ifdef ASYNC // receive ecrt_master_async_receive(master); @@ -83,6 +88,8 @@ void run(unsigned long data) ecrt_master_async_send(master); #endif + spin_unlock(&master_lock); + if (counter) { counter--; } @@ -101,13 +108,21 @@ void run(unsigned long data) int request_lock(void *data) { - return 0; + 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++; + } } /*****************************************************************************/ void release_lock(void *data) { + spin_unlock(&master_lock); } /*****************************************************************************/ @@ -152,13 +167,6 @@ int __init init_mini_module(void) ecrt_master_print(master, 0); #endif -#if 1 - if (ecrt_master_start_eoe(master)) { - printk(KERN_ERR "Failed to start EoE processing!\n"); - goto out_deactivate; - } -#endif - #if 0 if (!(slave = ecrt_master_get_slave(master, "5"))) { printk(KERN_ERR "Failed to get slave 5!\n"); @@ -192,6 +200,13 @@ int __init init_mini_module(void) ecrt_master_prepare_async_io(master); #endif +#if 1 + if (ecrt_master_start_eoe(master)) { + printk(KERN_ERR "Failed to start EoE processing!\n"); + goto out_deactivate; + } +#endif + printk("Starting cyclic sample thread.\n"); init_timer(&timer); timer.function = run; -- GitLab