command timeout, EoE processing with kernel timer.
--- 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;