IgH EtherCAT Master  1.5.3
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;
71  domain->data_origin = EC_ORIG_INTERNAL;
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 
99  ec_domain_clear_data(domain);
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;
115  domain->data_origin = EC_ORIG_INTERNAL;
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,
314  domain->expected_working_counter);
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 
332 unsigned 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 
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;
402  ec_slave_config_t *sc;
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 
414  ret = ecrt_slave_config_reg_pdo_entry(sc, reg->index,
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 
427 size_t ecrt_domain_size(const ec_domain_t *domain)
428 {
429  return domain->data_size;
430 }
431 
432 /*****************************************************************************/
433 
434 void 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;
444  domain->data_origin = EC_ORIG_EXTERNAL;
445 
446  up(&domain->master->master_sem);
447 }
448 
449 /*****************************************************************************/
450 
451 uint8_t *ecrt_domain_data(ec_domain_t *domain)
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 =
500  &pair->datagrams[EC_DEVICE_BACKUP];
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 ==
546  pair->expected_working_counter) {
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,
622  domain->working_counter_changes,
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 
707 EXPORT_SYMBOL(ecrt_domain_reg_pdo_entry_list);
708 EXPORT_SYMBOL(ecrt_domain_size);
709 EXPORT_SYMBOL(ecrt_domain_external_memory);
710 EXPORT_SYMBOL(ecrt_domain_data);
711 EXPORT_SYMBOL(ecrt_domain_process);
712 EXPORT_SYMBOL(ecrt_domain_queue);
713 EXPORT_SYMBOL(ecrt_domain_state);
714 
717 /*****************************************************************************/
unsigned int working_counter
Value of the last working counter.
Definition: ecrt.h:437
size_t ecrt_domain_size(const ec_domain_t *domain)
Returns the current size of the domain&#39;s process data.
Definition: domain.c:427
const ec_slave_config_t * sc
EtherCAT slave config.
Definition: fmmu_config.h:48
uint8_t subindex
PDO entry subindex.
Definition: ecrt.h:530
uint16_t position
Slave position.
Definition: ecrt.h:526
size_t data_size
Size of the data in data.
Definition: datagram.h:97
Domain datagram pair.
Definition: datagram_pair.h:49
FMMU configuration.
Definition: fmmu_config.h:46
size_t data_size
Size of the process data.
Definition: domain.h:61
unsigned int expected_working_counter
Expectord working conter.
Definition: datagram_pair.h:56
unsigned int redundancy_active
Redundant link is in use.
Definition: ecrt.h:439
uint16_t index
PDO entry index.
Definition: ecrt.h:529
#define ec_master_num_devices(MASTER)
Number of Ethernet devices.
Definition: master.h:328
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
EtherCAT datagram.
Definition: datagram.h:87
unsigned int data_size
Covered PDO size.
Definition: fmmu_config.h:53
char name[EC_DATAGRAM_NAME_SIZE]
Description of the datagram.
Definition: datagram.h:112
ec_wc_state_t wc_state
Working counter interpretation.
Definition: ecrt.h:438
int data_changed(uint8_t *send_buffer, const ec_datagram_t *datagram, size_t offset, size_t size)
Process received data.
Definition: domain.c:372
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:434
void ec_domain_clear_data(ec_domain_t *)
Frees internally allocated memory.
Definition: domain.c:106
Global definitions and macros.
Some of the registered process data were exchanged.
Definition: ecrt.h:425
EtherCAT master structure.
uint8_t * data
Memory for the process data.
Definition: domain.h:62
uint16_t alias
Slave alias address.
Definition: ecrt.h:525
Internal.
Definition: globals.h:295
#define EC_MASTER_DBG(master, level, fmt, args...)
Convenience macro for printing master-specific debug messages to syslog.
Definition: master.h:111
struct semaphore master_sem
Master semaphore.
Definition: master.h:209
uint32_t logical_start_address
Logical start address.
Definition: fmmu_config.h:52
struct list_head list
List node used by domain.
Definition: fmmu_config.h:47
unsigned int working_counter_changes
Working counter changes since last notification.
Definition: domain.h:71
const ec_domain_t * domain
Domain.
Definition: fmmu_config.h:49
Domain state.
Definition: ecrt.h:436
uint32_t vendor_id
Slave vendor ID.
Definition: ecrt.h:527
unsigned int * bit_position
Pointer to a variable to store a bit position (0-7) within the offset.
Definition: ecrt.h:533
void ec_domain_clear(ec_domain_t *domain)
Domain destructor.
Definition: domain.c:88
int ec_domain_finish(ec_domain_t *domain, uint32_t base_address)
Finishes a domain.
Definition: domain.c:226
unsigned int debug_level
Master debug level.
Definition: master.h:285
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:189
void ec_datagram_pair_clear(ec_datagram_pair_t *pair)
Datagram pair destructor.
unsigned int index
Index (just a number).
Definition: domain.h:58
External.
Definition: globals.h:296
Main device.
Definition: globals.h:190
#define EC_READ_U32(DATA)
Read a 32-bit unsigned value from EtherCAT data.
Definition: ecrt.h:2329
struct list_head fmmu_configs
FMMU configurations contained.
Definition: domain.h:60
#define EC_MASTER_WARN(master, fmt, args...)
Convenience macro for printing master-specific warnings to syslog.
Definition: master.h:97
unsigned int ec_domain_fmmu_count(const ec_domain_t *domain)
Get the number of FMMU configurations of the domain.
Definition: domain.c:332
#define EC_MASTER_ERR(master, fmt, args...)
Convenience macro for printing master-specific errors to syslog.
Definition: master.h:85
void ec_master_queue_datagram(ec_master_t *master, ec_datagram_t *datagram)
Places a datagram in the datagram queue.
Definition: master.c:952
Values read by the master.
Definition: ecrt.h:449
ec_origin_t data_origin
Origin of the data memory.
Definition: domain.h:63
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:68
uint32_t logical_base_address
Logical offset address of the process data.
Definition: domain.h:64
uint16_t expected_working_counter
Expected working counter.
Definition: domain.h:70
unsigned int redundancy_active
Non-zero, if redundancy is in use.
Definition: domain.h:73
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:845
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_domain_add_fmmu_config(ec_domain_t *domain, ec_fmmu_config_t *fmmu)
Adds an FMMU configuration to the domain.
Definition: domain.c:122
Number of directions.
Definition: ecrt.h:450
struct list_head list
List header.
Definition: datagram_pair.h:50
uint8_t * ecrt_domain_data(ec_domain_t *domain)
Returns the domain&#39;s process data.
Definition: domain.c:451
List record type for PDO entry mass-registration.
Definition: ecrt.h:524
EtherCAT domain structure.
No registered process data were exchanged.
Definition: ecrt.h:424
All registered process data were exchanged.
Definition: ecrt.h:427
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:645
uint8_t * data
Datagram payload.
Definition: datagram.h:94
EtherCAT slave configuration.
Definition: slave_config.h:117
ec_datagram_t datagrams[EC_MAX_NUM_DEVICES]
Datagrams.
Definition: datagram_pair.h:52
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:2578
unsigned int * offset
Pointer to a variable to store the PDO entry&#39;s (byte-)offset in the process data. ...
Definition: ecrt.h:531
void ecrt_domain_state(const ec_domain_t *domain, ec_domain_state_t *state)
Reads the state of a domain.
Definition: domain.c:678
uint8_t address[EC_ADDR_LEN]
Recipient address.
Definition: datagram.h:93
void ecrt_domain_process(ec_domain_t *domain)
Determines the states of the domain&#39;s datagrams.
Definition: domain.c:458
void ec_domain_init(ec_domain_t *domain, ec_master_t *master, unsigned int index)
Domain constructor.
Definition: domain.c:58
ec_direction_t dir
FMMU direction.
Definition: fmmu_config.h:51
Backup device.
Definition: globals.h:191
Values written by the master.
Definition: ecrt.h:448
struct list_head datagram_pairs
Datagrams pairs (main/backup) for process data exchange.
Definition: domain.h:66
void ecrt_domain_queue(ec_domain_t *domain)
(Re-)queues all domain datagrams in the master&#39;s datagram queue.
Definition: domain.c:648
#define EC_MASTER_INFO(master, fmt, args...)
Convenience macro for printing master-specific information to syslog.
Definition: master.h:73
uint32_t product_code
Slave product code.
Definition: ecrt.h:528
EtherCAT master.
Definition: master.h:194
unsigned long notify_jiffies
Time of last notification.
Definition: domain.h:74
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
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
EtherCAT domain.
Definition: domain.h:54
ec_master_t * master
EtherCAT master owning the domain.
Definition: domain.h:57
#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:350