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