IgH EtherCAT Master  1.7.0
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 
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
46 int ec_domain_add_datagram_pair(ec_domain_t *, uint32_t, size_t, uint8_t *,
47  const unsigned int []);
48 int shall_count(const ec_fmmu_config_t *, const ec_fmmu_config_t *);
49 #if EC_MAX_NUM_DEVICES > 1
50 int 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;
70  domain->data_origin = EC_ORIG_INTERNAL;
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 
98  ec_domain_clear_data(domain);
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;
114  domain->data_origin = EC_ORIG_INTERNAL;
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  if (first_fmmu->sc == cur_fmmu->sc
204  && first_fmmu->dir == cur_fmmu->dir) {
205  return 0; // was already counted
206  }
207  }
208 
209  return 1;
210 }
211 
212 /****************************************************************************/
213 
231  ec_domain_t *domain,
232  uint32_t base_address
233  )
234 {
235  uint32_t datagram_offset;
236  size_t datagram_size;
237  unsigned int datagram_count;
238  unsigned int datagram_used[EC_DIR_COUNT];
239  ec_fmmu_config_t *fmmu;
240  const ec_fmmu_config_t *datagram_first_fmmu = NULL;
241  const ec_datagram_pair_t *datagram_pair;
242  int ret;
243 
244  domain->logical_base_address = base_address;
245 
246  if (domain->data_size && domain->data_origin == EC_ORIG_INTERNAL) {
247  if (!(domain->data =
248  (uint8_t *) kmalloc(domain->data_size, GFP_KERNEL))) {
249  EC_MASTER_ERR(domain->master, "Failed to allocate %zu bytes"
250  " internal memory for domain %u!\n",
251  domain->data_size, domain->index);
252  return -ENOMEM;
253  }
254  }
255 
256  // Cycle through all domain FMMUs and
257  // - correct the logical base addresses
258  // - set up the datagrams to carry the process data
259  // - calculate the datagrams' expected working counters
260  datagram_offset = 0;
261  datagram_size = 0;
262  datagram_count = 0;
263  datagram_used[EC_DIR_OUTPUT] = 0;
264  datagram_used[EC_DIR_INPUT] = 0;
265 
266  if (!list_empty(&domain->fmmu_configs)) {
267  datagram_first_fmmu =
268  list_entry(domain->fmmu_configs.next, ec_fmmu_config_t, list);
269  }
270 
271  list_for_each_entry(fmmu, &domain->fmmu_configs, list) {
272  size_t fmmu_remaining;
273  // Correct logical FMMU address
274  fmmu->logical_start_address += base_address;
275 
276  // If the current FMMU's data do not fit in the current datagram,
277  // allocate a new one (unless the current datagram is already empty,
278  // e.g. because the FMMU's data alone exceed the maximum datagram
279  // size; that case is handled below).
280  if (datagram_size > 0 &&
281  datagram_size + fmmu->data_size > EC_MAX_DATA_SIZE) {
282  ret = ec_domain_add_datagram_pair(domain,
283  domain->logical_base_address + datagram_offset,
284  datagram_size, domain->data + datagram_offset,
285  datagram_used);
286  if (ret < 0)
287  return ret;
288 
289  datagram_offset += datagram_size;
290  datagram_size = 0;
291  datagram_count++;
292  datagram_used[EC_DIR_OUTPUT] = 0;
293  datagram_used[EC_DIR_INPUT] = 0;
294  datagram_first_fmmu = fmmu;
295  }
296 
297  // Increment Input/Output counter to determine datagram types
298  // and calculate expected working counters
299  if (shall_count(fmmu, datagram_first_fmmu)) {
300  datagram_used[fmmu->dir]++;
301  }
302 
303  // Usually, the sync manager's data covered by this (unsplit) FMMU
304  // fits completely into the (possibly just started) datagram. If it
305  // alone exceeds the maximum datagram size, though, address it via
306  // multiple consecutive datagrams that each cover a disjoint part
307  // of the sync manager's data; the FMMU configuration itself stays
308  // a single, unmodified mapping of the sync manager's full range.
309  fmmu_remaining = fmmu->data_size;
310 
311  while (datagram_size + fmmu_remaining > EC_MAX_DATA_SIZE) {
312  size_t chunk = EC_MAX_DATA_SIZE - datagram_size;
313 
314  datagram_size += chunk;
315  fmmu_remaining -= chunk;
316 
317  ret = ec_domain_add_datagram_pair(domain,
318  domain->logical_base_address + datagram_offset,
319  datagram_size, domain->data + datagram_offset,
320  datagram_used);
321  if (ret < 0)
322  return ret;
323 
324  datagram_offset += datagram_size;
325  datagram_size = 0;
326  datagram_count++;
327  datagram_used[EC_DIR_OUTPUT] = 0;
328  datagram_used[EC_DIR_INPUT] = 0;
329  datagram_first_fmmu = fmmu;
330 
331  // The remaining part of the sync manager's data is still
332  // covered by the same (unsplit) FMMU, hence the same slave
333  // config/direction, so it has to be counted again for the new
334  // datagram.
335  if (shall_count(fmmu, datagram_first_fmmu)) {
336  datagram_used[fmmu->dir]++;
337  }
338  }
339 
340  datagram_size += fmmu_remaining;
341  }
342 
343  /* Allocate last datagram pair, if data are left (this is also the case if
344  * the process data fit into a single datagram) */
345  if (datagram_size) {
346  ret = ec_domain_add_datagram_pair(domain,
347  domain->logical_base_address + datagram_offset,
348  datagram_size, domain->data + datagram_offset,
349  datagram_used);
350  if (ret < 0)
351  return ret;
352  datagram_count++;
353  }
354 
355  EC_MASTER_INFO(domain->master, "Domain%u: Logical address 0x%08x,"
356  " %zu byte, expected working counter %u.\n", domain->index,
357  domain->logical_base_address, domain->data_size,
358  domain->expected_working_counter);
359 
360  list_for_each_entry(datagram_pair, &domain->datagram_pairs, list) {
361  const ec_datagram_t *datagram =
362  &datagram_pair->datagrams[EC_DEVICE_MAIN];
363  EC_MASTER_INFO(domain->master, " Datagram %s: Logical offset 0x%08x,"
364  " %zu byte, type %s.\n", datagram->name,
365  EC_READ_U32(datagram->address), datagram->data_size,
366  ec_datagram_type_string(datagram));
367  }
368 
369  return 0;
370 }
371 
372 /****************************************************************************/
373 
376 unsigned int ec_domain_fmmu_count(const ec_domain_t *domain)
377 {
378  const ec_fmmu_config_t *fmmu;
379  unsigned int num = 0;
380 
381  list_for_each_entry(fmmu, &domain->fmmu_configs, list) {
382  num++;
383  }
384 
385  return num;
386 }
387 
388 /****************************************************************************/
389 
395  const ec_domain_t *domain,
396  unsigned int pos
397  )
398 {
399  const ec_fmmu_config_t *fmmu;
400 
401  list_for_each_entry(fmmu, &domain->fmmu_configs, list) {
402  if (pos--)
403  continue;
404  return fmmu;
405  }
406 
407  return NULL;
408 }
409 
410 /****************************************************************************/
411 
412 #if EC_MAX_NUM_DEVICES > 1
413 
417  uint8_t *send_buffer,
418  const ec_datagram_t *datagram,
419  size_t offset,
420  size_t size
421  )
422 {
423  uint8_t *sent = send_buffer + offset;
424  uint8_t *recv = datagram->data + offset;
425  size_t i;
426 
427  for (i = 0; i < size; i++) {
428  if (recv[i] != sent[i]) {
429  return 1;
430  }
431  }
432 
433  return 0;
434 }
435 
436 #endif
437 
438 /*****************************************************************************
439  * Application interface
440  ****************************************************************************/
441 
443  const ec_pdo_entry_reg_t *regs)
444 {
445  const ec_pdo_entry_reg_t *reg;
446  ec_slave_config_t *sc;
447  int ret;
448 
449  EC_MASTER_DBG(domain->master, 1, "%s(domain = 0x%p, regs = 0x%p)\n",
450  __func__, domain, regs);
451 
452  for (reg = regs; reg->index; reg++) {
453  sc = ecrt_master_slave_config_err(domain->master, reg->alias,
454  reg->position, reg->vendor_id, reg->product_code);
455  if (IS_ERR(sc))
456  return PTR_ERR(sc);
457 
458  ret = ecrt_slave_config_reg_pdo_entry(sc, reg->index,
459  reg->subindex, domain, reg->bit_position);
460  if (ret < 0)
461  return ret;
462 
463  *reg->offset = ret;
464  }
465 
466  return 0;
467 }
468 
469 /****************************************************************************/
470 
471 size_t ecrt_domain_size(const ec_domain_t *domain)
472 {
473  return domain->data_size;
474 }
475 
476 /****************************************************************************/
477 
478 void ecrt_domain_external_memory(ec_domain_t *domain, uint8_t *mem)
479 {
480  EC_MASTER_DBG(domain->master, 1, "%s(domain = 0x%p, mem = 0x%p)\n",
481  __func__, domain, mem);
482 
483  down(&domain->master->master_sem);
484 
485  ec_domain_clear_data(domain);
486 
487  domain->data = mem;
488  domain->data_origin = EC_ORIG_EXTERNAL;
489 
490  up(&domain->master->master_sem);
491 }
492 
493 /****************************************************************************/
494 
495 uint8_t *ecrt_domain_data(const ec_domain_t *domain)
496 {
497  return domain->data;
498 }
499 
500 /****************************************************************************/
501 
503 {
504  uint16_t wc_sum[EC_MAX_NUM_DEVICES] = {}, wc_total;
505  ec_datagram_pair_t *pair;
506 #if EC_MAX_NUM_DEVICES > 1
507  uint16_t datagram_pair_wc, redundant_wc;
508  unsigned int datagram_offset;
509  ec_fmmu_config_t *fmmu = list_first_entry(&domain->fmmu_configs,
510  ec_fmmu_config_t, list);
511  unsigned int redundancy;
512 #endif
513  unsigned int dev_idx;
514 #ifdef EC_RT_SYSLOG
515  unsigned int wc_change;
516 #endif
517 
518 #if DEBUG_REDUNDANCY
519  EC_MASTER_DBG(domain->master, 1, "domain %u process\n", domain->index);
520 #endif
521 
522  list_for_each_entry(pair, &domain->datagram_pairs, list) {
523 #if EC_MAX_NUM_DEVICES > 1
524  datagram_pair_wc = ec_datagram_pair_process(pair, wc_sum);
525 #else
526  ec_datagram_pair_process(pair, wc_sum);
527 #endif
528 
529 #if EC_MAX_NUM_DEVICES > 1
530  if (ec_master_num_devices(domain->master) > 1) {
531  ec_datagram_t *main_datagram = &pair->datagrams[EC_DEVICE_MAIN];
532  uint32_t logical_datagram_address =
533  EC_READ_U32(main_datagram->address);
534  size_t datagram_size = main_datagram->data_size;
535 
536 #if DEBUG_REDUNDANCY
537  EC_MASTER_DBG(domain->master, 1, "dgram %s log=%u\n",
538  main_datagram->name, logical_datagram_address);
539 #endif
540 
541  /* Redundancy: Go through FMMU configs to detect data changes. */
542  list_for_each_entry_from(fmmu, &domain->fmmu_configs, list) {
543  ec_datagram_t *backup_datagram =
544  &pair->datagrams[EC_DEVICE_BACKUP];
545 
546  if (fmmu->dir != EC_DIR_INPUT) {
547  continue;
548  }
549 
550  if (fmmu->logical_start_address >=
551  logical_datagram_address + datagram_size) {
552  // fmmu data contained in next datagram pair
553  break;
554  }
555 
556  datagram_offset =
557  fmmu->logical_start_address - logical_datagram_address;
558 
559 #if DEBUG_REDUNDANCY
560  EC_MASTER_DBG(domain->master, 1,
561  "input fmmu log=%u size=%u offset=%u\n",
562  fmmu->logical_start_address, fmmu->data_size,
563  datagram_offset);
564  if (domain->master->debug_level > 0) {
565  ec_print_data(pair->send_buffer + datagram_offset,
566  fmmu->data_size);
567  ec_print_data(main_datagram->data + datagram_offset,
568  fmmu->data_size);
569  ec_print_data(backup_datagram->data + datagram_offset,
570  fmmu->data_size);
571  }
572 #endif
573 
574  if (data_changed(pair->send_buffer, main_datagram,
575  datagram_offset, fmmu->data_size)) {
576  /* data changed on main link: no copying necessary. */
577 #if DEBUG_REDUNDANCY
578  EC_MASTER_DBG(domain->master, 1, "main changed\n");
579 #endif
580  } else if (data_changed(pair->send_buffer, backup_datagram,
581  datagram_offset, fmmu->data_size)) {
582  /* data changed on backup link: copy to main memory. */
583 #if DEBUG_REDUNDANCY
584  EC_MASTER_DBG(domain->master, 1, "backup changed\n");
585 #endif
586  memcpy(main_datagram->data + datagram_offset,
587  backup_datagram->data + datagram_offset,
588  fmmu->data_size);
589  } else if (datagram_pair_wc ==
590  pair->expected_working_counter) {
591  /* no change, but WC complete: use main data. */
592 #if DEBUG_REDUNDANCY
593  EC_MASTER_DBG(domain->master, 1,
594  "no change but complete\n");
595 #endif
596  } else {
597  /* no change and WC incomplete: mark WC as zero to avoid
598  * data.dependent WC flickering. */
599  datagram_pair_wc = 0;
600 #if DEBUG_REDUNDANCY
601  EC_MASTER_DBG(domain->master, 1,
602  "no change and incomplete\n");
603 #endif
604  }
605  }
606  }
607 #endif // EC_MAX_NUM_DEVICES > 1
608  }
609 
610 #if EC_MAX_NUM_DEVICES > 1
611  redundant_wc = 0;
612  for (dev_idx = EC_DEVICE_BACKUP;
613  dev_idx < ec_master_num_devices(domain->master); dev_idx++) {
614  redundant_wc += wc_sum[dev_idx];
615  }
616 
617  redundancy = redundant_wc > 0;
618  if (redundancy != domain->redundancy_active) {
619 #ifdef EC_RT_SYSLOG
620  if (redundancy) {
621  EC_MASTER_WARN(domain->master,
622  "Domain %u: Redundant link in use!\n",
623  domain->index);
624  } else {
625  EC_MASTER_INFO(domain->master,
626  "Domain %u: Redundant link unused again.\n",
627  domain->index);
628  }
629 #endif
630  domain->redundancy_active = redundancy;
631  }
632 #else
633  domain->redundancy_active = 0;
634 #endif
635 
636 #ifdef EC_RT_SYSLOG
637  wc_change = 0;
638 #endif
639  wc_total = 0;
640  for (dev_idx = EC_DEVICE_MAIN;
641  dev_idx < ec_master_num_devices(domain->master); dev_idx++) {
642  if (wc_sum[dev_idx] != domain->working_counter[dev_idx]) {
643 #ifdef EC_RT_SYSLOG
644  wc_change = 1;
645 #endif
646  domain->working_counter[dev_idx] = wc_sum[dev_idx];
647  }
648  wc_total += wc_sum[dev_idx];
649  }
650 
651 #ifdef EC_RT_SYSLOG
652  if (wc_change) {
653  domain->working_counter_changes++;
654  }
655 
656  if (domain->working_counter_changes &&
657  jiffies - domain->notify_jiffies > HZ) {
658  domain->notify_jiffies = jiffies;
659  if (domain->working_counter_changes == 1) {
660  EC_MASTER_INFO(domain->master, "Domain %u: Working counter"
661  " changed to %u/%u", domain->index,
662  wc_total, domain->expected_working_counter);
663  } else {
664  EC_MASTER_INFO(domain->master, "Domain %u: %u working counter"
665  " changes - now %u/%u", domain->index,
666  domain->working_counter_changes,
667  wc_total, domain->expected_working_counter);
668  }
669 #if EC_MAX_NUM_DEVICES > 1
670  if (ec_master_num_devices(domain->master) > 1) {
671  printk(KERN_CONT " (");
672  for (dev_idx = EC_DEVICE_MAIN;
673  dev_idx < ec_master_num_devices(domain->master);
674  dev_idx++) {
675  printk(KERN_CONT "%u", domain->working_counter[dev_idx]);
676  if (dev_idx + 1 < ec_master_num_devices(domain->master)) {
677  printk(KERN_CONT "+");
678  }
679  }
680  printk(KERN_CONT ")");
681  }
682 #endif
683  printk(KERN_CONT ".\n");
684 
685  domain->working_counter_changes = 0;
686  }
687 #endif
688  return 0;
689 }
690 
691 /****************************************************************************/
692 
694 {
695  ec_datagram_pair_t *datagram_pair;
696  ec_device_index_t dev_idx;
697 
698  list_for_each_entry(datagram_pair, &domain->datagram_pairs, list) {
699 #if EC_MAX_NUM_DEVICES > 1
700  /* copy main data to send buffer */
701  memcpy(datagram_pair->send_buffer,
702  datagram_pair->datagrams[EC_DEVICE_MAIN].data,
703  datagram_pair->datagrams[EC_DEVICE_MAIN].data_size);
704 #endif
706  &datagram_pair->datagrams[EC_DEVICE_MAIN]);
707 
708  /* copy main data to backup datagram */
709  for (dev_idx = EC_DEVICE_BACKUP;
710  dev_idx < ec_master_num_devices(domain->master); dev_idx++) {
711  memcpy(datagram_pair->datagrams[dev_idx].data,
712  datagram_pair->datagrams[EC_DEVICE_MAIN].data,
713  datagram_pair->datagrams[EC_DEVICE_MAIN].data_size);
715  &datagram_pair->datagrams[dev_idx]);
716  }
717  }
718  return 0;
719 }
720 
721 /****************************************************************************/
722 
724 {
725  unsigned int dev_idx;
726  uint16_t wc = 0;
727 
728  for (dev_idx = EC_DEVICE_MAIN;
729  dev_idx < ec_master_num_devices(domain->master); dev_idx++) {
730  wc += domain->working_counter[dev_idx];
731  }
732 
733  state->working_counter = wc;
734 
735  if (wc) {
736  if (wc == domain->expected_working_counter) {
737  state->wc_state = EC_WC_COMPLETE;
738  } else {
739  state->wc_state = EC_WC_INCOMPLETE;
740  }
741  } else {
742  state->wc_state = EC_WC_ZERO;
743  }
744 
745  state->redundancy_active = domain->redundancy_active;
746  return 0;
747 }
748 
749 /****************************************************************************/
750 
753 EXPORT_SYMBOL(ecrt_domain_reg_pdo_entry_list);
754 EXPORT_SYMBOL(ecrt_domain_size);
755 EXPORT_SYMBOL(ecrt_domain_external_memory);
756 EXPORT_SYMBOL(ecrt_domain_data);
757 EXPORT_SYMBOL(ecrt_domain_process);
758 EXPORT_SYMBOL(ecrt_domain_queue);
759 EXPORT_SYMBOL(ecrt_domain_state);
760 
763 /****************************************************************************/
unsigned int working_counter
Value of the last working counter.
Definition: ecrt.h:513
const ec_slave_config_t * sc
EtherCAT slave config.
Definition: fmmu_config.h:40
uint8_t subindex
PDO entry subindex.
Definition: ecrt.h:642
uint16_t position
Slave position.
Definition: ecrt.h:638
size_t data_size
Size of the data in data.
Definition: datagram.h:94
Domain datagram pair.
Definition: datagram_pair.h:41
FMMU configuration.
Definition: fmmu_config.h:38
size_t data_size
Size of the process data.
Definition: domain.h:53
unsigned int expected_working_counter
Expectord working conter.
Definition: datagram_pair.h:48
unsigned int redundancy_active
Redundant link is in use.
Definition: ecrt.h:515
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:442
uint16_t index
PDO entry index.
Definition: ecrt.h:641
#define ec_master_num_devices(MASTER)
Number of Ethernet devices.
Definition: master.h:333
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:930
int ecrt_domain_state(const ec_domain_t *domain, ec_domain_state_t *state)
Reads the state of a domain.
Definition: domain.c:723
EtherCAT datagram.
Definition: datagram.h:81
unsigned int data_size
Covered PDO size.
Definition: fmmu_config.h:45
char name[EC_DATAGRAM_NAME_SIZE]
Description of the datagram.
Definition: datagram.h:109
ec_wc_state_t wc_state
Working counter interpretation.
Definition: ecrt.h:514
int data_changed(uint8_t *, const ec_datagram_t *, size_t, size_t)
Process received data.
Definition: domain.c:416
void ecrt_domain_external_memory(ec_domain_t *domain, uint8_t *mem)
Provide external memory to store the domain&#39;s process data.
Definition: domain.c:478
void ec_domain_clear_data(ec_domain_t *)
Frees internally allocated memory.
Definition: domain.c:105
Global definitions and macros.
Some of the registered process data were exchanged.
Definition: ecrt.h:501
EtherCAT master structure.
uint8_t * data
Memory for the process data.
Definition: domain.h:54
uint8_t * ecrt_domain_data(const ec_domain_t *domain)
Returns the domain&#39;s process data.
Definition: domain.c:495
int ecrt_domain_queue(ec_domain_t *domain)
(Re-)queues all domain datagrams in the master&#39;s datagram queue.
Definition: domain.c:693
uint16_t alias
Slave alias address.
Definition: ecrt.h:637
Internal.
Definition: globals.h:309
#define EC_MASTER_DBG(master, level, fmt, args...)
Convenience macro for printing master-specific debug messages to syslog.
Definition: master.h:100
struct semaphore master_sem
Master semaphore.
Definition: master.h:205
uint32_t logical_start_address
Logical start address.
Definition: fmmu_config.h:44
struct list_head list
List node used by domain.
Definition: fmmu_config.h:39
unsigned int working_counter_changes
Working counter changes since last notification.
Definition: domain.h:63
const ec_domain_t * domain
Domain.
Definition: fmmu_config.h:41
Domain state.
Definition: ecrt.h:512
uint32_t vendor_id
Slave vendor ID.
Definition: ecrt.h:639
unsigned int * bit_position
Pointer to a variable to store a bit position (0-7) within the offset.
Definition: ecrt.h:645
void ec_domain_clear(ec_domain_t *domain)
Domain destructor.
Definition: domain.c:87
int ec_domain_finish(ec_domain_t *domain, uint32_t base_address)
Finishes a domain.
Definition: domain.c:230
size_t ecrt_domain_size(const ec_domain_t *domain)
Returns the current size of the domain&#39;s process data.
Definition: domain.c:471
unsigned int debug_level
Master debug level.
Definition: master.h:284
uint16_t ec_datagram_pair_process(ec_datagram_pair_t *pair, uint16_t wc_sum[])
Process received data.
ec_device_index_t
Master devices.
Definition: globals.h:203
void ec_datagram_pair_clear(ec_datagram_pair_t *pair)
Datagram pair destructor.
unsigned int index
Index (just a number).
Definition: domain.h:50
External.
Definition: globals.h:310
Main device.
Definition: globals.h:204
#define EC_READ_U32(DATA)
Read a 32-bit unsigned value from EtherCAT data.
Definition: ecrt.h:3277
struct list_head fmmu_configs
FMMU configurations contained.
Definition: domain.h:52
#define EC_MASTER_WARN(master, fmt, args...)
Convenience macro for printing master-specific warnings to syslog.
Definition: master.h:86
unsigned int ec_domain_fmmu_count(const ec_domain_t *domain)
Get the number of FMMU configurations of the domain.
Definition: domain.c:376
#define EC_MASTER_ERR(master, fmt, args...)
Convenience macro for printing master-specific errors to syslog.
Definition: master.h:74
void ec_master_queue_datagram(ec_master_t *master, ec_datagram_t *datagram)
Places a datagram in the datagram queue.
Definition: master.c:980
Values read by the master.
Definition: ecrt.h:525
ec_origin_t data_origin
Origin of the data memory.
Definition: domain.h:55
void ec_print_data(const uint8_t *, size_t)
Outputs frame contents for debugging purposes.
Definition: module.c:348
uint16_t working_counter[EC_MAX_NUM_DEVICES]
Last working counter values.
Definition: domain.h:60
uint32_t logical_base_address
Logical offset address of the process data.
Definition: domain.h:56
uint16_t expected_working_counter
Expected working counter.
Definition: domain.h:62
unsigned int redundancy_active
Non-zero, if redundancy is in use.
Definition: domain.h:65
int ecrt_domain_process(ec_domain_t *domain)
Determines the states of the domain&#39;s datagrams.
Definition: domain.c:502
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:40
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
Number of directions.
Definition: ecrt.h:526
struct list_head list
List header.
Definition: datagram_pair.h:42
List record type for PDO entry mass-registration.
Definition: ecrt.h:636
EtherCAT domain structure.
No registered process data were exchanged.
Definition: ecrt.h:500
All registered process data were exchanged.
Definition: ecrt.h:503
EtherCAT datagram pair structure.
const char * ec_datagram_type_string(const ec_datagram_t *datagram)
Returns a string describing the datagram type.
Definition: datagram.c:648
uint8_t * data
Datagram payload.
Definition: datagram.h:91
EtherCAT slave configuration.
Definition: slave_config.h:111
ec_datagram_t datagrams[EC_MAX_NUM_DEVICES]
Datagrams.
Definition: datagram_pair.h:44
EtherCAT slave configuration structure.
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:2953
unsigned int * offset
Pointer to a variable to store the PDO entry&#39;s (byte-)offset in the process data. ...
Definition: ecrt.h:643
uint8_t address[EC_ADDR_LEN]
Recipient address.
Definition: datagram.h:90
void ec_domain_init(ec_domain_t *domain, ec_master_t *master, unsigned int index)
Domain constructor.
Definition: domain.c:57
ec_direction_t dir
FMMU direction.
Definition: fmmu_config.h:43
Backup device.
Definition: globals.h:205
Values written by the master.
Definition: ecrt.h:524
struct list_head datagram_pairs
Datagrams pairs (main/backup) for process data exchange.
Definition: domain.h:58
#define EC_MASTER_INFO(master, fmt, args...)
Convenience macro for printing master-specific information to syslog.
Definition: master.h:62
uint32_t product_code
Slave product code.
Definition: ecrt.h:640
EtherCAT master.
Definition: master.h:194
unsigned long notify_jiffies
Time of last notification.
Definition: domain.h:66
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
int shall_count(const ec_fmmu_config_t *, const ec_fmmu_config_t *)
Domain finish helper function.
Definition: domain.c:194
EtherCAT domain.
Definition: domain.h:46
ec_master_t * master
EtherCAT master owning the domain.
Definition: domain.h:49
#define EC_MAX_DATA_SIZE
Resulting maximum data size of a single datagram in a frame.
Definition: globals.h:79
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:394