31#include <linux/module.h>
32#include <linux/kernel.h>
33#include <linux/string.h>
34#include <linux/slab.h>
35#include <linux/delay.h>
36#include <linux/device.h>
37#include <linux/version.h>
38#include <linux/hrtimer.h>
39#include <linux/kthread.h>
49#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0)
50#include <uapi/linux/sched/types.h>
51#include <linux/sched/types.h>
56#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 17, 0) || \
57 (defined(CONFIG_PREEMPT_RT_FULL) && \
58 LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0))
59# define ec_rt_lock_interruptible(lock) \
60 rt_mutex_lock_interruptible(lock)
62# define ec_rt_lock_interruptible(lock) \
63 rt_mutex_lock_interruptible(lock, 0)
76#define FORCE_OUTPUT_CORRUPTED 0
79#define EC_SDO_INJECTION_TIMEOUT 10000
85static cycles_t timeout_cycles;
89static cycles_t ext_injection_timeout_cycles;
131void ec_master_nanosleep(
const unsigned long);
132static void sc_reset_task_kicker(
struct irq_work *work);
133static void sc_reset_task(
struct work_struct *work);
142 timeout_cycles = (cycles_t)
EC_IO_TIMEOUT * (cpu_khz / 1000);
143 ext_injection_timeout_cycles =
162 const uint8_t *main_mac,
163 const uint8_t *backup_mac,
171 unsigned int dev_idx, i;
173 master->
index = index;
178 for (dev_idx =
EC_DEVICE_MAIN; dev_idx < EC_MAX_NUM_DEVICES; dev_idx++) {
179 master->
macs[dev_idx] = NULL;
184#if EC_MAX_NUM_DEVICES > 1
207 INIT_LIST_HEAD(&master->
configs);
208 INIT_LIST_HEAD(&master->
domains);
278 goto out_clear_devices;
289 goto out_clear_devices;
301 " datagram %u.\n", i);
302 goto out_clear_ext_datagrams;
314 " synchronisation datagram.\n");
315 goto out_clear_ext_datagrams;
325 " synchronisation datagram.\n");
326 goto out_clear_ref_sync;
337 " monitoring datagram.\n");
350 goto out_clear_sync_mon;
354 "EtherCAT%u", master->
index);
365 goto out_unregister_class_device;
372out_unregister_class_device:
383out_clear_ext_datagrams:
390 for (; dev_idx > 0; dev_idx--) {
404 unsigned int dev_idx, i;
452 list_for_each_entry_safe(eoe, next, &master->
eoe_handlers, list) {
453 list_del(&eoe->
list);
471 list_for_each_entry_safe(sc, next, &master->
configs, list) {
495 list_del_init(&request->
list);
498 request->
state = EC_INT_REQUEST_FAILURE;
506 for (slave = master->
slaves;
528 list_for_each_entry_safe(domain, next, &master->
domains, list) {
529 list_del(&domain->
list);
558 if (ec_rt_lock_interruptible(&master->
io_mutex))
573 if (ec_rt_lock_interruptible(&master->
io_mutex))
588 int (*thread_func)(
void *),
593 master->
thread = kthread_create(thread_func, master, name);
594 if (IS_ERR(master->
thread)) {
595 int err = (int) PTR_ERR(master->
thread);
596 EC_MASTER_ERR(master,
"Failed to start master thread (error %i)!\n",
607 (void) wake_up_process(master->
thread);
620 unsigned long sleep_jiffies;
629 kthread_stop(master->
thread);
638 sleep_jiffies = max(HZ / 100, 1);
639 schedule_timeout(sleep_jiffies);
723 " interrupted by signal.\n");
728 " configuration returned.\n");
741 ret = wait_event_interruptible(master->
scan_queue,
745 " interrupted by signal.\n");
750 " slave scan returned.\n");
754 for (slave = master->
slaves;
803 size_t queue_size = 0, new_queue_size = 0;
805 unsigned int datagram_count = 0;
820 EC_MASTER_DBG(master, 1,
"Injecting datagrams, queue_size=%zu\n",
834 new_queue_size = queue_size + datagram->
data_size;
835 if (new_queue_size <= master->max_queue_size) {
838 " size=%zu, queue_size=%zu\n", datagram->
name,
843 datagram->cycles_sent = 0;
847 queue_size = new_queue_size;
852 " size=%zu, max_queue_size=%zu\n",
858 cycles_t cycles_now = get_cycles();
860 if (cycles_now - datagram->cycles_sent
861 > ext_injection_timeout_cycles)
867#if defined EC_RT_SYSLOG || DEBUG_INJECT
868 unsigned int time_us;
873#if defined EC_RT_SYSLOG || DEBUG_INJECT
875 time_us = (
unsigned int)
876 ((cycles_now - datagram->cycles_sent) * 1000LL)
879 time_us = (
unsigned int)
883 " external datagram %s size=%zu,"
884 " max_queue_size=%zu\n", time_us, datagram->
name,
891 " external datagram %s size=%u, queue_size=%u\n",
903 EC_MASTER_DBG(master, 1,
"Injected %u datagrams.\n", datagram_count);
914 unsigned int send_interval
961 list_for_each_entry(queued_datagram, &master->
datagram_queue, queue) {
962 if (queued_datagram == datagram) {
966 "Datagram %p already queued (skipping).\n", datagram);
1002 size_t datagram_size;
1003 uint8_t *frame_data, *cur_data = NULL;
1005#ifdef EC_HAVE_CYCLES
1006 cycles_t cycles_start, cycles_sent, cycles_end;
1008 unsigned long jiffies_sent;
1009 unsigned int frame_count, more_datagrams_waiting;
1010 struct list_head sent_datagrams;
1012#ifdef EC_HAVE_CYCLES
1013 cycles_start = get_cycles();
1016 INIT_LIST_HEAD(&sent_datagrams);
1019 __func__, device_index);
1023 follows_word = NULL;
1024 more_datagrams_waiting = 0;
1043 if (cur_data - frame_data + datagram_size > ETH_DATA_LEN) {
1044 more_datagrams_waiting = 1;
1048 list_add_tail(&datagram->
sent, &sent_datagrams);
1066 follows_word = cur_data + 6;
1078 if (list_empty(&sent_datagrams)) {
1088 while (cur_data - frame_data < ETH_ZLEN - ETH_HLEN)
1091 EC_MASTER_DBG(master, 2,
"frame size: %zu\n", cur_data - frame_data);
1095 cur_data - frame_data);
1096#ifdef EC_HAVE_CYCLES
1097 cycles_sent = get_cycles();
1099 jiffies_sent = jiffies;
1102 list_for_each_entry_safe(datagram, next, &sent_datagrams, sent) {
1103#ifdef EC_HAVE_CYCLES
1104 datagram->cycles_sent = cycles_sent;
1107 list_del_init(&datagram->
sent);
1113 while (more_datagrams_waiting);
1115#ifdef EC_HAVE_CYCLES
1117 cycles_end = get_cycles();
1119 " sent %u frames in %uus.\n", __func__, frame_count,
1120 (
unsigned int) (cycles_end - cycles_start) * 1000 / cpu_khz);
1136 const uint8_t *frame_data,
1140 size_t frame_size, data_size;
1141 uint8_t datagram_type, datagram_index;
1142 unsigned int cmd_follows, matched;
1143 const uint8_t *cur_data;
1149 " on %s (size %zu < %u byte):\n",
1160 cur_data = frame_data;
1166 if (unlikely(frame_size > size)) {
1169 " on %s (invalid frame size %zu for "
1170 "received size %zu):\n", device->
dev->name,
1182 while (cmd_follows) {
1190 if (unlikely(cur_data - frame_data
1194 " on %s (invalid data size %zu):\n",
1195 device->
dev->name, data_size);
1208 if (datagram->
index == datagram_index
1210 && datagram->
type == datagram_type
1244 memcpy(datagram->
data, cur_data, data_size);
1246 cur_data += data_size;
1253#ifdef EC_HAVE_CYCLES
1254 datagram->cycles_received =
1261 list_del_init(&datagram->
queue);
1342 s32 tx_frame_rate, rx_frame_rate, tx_byte_rate, rx_byte_rate, loss_rate;
1344 unsigned int i, dev_idx;
1347 if (likely(jiffies - s->
jiffies < HZ)) {
1356 loss_rate = (loss - s->
last_loss) * 1000;
1387#ifdef EC_USE_HRTIMER
1392static enum hrtimer_restart ec_master_nanosleep_wakeup(
struct hrtimer *timer)
1394 struct hrtimer_sleeper *t =
1395 container_of(timer,
struct hrtimer_sleeper, timer);
1396 struct task_struct *task = t->task;
1400 wake_up_process(task);
1402 return HRTIMER_NORESTART;
1407void ec_master_nanosleep(
const unsigned long nsecs)
1409 struct hrtimer_sleeper t;
1410 enum hrtimer_mode mode = HRTIMER_MODE_REL;
1412#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 15, 0)
1413 hrtimer_setup(&t.timer, ec_master_nanosleep_wakeup,
1414 CLOCK_MONOTONIC, mode);
1416 hrtimer_init(&t.timer, CLOCK_MONOTONIC, mode);
1417 t.timer.function = ec_master_nanosleep_wakeup;
1420 hrtimer_set_expires(&t.timer, ktime_set(0, nsecs));
1423 set_current_state(TASK_INTERRUPTIBLE);
1424 hrtimer_start(&t.timer, hrtimer_get_expires(&t.timer), mode);
1426 if (likely(t.task)) {
1430 hrtimer_cancel(&t.timer);
1431 mode = HRTIMER_MODE_ABS;
1432 }
while (t.task && !signal_pending(current));
1447 unsigned int count = 0;
1449 list_for_each_entry_safe(fsm, next, &master->
fsm_exec_list, list) {
1453 list_del_init(&fsm->
list);
1470 " slave FSM execution. This is a bug!\n");
1489 list_del_init(&fsm->
list);
1499 && count < master->slave_count) {
1511 " consumed datagram %s, now %u FSMs in list.\n",
1534#ifdef EC_USE_HRTIMER
1541 EC_MASTER_DBG(master, 1,
"Idle thread running with send interval = %u us,"
1545 while (!kthread_should_stop()) {
1549 if (ec_rt_lock_interruptible(&master->
io_mutex))
1552 rt_mutex_unlock(&master->
io_mutex);
1555 if (down_interruptible(&master->
master_sem)) {
1566 if (ec_rt_lock_interruptible(&master->
io_mutex))
1572#ifdef EC_USE_HRTIMER
1576 rt_mutex_unlock(&master->
io_mutex);
1579#ifdef EC_USE_HRTIMER
1582 set_current_state(TASK_INTERRUPTIBLE);
1583 schedule_timeout(1);
1586#ifdef EC_USE_HRTIMER
1594 EC_MASTER_DBG(master, 1,
"Master IDLE thread exiting...\n");
1606 unsigned int seq_rt;
1609 " with fsm interval = %u us, max data size=%zu\n",
1612 while (!kthread_should_stop()) {
1623 if (down_interruptible(&master->
master_sem)) {
1640#ifdef EC_USE_HRTIMER
1645 set_current_state(TASK_INTERRUPTIBLE);
1646 schedule_timeout(1);
1663static inline void set_normal_priority(
struct task_struct *p,
int nice)
1665#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 9, 0)
1666 sched_set_normal(p, nice);
1668 struct sched_param param = { .sched_priority = 0 };
1669 sched_setscheduler(p, SCHED_NORMAL, ¶m);
1670 set_user_nice(p, nice);
1690 " because of missing callbacks!\n");
1699 EC_MASTER_ERR(master,
"Failed to start EoE thread (error %i)!\n",
1731 unsigned int none_open, sth_to_send, all_idle;
1735 while (!kthread_should_stop()) {
1739 list_for_each_entry(eoe, &master->
eoe_handlers, list) {
1753 list_for_each_entry(eoe, &master->
eoe_handlers, list) {
1764 list_for_each_entry(eoe, &master->
eoe_handlers, list) {
1773 set_current_state(TASK_INTERRUPTIBLE);
1774 schedule_timeout(1);
1796 list_for_each_entry(sc, &master->
configs, list) {
1806#define EC_FIND_SLAVE \
1809 for (; slave < master->slaves + master->slave_count; \
1811 if (slave->effective_alias == alias) \
1814 if (slave == master->slaves + master->slave_count) \
1818 slave += position; \
1819 if (slave < master->slaves + master->slave_count) { \
1867 unsigned int count = 0;
1869 list_for_each_entry(sc, &master->
configs, list) {
1881#define EC_FIND_CONFIG \
1883 list_for_each_entry(sc, &master->configs, list) { \
1930 unsigned int count = 0;
1932 list_for_each_entry(domain, &master->
domains, list) {
1944#define EC_FIND_DOMAIN \
1946 list_for_each_entry(domain, &master->domains, list) { \
1996 unsigned int count = 0;
1998 list_for_each_entry(eoe, &master->
eoe_handlers, list) {
2020 list_for_each_entry(eoe, &master->
eoe_handlers, list) {
2088 for (slave = master->
slaves;
2101 EC_MASTER_INFO(master,
"Using slave %u as DC reference clock.\n",
2125 unsigned int *slave_position
2129 unsigned int port_index;
2139 while (port_index != 0) {
2141 *slave_position = *slave_position + 1;
2142 if (*slave_position < master->slave_count) {
2144 master->
slaves + *slave_position;
2146 slave, slave_position);
2155 port_index = next_table[port_index];
2169 unsigned int slave_position = 0;
2175 EC_MASTER_ERR(master,
"Failed to calculate bus topology.\n");
2188 for (slave = master->
slaves;
2235 slave = master->
slaves + i;
2262 EC_MASTER_DBG(master, 1,
"ecrt_master_create_domain(master = 0x%p)\n",
2268 return ERR_PTR(-ENOMEM);
2273 if (list_empty(&master->
domains)) {
2277 index = last_domain->
index + 1;
2297 return IS_ERR(d) ? NULL : d;
2304 uint32_t domain_offset;
2308 int eoe_was_running;
2311 EC_MASTER_DBG(master, 1,
"ecrt_master_activate(master = 0x%p)\n", master);
2314 EC_MASTER_WARN(master,
"%s: Master already active!\n", __func__);
2322 list_for_each_entry(domain, &master->
domains, list) {
2326 EC_MASTER_ERR(master,
"Failed to finish domain 0x%p!\n", domain);
2338 eoe_was_running = master->
eoe_thread != NULL;
2352 if (eoe_was_running) {
2381 int eoe_was_running;
2384 EC_MASTER_DBG(master, 1,
"%s(master = 0x%p)\n", __func__, master);
2393 eoe_was_running = master->
eoe_thread != NULL;
2403 for (slave = master->
slaves;
2417 list_for_each_entry(eoe, &master->
eoe_handlers, list) {
2427 if (eoe_was_running) {
2450 unsigned int seq_fsm;
2466 list_for_each_entry_safe(datagram, n,
2469 list_del_init(&datagram->
queue);
2496 unsigned int dev_idx;
2507 list_for_each_entry_safe(datagram, next, &master->
datagram_queue, queue) {
2510#ifdef EC_HAVE_CYCLES
2512 datagram->cycles_sent > timeout_cycles) {
2517 list_del_init(&datagram->
queue);
2525 unsigned int time_us;
2526#ifdef EC_HAVE_CYCLES
2527 time_us = (
unsigned int)
2529 datagram->cycles_sent) * 1000 / cpu_khz;
2531 time_us = (
unsigned int)
2536 " index %02X waited %u us.\n",
2537 datagram, datagram->
index, time_us);
2569 uint16_t alias, uint16_t position, uint32_t vendor_id,
2570 uint32_t product_code)
2573 unsigned int found = 0;
2576 EC_MASTER_DBG(master, 1,
"ecrt_master_slave_config(master = 0x%p,"
2577 " alias = %u, position = %u, vendor_id = 0x%08x,"
2578 " product_code = 0x%08x)\n",
2579 master, alias, position, vendor_id, product_code);
2581 list_for_each_entry(sc, &master->
configs, list) {
2591 " configured as 0x%08X/0x%08X before. Now configuring"
2593 vendor_id, product_code);
2594 return ERR_PTR(-ENOENT);
2597 EC_MASTER_DBG(master, 1,
"Creating slave configuration for %u:%u,"
2598 " 0x%08X/0x%08X.\n",
2599 alias, position, vendor_id, product_code);
2604 " for slave configuration.\n");
2605 return ERR_PTR(-ENOMEM);
2609 alias, position, vendor_id, product_code);
2627 uint16_t alias, uint16_t position, uint32_t vendor_id,
2628 uint32_t product_code)
2631 position, vendor_id, product_code);
2632 return IS_ERR(sc) ? NULL : sc;
2660 " master_info = 0x%p)\n", master, master_info);
2674 EC_MASTER_DBG(master, 1,
"ecrt_master_scan_progress(master = 0x%p,"
2675 " progress = 0x%p)\n", master, progress);
2691 if (down_interruptible(&master->
master_sem)) {
2697 if (slave == NULL) {
2735 slave_info->
name[0] = 0;
2747 void (*send_cb)(
void *),
void (*receive_cb)(
void *),
void *cb_data)
2749 EC_MASTER_DBG(master, 1,
"ecrt_master_callbacks(master = 0x%p,"
2750 " send_cb = 0x%p, receive_cb = 0x%p, cb_data = 0x%p)\n",
2751 master, send_cb, receive_cb, cb_data);
2895 uint16_t index, uint8_t subindex,
const uint8_t *data,
2896 size_t data_size, uint32_t *abort_code)
2903 " slave_position = %u, index = 0x%04X, subindex = 0x%02X,"
2904 " data = 0x%p, data_size = %zu, abort_code = 0x%p)\n",
2905 __func__, master, slave_position, index, subindex,
2906 data, data_size, abort_code);
2916 memcpy(request.
data, data, data_size);
2920 if (down_interruptible(&master->
master_sem)) {
2927 EC_MASTER_ERR(master,
"Slave %u does not exist!\n", slave_position);
2932 EC_SLAVE_DBG(slave, 1,
"Scheduling SDO download request.\n");
2941 request.
state != EC_INT_REQUEST_QUEUED)) {
2944 if (request.
state == EC_INT_REQUEST_QUEUED) {
2945 list_del(&request.
list);
2959 if (request.
state == EC_INT_REQUEST_SUCCESS) {
2961 }
else if (request.
errno) {
2962 ret = -request.
errno;
2974 uint16_t slave_position, uint16_t index,
const uint8_t *data,
2975 size_t data_size, uint32_t *abort_code)
2982 " slave_position = %u, index = 0x%04X,"
2983 " data = 0x%p, data_size = %zu, abort_code = 0x%p)\n",
2984 __func__, master, slave_position, index, data, data_size,
2996 memcpy(request.
data, data, data_size);
3000 if (down_interruptible(&master->
master_sem)) {
3007 EC_MASTER_ERR(master,
"Slave %u does not exist!\n", slave_position);
3012 EC_SLAVE_DBG(slave, 1,
"Scheduling SDO download request"
3013 " (complete access).\n");
3022 request.
state != EC_INT_REQUEST_QUEUED)) {
3025 if (request.
state == EC_INT_REQUEST_QUEUED) {
3026 list_del(&request.
list);
3040 if (request.
state == EC_INT_REQUEST_SUCCESS) {
3042 }
else if (request.
errno) {
3043 ret = -request.
errno;
3055 uint16_t index, uint8_t subindex, uint8_t *target,
3056 size_t target_size,
size_t *result_size, uint32_t *abort_code)
3063 " slave_position = %u, index = 0x%04X, subindex = 0x%02X,"
3064 " target = 0x%p, target_size = %zu, result_size = 0x%p,"
3065 " abort_code = 0x%p)\n",
3066 __func__, master, slave_position, index, subindex,
3067 target, target_size, result_size, abort_code);
3073 if (down_interruptible(&master->
master_sem)) {
3081 EC_MASTER_ERR(master,
"Slave %u does not exist!\n", slave_position);
3085 EC_SLAVE_DBG(slave, 1,
"Scheduling SDO upload request.\n");
3094 request.
state != EC_INT_REQUEST_QUEUED)) {
3097 if (request.
state == EC_INT_REQUEST_QUEUED) {
3098 list_del(&request.
list);
3112 if (request.
state != EC_INT_REQUEST_SUCCESS) {
3114 if (request.
errno) {
3115 ret = -request.
errno;
3121 EC_SLAVE_ERR(slave,
"%s(): Buffer too small.\n", __func__);
3138 uint8_t drive_no, uint16_t idn,
const uint8_t *data,
size_t data_size,
3139 uint16_t *error_code)
3160 memcpy(request.
data, data, data_size);
3164 if (down_interruptible(&master->
master_sem)) {
3177 EC_SLAVE_DBG(slave, 1,
"Scheduling SoE write request.\n");
3186 request.
state != EC_INT_REQUEST_QUEUED)) {
3189 if (request.
state == EC_INT_REQUEST_QUEUED) {
3191 list_del(&request.
list);
3205 ret = request.
state == EC_INT_REQUEST_SUCCESS ? 0 : -EIO;
3214 uint8_t drive_no, uint16_t idn, uint8_t *target,
size_t target_size,
3215 size_t *result_size, uint16_t *error_code)
3231 if (down_interruptible(&master->
master_sem)) {
3239 EC_MASTER_ERR(master,
"Slave %u does not exist!\n", slave_position);
3243 EC_SLAVE_DBG(slave, 1,
"Scheduling SoE read request.\n");
3252 request.
state != EC_INT_REQUEST_QUEUED)) {
3255 if (request.
state == EC_INT_REQUEST_QUEUED) {
3256 list_del(&request.
list);
3272 if (request.
state != EC_INT_REQUEST_SUCCESS) {
3279 EC_SLAVE_ERR(slave,
"%s(): Buffer too small.\n", __func__);
3301 list_for_each_entry(sc, &master->
configs, list) {
3311static void sc_reset_task_kicker(
struct irq_work *work)
3320static void sc_reset_task(
struct work_struct *work)
int ec_cdev_init(ec_cdev_t *cdev, ec_master_t *master, dev_t dev_num)
Constructor.
void ec_cdev_clear(ec_cdev_t *cdev)
Destructor.
int ec_datagram_frmw(ec_datagram_t *datagram, uint16_t configured_address, uint16_t mem_address, size_t data_size)
Initializes an EtherCAT FRMW datagram.
int ec_datagram_prealloc(ec_datagram_t *datagram, size_t size)
Allocates internal payload memory.
void ec_datagram_zero(ec_datagram_t *datagram)
Fills the datagram payload memory with zeros.
int ec_datagram_brd(ec_datagram_t *datagram, uint16_t mem_address, size_t data_size)
Initializes an EtherCAT BRD datagram.
void ec_datagram_output_stats(ec_datagram_t *datagram)
Outputs datagram statistics at most every second.
void ec_datagram_clear(ec_datagram_t *datagram)
Destructor.
int ec_datagram_fpwr(ec_datagram_t *datagram, uint16_t configured_address, uint16_t mem_address, size_t data_size)
Initializes an EtherCAT FPWR datagram.
void ec_datagram_init(ec_datagram_t *datagram)
Constructor.
EtherCAT datagram structure.
@ EC_DATAGRAM_FPWR
Configured Address Physical Write.
@ EC_DATAGRAM_LWR
Logical Write.
@ EC_DATAGRAM_BWR
Broadcast Write.
@ EC_DATAGRAM_APWR
Auto Increment Physical Write.
@ EC_DATAGRAM_INIT
Initial state of a new datagram.
@ EC_DATAGRAM_RECEIVED
Received (dequeued).
@ EC_DATAGRAM_TIMED_OUT
Timed out (dequeued).
@ EC_DATAGRAM_SENT
Sent (still in the queue).
@ EC_DATAGRAM_QUEUED
Queued for sending.
@ EC_DATAGRAM_ERROR
Error while sending/receiving (dequeued).
void ec_device_update_stats(ec_device_t *device)
Update device statistics.
int ec_device_init(ec_device_t *device, ec_master_t *master)
Constructor.
uint8_t * ec_device_tx_data(ec_device_t *device)
Returns a pointer to the device's transmit memory.
void ec_device_poll(ec_device_t *device)
Calls the poll function of the assigned net_device.
void ec_device_clear_stats(ec_device_t *device)
Clears the frame statistics.
void ec_device_clear(ec_device_t *device)
Destructor.
void ec_device_send(ec_device_t *device, size_t size)
Sends the content of the transmit socket buffer.
EtherCAT device structure.
int ec_domain_finish(ec_domain_t *domain, uint32_t base_address)
Finishes a domain.
void ec_domain_init(ec_domain_t *domain, ec_master_t *master, unsigned int index)
Domain constructor.
void ec_domain_clear(ec_domain_t *domain)
Domain destructor.
struct ec_device ec_device_t
int ec_eoe_is_open(const ec_eoe_t *eoe)
Returns the state of the device.
void ec_eoe_run(ec_eoe_t *eoe)
Runs the EoE state machine.
void ec_eoe_clear(ec_eoe_t *eoe)
EoE destructor.
void ec_eoe_queue(ec_eoe_t *eoe)
Queues the datagram, if necessary.
int ec_eoe_is_idle(const ec_eoe_t *eoe)
Returns the idle state.
Ethernet over EtherCAT (EoE).
int ec_fsm_master_exec(ec_fsm_master_t *fsm)
Executes the current state of the state machine.
void ec_fsm_master_init(ec_fsm_master_t *fsm, ec_master_t *master, ec_datagram_t *datagram)
Constructor.
int ec_fsm_master_idle(const ec_fsm_master_t *fsm)
void ec_fsm_master_clear(ec_fsm_master_t *fsm)
Destructor.
void ec_fsm_master_reset(ec_fsm_master_t *fsm)
Reset state machine.
int ec_fsm_slave_exec(ec_fsm_slave_t *fsm, ec_datagram_t *datagram)
Executes the current state of the state machine.
int ec_fsm_slave_is_ready(const ec_fsm_slave_t *fsm)
Returns, if the FSM is currently not busy and ready to execute.
struct ec_fsm_slave ec_fsm_slave_t
Global definitions and macros.
#define EC_RATE_COUNT
Number of statistic rate intervals to maintain.
#define EC_BYTE_TRANSMISSION_TIME_NS
Time to send a byte in nanoseconds.
@ EC_SLAVE_STATE_PREOP
PREOP state (mailbox communication, no IO).
@ EC_SLAVE_STATE_OP
OP (mailbox communication and input/output update).
#define EC_MAX_DATA_SIZE
Resulting maximum data size of a single datagram in a frame.
int ec_mac_is_zero(const uint8_t *)
#define EC_IO_TIMEOUT
Datagram timeout in microseconds.
#define EC_FRAME_HEADER_SIZE
Size of an EtherCAT frame header.
#define EC_ADDR_LEN
Size of the EtherCAT address field.
#define EC_DATAGRAM_HEADER_SIZE
Size of an EtherCAT datagram header.
struct ec_slave ec_slave_t
#define EC_DATAGRAM_FOOTER_SIZE
Size of an EtherCAT datagram footer.
#define EC_DATAGRAM_NAME_SIZE
Size of the datagram description string.
ec_device_index_t
Master devices.
@ EC_DEVICE_MAIN
Main device.
@ EC_DEVICE_BACKUP
Backup device.
void ec_print_data(const uint8_t *, size_t)
Outputs frame contents for debugging purposes.
int ecrt_sdo_request_read(ec_sdo_request_t *req)
Schedule an SDO read operation.
struct ec_soe_request ec_soe_request_t
int ecrt_master_sdo_download_complete(ec_master_t *master, uint16_t slave_position, uint16_t index, const uint8_t *data, size_t data_size, uint32_t *abort_code)
Executes an SDO download request to write data to a slave via complete access.
int ecrt_master_read_idn(ec_master_t *master, uint16_t slave_position, uint8_t drive_no, uint16_t idn, uint8_t *target, size_t target_size, size_t *result_size, uint16_t *error_code)
Executes an SoE read request.
#define EC_MAX_PORTS
Maximum number of slave ports.
int ecrt_master_sync_reference_clock_to(ec_master_t *master, uint64_t sync_time)
Queues the DC reference clock drift compensation datagram for sending.
int ecrt_master_write_idn(ec_master_t *master, uint16_t slave_position, uint8_t drive_no, uint16_t idn, const uint8_t *data, size_t data_size, uint16_t *error_code)
Executes an SoE write request.
int ecrt_master_scan_progress(ec_master_t *master, ec_master_scan_progress_t *progress)
Obtains network scan progress information.
uint32_t ecrt_master_sync_monitor_process(const ec_master_t *master)
Processes the DC synchrony monitoring datagram.
int ecrt_master_state(const ec_master_t *master, ec_master_state_t *state)
Reads the current master state.
int ecrt_master_sync_slave_clocks(ec_master_t *master)
Queues the DC clock drift compensation datagram for sending.
int ecrt_master_sdo_upload(ec_master_t *master, uint16_t slave_position, uint16_t index, uint8_t subindex, uint8_t *target, size_t target_size, size_t *result_size, uint32_t *abort_code)
Executes an SDO upload request to read data from a slave.
int ecrt_master_receive(ec_master_t *master)
Fetches received frames from the hardware and processes the datagrams.
#define EC_WRITE_U8(DATA, VAL)
Write an 8-bit unsigned value to EtherCAT data.
ec_domain_t * ecrt_master_create_domain(ec_master_t *master)
Creates a new process data domain.
int ecrt_master_select_reference_clock(ec_master_t *master, ec_slave_config_t *sc)
Selects the reference clock for distributed clocks.
struct ec_sdo_request ec_sdo_request_t
struct ec_master ec_master_t
void ecrt_master_callbacks(ec_master_t *master, void(*send_cb)(void *), void(*receive_cb)(void *), void *cb_data)
Sets the locking callbacks.
int ecrt_master_application_time(ec_master_t *master, uint64_t app_time)
Sets the application time.
int ecrt_master_send(ec_master_t *master)
Sends all datagrams in the queue.
int ecrt_master_link_state(const ec_master_t *master, unsigned int dev_idx, ec_master_link_state_t *state)
Reads the current state of a redundant link.
struct ec_domain ec_domain_t
struct ec_slave_config ec_slave_config_t
int ecrt_master_reference_clock_time(const ec_master_t *master, uint32_t *time)
Get the lower 32 bit of the reference clock system time.
int ecrt_master_send_ext(ec_master_t *master)
Sends non-application datagrams.
#define EC_WRITE_U32(DATA, VAL)
Write a 32-bit unsigned value to EtherCAT data.
int ecrt_master_sync_reference_clock(ec_master_t *master)
Queues the DC reference clock drift compensation datagram for sending.
int ecrt_sdo_request_write(ec_sdo_request_t *req)
Schedule an SDO write operation.
int ecrt_master(ec_master_t *master, ec_master_info_t *master_info)
Obtains master information.
int ecrt_master_get_slave(ec_master_t *master, uint16_t slave_position, ec_slave_info_t *slave_info)
Obtains slave information.
#define EC_READ_U16(DATA)
Read a 16-bit unsigned value from EtherCAT data.
int ecrt_master_activate(ec_master_t *master)
Finishes the configuration phase and prepares for cyclic operation.
#define EC_READ_U8(DATA)
Read an 8-bit unsigned value from EtherCAT data.
int ecrt_master_deactivate(ec_master_t *master)
Deactivates the master.
int ecrt_master_sync_monitor_queue(ec_master_t *master)
Queues the DC synchrony monitoring datagram for sending.
#define EC_READ_U32(DATA)
Read a 32-bit unsigned value from EtherCAT data.
int ecrt_master_reset(ec_master_t *master)
Retry configuring slaves.
int ecrt_master_sdo_download(ec_master_t *master, uint16_t slave_position, uint16_t index, uint8_t subindex, const uint8_t *data, size_t data_size, uint32_t *abort_code)
Executes an SDO download request to write data to a slave.
#define EC_WRITE_U16(DATA, VAL)
Write a 16-bit unsigned value to EtherCAT data.
#define EC_MAX_STRING_LENGTH
Maximum string length.
ec_slave_config_t * ecrt_master_slave_config(ec_master_t *master, uint16_t alias, uint16_t position, uint32_t vendor_id, uint32_t product_code)
Obtains a slave configuration.
int ecrt_sdo_request_index(ec_sdo_request_t *req, uint16_t index, uint8_t subindex)
Set the SDO index and subindex.
ec_domain_t * ecrt_master_create_domain_err(ec_master_t *master)
Same as ecrt_master_create_domain(), but with ERR_PTR() return value.
void ec_master_request_op(ec_master_t *master)
Request OP state for configured slaves.
void ec_master_leave_idle_phase(ec_master_t *master)
Transition function from IDLE to ORPHANED phase.
const unsigned int rate_intervals[]
List of intervals for statistics [s].
void ec_master_update_device_stats(ec_master_t *)
Updates the common device statistics.
void ec_master_init_static(void)
Static variables initializer.
int ec_master_thread_start(ec_master_t *, int(*)(void *), const char *)
Starts the master thread.
static int ec_master_eoe_thread(void *)
Does the Ethernet over EtherCAT processing.
int ec_master_calc_topology_rec(ec_master_t *, ec_slave_t *, unsigned int *)
Calculates the bus topology; recursion function.
uint16_t ec_master_eoe_handler_count(const ec_master_t *master)
Get the number of EoE handlers.
void ec_master_exec_slave_fsms(ec_master_t *)
Execute slave FSMs.
void ec_master_set_send_interval(ec_master_t *master, unsigned int send_interval)
Sets the expected interval between calls to ecrt_master_send and calculates the maximum amount of dat...
static int ec_master_idle_thread(void *)
Master kernel thread function for IDLE phase.
static int ec_master_operation_thread(void *)
Master kernel thread function for OPERATION phase.
int ec_master_init(ec_master_t *master, unsigned int index, const uint8_t *main_mac, const uint8_t *backup_mac, dev_t device_number, struct class *class, unsigned int debug_level, unsigned int run_on_cpu)
Master constructor.
ec_slave_config_t * ecrt_master_slave_config_err(ec_master_t *master, uint16_t alias, uint16_t position, uint32_t vendor_id, uint32_t product_code)
Same as ecrt_master_slave_config(), but with ERR_PTR() return value.
void ec_master_calc_topology(ec_master_t *)
Calculates the bus topology.
int ec_master_enter_operation_phase(ec_master_t *master)
Transition function from IDLE to OPERATION phase.
void ec_master_find_dc_ref_clock(ec_master_t *)
Finds the DC reference clock.
#define FORCE_OUTPUT_CORRUPTED
Always output corrupted frames.
void ec_master_queue_datagram_ext(ec_master_t *master, ec_datagram_t *datagram)
Places a datagram in the non-application datagram queue.
void ec_master_queue_datagram(ec_master_t *master, ec_datagram_t *datagram)
Places a datagram in the datagram queue.
void ec_master_eoe_start(ec_master_t *master)
Starts Ethernet over EtherCAT processing on demand.
const ec_domain_t * ec_master_find_domain_const(const ec_master_t *master, unsigned int index)
Get a domain via its position in the list.
const ec_eoe_t * ec_master_get_eoe_handler_const(const ec_master_t *master, uint16_t index)
Get an EoE handler via its position in the list.
void ec_master_clear_domains(ec_master_t *)
Clear all domains.
void ec_master_clear_slave_configs(ec_master_t *)
Clear all slave configurations.
ec_domain_t * ec_master_find_domain(ec_master_t *master, unsigned int index)
Get a domain via its position in the list.
void ec_master_receive_datagrams(ec_master_t *master, ec_device_t *device, const uint8_t *frame_data, size_t size)
Processes a received frame.
void ec_master_inject_external_datagrams(ec_master_t *)
Injects external datagrams that fit into the datagram queue.
int ec_master_enter_idle_phase(ec_master_t *master)
Transition function from ORPHANED to IDLE phase.
int ec_master_debug_level(ec_master_t *master, unsigned int level)
Set the debug level.
ec_slave_t * ec_master_find_slave(ec_master_t *master, uint16_t alias, uint16_t position)
Finds a slave in the bus, given the alias and position.
const ec_slave_config_t * ec_master_get_config_const(const ec_master_t *master, unsigned int pos)
Get a slave configuration via its position in the list.
const ec_slave_t * ec_master_find_slave_const(const ec_master_t *master, uint16_t alias, uint16_t position)
Finds a slave in the bus, given the alias and position.
void ec_master_calc_transmission_delays(ec_master_t *)
Calculates the bus transmission delays.
void ec_master_attach_slave_configs(ec_master_t *master)
Attaches the slave configurations to the slaves.
void ec_master_calc_dc(ec_master_t *master)
Distributed-clocks calculations.
void ec_master_clear_eoe_handlers(ec_master_t *master)
Clear and free all EoE handlers.
void ec_master_clear_slaves(ec_master_t *master)
Clear all slaves.
void ec_master_clear(ec_master_t *master)
Destructor.
unsigned int ec_master_config_count(const ec_master_t *master)
Get the number of slave configurations provided by the application.
void ec_master_internal_send_cb(void *cb_data)
Internal sending callback.
void ec_master_send_datagrams(ec_master_t *, ec_device_index_t)
Sends the datagrams in the queue for a certain device.
void ec_master_output_stats(ec_master_t *master)
Output master statistics.
void ec_master_clear_config(ec_master_t *)
Clear the configuration applied by the application.
void ec_master_eoe_stop(ec_master_t *master)
Stops the Ethernet over EtherCAT processing.
#define EC_FIND_SLAVE
Common implementation for ec_master_find_slave() and ec_master_find_slave_const().
void ec_master_clear_device_stats(ec_master_t *)
Clears the common device statistics.
#define EC_FIND_DOMAIN
Common implementation for ec_master_find_domain() and ec_master_find_domain_const().
ec_datagram_t * ec_master_get_external_datagram(ec_master_t *)
Searches for a free datagram in the external datagram ring.
static unsigned long ext_injection_timeout_jiffies
Timeout for external datagram injection [jiffies].
#define EC_SDO_INJECTION_TIMEOUT
SDO injection timeout in microseconds.
#define EC_FIND_CONFIG
Common implementation for ec_master_get_config() and ec_master_get_config_const().
void ec_master_leave_operation_phase(ec_master_t *master)
Transition function from OPERATION to IDLE phase.
unsigned int ec_master_domain_count(const ec_master_t *master)
Get the number of domains.
ec_slave_config_t * ec_master_get_config(const ec_master_t *master, unsigned int pos)
Get a slave configuration via its position in the list.
void ec_master_internal_receive_cb(void *cb_data)
Internal receiving callback.
void ec_master_thread_stop(ec_master_t *)
Stops the master thread.
static unsigned long timeout_jiffies
Frame timeout in jiffies.
EtherCAT master structure.
#define ec_master_num_devices(MASTER)
Number of Ethernet devices.
#define EC_MASTER_INFO(master, fmt, args...)
Convenience macro for printing master-specific information to syslog.
#define EC_MASTER_DBG(master, level, fmt, args...)
Convenience macro for printing master-specific debug messages to syslog.
#define EC_EXT_RING_SIZE
Size of the external datagram ring.
@ EC_ORPHANED
Orphaned phase.
@ EC_OPERATION
Operation phase.
#define EC_MASTER_ERR(master, fmt, args...)
Convenience macro for printing master-specific errors to syslog.
#define EC_MASTER_WARN(master, fmt, args...)
Convenience macro for printing master-specific warnings to syslog.
dev_t device_number
Device number for master cdevs.
static unsigned int run_on_cpu
Bind created kernel threads to a cpu.
static unsigned int debug_level
Debug level parameter.
void ec_rtdm_dev_clear(ec_rtdm_dev_t *rtdm_dev)
Clear an RTDM device.
int ec_rtdm_dev_init(ec_rtdm_dev_t *rtdm_dev, ec_master_t *master)
Initialize an RTDM device.
void ec_sdo_request_init(ec_sdo_request_t *req)
SDO request constructor.
int ec_sdo_request_alloc(ec_sdo_request_t *req, size_t size)
Pre-allocates the data memory.
void ec_sdo_request_clear(ec_sdo_request_t *req)
SDO request destructor.
void ec_slave_calc_port_delays(ec_slave_t *slave)
Calculates the port transmission delays.
void ec_slave_request_state(ec_slave_t *slave, ec_slave_state_t state)
Request a slave state and resets the error flag.
void ec_slave_clear(ec_slave_t *slave)
Slave destructor.
void ec_slave_calc_transmission_delays_rec(ec_slave_t *slave, uint32_t *delay)
Recursively calculates transmission delays.
uint16_t ec_slave_sdo_count(const ec_slave_t *slave)
Get the number of SDOs in the dictionary.
EtherCAT slave structure.
#define EC_SLAVE_DBG(slave, level, fmt, args...)
Convenience macro for printing slave-specific debug messages to syslog.
#define EC_SLAVE_ERR(slave, fmt, args...)
Convenience macro for printing slave-specific errors to syslog.
void ec_slave_config_load_default_sync_config(ec_slave_config_t *sc)
Loads the default PDO assignment from the slave object.
void ec_slave_config_clear(ec_slave_config_t *sc)
Slave configuration destructor.
void ec_slave_config_init(ec_slave_config_t *sc, ec_master_t *master, uint16_t alias, uint16_t position, uint32_t vendor_id, uint32_t product_code)
Slave configuration constructor.
int ec_slave_config_attach(ec_slave_config_t *sc)
Attaches the configuration to the addressed slave object.
EtherCAT slave configuration structure.
Definitions of Kernel SMP macros.
int ec_soe_request_read(ec_soe_request_t *req)
Request a read operation.
void ec_soe_request_set_idn(ec_soe_request_t *req, uint16_t idn)
Set IDN.
void ec_soe_request_set_drive_no(ec_soe_request_t *req, uint8_t drive_no)
Set drive number.
int ec_soe_request_write(ec_soe_request_t *req)
Request a write operation.
void ec_soe_request_init(ec_soe_request_t *req)
SoE request constructor.
int ec_soe_request_alloc(ec_soe_request_t *req, size_t size)
Pre-allocates the data memory.
void ec_soe_request_clear(ec_soe_request_t *req)
SoE request destructor.
uint16_t working_counter
Working counter.
size_t data_size
Size of the data in data.
struct list_head ext_queue
External datagram queue item, protected by ext_queue_sem.
unsigned long jiffies_received
Jiffies, when the datagram was received.
ec_datagram_type_t type
Datagram type (APRD, BWR, etc.).
unsigned long jiffies_sent
Jiffies, when the datagram was sent.
struct list_head queue
Master datagram queue item, protected by user-supplied mutex.
uint8_t index
Index (set by master).
ec_datagram_state_t state
State.
ec_device_index_t device_index
Device via which the datagram shall be / was sent.
struct list_head sent
Master list item for sent datagrams.
uint8_t address[EC_ADDR_LEN]
Recipient address.
uint8_t * data
Datagram payload.
char name[EC_DATAGRAM_NAME_SIZE]
Description of the datagram.
unsigned int skip_count
Number of requeues when not yet received.
s32 rx_byte_rates[EC_RATE_COUNT]
Receive rates in byte/s for different statistics cycle periods.
s32 loss_rates[EC_RATE_COUNT]
Frame loss rates for different statistics cycle periods.
u64 tx_count
Number of frames sent.
s32 rx_frame_rates[EC_RATE_COUNT]
Receive rates in frames/s for different statistics cycle periods.
u64 rx_bytes
Number of bytes received.
u64 last_loss
Tx/Rx difference of last statistics cycle.
u64 last_tx_bytes
Number of bytes sent of last statistics cycle.
u64 last_tx_count
Number of frames sent of last statistics cycle.
s32 tx_byte_rates[EC_RATE_COUNT]
Transmit rates in byte/s for different statistics cycle periods.
u64 tx_bytes
Number of bytes sent.
u64 rx_count
Number of frames received.
s32 tx_frame_rates[EC_RATE_COUNT]
Transmit rates in frames/s for different statistics cycle periods.
u64 last_rx_bytes
Number of bytes received of last statistics cycle.
u64 last_rx_count
Number of frames received of last statistics cycle.
unsigned long jiffies
Jiffies of last statistic cycle.
struct sk_buff * tx_skb[EC_TX_RING_SIZE]
transmit skb ring
struct net_device * dev
pointer to the assigned net_device
uint8_t link_state
device link state
unsigned int tx_ring_index
last ring entry used to transmit
unsigned long jiffies_poll
jiffies of last poll
struct list_head list
List item.
size_t data_size
Size of the process data.
unsigned int index
Index (just a number).
unsigned int queue_datagram
the datagram is ready for queuing
ec_slave_t * slave
pointer to the corresponding slave
struct list_head list
list item
unsigned int slaves_responding[EC_MAX_NUM_DEVICES]
Number of responding slaves for every device.
ec_sdo_request_t * sdo_request
SDO request to process.
ec_slave_state_t slave_states[EC_MAX_NUM_DEVICES]
AL states of responding slaves for every device.
ec_datagram_t * datagram
Previous state datagram.
ec_slave_t * slave
slave the FSM runs on
struct list_head list
Used for execution list.
unsigned int slave_count
Number of slaves in the network.
uint64_t app_time
Application time.
uint8_t scan_busy
true, while the master is scanning the network.
unsigned int link_up
true, if the network link is up.
unsigned int link_up
true, if the given Ethernet link is up.
unsigned int al_states
Application-layer states of the slaves on the given link.
unsigned int slaves_responding
Sum of responding slaves on the given link.
Master scan progress information.
unsigned int slave_count
Number of slaves detected.
unsigned int scan_index
Index of the slave that is currently scanned.
unsigned int al_states
Application-layer states of all slaves.
unsigned int slaves_responding
Sum of responding slaves on all Ethernet devices.
unsigned int link_up
true, if at least one Ethernet link is up.
struct list_head datagram_queue
Datagram queue.
struct task_struct * eoe_thread
EoE thread.
struct work_struct sc_reset_work
Task to reset slave configuration.
unsigned int injection_seq_fsm
Datagram injection sequence number for the FSM side.
struct task_struct * thread
Master thread.
struct list_head eoe_handlers
Ethernet over EtherCAT handlers.
ec_datagram_t fsm_datagram
Datagram used for state machines.
struct list_head emerg_reg_requests
Emergency register access requests.
struct semaphore master_sem
Master semaphore.
struct list_head ext_datagram_queue
Queue for non-application datagrams.
ec_datagram_t sync_datagram
Datagram used for DC drift compensation.
size_t max_queue_size
Maximum size of datagram queue.
wait_queue_head_t request_queue
Wait queue for external requests from user space.
struct list_head fsm_exec_list
Slave FSM execution list.
struct list_head sii_requests
SII write requests.
ec_fsm_master_t fsm
Master state machine.
u64 app_time
Time of the last ecrt_master_sync() call.
wait_queue_head_t scan_queue
Queue for processes that wait for slave scanning.
unsigned int scan_busy
Current scan state.
unsigned int send_interval
Interval between two calls to ecrt_master_send().
unsigned int slave_count
Number of slaves on the bus.
void * app_cb_data
Application callback data.
void(* app_receive_cb)(void *)
Application's receive datagrams callback.
void(* receive_cb)(void *)
Current receive datagrams callback.
uint8_t datagram_index
Current datagram index.
unsigned int ext_ring_idx_fsm
Index in external datagram ring for FSM side.
ec_device_stats_t device_stats
Device statistics.
void(* send_cb)(void *)
Current send datagrams callback.
unsigned int config_busy
State of slave configuration.
ec_slave_t * dc_ref_clock
DC reference clock slave.
ec_datagram_t ref_sync_datagram
Datagram used for synchronizing the reference clock to the master clock.
struct list_head domains
List of domains.
struct semaphore config_sem
Semaphore protecting the config_busy variable and the allow_config flag.
unsigned int fsm_exec_count
Number of entries in execution list.
struct irq_work sc_reset_work_kicker
NMI-Safe kicker to trigger reset task above.
void(* app_send_cb)(void *)
Application's send datagrams callback.
u64 dc_ref_time
Common reference timestamp for DC start times.
ec_slave_t * fsm_slave
Slave that is queried next for FSM exec.
unsigned int injection_seq_rt
Datagram injection sequence number for the realtime side.
wait_queue_head_t config_queue
Queue for processes that wait for slave configuration.
struct semaphore scan_sem
Semaphore protecting the scan_busy variable and the allow_scan flag.
unsigned int run_on_cpu
bind kernel threads to this cpu
ec_datagram_t sync_mon_datagram
Datagram used for DC synchronisation monitoring.
struct rt_mutex io_mutex
Mutex used in IDLE and OP phase.
ec_slave_t * slaves
Array of slaves on the bus.
unsigned int active
Master has been activated.
unsigned int ext_ring_idx_rt
Index in external datagram ring for RT side.
unsigned int debug_level
Master debug level.
ec_stats_t stats
Cyclic statistics.
ec_slave_config_t * dc_ref_config
Application-selected DC reference clock slave config.
struct device * class_device
Master class device.
struct semaphore device_sem
Device semaphore.
ec_cdev_t cdev
Master character device.
unsigned int reserved
True, if the master is in use.
unsigned int allow_scan
True, if slave scanning is allowed.
unsigned int config_changed
The configuration changed.
struct list_head configs
List of slave configurations.
const uint8_t * macs[EC_MAX_NUM_DEVICES]
Device MAC addresses.
unsigned int scan_index
Index of slave currently scanned.
ec_datagram_t ext_datagram_ring[EC_EXT_RING_SIZE]
External datagram ring.
ec_master_phase_t phase
Master phase.
ec_device_t devices[EC_MAX_NUM_DEVICES]
EtherCAT devices.
void * cb_data
Current callback data.
struct semaphore ext_queue_sem
Semaphore protecting the ext_datagram_queue.
ec_internal_request_state_t state
SDO request state.
struct list_head list
List item.
uint8_t complete_access
SDO shall be transferred completely.
size_t data_size
Size of SDO data.
uint8_t * data
Pointer to SDO data.
uint32_t abort_code
SDO request abort code.
uint32_t serial_number
Serial number.
int16_t current_on_ebus
Power consumption in mA.
uint32_t product_code
Vendor-specific product code.
uint32_t revision_number
Revision number.
uint32_t vendor_id
Vendor ID.
unsigned int sync_count
Number of sync managers.
struct list_head list
List head.
ec_slave_t * slave
EtherCAT slave.
ec_internal_request_state_t state
State of the request.
uint32_t product_code
Slave product code.
struct list_head list
List item.
uint16_t alias
Slave alias.
ec_slave_t * slave
Slave pointer.
uint32_t vendor_id
Slave vendor ID.
uint16_t position
Index after alias.
uint32_t delay_to_next_dc
Delay [ns] to next DC slave.
uint32_t revision_number
Revision-Number stored on the slave.
uint8_t error_flag
Error flag for that slave.
int16_t current_on_ebus
Used current in mA.
uint16_t position
Offset of the slave in the ring.
uint16_t next_slave
Ring position of next DC slave on that port.
uint8_t al_state
Current state of the slave.
uint32_t product_code
Product-Code stored on the slave.
ec_slave_port_link_t link
Port link state.
uint32_t vendor_id
Vendor-ID stored on the slave.
uint16_t alias
The slaves alias if not equal to 0.
uint32_t serial_number
Serial-Number stored on the slave.
ec_slave_port_desc_t desc
Physical port type.
char name[EC_MAX_STRING_LENGTH]
Name of the slave.
uint16_t sdo_count
Number of SDOs.
struct ec_slave_info_t::@361233211213230025175247356016005201202242273317 ports[EC_MAX_PORTS]
Port information.
uint8_t sync_count
Number of sync managers.
uint32_t receive_time
Receive time on DC transmission delay measurement.
uint8_t signal_detected
Detected signal on RX port.
uint8_t link_up
Link detected.
uint8_t loop_closed
Loop closed.
uint32_t receive_time
Port receive times for delay measurement.
ec_slave_t * next_slave
Connected slaves.
ec_slave_port_link_t link
Port link status.
uint32_t delay_to_next_dc
Delay to next slave with DC support behind this port [ns].
ec_slave_port_desc_t desc
Port descriptors.
ec_sii_t sii
Extracted SII data.
unsigned int force_config
Force (re-)configuration.
ec_slave_port_t ports[EC_MAX_PORTS]
Ports.
uint32_t transmission_delay
DC system time transmission delay (offset from reference clock).
uint8_t base_dc_supported
Distributed clocks are supported.
uint16_t ring_position
Ring position.
ec_slave_config_t * config
Current configuration.
ec_slave_state_t current_state
Current application state.
uint8_t has_dc_system_time
The slave supports the DC system time register.
struct list_head sdo_requests
SDO access requests.
struct list_head soe_requests
SoE requests.
uint16_t effective_alias
Effective alias address.
uint16_t station_address
Configured station address.
ec_fsm_slave_t fsm
Slave state machine.
unsigned int error_flag
Stop processing after an error.
size_t data_size
Size of SDO data.
uint16_t error_code
SoE error code.
ec_internal_request_state_t state
Request state.
uint8_t * data
Pointer to SDO data.
struct list_head list
List item.
unsigned int corrupted
corrupted frames
unsigned long output_jiffies
time of last output
unsigned int timeouts
datagram timeouts
unsigned int unmatched
unmatched datagrams (received, but not queued any longer)