command timeout, EoE processing with kernel timer.
This commit is contained in:
parent
5536f5fe0f
commit
9821b7ca87
|
|
@ -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;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
};
|
||||
|
||||
/*****************************************************************************/
|
||||
|
|
|
|||
31
mini/mini.c
31
mini/mini.c
|
|
@ -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;
|
||||
|
|
|
|||
Loading…
Reference in New Issue