IgH EtherCAT Master  1.6.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 
45 
46 /****************************************************************************/
47 
51  ec_domain_t *domain,
52  ec_master_t *master,
53  unsigned int index
54  )
55 {
56  unsigned int dev_idx;
57 
58  domain->master = master;
59  domain->index = index;
60  INIT_LIST_HEAD(&domain->fmmu_configs);
61  domain->data_size = 0;
62  domain->data = NULL;
63  domain->data_origin = EC_ORIG_INTERNAL;
64  domain->logical_base_address = 0x00000000;
65  INIT_LIST_HEAD(&domain->datagram_pairs);
66  for (dev_idx = EC_DEVICE_MAIN; dev_idx < ec_master_num_devices(master);
67  dev_idx++) {
68  domain->working_counter[dev_idx] = 0x0000;
69  }
70  domain->expected_working_counter = 0x0000;
71  domain->working_counter_changes = 0;
72  domain->redundancy_active = 0;
73  domain->notify_jiffies = 0;
74 }
75 
76 /****************************************************************************/
77 
81 {
82  ec_datagram_pair_t *datagram_pair, *next_pair;
83 
84  // dequeue and free datagrams
85  list_for_each_entry_safe(datagram_pair, next_pair,
86  &domain->datagram_pairs, list) {
87  ec_datagram_pair_clear(datagram_pair);
88  kfree(datagram_pair);
89  }
90 
91  ec_domain_clear_data(domain);
92 }
93 
94 /****************************************************************************/
95 
99  ec_domain_t *domain
100  )
101 {
102  if (domain->data_origin == EC_ORIG_INTERNAL && domain->data) {
103  kfree(domain->data);
104  }
105 
106  domain->data = NULL;
107  domain->data_origin = EC_ORIG_INTERNAL;
108 }
109 
110 /****************************************************************************/
111 
115  ec_domain_t *domain,
116  ec_fmmu_config_t *fmmu
117  )
118 {
119  fmmu->domain = domain;
120 
121  domain->data_size += fmmu->data_size;
122  list_add_tail(&fmmu->list, &domain->fmmu_configs);
123 
124  EC_MASTER_DBG(domain->master, 1, "Domain %u:"
125  " Added %u bytes, total %zu.\n",
126  domain->index, fmmu->data_size, domain->data_size);
127 }
128 
129 /****************************************************************************/
130 
140  ec_domain_t *domain,
141  uint32_t logical_offset,
142  size_t data_size,
143  uint8_t *data,
144  const unsigned int used[]
145  )
146 {
147  ec_datagram_pair_t *datagram_pair;
148  int ret;
149 
150  if (!(datagram_pair = kmalloc(sizeof(ec_datagram_pair_t), GFP_KERNEL))) {
151  EC_MASTER_ERR(domain->master,
152  "Failed to allocate domain datagram pair!\n");
153  return -ENOMEM;
154  }
155 
156  ret = ec_datagram_pair_init(datagram_pair, domain, logical_offset, data,
157  data_size, used);
158  if (ret) {
159  kfree(datagram_pair);
160  return ret;
161  }
162 
163  domain->expected_working_counter +=
164  datagram_pair->expected_working_counter;
165 
166  EC_MASTER_DBG(domain->master, 1,
167  "Adding datagram pair with expected WC %u.\n",
168  datagram_pair->expected_working_counter);
169 
170 
171  list_add_tail(&datagram_pair->list, &domain->datagram_pairs);
172  return 0;
173 }
174 
175 /****************************************************************************/
176 
188  const ec_fmmu_config_t *cur_fmmu,
190  const ec_fmmu_config_t *first_fmmu
191  )
192 {
193  for (; first_fmmu != cur_fmmu;
194  first_fmmu = list_entry(first_fmmu->list.next,
195  ec_fmmu_config_t, list)) {
196 
197  if (first_fmmu->sc == cur_fmmu->sc
198  && first_fmmu->dir == cur_fmmu->dir) {
199  return 0; // was already counted
200  }
201  }
202 
203  return 1;
204 }
205 
206 /****************************************************************************/
207 
219  ec_domain_t *domain,
220  uint32_t base_address
221  )
222 {
223  uint32_t datagram_offset;
224  size_t datagram_size;
225  unsigned int datagram_count;
226  unsigned int datagram_used[EC_DIR_COUNT];
227  ec_fmmu_config_t *fmmu;
228  const ec_fmmu_config_t *datagram_first_fmmu = NULL;
229  const ec_datagram_pair_t *datagram_pair;
230  int ret;
231 
232  domain->logical_base_address = base_address;
233 
234  if (domain->data_size && domain->data_origin == EC_ORIG_INTERNAL) {
235  if (!(domain->data =
236  (uint8_t *) kmalloc(domain->data_size, GFP_KERNEL))) {
237  EC_MASTER_ERR(domain->master, "Failed to allocate %zu bytes"
238  " internal memory for domain %u!\n",
239  domain->data_size, domain->index);
240  return -ENOMEM;
241  }
242  }
243 
244  // Cycle through all domain FMMUs and
245  // - correct the logical base addresses
246  // - set up the datagrams to carry the process data
247  // - calculate the datagrams' expected working counters
248  datagram_offset = 0;
249  datagram_size = 0;
250  datagram_count = 0;
251  datagram_used[EC_DIR_OUTPUT] = 0;
252  datagram_used[EC_DIR_INPUT] = 0;
253 
254  if (!list_empty(&domain->fmmu_configs)) {
255  datagram_first_fmmu =
256  list_entry(domain->fmmu_configs.next, ec_fmmu_config_t, list);
257  }
258 
259  list_for_each_entry(fmmu, &domain->fmmu_configs, list) {
260 
261  // Correct logical FMMU address
262  fmmu->logical_start_address += base_address;
263 
264  // If the current FMMU's data do not fit in the current datagram,
265  // allocate a new one.
266  if (datagram_size + fmmu->data_size > EC_MAX_DATA_SIZE) {
267  ret = ec_domain_add_datagram_pair(domain,
268  domain->logical_base_address + datagram_offset,
269  datagram_size, domain->data + datagram_offset,
270  datagram_used);
271  if (ret < 0)
272  return ret;
273 
274  datagram_offset += datagram_size;
275  datagram_size = 0;
276  datagram_count++;
277  datagram_used[EC_DIR_OUTPUT] = 0;
278  datagram_used[EC_DIR_INPUT] = 0;
279  datagram_first_fmmu = fmmu;
280  }
281 
282  // Increment Input/Output counter to determine datagram types
283  // and calculate expected working counters
284  if (shall_count(fmmu, datagram_first_fmmu)) {
285  datagram_used[fmmu->dir]++;
286  }
287 
288  datagram_size += fmmu->data_size;
289  }
290 
291  /* Allocate last datagram pair, if data are left (this is also the case if
292  * the process data fit into a single datagram) */
293  if (datagram_size) {
294  ret = ec_domain_add_datagram_pair(domain,
295  domain->logical_base_address + datagram_offset,
296  datagram_size, domain->data + datagram_offset,
297  datagram_used);
298  if (ret < 0)
299  return ret;
300  datagram_count++;
301  }
302 
303  EC_MASTER_INFO(domain->master, "Domain%u: Logical address 0x%08x,"
304  " %zu byte, expected working counter %u.\n", domain->index,
305  domain->logical_base_address, domain->data_size,
306  domain->expected_working_counter);
307 
308  list_for_each_entry(datagram_pair, &domain->datagram_pairs, list) {
309  const ec_datagram_t *datagram =
310  &datagram_pair->datagrams[EC_DEVICE_MAIN];
311  EC_MASTER_INFO(domain->master, " Datagram %s: Logical offset 0x%08x,"
312  " %zu byte, type %s.\n", datagram->name,
313  EC_READ_U32(datagram->address), datagram->data_size,
314  ec_datagram_type_string(datagram));
315  }
316 
317  return 0;
318 }
319 
320 /****************************************************************************/
321 
324 unsigned int ec_domain_fmmu_count(const ec_domain_t *domain)
325 {
326  const ec_fmmu_config_t *fmmu;
327  unsigned int num = 0;
328 
329  list_for_each_entry(fmmu, &domain->fmmu_configs, list) {
330  num++;
331  }
332 
333  return num;
334 }
335 
336 /****************************************************************************/
337 
343  const ec_domain_t *domain,
344  unsigned int pos
345  )
346 {
347  const ec_fmmu_config_t *fmmu;
348 
349  list_for_each_entry(fmmu, &domain->fmmu_configs, list) {
350  if (pos--)
351  continue;
352  return fmmu;
353  }
354 
355  return NULL;
356 }
357 
358 /****************************************************************************/
359 
360 #if EC_MAX_NUM_DEVICES > 1
361 
364 int data_changed(
365  uint8_t *send_buffer,
366  const ec_datagram_t *datagram,
367  size_t offset,
368  size_t size
369  )
370 {
371  uint8_t *sent = send_buffer + offset;
372  uint8_t *recv = datagram->data + offset;
373  size_t i;
374 
375  for (i = 0; i < size; i++) {
376  if (recv[i] != sent[i]) {
377  return 1;
378  }
379  }
380 
381  return 0;
382 }
383 
384 #endif
385 
386 /*****************************************************************************
387  * Application interface
388  ****************************************************************************/
389 
391  const ec_pdo_entry_reg_t *regs)
392 {
393  const ec_pdo_entry_reg_t *reg;
394  ec_slave_config_t *sc;
395  int ret;
396 
397  EC_MASTER_DBG(domain->master, 1, "ecrt_domain_reg_pdo_entry_list("
398  "domain = 0x%p, regs = 0x%p)\n", domain, regs);
399 
400  for (reg = regs; reg->index; reg++) {
401  sc = ecrt_master_slave_config_err(domain->master, reg->alias,
402  reg->position, reg->vendor_id, reg->product_code);
403  if (IS_ERR(sc))
404  return PTR_ERR(sc);
405 
406  ret = ecrt_slave_config_reg_pdo_entry(sc, reg->index,
407  reg->subindex, domain, reg->bit_position);
408  if (ret < 0)
409  return ret;
410 
411  *reg->offset = ret;
412  }
413 
414  return 0;
415 }
416 
417 /****************************************************************************/
418 
419 size_t ecrt_domain_size(const ec_domain_t *domain)
420 {
421  return domain->data_size;
422 }
423 
424 /****************************************************************************/
425 
426 void ecrt_domain_external_memory(ec_domain_t *domain, uint8_t *mem)
427 {
428  EC_MASTER_DBG(domain->master, 1, "ecrt_domain_external_memory("
429  "domain = 0x%p, mem = 0x%p)\n", domain, mem);
430 
431  down(&domain->master->master_sem);
432 
433  ec_domain_clear_data(domain);
434 
435  domain->data = mem;
436  domain->data_origin = EC_ORIG_EXTERNAL;
437 
438  up(&domain->master->master_sem);
439 }
440 
441 /****************************************************************************/
442 
443 uint8_t *ecrt_domain_data(const ec_domain_t *domain)
444 {
445  return domain->data;
446 }
447 
448 /****************************************************************************/
449 
451 {
452  uint16_t wc_sum[EC_MAX_NUM_DEVICES] = {}, wc_total;
453  ec_datagram_pair_t *pair;
454 #if EC_MAX_NUM_DEVICES > 1
455  uint16_t datagram_pair_wc, redundant_wc;
456  unsigned int datagram_offset;
457  ec_fmmu_config_t *fmmu = list_first_entry(&domain->fmmu_configs,
458  ec_fmmu_config_t, list);
459  unsigned int redundancy;
460 #endif
461  unsigned int dev_idx;
462 #ifdef EC_RT_SYSLOG
463  unsigned int wc_change;
464 #endif
465 
466 #if DEBUG_REDUNDANCY
467  EC_MASTER_DBG(domain->master, 1, "domain %u process\n", domain->index);
468 #endif
469 
470  list_for_each_entry(pair, &domain->datagram_pairs, list) {
471 #if EC_MAX_NUM_DEVICES > 1
472  datagram_pair_wc = ec_datagram_pair_process(pair, wc_sum);
473 #else
474  ec_datagram_pair_process(pair, wc_sum);
475 #endif
476 
477 #if EC_MAX_NUM_DEVICES > 1
478  if (ec_master_num_devices(domain->master) > 1) {
479  ec_datagram_t *main_datagram = &pair->datagrams[EC_DEVICE_MAIN];
480  uint32_t logical_datagram_address =
481  EC_READ_U32(main_datagram->address);
482  size_t datagram_size = main_datagram->data_size;
483 
484 #if DEBUG_REDUNDANCY
485  EC_MASTER_DBG(domain->master, 1, "dgram %s log=%u\n",
486  main_datagram->name, logical_datagram_address);
487 #endif
488 
489  /* Redundancy: Go through FMMU configs to detect data changes. */
490  list_for_each_entry_from(fmmu, &domain->fmmu_configs, list) {
491  ec_datagram_t *backup_datagram =
492  &pair->datagrams[EC_DEVICE_BACKUP];
493 
494  if (fmmu->dir != EC_DIR_INPUT) {
495  continue;
496  }
497 
498  if (fmmu->logical_start_address >=
499  logical_datagram_address + datagram_size) {
500  // fmmu data contained in next datagram pair
501  break;
502  }
503 
504  datagram_offset =
505  fmmu->logical_start_address - logical_datagram_address;
506 
507 #if DEBUG_REDUNDANCY
508  EC_MASTER_DBG(domain->master, 1,
509  "input fmmu log=%u size=%u offset=%u\n",
510  fmmu->logical_start_address, fmmu->data_size,
511  datagram_offset);
512  if (domain->master->debug_level > 0) {
513  ec_print_data(pair->send_buffer + datagram_offset,
514  fmmu->data_size);
515  ec_print_data(main_datagram->data + datagram_offset,
516  fmmu->data_size);
517  ec_print_data(backup_datagram->data + datagram_offset,
518  fmmu->data_size);
519  }
520 #endif
521 
522  if (data_changed(pair->send_buffer, main_datagram,
523  datagram_offset, fmmu->data_size)) {
524  /* data changed on main link: no copying necessary. */
525 #if DEBUG_REDUNDANCY
526  EC_MASTER_DBG(domain->master, 1, "main changed\n");
527 #endif
528  } else if (data_changed(pair->send_buffer, backup_datagram,
529  datagram_offset, fmmu->data_size)) {
530  /* data changed on backup link: copy to main memory. */
531 #if DEBUG_REDUNDANCY
532  EC_MASTER_DBG(domain->master, 1, "backup changed\n");
533 #endif
534  memcpy(main_datagram->data + datagram_offset,
535  backup_datagram->data + datagram_offset,
536  fmmu->data_size);
537  } else if (datagram_pair_wc ==
538  pair->expected_working_counter) {
539  /* no change, but WC complete: use main data. */
540 #if DEBUG_REDUNDANCY
541  EC_MASTER_DBG(domain->master, 1,
542  "no change but complete\n");
543 #endif
544  } else {
545  /* no change and WC incomplete: mark WC as zero to avoid
546  * data.dependent WC flickering. */
547  datagram_pair_wc = 0;
548 #if DEBUG_REDUNDANCY
549  EC_MASTER_DBG(domain->master, 1,
550  "no change and incomplete\n");
551 #endif
552  }
553  }
554  }
555 #endif // EC_MAX_NUM_DEVICES > 1
556  }
557 
558 #if EC_MAX_NUM_DEVICES > 1
559  redundant_wc = 0;
560  for (dev_idx = EC_DEVICE_BACKUP;
561  dev_idx < ec_master_num_devices(domain->master); dev_idx++) {
562  redundant_wc += wc_sum[dev_idx];
563  }
564 
565  redundancy = redundant_wc > 0;
566  if (redundancy != domain->redundancy_active) {
567 #ifdef EC_RT_SYSLOG
568  if (redundancy) {
569  EC_MASTER_WARN(domain->master,
570  "Domain %u: Redundant link in use!\n",
571  domain->index);
572  } else {
573  EC_MASTER_INFO(domain->master,
574  "Domain %u: Redundant link unused again.\n",
575  domain->index);
576  }
577 #endif
578  domain->redundancy_active = redundancy;
579  }
580 #else
581  domain->redundancy_active = 0;
582 #endif
583 
584 #ifdef EC_RT_SYSLOG
585  wc_change = 0;
586 #endif
587  wc_total = 0;
588  for (dev_idx = EC_DEVICE_MAIN;
589  dev_idx < ec_master_num_devices(domain->master); dev_idx++) {
590  if (wc_sum[dev_idx] != domain->working_counter[dev_idx]) {
591 #ifdef EC_RT_SYSLOG
592  wc_change = 1;
593 #endif
594  domain->working_counter[dev_idx] = wc_sum[dev_idx];
595  }
596  wc_total += wc_sum[dev_idx];
597  }
598 
599 #ifdef EC_RT_SYSLOG
600  if (wc_change) {
601  domain->working_counter_changes++;
602  }
603 
604  if (domain->working_counter_changes &&
605  jiffies - domain->notify_jiffies > HZ) {
606  domain->notify_jiffies = jiffies;
607  if (domain->working_counter_changes == 1) {
608  EC_MASTER_INFO(domain->master, "Domain %u: Working counter"
609  " changed to %u/%u", domain->index,
610  wc_total, domain->expected_working_counter);
611  } else {
612  EC_MASTER_INFO(domain->master, "Domain %u: %u working counter"
613  " changes - now %u/%u", domain->index,
614  domain->working_counter_changes,
615  wc_total, domain->expected_working_counter);
616  }
617 #if EC_MAX_NUM_DEVICES > 1
618  if (ec_master_num_devices(domain->master) > 1) {
619  printk(KERN_CONT " (");
620  for (dev_idx = EC_DEVICE_MAIN;
621  dev_idx < ec_master_num_devices(domain->master);
622  dev_idx++) {
623  printk(KERN_CONT "%u", domain->working_counter[dev_idx]);
624  if (dev_idx + 1 < ec_master_num_devices(domain->master)) {
625  printk(KERN_CONT "+");
626  }
627  }
628  printk(KERN_CONT ")");
629  }
630 #endif
631  printk(KERN_CONT ".\n");
632 
633  domain->working_counter_changes = 0;
634  }
635 #endif
636  return 0;
637 }
638 
639 /****************************************************************************/
640 
642 {
643  ec_datagram_pair_t *datagram_pair;
644  ec_device_index_t dev_idx;
645 
646  list_for_each_entry(datagram_pair, &domain->datagram_pairs, list) {
647 
648 #if EC_MAX_NUM_DEVICES > 1
649  /* copy main data to send buffer */
650  memcpy(datagram_pair->send_buffer,
651  datagram_pair->datagrams[EC_DEVICE_MAIN].data,
652  datagram_pair->datagrams[EC_DEVICE_MAIN].data_size);
653 #endif
655  &datagram_pair->datagrams[EC_DEVICE_MAIN]);
656 
657  /* copy main data to backup datagram */
658  for (dev_idx = EC_DEVICE_BACKUP;
659  dev_idx < ec_master_num_devices(domain->master); dev_idx++) {
660  memcpy(datagram_pair->datagrams[dev_idx].data,
661  datagram_pair->datagrams[EC_DEVICE_MAIN].data,
662  datagram_pair->datagrams[EC_DEVICE_MAIN].data_size);
664  &datagram_pair->datagrams[dev_idx]);
665  }
666  }
667  return 0;
668 }
669 
670 /****************************************************************************/
671 
673 {
674  unsigned int dev_idx;
675  uint16_t wc = 0;
676 
677  for (dev_idx = EC_DEVICE_MAIN;
678  dev_idx < ec_master_num_devices(domain->master); dev_idx++) {
679  wc += domain->working_counter[dev_idx];
680  }
681 
682  state->working_counter = wc;
683 
684  if (wc) {
685  if (wc == domain->expected_working_counter) {
686  state->wc_state = EC_WC_COMPLETE;
687  } else {
688  state->wc_state = EC_WC_INCOMPLETE;
689  }
690  } else {
691  state->wc_state = EC_WC_ZERO;
692  }
693 
694  state->redundancy_active = domain->redundancy_active;
695  return 0;
696 }
697 
698 /****************************************************************************/
699 
702 EXPORT_SYMBOL(ecrt_domain_reg_pdo_entry_list);
703 EXPORT_SYMBOL(ecrt_domain_size);
704 EXPORT_SYMBOL(ecrt_domain_external_memory);
705 EXPORT_SYMBOL(ecrt_domain_data);
706 EXPORT_SYMBOL(ecrt_domain_process);
707 EXPORT_SYMBOL(ecrt_domain_queue);
708 EXPORT_SYMBOL(ecrt_domain_state);
709 
712 /****************************************************************************/
unsigned int working_counter
Value of the last working counter.
Definition: ecrt.h:492
const ec_slave_config_t * sc
EtherCAT slave config.
Definition: fmmu_config.h:40
uint8_t subindex
PDO entry subindex.
Definition: ecrt.h:585
uint16_t position
Slave position.
Definition: ecrt.h:581
size_t data_size
Size of the data in data.
Definition: datagram.h:89
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:494
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:390
uint16_t index
PDO entry index.
Definition: ecrt.h:584
#define ec_master_num_devices(MASTER)
Number of Ethernet devices.
Definition: master.h:319
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:842
EtherCAT datagram.
Definition: datagram.h:79
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:104
ec_wc_state_t wc_state
Working counter interpretation.
Definition: ecrt.h:493
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:426
void ec_domain_clear_data(ec_domain_t *)
Frees internally allocated memory.
Definition: domain.c:98
Global definitions and macros.
Some of the registered process data were exchanged.
Definition: ecrt.h:480
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:443
uint16_t alias
Slave alias address.
Definition: ecrt.h:580
Internal.
Definition: globals.h:304
#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:194
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:491
uint32_t vendor_id
Slave vendor ID.
Definition: ecrt.h:582
unsigned int * bit_position
Pointer to a variable to store a bit position (0-7) within the offset.
Definition: ecrt.h:588
void ec_domain_clear(ec_domain_t *domain)
Domain destructor.
Definition: domain.c:80
int ec_domain_finish(ec_domain_t *domain, uint32_t base_address)
Finishes a domain.
Definition: domain.c:218
size_t ecrt_domain_size(const ec_domain_t *domain)
Returns the current size of the domain&#39;s process data.
Definition: domain.c:419
unsigned int debug_level
Master debug level.
Definition: master.h:271
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:198
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:305
int ecrt_domain_queue(ec_domain_t *domain)
(Re-)queues all domain datagrams in the master&#39;s datagram queue.
Definition: domain.c:641
Main device.
Definition: globals.h:199
#define EC_READ_U32(DATA)
Read a 32-bit unsigned value from EtherCAT data.
Definition: ecrt.h:2627
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:324
#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:935
Values read by the master.
Definition: ecrt.h:504
int ecrt_domain_process(ec_domain_t *domain)
Determines the states of the domain&#39;s datagrams.
Definition: domain.c:450
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:342
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 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:114
Number of directions.
Definition: ecrt.h:505
struct list_head list
List header.
Definition: datagram_pair.h:42
List record type for PDO entry mass-registration.
Definition: ecrt.h:579
EtherCAT domain structure.
int ecrt_domain_state(const ec_domain_t *domain, ec_domain_state_t *state)
Reads the state of a domain.
Definition: domain.c:672
No registered process data were exchanged.
Definition: ecrt.h:479
All registered process data were exchanged.
Definition: ecrt.h:482
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:637
uint8_t * data
Datagram payload.
Definition: datagram.h:86
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:2541
unsigned int * offset
Pointer to a variable to store the PDO entry&#39;s (byte-)offset in the process data. ...
Definition: ecrt.h:586
uint8_t address[EC_ADDR_LEN]
Recipient address.
Definition: datagram.h:85
void ec_domain_init(ec_domain_t *domain, ec_master_t *master, unsigned int index)
Domain constructor.
Definition: domain.c:50
ec_direction_t dir
FMMU direction.
Definition: fmmu_config.h:43
Backup device.
Definition: globals.h:200
Values written by the master.
Definition: ecrt.h:503
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:583
EtherCAT master.
Definition: master.h:183
unsigned long notify_jiffies
Time of last notification.
Definition: domain.h:66
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:139
int shall_count(const ec_fmmu_config_t *cur_fmmu, const ec_fmmu_config_t *first_fmmu)
Domain finish helper function.
Definition: domain.c:187
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:342