IgH EtherCAT Master  1.5.2
domain.c
Go to the documentation of this file.
1/******************************************************************************
2 *
3 * $Id$
4 *
5 * Copyright (C) 2006-2008 Florian Pose, Ingenieurgemeinschaft IgH
6 *
7 * This file is part of the IgH EtherCAT Master.
8 *
9 * The IgH EtherCAT Master is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License version 2, as
11 * published by the Free Software Foundation.
12 *
13 * The IgH EtherCAT Master is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
16 * Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License along
19 * with the IgH EtherCAT Master; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
21 *
22 * ---
23 *
24 * The license mentioned above concerns the source code only. Using the
25 * EtherCAT technology and brand is only permitted in compliance with the
26 * industrial property and similar rights of Beckhoff Automation GmbH.
27 *
28 *****************************************************************************/
29
35/*****************************************************************************/
36
37#include <linux/module.h>
38
39#include "globals.h"
40#include "master.h"
41#include "slave_config.h"
42
43#include "domain.h"
44#include "datagram_pair.h"
45
48#define DEBUG_REDUNDANCY 0
49
50/*****************************************************************************/
51
53
54/*****************************************************************************/
55
59 ec_domain_t *domain,
60 ec_master_t *master,
61 unsigned int index
62 )
63{
64 unsigned int dev_idx;
65
66 domain->master = master;
67 domain->index = index;
68 INIT_LIST_HEAD(&domain->fmmu_configs);
69 domain->data_size = 0;
70 domain->data = NULL;
72 domain->logical_base_address = 0x00000000;
73 INIT_LIST_HEAD(&domain->datagram_pairs);
74 for (dev_idx = EC_DEVICE_MAIN; dev_idx < ec_master_num_devices(master);
75 dev_idx++) {
76 domain->working_counter[dev_idx] = 0x0000;
77 }
78 domain->expected_working_counter = 0x0000;
79 domain->working_counter_changes = 0;
80 domain->redundancy_active = 0;
81 domain->notify_jiffies = 0;
82}
83
84/*****************************************************************************/
85
89{
90 ec_datagram_pair_t *datagram_pair, *next_pair;
91
92 // dequeue and free datagrams
93 list_for_each_entry_safe(datagram_pair, next_pair,
94 &domain->datagram_pairs, list) {
95 ec_datagram_pair_clear(datagram_pair);
96 kfree(datagram_pair);
97 }
98
100}
101
102/*****************************************************************************/
103
107 ec_domain_t *domain
108 )
109{
110 if (domain->data_origin == EC_ORIG_INTERNAL && domain->data) {
111 kfree(domain->data);
112 }
113
114 domain->data = NULL;
116}
117
118/*****************************************************************************/
119
123 ec_domain_t *domain,
124 ec_fmmu_config_t *fmmu
125 )
126{
127 fmmu->domain = domain;
128
129 domain->data_size += fmmu->data_size;
130 list_add_tail(&fmmu->list, &domain->fmmu_configs);
131
132 EC_MASTER_DBG(domain->master, 1, "Domain %u:"
133 " Added %u bytes, total %zu.\n",
134 domain->index, fmmu->data_size, domain->data_size);
135}
136
137/*****************************************************************************/
138
148 ec_domain_t *domain,
149 uint32_t logical_offset,
150 size_t data_size,
151 uint8_t *data,
152 const unsigned int used[]
153 )
154{
155 ec_datagram_pair_t *datagram_pair;
156 int ret;
157
158 if (!(datagram_pair = kmalloc(sizeof(ec_datagram_pair_t), GFP_KERNEL))) {
159 EC_MASTER_ERR(domain->master,
160 "Failed to allocate domain datagram pair!\n");
161 return -ENOMEM;
162 }
163
164 ret = ec_datagram_pair_init(datagram_pair, domain, logical_offset, data,
165 data_size, used);
166 if (ret) {
167 kfree(datagram_pair);
168 return ret;
169 }
170
171 domain->expected_working_counter +=
172 datagram_pair->expected_working_counter;
173
174 EC_MASTER_DBG(domain->master, 1,
175 "Adding datagram pair with expected WC %u.\n",
176 datagram_pair->expected_working_counter);
177
178
179 list_add_tail(&datagram_pair->list, &domain->datagram_pairs);
180 return 0;
181}
182
183/*****************************************************************************/
184
196 const ec_fmmu_config_t *cur_fmmu,
198 const ec_fmmu_config_t *first_fmmu
199 )
200{
201 for (; first_fmmu != cur_fmmu;
202 first_fmmu = list_entry(first_fmmu->list.next,
203 ec_fmmu_config_t, list)) {
204
205 if (first_fmmu->sc == cur_fmmu->sc
206 && first_fmmu->dir == cur_fmmu->dir) {
207 return 0; // was already counted
208 }
209 }
210
211 return 1;
212}
213
214/*****************************************************************************/
215
227 ec_domain_t *domain,
228 uint32_t base_address
229 )
230{
231 uint32_t datagram_offset;
232 size_t datagram_size;
233 unsigned int datagram_count;
234 unsigned int datagram_used[EC_DIR_COUNT];
235 ec_fmmu_config_t *fmmu;
236 const ec_fmmu_config_t *datagram_first_fmmu = NULL;
237 const ec_datagram_pair_t *datagram_pair;
238 int ret;
239
240 domain->logical_base_address = base_address;
241
242 if (domain->data_size && domain->data_origin == EC_ORIG_INTERNAL) {
243 if (!(domain->data =
244 (uint8_t *) kmalloc(domain->data_size, GFP_KERNEL))) {
245 EC_MASTER_ERR(domain->master, "Failed to allocate %zu bytes"
246 " internal memory for domain %u!\n",
247 domain->data_size, domain->index);
248 return -ENOMEM;
249 }
250 }
251
252 // Cycle through all domain FMMUs and
253 // - correct the logical base addresses
254 // - set up the datagrams to carry the process data
255 // - calculate the datagrams' expected working counters
256 datagram_offset = 0;
257 datagram_size = 0;
258 datagram_count = 0;
259 datagram_used[EC_DIR_OUTPUT] = 0;
260 datagram_used[EC_DIR_INPUT] = 0;
261
262 if (!list_empty(&domain->fmmu_configs)) {
263 datagram_first_fmmu =
264 list_entry(domain->fmmu_configs.next, ec_fmmu_config_t, list);
265 }
266
267 list_for_each_entry(fmmu, &domain->fmmu_configs, list) {
268
269 // Correct logical FMMU address
270 fmmu->logical_start_address += base_address;
271
272 // If the current FMMU's data do not fit in the current datagram,
273 // allocate a new one.
274 if (datagram_size + fmmu->data_size > EC_MAX_DATA_SIZE) {
275 ret = ec_domain_add_datagram_pair(domain,
276 domain->logical_base_address + datagram_offset,
277 datagram_size, domain->data + datagram_offset,
278 datagram_used);
279 if (ret < 0)
280 return ret;
281
282 datagram_offset += datagram_size;
283 datagram_size = 0;
284 datagram_count++;
285 datagram_used[EC_DIR_OUTPUT] = 0;
286 datagram_used[EC_DIR_INPUT] = 0;
287 datagram_first_fmmu = fmmu;
288 }
289
290 // Increment Input/Output counter to determine datagram types
291 // and calculate expected working counters
292 if (shall_count(fmmu, datagram_first_fmmu)) {
293 datagram_used[fmmu->dir]++;
294 }
295
296 datagram_size += fmmu->data_size;
297 }
298
299 /* Allocate last datagram pair, if data are left (this is also the case if
300 * the process data fit into a single datagram) */
301 if (datagram_size) {
302 ret = ec_domain_add_datagram_pair(domain,
303 domain->logical_base_address + datagram_offset,
304 datagram_size, domain->data + datagram_offset,
305 datagram_used);
306 if (ret < 0)
307 return ret;
308 datagram_count++;
309 }
310
311 EC_MASTER_INFO(domain->master, "Domain%u: Logical address 0x%08x,"
312 " %zu byte, expected working counter %u.\n", domain->index,
313 domain->logical_base_address, domain->data_size,
315
316 list_for_each_entry(datagram_pair, &domain->datagram_pairs, list) {
317 const ec_datagram_t *datagram =
318 &datagram_pair->datagrams[EC_DEVICE_MAIN];
319 EC_MASTER_INFO(domain->master, " Datagram %s: Logical offset 0x%08x,"
320 " %zu byte, type %s.\n", datagram->name,
321 EC_READ_U32(datagram->address), datagram->data_size,
322 ec_datagram_type_string(datagram));
323 }
324
325 return 0;
326}
327
328/*****************************************************************************/
329
332unsigned int ec_domain_fmmu_count(const ec_domain_t *domain)
333{
334 const ec_fmmu_config_t *fmmu;
335 unsigned int num = 0;
336
337 list_for_each_entry(fmmu, &domain->fmmu_configs, list) {
338 num++;
339 }
340
341 return num;
342}
343
344/*****************************************************************************/
345
351 const ec_domain_t *domain,
352 unsigned int pos
353 )
354{
355 const ec_fmmu_config_t *fmmu;
356
357 list_for_each_entry(fmmu, &domain->fmmu_configs, list) {
358 if (pos--)
359 continue;
360 return fmmu;
361 }
362
363 return NULL;
364}
365
366/*****************************************************************************/
367
368#if EC_MAX_NUM_DEVICES > 1
369
372int data_changed(
373 uint8_t *send_buffer,
374 const ec_datagram_t *datagram,
375 size_t offset,
376 size_t size
377 )
378{
379 uint8_t *sent = send_buffer + offset;
380 uint8_t *recv = datagram->data + offset;
381 size_t i;
382
383 for (i = 0; i < size; i++) {
384 if (recv[i] != sent[i]) {
385 return 1;
386 }
387 }
388
389 return 0;
390}
391
392#endif
393
394/******************************************************************************
395 * Application interface
396 *****************************************************************************/
397
399 const ec_pdo_entry_reg_t *regs)
400{
401 const ec_pdo_entry_reg_t *reg;
403 int ret;
404
405 EC_MASTER_DBG(domain->master, 1, "ecrt_domain_reg_pdo_entry_list("
406 "domain = 0x%p, regs = 0x%p)\n", domain, regs);
407
408 for (reg = regs; reg->index; reg++) {
409 sc = ecrt_master_slave_config_err(domain->master, reg->alias,
410 reg->position, reg->vendor_id, reg->product_code);
411 if (IS_ERR(sc))
412 return PTR_ERR(sc);
413
415 reg->subindex, domain, reg->bit_position);
416 if (ret < 0)
417 return ret;
418
419 *reg->offset = ret;
420 }
421
422 return 0;
423}
424
425/*****************************************************************************/
426
427size_t ecrt_domain_size(const ec_domain_t *domain)
428{
429 return domain->data_size;
430}
431
432/*****************************************************************************/
433
434void ecrt_domain_external_memory(ec_domain_t *domain, uint8_t *mem)
435{
436 EC_MASTER_DBG(domain->master, 1, "ecrt_domain_external_memory("
437 "domain = 0x%p, mem = 0x%p)\n", domain, mem);
438
439 down(&domain->master->master_sem);
440
441 ec_domain_clear_data(domain);
442
443 domain->data = mem;
445
446 up(&domain->master->master_sem);
447}
448
449/*****************************************************************************/
450
452{
453 return domain->data;
454}
455
456/*****************************************************************************/
457
459{
460 uint16_t wc_sum[EC_MAX_NUM_DEVICES] = {}, wc_total;
461 ec_datagram_pair_t *pair;
462#if EC_MAX_NUM_DEVICES > 1
463 uint16_t datagram_pair_wc, redundant_wc;
464 unsigned int datagram_offset;
465 ec_fmmu_config_t *fmmu = list_first_entry(&domain->fmmu_configs,
466 ec_fmmu_config_t, list);
467 unsigned int redundancy;
468#endif
469 unsigned int dev_idx;
470#ifdef EC_RT_SYSLOG
471 unsigned int wc_change;
472#endif
473
474#if DEBUG_REDUNDANCY
475 EC_MASTER_DBG(domain->master, 1, "domain %u process\n", domain->index);
476#endif
477
478 list_for_each_entry(pair, &domain->datagram_pairs, list) {
479#if EC_MAX_NUM_DEVICES > 1
480 datagram_pair_wc = ec_datagram_pair_process(pair, wc_sum);
481#else
482 ec_datagram_pair_process(pair, wc_sum);
483#endif
484
485#if EC_MAX_NUM_DEVICES > 1
486 if (ec_master_num_devices(domain->master) > 1) {
487 ec_datagram_t *main_datagram = &pair->datagrams[EC_DEVICE_MAIN];
488 uint32_t logical_datagram_address =
489 EC_READ_U32(main_datagram->address);
490 size_t datagram_size = main_datagram->data_size;
491
492#if DEBUG_REDUNDANCY
493 EC_MASTER_DBG(domain->master, 1, "dgram %s log=%u\n",
494 main_datagram->name, logical_datagram_address);
495#endif
496
497 /* Redundancy: Go through FMMU configs to detect data changes. */
498 list_for_each_entry_from(fmmu, &domain->fmmu_configs, list) {
499 ec_datagram_t *backup_datagram =
501
502 if (fmmu->dir != EC_DIR_INPUT) {
503 continue;
504 }
505
506 if (fmmu->logical_start_address >=
507 logical_datagram_address + datagram_size) {
508 // fmmu data contained in next datagram pair
509 break;
510 }
511
512 datagram_offset =
513 fmmu->logical_start_address - logical_datagram_address;
514
515#if DEBUG_REDUNDANCY
516 EC_MASTER_DBG(domain->master, 1,
517 "input fmmu log=%u size=%u offset=%u\n",
518 fmmu->logical_start_address, fmmu->data_size,
519 datagram_offset);
520 if (domain->master->debug_level > 0) {
521 ec_print_data(pair->send_buffer + datagram_offset,
522 fmmu->data_size);
523 ec_print_data(main_datagram->data + datagram_offset,
524 fmmu->data_size);
525 ec_print_data(backup_datagram->data + datagram_offset,
526 fmmu->data_size);
527 }
528#endif
529
530 if (data_changed(pair->send_buffer, main_datagram,
531 datagram_offset, fmmu->data_size)) {
532 /* data changed on main link: no copying necessary. */
533#if DEBUG_REDUNDANCY
534 EC_MASTER_DBG(domain->master, 1, "main changed\n");
535#endif
536 } else if (data_changed(pair->send_buffer, backup_datagram,
537 datagram_offset, fmmu->data_size)) {
538 /* data changed on backup link: copy to main memory. */
539#if DEBUG_REDUNDANCY
540 EC_MASTER_DBG(domain->master, 1, "backup changed\n");
541#endif
542 memcpy(main_datagram->data + datagram_offset,
543 backup_datagram->data + datagram_offset,
544 fmmu->data_size);
545 } else if (datagram_pair_wc ==
547 /* no change, but WC complete: use main data. */
548#if DEBUG_REDUNDANCY
549 EC_MASTER_DBG(domain->master, 1,
550 "no change but complete\n");
551#endif
552 } else {
553 /* no change and WC incomplete: mark WC as zero to avoid
554 * data.dependent WC flickering. */
555 datagram_pair_wc = 0;
556#if DEBUG_REDUNDANCY
557 EC_MASTER_DBG(domain->master, 1,
558 "no change and incomplete\n");
559#endif
560 }
561 }
562 }
563#endif // EC_MAX_NUM_DEVICES > 1
564 }
565
566#if EC_MAX_NUM_DEVICES > 1
567 redundant_wc = 0;
568 for (dev_idx = EC_DEVICE_BACKUP;
569 dev_idx < ec_master_num_devices(domain->master); dev_idx++) {
570 redundant_wc += wc_sum[dev_idx];
571 }
572
573 redundancy = redundant_wc > 0;
574 if (redundancy != domain->redundancy_active) {
575#ifdef EC_RT_SYSLOG
576 if (redundancy) {
577 EC_MASTER_WARN(domain->master,
578 "Domain %u: Redundant link in use!\n",
579 domain->index);
580 } else {
581 EC_MASTER_INFO(domain->master,
582 "Domain %u: Redundant link unused again.\n",
583 domain->index);
584 }
585#endif
586 domain->redundancy_active = redundancy;
587 }
588#else
589 domain->redundancy_active = 0;
590#endif
591
592#ifdef EC_RT_SYSLOG
593 wc_change = 0;
594#endif
595 wc_total = 0;
596 for (dev_idx = EC_DEVICE_MAIN;
597 dev_idx < ec_master_num_devices(domain->master); dev_idx++) {
598 if (wc_sum[dev_idx] != domain->working_counter[dev_idx]) {
599#ifdef EC_RT_SYSLOG
600 wc_change = 1;
601#endif
602 domain->working_counter[dev_idx] = wc_sum[dev_idx];
603 }
604 wc_total += wc_sum[dev_idx];
605 }
606
607#ifdef EC_RT_SYSLOG
608 if (wc_change) {
609 domain->working_counter_changes++;
610 }
611
612 if (domain->working_counter_changes &&
613 jiffies - domain->notify_jiffies > HZ) {
614 domain->notify_jiffies = jiffies;
615 if (domain->working_counter_changes == 1) {
616 EC_MASTER_INFO(domain->master, "Domain %u: Working counter"
617 " changed to %u/%u", domain->index,
618 wc_total, domain->expected_working_counter);
619 } else {
620 EC_MASTER_INFO(domain->master, "Domain %u: %u working counter"
621 " changes - now %u/%u", domain->index,
623 wc_total, domain->expected_working_counter);
624 }
625#if EC_MAX_NUM_DEVICES > 1
626 if (ec_master_num_devices(domain->master) > 1) {
627 printk(KERN_CONT " (");
628 for (dev_idx = EC_DEVICE_MAIN;
629 dev_idx < ec_master_num_devices(domain->master);
630 dev_idx++) {
631 printk(KERN_CONT "%u", domain->working_counter[dev_idx]);
632 if (dev_idx + 1 < ec_master_num_devices(domain->master)) {
633 printk(KERN_CONT "+");
634 }
635 }
636 printk(KERN_CONT ")");
637 }
638#endif
639 printk(KERN_CONT ".\n");
640
641 domain->working_counter_changes = 0;
642 }
643#endif
644}
645
646/*****************************************************************************/
647
649{
650 ec_datagram_pair_t *datagram_pair;
651 ec_device_index_t dev_idx;
652
653 list_for_each_entry(datagram_pair, &domain->datagram_pairs, list) {
654
655#if EC_MAX_NUM_DEVICES > 1
656 /* copy main data to send buffer */
657 memcpy(datagram_pair->send_buffer,
658 datagram_pair->datagrams[EC_DEVICE_MAIN].data,
659 datagram_pair->datagrams[EC_DEVICE_MAIN].data_size);
660#endif
662 &datagram_pair->datagrams[EC_DEVICE_MAIN]);
663
664 /* copy main data to backup datagram */
665 for (dev_idx = EC_DEVICE_BACKUP;
666 dev_idx < ec_master_num_devices(domain->master); dev_idx++) {
667 memcpy(datagram_pair->datagrams[dev_idx].data,
668 datagram_pair->datagrams[EC_DEVICE_MAIN].data,
669 datagram_pair->datagrams[EC_DEVICE_MAIN].data_size);
671 &datagram_pair->datagrams[dev_idx]);
672 }
673 }
674}
675
676/*****************************************************************************/
677
679{
680 unsigned int dev_idx;
681 uint16_t wc = 0;
682
683 for (dev_idx = EC_DEVICE_MAIN;
684 dev_idx < ec_master_num_devices(domain->master); dev_idx++) {
685 wc += domain->working_counter[dev_idx];
686 }
687
688 state->working_counter = wc;
689
690 if (wc) {
691 if (wc == domain->expected_working_counter) {
692 state->wc_state = EC_WC_COMPLETE;
693 } else {
694 state->wc_state = EC_WC_INCOMPLETE;
695 }
696 } else {
697 state->wc_state = EC_WC_ZERO;
698 }
699
700 state->redundancy_active = domain->redundancy_active;
701}
702
703/*****************************************************************************/
704
707EXPORT_SYMBOL(ecrt_domain_reg_pdo_entry_list);
708EXPORT_SYMBOL(ecrt_domain_size);
709EXPORT_SYMBOL(ecrt_domain_external_memory);
710EXPORT_SYMBOL(ecrt_domain_data);
711EXPORT_SYMBOL(ecrt_domain_process);
712EXPORT_SYMBOL(ecrt_domain_queue);
713EXPORT_SYMBOL(ecrt_domain_state);
714
717/*****************************************************************************/
const char * ec_datagram_type_string(const ec_datagram_t *datagram)
Returns a string describing the datagram type.
Definition: datagram.c:645
uint16_t ec_datagram_pair_process(ec_datagram_pair_t *pair, uint16_t wc_sum[])
Process received data.
int ec_datagram_pair_init(ec_datagram_pair_t *pair, ec_domain_t *domain, uint32_t logical_offset, uint8_t *data, size_t data_size, const unsigned int used[])
Datagram pair constructor.
Definition: datagram_pair.c:48
void ec_datagram_pair_clear(ec_datagram_pair_t *pair)
Datagram pair destructor.
EtherCAT datagram pair structure.
int ec_domain_finish(ec_domain_t *domain, uint32_t base_address)
Finishes a domain.
Definition: domain.c:226
void ec_domain_init(ec_domain_t *domain, ec_master_t *master, unsigned int index)
Domain constructor.
Definition: domain.c:58
void ec_domain_add_fmmu_config(ec_domain_t *domain, ec_fmmu_config_t *fmmu)
Adds an FMMU configuration to the domain.
Definition: domain.c:122
unsigned int ec_domain_fmmu_count(const ec_domain_t *domain)
Get the number of FMMU configurations of the domain.
Definition: domain.c:332
int shall_count(const ec_fmmu_config_t *cur_fmmu, const ec_fmmu_config_t *first_fmmu)
Domain finish helper function.
Definition: domain.c:195
void ec_domain_clear_data(ec_domain_t *)
Frees internally allocated memory.
Definition: domain.c:106
const ec_fmmu_config_t * ec_domain_find_fmmu(const ec_domain_t *domain, unsigned int pos)
Get a certain FMMU configuration via its position in the list.
Definition: domain.c:350
void ec_domain_clear(ec_domain_t *domain)
Domain destructor.
Definition: domain.c:88
int ec_domain_add_datagram_pair(ec_domain_t *domain, uint32_t logical_offset, size_t data_size, uint8_t *data, const unsigned int used[])
Allocates a domain datagram pair and appends it to the list.
Definition: domain.c:147
EtherCAT domain structure.
Global definitions and macros.
#define EC_MAX_DATA_SIZE
Resulting maximum data size of a single datagram in a frame.
Definition: globals.h:79
@ EC_ORIG_EXTERNAL
External.
Definition: globals.h:296
@ EC_ORIG_INTERNAL
Internal.
Definition: globals.h:295
ec_device_index_t
Master devices.
Definition: globals.h:189
@ EC_DEVICE_MAIN
Main device.
Definition: globals.h:190
@ EC_DEVICE_BACKUP
Backup device.
Definition: globals.h:191
void ec_print_data(const uint8_t *, size_t)
Outputs frame contents for debugging purposes.
Definition: module.c:348
int ecrt_slave_config_reg_pdo_entry(ec_slave_config_t *sc, uint16_t index, uint8_t subindex, ec_domain_t *domain, unsigned int *bit_position)
Registers a PDO entry for process data exchange in a domain.
Definition: slave_config.c:817
void ecrt_domain_queue(ec_domain_t *domain)
(Re-)queues all domain datagrams in the master's datagram queue.
Definition: domain.c:648
uint8_t * ecrt_domain_data(ec_domain_t *domain)
Returns the domain's process data.
Definition: domain.c:451
int ecrt_domain_reg_pdo_entry_list(ec_domain_t *domain, const ec_pdo_entry_reg_t *regs)
Registers a bunch of PDO entries for a domain.
Definition: domain.c:398
void ecrt_domain_state(const ec_domain_t *domain, ec_domain_state_t *state)
Reads the state of a domain.
Definition: domain.c:678
void ecrt_domain_external_memory(ec_domain_t *domain, uint8_t *mem)
Provide external memory to store the domain's process data.
Definition: domain.c:434
#define EC_READ_U32(DATA)
Read a 32-bit unsigned value from EtherCAT data.
Definition: ecrt.h:2194
void ecrt_domain_process(ec_domain_t *domain)
Determines the states of the domain's datagrams.
Definition: domain.c:458
size_t ecrt_domain_size(const ec_domain_t *domain)
Returns the current size of the domain's process data.
Definition: domain.c:427
@ EC_WC_COMPLETE
All registered process data were exchanged.
Definition: ecrt.h:411
@ EC_WC_ZERO
No registered process data were exchanged.
Definition: ecrt.h:408
@ EC_WC_INCOMPLETE
Some of the registered process data were exchanged.
Definition: ecrt.h:409
@ EC_DIR_COUNT
Number of directions.
Definition: ecrt.h:434
@ EC_DIR_INPUT
Values read by the master.
Definition: ecrt.h:433
@ EC_DIR_OUTPUT
Values written by the master.
Definition: ecrt.h:432
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.
Definition: master.c:2578
void ec_master_queue_datagram(ec_master_t *master, ec_datagram_t *datagram)
Places a datagram in the datagram queue.
Definition: master.c:952
EtherCAT master structure.
#define ec_master_num_devices(MASTER)
Number of Ethernet devices.
Definition: master.h:330
#define EC_MASTER_INFO(master, fmt, args...)
Convenience macro for printing master-specific information to syslog.
Definition: master.h:73
#define EC_MASTER_DBG(master, level, fmt, args...)
Convenience macro for printing master-specific debug messages to syslog.
Definition: master.h:111
#define EC_MASTER_ERR(master, fmt, args...)
Convenience macro for printing master-specific errors to syslog.
Definition: master.h:85
#define EC_MASTER_WARN(master, fmt, args...)
Convenience macro for printing master-specific warnings to syslog.
Definition: master.h:97
EtherCAT slave configuration structure.
Domain datagram pair.
Definition: datagram_pair.h:49
ec_datagram_t datagrams[EC_MAX_NUM_DEVICES]
Datagrams.
Definition: datagram_pair.h:52
struct list_head list
List header.
Definition: datagram_pair.h:50
unsigned int expected_working_counter
Expectord working conter.
Definition: datagram_pair.h:56
EtherCAT datagram.
Definition: datagram.h:87
size_t data_size
Size of the data in data.
Definition: datagram.h:97
uint8_t address[EC_ADDR_LEN]
Recipient address.
Definition: datagram.h:93
uint8_t * data
Datagram payload.
Definition: datagram.h:94
char name[EC_DATAGRAM_NAME_SIZE]
Description of the datagram.
Definition: datagram.h:112
Domain state.
Definition: ecrt.h:420
ec_wc_state_t wc_state
Working counter interpretation.
Definition: ecrt.h:422
unsigned int working_counter
Value of the last working counter.
Definition: ecrt.h:421
unsigned int redundancy_active
Redundant link is in use.
Definition: ecrt.h:423
EtherCAT domain.
Definition: domain.h:55
ec_origin_t data_origin
Origin of the data memory.
Definition: domain.h:63
ec_master_t * master
EtherCAT master owning the domain.
Definition: domain.h:57
unsigned long notify_jiffies
Time of last notification.
Definition: domain.h:74
uint32_t logical_base_address
Logical offset address of the process data.
Definition: domain.h:64
uint16_t working_counter[EC_MAX_NUM_DEVICES]
Last working counter values.
Definition: domain.h:68
size_t data_size
Size of the process data.
Definition: domain.h:61
struct list_head datagram_pairs
Datagrams pairs (main/backup) for process data exchange.
Definition: domain.h:66
uint8_t * data
Memory for the process data.
Definition: domain.h:62
unsigned int working_counter_changes
Working counter changes since last notification.
Definition: domain.h:71
unsigned int index
Index (just a number).
Definition: domain.h:58
unsigned int redundancy_active
Non-zero, if redundancy is in use.
Definition: domain.h:73
struct list_head fmmu_configs
FMMU configurations contained.
Definition: domain.h:60
uint16_t expected_working_counter
Expected working counter.
Definition: domain.h:70
FMMU configuration.
Definition: fmmu_config.h:46
uint32_t logical_start_address
Logical start address.
Definition: fmmu_config.h:52
const ec_domain_t * domain
Domain.
Definition: fmmu_config.h:49
const ec_slave_config_t * sc
EtherCAT slave config.
Definition: fmmu_config.h:48
unsigned int data_size
Covered PDO size.
Definition: fmmu_config.h:53
struct list_head list
List node used by domain.
Definition: fmmu_config.h:47
ec_direction_t dir
FMMU direction.
Definition: fmmu_config.h:51
EtherCAT master.
Definition: master.h:194
struct semaphore master_sem
Master semaphore.
Definition: master.h:209
unsigned int debug_level
Master debug level.
Definition: master.h:285
List record type for PDO entry mass-registration.
Definition: ecrt.h:508
uint32_t product_code
Slave product code.
Definition: ecrt.h:512
unsigned int * offset
Pointer to a variable to store the PDO entry's (byte-)offset in the process data.
Definition: ecrt.h:515
unsigned int * bit_position
Pointer to a variable to store a bit position (0-7) within the offset.
Definition: ecrt.h:517
uint8_t subindex
PDO entry subindex.
Definition: ecrt.h:514
uint16_t index
PDO entry index.
Definition: ecrt.h:513
uint16_t alias
Slave alias address.
Definition: ecrt.h:509
uint32_t vendor_id
Slave vendor ID.
Definition: ecrt.h:511
uint16_t position
Slave position.
Definition: ecrt.h:510
EtherCAT slave configuration.
Definition: slave_config.h:119