command timeout, EoE processing with kernel timer.
authorFlorian Pose <fp@igh-essen.com>
Wed, 26 Apr 2006 10:15:02 +0000
changeset 208 b7797f8a813d
parent 207 3e0a148eb38d
child 209 fe044345aaec
command timeout, EoE processing with kernel timer.
master/command.c
master/command.h
master/ethernet.c
master/master.c
master/master.h
mini/mini.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;
 }
 
 /*****************************************************************************/
--- 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 <linux/list.h>
+#include <linux/timex.h>
 
 #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;
 
--- 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;
--- 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;
 }
 
--- 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 */
 };
 
 /*****************************************************************************/
--- 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 <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 @@
 // 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;