Skip to content
Snippets Groups Projects
Commit 0b33a62c authored by Florian Pose's avatar Florian Pose
Browse files

command timeout, EoE processing with kernel timer.

parent 4860d244
No related branches found
No related tags found
No related merge requests found
...@@ -68,6 +68,7 @@ void ec_command_init(ec_command_t *command /**< EtherCAT command */) ...@@ -68,6 +68,7 @@ void ec_command_init(ec_command_t *command /**< EtherCAT command */)
command->index = 0x00; command->index = 0x00;
command->working_counter = 0x00; command->working_counter = 0x00;
command->state = EC_CMD_INIT; command->state = EC_CMD_INIT;
command->t_sent = 0;
} }
/*****************************************************************************/ /*****************************************************************************/
......
...@@ -32,6 +32,7 @@ ...@@ -32,6 +32,7 @@
#define _EC_COMMAND_H_ #define _EC_COMMAND_H_
#include <linux/list.h> #include <linux/list.h>
#include <linux/timex.h>
#include "globals.h" #include "globals.h"
...@@ -106,6 +107,7 @@ typedef struct ...@@ -106,6 +107,7 @@ typedef struct
uint8_t index; /**< command index (set by master) */ uint8_t index; /**< command index (set by master) */
uint16_t working_counter; /**< working counter */ uint16_t working_counter; /**< working counter */
ec_command_state_t state; /**< command state */ ec_command_state_t state; /**< command state */
cycles_t t_sent; /**< time, the commands was sent */
} }
ec_command_t; ec_command_t;
......
...@@ -120,13 +120,11 @@ void ec_eoe_run(ec_eoe_t *eoe) ...@@ -120,13 +120,11 @@ void ec_eoe_run(ec_eoe_t *eoe)
uint8_t *data; uint8_t *data;
ec_master_t *master; ec_master_t *master;
size_t rec_size; size_t rec_size;
#if 0
unsigned int i; unsigned int i;
uint8_t fragment_number; uint8_t fragment_number;
uint8_t complete_size; uint8_t complete_size;
uint8_t frame_number; uint8_t frame_number;
uint8_t last_fragment; uint8_t last_fragment;
#endif
master = eoe->slave->master; master = eoe->slave->master;
...@@ -165,7 +163,6 @@ void ec_eoe_run(ec_eoe_t *eoe) ...@@ -165,7 +163,6 @@ void ec_eoe_run(ec_eoe_t *eoe)
return; return;
} }
#if 0
fragment_number = EC_READ_U16(data + 2) & 0x003F; fragment_number = EC_READ_U16(data + 2) & 0x003F;
complete_size = (EC_READ_U16(data + 2) >> 6) & 0x003F; complete_size = (EC_READ_U16(data + 2) >> 6) & 0x003F;
frame_number = (EC_READ_U16(data + 2) >> 12) & 0x0003; frame_number = (EC_READ_U16(data + 2) >> 12) & 0x0003;
...@@ -185,7 +182,6 @@ void ec_eoe_run(ec_eoe_t *eoe) ...@@ -185,7 +182,6 @@ void ec_eoe_run(ec_eoe_t *eoe)
} }
} }
printk("\n"); printk("\n");
#endif
eoe->rx_state = EC_EOE_IDLE; eoe->rx_state = EC_EOE_IDLE;
return; return;
......
...@@ -46,7 +46,7 @@ ...@@ -46,7 +46,7 @@
/*****************************************************************************/ /*****************************************************************************/
void ec_master_freerun(unsigned long); 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 *); ssize_t ec_show_master_attribute(struct kobject *, struct attribute *, char *);
void ec_master_process_watch_command(ec_master_t *); void ec_master_process_watch_command(ec_master_t *);
...@@ -113,8 +113,10 @@ int ec_master_init(ec_master_t *master, /**< EtherCAT master */ ...@@ -113,8 +113,10 @@ int ec_master_init(ec_master_t *master, /**< EtherCAT master */
master->freerun_timer.function = ec_master_freerun; master->freerun_timer.function = ec_master_freerun;
master->freerun_timer.data = (unsigned long) master; master->freerun_timer.data = (unsigned long) master;
master->eoe_wq = NULL; // init eoe timer
INIT_WORK(&master->eoe_work, ec_master_run_eoe, master); 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->simple_command);
ec_command_init(&master->watch_command); ec_command_init(&master->watch_command);
...@@ -137,6 +139,7 @@ void ec_master_clear(struct kobject *kobj /**< kobject of the master */) ...@@ -137,6 +139,7 @@ void ec_master_clear(struct kobject *kobj /**< kobject of the master */)
EC_INFO("Clearing master %i...\n", master->index); EC_INFO("Clearing master %i...\n", master->index);
del_timer_sync(&master->eoe_timer);
del_timer_sync(&master->freerun_timer); del_timer_sync(&master->freerun_timer);
ec_master_reset(master); ec_master_reset(master);
...@@ -149,8 +152,6 @@ void ec_master_clear(struct kobject *kobj /**< kobject of the 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->simple_command);
ec_command_clear(&master->watch_command); ec_command_clear(&master->watch_command);
if (master->eoe_wq) destroy_workqueue(master->eoe_wq);
EC_INFO("Master %i cleared.\n", master->index); EC_INFO("Master %i cleared.\n", master->index);
} }
...@@ -170,10 +171,9 @@ void ec_master_reset(ec_master_t *master /**< EtherCAT master */) ...@@ -170,10 +171,9 @@ void ec_master_reset(ec_master_t *master /**< EtherCAT master */)
ec_eoe_t *eoe, *next_eoe; ec_eoe_t *eoe, *next_eoe;
// stop EoE processing // stop EoE processing
if (master->eoe_wq && !cancel_delayed_work(&master->eoe_work)) { del_timer_sync(&master->eoe_timer);
flush_workqueue(master->eoe_wq);
}
// stop free-run mode
ec_master_freerun_stop(master); ec_master_freerun_stop(master);
// remove all slaves // remove all slaves
...@@ -264,15 +264,14 @@ void ec_master_send_commands(ec_master_t *master /**< EtherCAT master */) ...@@ -264,15 +264,14 @@ void ec_master_send_commands(ec_master_t *master /**< EtherCAT master */)
size_t command_size; size_t command_size;
uint8_t *frame_data, *cur_data; uint8_t *frame_data, *cur_data;
void *follows_word; void *follows_word;
cycles_t start = 0, end; cycles_t t_start, t_end;
unsigned int frame_count, more_commands_waiting; unsigned int frame_count, more_commands_waiting;
frame_count = 0; 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"); EC_DBG("ec_master_send_commands\n");
start = get_cycles();
}
do { do {
// fetch pointer to transmit socket buffer // fetch pointer to transmit socket buffer
...@@ -294,6 +293,7 @@ void ec_master_send_commands(ec_master_t *master /**< EtherCAT master */) ...@@ -294,6 +293,7 @@ void ec_master_send_commands(ec_master_t *master /**< EtherCAT master */)
} }
command->state = EC_CMD_SENT; command->state = EC_CMD_SENT;
command->t_sent = t_start;
command->index = master->command_index++; command->index = master->command_index++;
if (unlikely(master->debug_level > 0)) if (unlikely(master->debug_level > 0))
...@@ -345,9 +345,9 @@ void ec_master_send_commands(ec_master_t *master /**< EtherCAT master */) ...@@ -345,9 +345,9 @@ void ec_master_send_commands(ec_master_t *master /**< EtherCAT master */)
while (more_commands_waiting); while (more_commands_waiting);
if (unlikely(master->debug_level > 0)) { 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", 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 ...@@ -844,19 +844,24 @@ void ec_master_process_watch_command(ec_master_t *master
Does the Ethernet-over-EtherCAT processing. 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; ec_master_t *master = (ec_master_t *) data;
#if 0
ec_eoe_t *eoe; 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) { 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 */) ...@@ -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 */) void ecrt_master_async_receive(ec_master_t *master /**< EtherCAT master */)
{ {
ec_command_t *command, *next; ec_command_t *command, *next;
cycles_t t_received, t_timeout;
ec_device_call_isr(master->device); ec_device_call_isr(master->device);
t_received = get_cycles();
t_timeout = (cycles_t) master->timeout * (cpu_khz / 1000);
// dequeue all received commands // dequeue all received commands
list_for_each_entry_safe(command, next, &master->command_queue, queue) list_for_each_entry_safe(command, next, &master->command_queue, queue)
if (command->state == EC_CMD_RECEIVED) list_del_init(&command->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) { list_for_each_entry_safe(command, next, &master->command_queue, queue) {
switch (command->state) { switch (command->state) {
case EC_CMD_SENT: case EC_CMD_SENT:
case EC_CMD_QUEUED: case EC_CMD_QUEUED:
command->state = EC_CMD_TIMEOUT; if (t_received - command->t_sent > t_timeout) {
master->stats.timeouts++; list_del_init(&command->queue);
ec_master_output_stats(master); command->state = EC_CMD_TIMEOUT;
master->stats.timeouts++;
ec_master_output_stats(master);
}
break; break;
default: default:
break; break;
} }
list_del_init(&command->queue);
} }
} }
...@@ -1465,16 +1476,9 @@ int ecrt_master_start_eoe(ec_master_t *master /**< EtherCAT master */) ...@@ -1465,16 +1476,9 @@ int ecrt_master_start_eoe(ec_master_t *master /**< EtherCAT master */)
return 0; 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 // start EoE processing
queue_work(master->eoe_wq, &master->eoe_work); master->eoe_timer.expires = jiffies + 10;
add_timer(&master->eoe_timer);
return 0; return 0;
} }
......
...@@ -101,8 +101,7 @@ struct ec_master ...@@ -101,8 +101,7 @@ struct ec_master
int (*request_cb)(void *); /**< lock request callback */ int (*request_cb)(void *); /**< lock request callback */
void (*release_cb)(void *); /**< lock release callback */ void (*release_cb)(void *); /**< lock release callback */
void *cb_data; /**< data parameter of locking callbacks */ void *cb_data; /**< data parameter of locking callbacks */
struct workqueue_struct *eoe_wq; /**< work queue for EoE processing */ struct timer_list eoe_timer; /** EoE timer object */
struct work_struct eoe_work; /**< EoE work object */
}; };
/*****************************************************************************/ /*****************************************************************************/
......
...@@ -28,6 +28,8 @@ ...@@ -28,6 +28,8 @@
#include <linux/module.h> #include <linux/module.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/timer.h> #include <linux/timer.h>
#include <linux/spinlock.h>
#include <linux/interrupt.h>
#include "../include/ecrt.h" // EtherCAT realtime interface #include "../include/ecrt.h" // EtherCAT realtime interface
...@@ -41,6 +43,7 @@ struct timer_list timer; ...@@ -41,6 +43,7 @@ struct timer_list timer;
// EtherCAT // EtherCAT
ec_master_t *master = NULL; ec_master_t *master = NULL;
ec_domain_t *domain1 = NULL; ec_domain_t *domain1 = NULL;
spinlock_t master_lock = SPIN_LOCK_UNLOCKED;
// data fields // data fields
//void *r_ssi_input, *r_ssi_status, *r_4102[3]; //void *r_ssi_input, *r_ssi_status, *r_4102[3];
...@@ -61,6 +64,8 @@ void run(unsigned long data) ...@@ -61,6 +64,8 @@ void run(unsigned long data)
{ {
static unsigned int counter = 0; static unsigned int counter = 0;
spin_lock(&master_lock);
#ifdef ASYNC #ifdef ASYNC
// receive // receive
ecrt_master_async_receive(master); ecrt_master_async_receive(master);
...@@ -83,6 +88,8 @@ void run(unsigned long data) ...@@ -83,6 +88,8 @@ void run(unsigned long data)
ecrt_master_async_send(master); ecrt_master_async_send(master);
#endif #endif
spin_unlock(&master_lock);
if (counter) { if (counter) {
counter--; counter--;
} }
...@@ -101,13 +108,21 @@ void run(unsigned long data) ...@@ -101,13 +108,21 @@ void run(unsigned long data)
int request_lock(void *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) void release_lock(void *data)
{ {
spin_unlock(&master_lock);
} }
/*****************************************************************************/ /*****************************************************************************/
...@@ -152,13 +167,6 @@ int __init init_mini_module(void) ...@@ -152,13 +167,6 @@ int __init init_mini_module(void)
ecrt_master_print(master, 0); ecrt_master_print(master, 0);
#endif #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 0
if (!(slave = ecrt_master_get_slave(master, "5"))) { if (!(slave = ecrt_master_get_slave(master, "5"))) {
printk(KERN_ERR "Failed to get slave 5!\n"); printk(KERN_ERR "Failed to get slave 5!\n");
...@@ -192,6 +200,13 @@ int __init init_mini_module(void) ...@@ -192,6 +200,13 @@ int __init init_mini_module(void)
ecrt_master_prepare_async_io(master); ecrt_master_prepare_async_io(master);
#endif #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"); printk("Starting cyclic sample thread.\n");
init_timer(&timer); init_timer(&timer);
timer.function = run; timer.function = run;
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment