# HG changeset patch # User Florian Pose # Date 1146046502 0 # Node ID b7797f8a813db54ac9a9f73c2b1326d1fc421b04 # Parent 3e0a148eb38d014443e153ccd59f416404299700 command timeout, EoE processing with kernel timer. diff -r 3e0a148eb38d -r b7797f8a813d master/command.c --- a/master/command.c Tue Apr 25 13:45:00 2006 +0000 +++ b/master/command.c Wed Apr 26 10:15:02 2006 +0000 @@ -68,6 +68,7 @@ command->index = 0x00; command->working_counter = 0x00; command->state = EC_CMD_INIT; + command->t_sent = 0; } /*****************************************************************************/ diff -r 3e0a148eb38d -r b7797f8a813d master/command.h --- a/master/command.h Tue Apr 25 13:45:00 2006 +0000 +++ b/master/command.h Wed Apr 26 10:15:02 2006 +0000 @@ -32,6 +32,7 @@ #define _EC_COMMAND_H_ #include +#include #include "globals.h" @@ -106,6 +107,7 @@ 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 -r 3e0a148eb38d -r b7797f8a813d master/ethernet.c --- a/master/ethernet.c Tue Apr 25 13:45:00 2006 +0000 +++ b/master/ethernet.c Wed Apr 26 10:15:02 2006 +0000 @@ -120,13 +120,11 @@ 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 @@ 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 @@ } } printk("\n"); -#endif eoe->rx_state = EC_EOE_IDLE; return; diff -r 3e0a148eb38d -r b7797f8a813d master/master.c --- a/master/master.c Tue Apr 25 13:45:00 2006 +0000 +++ b/master/master.c Wed Apr 26 10:15:02 2006 +0000 @@ -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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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; - - if (unlikely(master->debug_level > 0)) { + t_start = get_cycles(); + + 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 @@ } 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 @@ 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 @@ 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); - } -#endif - - queue_delayed_work(master->eoe_wq, &master->eoe_work, HZ); + ec_eoe_run(eoe); + } + ecrt_master_async_send(master); + + 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_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 @@ 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 -r 3e0a148eb38d -r b7797f8a813d master/master.h --- a/master/master.h Tue Apr 25 13:45:00 2006 +0000 +++ b/master/master.h Wed Apr 26 10:15:02 2006 +0000 @@ -101,8 +101,7 @@ 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 -r 3e0a148eb38d -r b7797f8a813d mini/mini.c --- a/mini/mini.c Tue Apr 25 13:45:00 2006 +0000 +++ b/mini/mini.c Wed Apr 26 10:15:02 2006 +0000 @@ -28,6 +28,8 @@ #include #include #include +#include +#include #include "../include/ecrt.h" // EtherCAT realtime interface @@ -41,6 +43,7 @@ // 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 @@ { static unsigned int counter = 0; + spin_lock(&master_lock); + #ifdef ASYNC // receive ecrt_master_async_receive(master); @@ -83,6 +88,8 @@ ecrt_master_async_send(master); #endif + spin_unlock(&master_lock); + if (counter) { counter--; } @@ -101,13 +108,21 @@ 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 @@ 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 @@ 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;