command timeout, EoE processing with kernel timer.

This commit is contained in:
Florian Pose 2006-04-26 10:15:02 +00:00
parent 5536f5fe0f
commit 9821b7ca87
6 changed files with 67 additions and 50 deletions

View File

@ -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;
}
/*****************************************************************************/

View File

@ -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;

View File

@ -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;

View File

@ -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;
list_for_each_entry(eoe, &master->eoe_slaves, list) {
ec_eoe_run(eoe);
}
#endif
if (!master->request_cb(master->cb_data)) goto restart_timer;
queue_delayed_work(master->eoe_wq, &master->eoe_work, HZ);
ecrt_master_async_receive(master);
list_for_each_entry(eoe, &master->eoe_slaves, list) {
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_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;
}

View File

@ -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 */
};
/*****************************************************************************/

View File

@ -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;