IgH EtherCAT Master  1.7.0
slave.c
Go to the documentation of this file.
1 /*****************************************************************************
2  *
3  * Copyright (C) 2006-2026 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 #include <linux/delay.h>
31 
32 #include "globals.h"
33 #include "datagram.h"
34 #include "master.h"
35 #include "slave_config.h"
36 
37 #include "slave.h"
38 
39 /****************************************************************************/
40 
41 extern const ec_code_msg_t al_status_messages[];
42 
43 /****************************************************************************/
44 
45 // prototypes for private methods
46 char *ec_slave_sii_string(const ec_slave_t *, unsigned int);
48 unsigned int ec_slave_get_previous_port(const ec_slave_t *, unsigned int);
49 unsigned int ec_slave_get_next_port(const ec_slave_t *, unsigned int);
50 uint32_t ec_slave_calc_rtt_sum(const ec_slave_t *);
52 int ec_slave_fetch_sii_strings(ec_slave_t *, const uint8_t *, size_t);
53 int ec_slave_fetch_sii_general(ec_slave_t *, const uint8_t *, size_t);
54 int ec_slave_fetch_sii_syncs(ec_slave_t *, const uint8_t *, size_t);
55 int ec_slave_fetch_sii_pdos(ec_slave_t *, const uint8_t *, size_t,
57 
58 /****************************************************************************/
59 
66  ec_slave_t *slave,
67  ec_master_t *master,
68  ec_device_index_t dev_idx,
69  uint16_t ring_position,
70  uint16_t station_address
71  )
72 {
73  unsigned int i;
74 
75  slave->master = master;
76  slave->device_index = dev_idx;
77  slave->ring_position = ring_position;
78  slave->station_address = station_address;
79  slave->effective_alias = 0x0000;
80 
81  slave->config = NULL;
84  slave->error_flag = 0;
85  slave->force_config = 0;
86  slave->configured_rx_mailbox_offset = 0x0000;
87  slave->configured_rx_mailbox_size = 0x0000;
88  slave->configured_tx_mailbox_offset = 0x0000;
89  slave->configured_tx_mailbox_size = 0x0000;
90 
91  slave->base_type = 0;
92  slave->base_revision = 0;
93  slave->base_build = 0;
94  slave->base_fmmu_count = 0;
95  slave->base_sync_count = 0;
96 
97  for (i = 0; i < EC_MAX_PORTS; i++) {
99 
100  slave->ports[i].link.link_up = 0;
101  slave->ports[i].link.loop_closed = 0;
102  slave->ports[i].link.signal_detected = 0;
103  slave->sii.physical_layer[i] = 0xFF;
104 
105  slave->ports[i].receive_time = 0U;
106 
107  slave->ports[i].next_slave = NULL;
108  slave->ports[i].delay_to_next_dc = 0U;
109  }
110 
111  slave->base_fmmu_bit_operation = 0;
112  slave->base_dc_supported = 0;
113  slave->base_dc_range = EC_DC_32;
114  slave->has_dc_system_time = 0;
115  slave->transmission_delay = 0U;
116 
117  ec_sii_page_init(&slave->sii_page);
118  slave->sii_parallel_words = 0;
119 
120  slave->sii.alias = 0x0000;
121  slave->sii.vendor_id = 0x00000000;
122  slave->sii.product_code = 0x00000000;
123  slave->sii.revision_number = 0x00000000;
124  slave->sii.serial_number = 0x00000000;
125  slave->sii.boot_rx_mailbox_offset = 0x0000;
126  slave->sii.boot_rx_mailbox_size = 0x0000;
127  slave->sii.boot_tx_mailbox_offset = 0x0000;
128  slave->sii.boot_tx_mailbox_size = 0x0000;
129  slave->sii.std_rx_mailbox_offset = 0x0000;
130  slave->sii.std_rx_mailbox_size = 0x0000;
131  slave->sii.std_tx_mailbox_offset = 0x0000;
132  slave->sii.std_tx_mailbox_size = 0x0000;
133  slave->sii.mailbox_protocols = 0;
134 
135  slave->sii.strings = NULL;
136  slave->sii.string_count = 0;
137 
138  slave->sii.has_general = 0;
139  slave->sii.group = NULL;
140  slave->sii.image = NULL;
141  slave->sii.order = NULL;
142  slave->sii.name = NULL;
143  memset(&slave->sii.coe_details, 0x00, sizeof(ec_sii_coe_details_t));
144  memset(&slave->sii.general_flags, 0x00, sizeof(ec_sii_general_flags_t));
145  slave->sii.current_on_ebus = 0;
146 
147  slave->sii.syncs = NULL;
148  slave->sii.sync_count = 0;
149 
150  INIT_LIST_HEAD(&slave->sii.pdos);
151 
152  INIT_LIST_HEAD(&slave->sdo_dictionary);
153 
154  slave->sdo_dictionary_fetched = 0;
155  slave->jiffies_preop = 0;
156 
157  INIT_LIST_HEAD(&slave->sdo_requests);
158  INIT_LIST_HEAD(&slave->reg_requests);
159  INIT_LIST_HEAD(&slave->foe_requests);
160  INIT_LIST_HEAD(&slave->soe_requests);
161  INIT_LIST_HEAD(&slave->eoe_requests);
162 
163  // create state machine object
164  ec_fsm_slave_init(&slave->fsm, slave);
165 }
166 
167 /****************************************************************************/
168 
175 {
176  ec_sdo_t *sdo, *next_sdo;
177  unsigned int i;
178  ec_pdo_t *pdo, *next_pdo;
179 
180  // abort all pending requests
181 
182  while (!list_empty(&slave->sdo_requests)) {
183  ec_sdo_request_t *request =
184  list_entry(slave->sdo_requests.next, ec_sdo_request_t, list);
185  list_del_init(&request->list); // dequeue
186  EC_SLAVE_WARN(slave, "Discarding SDO request,"
187  " slave about to be deleted.\n");
188  request->state = EC_INT_REQUEST_FAILURE;
189  }
190 
191  while (!list_empty(&slave->reg_requests)) {
192  ec_reg_request_t *reg =
193  list_entry(slave->reg_requests.next, ec_reg_request_t, list);
194  list_del_init(&reg->list); // dequeue
195  EC_SLAVE_WARN(slave, "Discarding register request,"
196  " slave about to be deleted.\n");
197  reg->state = EC_INT_REQUEST_FAILURE;
198  }
199 
200  while (!list_empty(&slave->foe_requests)) {
201  ec_foe_request_t *request =
202  list_entry(slave->foe_requests.next, ec_foe_request_t, list);
203  list_del_init(&request->list); // dequeue
204  EC_SLAVE_WARN(slave, "Discarding FoE request,"
205  " slave about to be deleted.\n");
206  request->state = EC_INT_REQUEST_FAILURE;
207  }
208 
209  while (!list_empty(&slave->soe_requests)) {
210  ec_soe_request_t *request =
211  list_entry(slave->soe_requests.next, ec_soe_request_t, list);
212  list_del_init(&request->list); // dequeue
213  EC_SLAVE_WARN(slave, "Discarding SoE request,"
214  " slave about to be deleted.\n");
215  request->state = EC_INT_REQUEST_FAILURE;
216  }
217 
218 #ifdef EC_EOE
219  while (!list_empty(&slave->eoe_requests)) {
220  ec_eoe_request_t *request =
221  list_entry(slave->eoe_requests.next, ec_eoe_request_t, list);
222  list_del_init(&request->list); // dequeue
223  EC_SLAVE_WARN(slave, "Discarding EoE request,"
224  " slave about to be deleted.\n");
225  request->state = EC_INT_REQUEST_FAILURE;
226  }
227 #endif
228 
229  wake_up_all(&slave->master->request_queue);
230 
231  if (slave->config) {
233  }
234 
235  // free all SDOs
236  list_for_each_entry_safe(sdo, next_sdo, &slave->sdo_dictionary, list) {
237  list_del(&sdo->list);
238  ec_sdo_clear(sdo);
239  kfree(sdo);
240  }
241 
242  // free all strings
243  if (slave->sii.strings) {
244  for (i = 0; i < slave->sii.string_count; i++)
245  kfree(slave->sii.strings[i]);
246  kfree(slave->sii.strings);
247  }
248 
249  // free all sync managers
251 
252  // free all SII PDOs
253  list_for_each_entry_safe(pdo, next_pdo, &slave->sii.pdos, list) {
254  list_del(&pdo->list);
255  ec_pdo_clear(pdo);
256  kfree(pdo);
257  }
258 
259  ec_sii_page_clear(&slave->sii_page);
260  ec_fsm_slave_clear(&slave->fsm);
261 }
262 
263 /****************************************************************************/
264 
268 {
269  unsigned int i;
270 
271  if (slave->sii.syncs) {
272  for (i = 0; i < slave->sii.sync_count; i++) {
273  ec_sync_clear(&slave->sii.syncs[i]);
274  }
275  kfree(slave->sii.syncs);
276  slave->sii.syncs = NULL;
277  }
278 }
279 
280 /****************************************************************************/
281 
287  ec_slave_state_t new_state
288  )
289 {
290  if (new_state != slave->current_state) {
291  if (slave->master->debug_level) {
292  char old_state[EC_STATE_STRING_SIZE],
293  cur_state[EC_STATE_STRING_SIZE];
294  ec_state_string(slave->current_state, old_state, 0);
295  ec_state_string(new_state, cur_state, 0);
296  EC_SLAVE_DBG(slave, 0, "%s -> %s.\n", old_state, cur_state);
297  }
298  slave->current_state = new_state;
299  }
300 }
301 
302 /****************************************************************************/
303 
309  ec_slave_state_t state
310  )
311 {
312  slave->requested_state = state;
313  slave->error_flag = 0;
314 }
315 
316 /****************************************************************************/
317 
324  ec_slave_t *slave
325  )
326 {
327  uint16_t *cat_word, cat_type, cat_size;
328  int ret;
329 
331 
332  slave->sii.alias =
334  slave->effective_alias = slave->sii.alias;
335  slave->sii_page.alias = slave->sii.alias;
336 
337  slave->sii.vendor_id =
339  slave->sii_page.vendor_id = slave->sii.vendor_id;
340 
341  slave->sii.product_code =
342  EC_READ_U32(slave->sii_page.words + 0x000A);
343  slave->sii_page.product_code = slave->sii.product_code;
344 
345  slave->sii.revision_number =
346  EC_READ_U32(slave->sii_page.words + 0x000C);
348 
349  slave->sii.serial_number =
350  EC_READ_U32(slave->sii_page.words + 0x000E);
351  slave->sii_page.serial_number = slave->sii.serial_number;
352 
353  slave->sii.boot_rx_mailbox_offset =
354  EC_READ_U16(slave->sii_page.words + 0x0014);
355  slave->sii.boot_rx_mailbox_size =
356  EC_READ_U16(slave->sii_page.words + 0x0015);
357  slave->sii.boot_tx_mailbox_offset =
358  EC_READ_U16(slave->sii_page.words + 0x0016);
359  slave->sii.boot_tx_mailbox_size =
360  EC_READ_U16(slave->sii_page.words + 0x0017);
361  slave->sii.std_rx_mailbox_offset =
362  EC_READ_U16(slave->sii_page.words + 0x0018);
363  slave->sii.std_rx_mailbox_size =
364  EC_READ_U16(slave->sii_page.words + 0x0019);
365  slave->sii.std_tx_mailbox_offset =
366  EC_READ_U16(slave->sii_page.words + 0x001A);
367  slave->sii.std_tx_mailbox_size =
368  EC_READ_U16(slave->sii_page.words + 0x001B);
369  slave->sii.mailbox_protocols =
370  EC_READ_U16(slave->sii_page.words + 0x001C);
371  if (slave->sii.mailbox_protocols) {
372  int need_delim = 0;
373  uint16_t all = EC_MBOX_AOE | EC_MBOX_COE | EC_MBOX_FOE |
375  if ((slave->sii.mailbox_protocols & all) &&
376  slave->master->debug_level >= 1) {
377  EC_SLAVE_DBG(slave, 1, "Slave announces to support ");
378  if (slave->sii.mailbox_protocols & EC_MBOX_AOE) {
379  printk(KERN_CONT "AoE");
380  need_delim = 1;
381  }
382  if (slave->sii.mailbox_protocols & EC_MBOX_COE) {
383  if (need_delim) {
384  printk(KERN_CONT ", ");
385  }
386  printk(KERN_CONT "CoE");
387  need_delim = 1;
388  }
389  if (slave->sii.mailbox_protocols & EC_MBOX_FOE) {
390  if (need_delim) {
391  printk(KERN_CONT ", ");
392  }
393  printk(KERN_CONT "FoE");
394  need_delim = 1;
395  }
396  if (slave->sii.mailbox_protocols & EC_MBOX_SOE) {
397  if (need_delim) {
398  printk(KERN_CONT ", ");
399  }
400  printk(KERN_CONT "SoE");
401  need_delim = 1;
402  }
403  if (slave->sii.mailbox_protocols & EC_MBOX_VOE) {
404  if (need_delim) {
405  printk(KERN_CONT ", ");
406  }
407  printk(KERN_CONT "VoE");
408  need_delim = 1;
409  }
410  printk(KERN_CONT ".\n");
411  }
412  if (slave->sii.mailbox_protocols & ~all) {
413  EC_SLAVE_DBG(slave, 1, "Slave announces to support unknown"
414  " mailbox protocols 0x%04X.",
415  slave->sii.mailbox_protocols & ~all);
416  }
417  }
418  else {
419  EC_SLAVE_DBG(slave, 1, "Slave announces to support no mailbox"
420  " protocols.");
421  }
422 
423  if (slave->sii.boot_rx_mailbox_offset == 0xffff ||
424  slave->sii.boot_rx_mailbox_size == 0xffff ||
425  slave->sii.boot_tx_mailbox_offset == 0xffff ||
426  slave->sii.boot_tx_mailbox_size == 0xffff ||
427  slave->sii.std_rx_mailbox_offset == 0xffff ||
428  slave->sii.std_rx_mailbox_size == 0xffff ||
429  slave->sii.std_tx_mailbox_offset == 0xffff ||
430  slave->sii.std_tx_mailbox_size == 0xffff) {
431  slave->sii.mailbox_protocols = 0x0000;
432  EC_SLAVE_ERR(slave, "Invalid mailbox settings in SII."
433  " Disabling mailbox communication.");
434  }
435 
437  // SII does not contain category data
438  return 0;
439  }
440 
442  EC_SLAVE_ERR(slave, "Unexpected end of SII data:"
443  " First category header missing.\n");
444  return -ENOENT;
445  }
446 
447  // evaluate category data
448  cat_word = slave->sii_page.words + EC_FIRST_SII_CATEGORY_OFFSET;
449  while (EC_READ_U16(cat_word) != 0xFFFF) {
450  // type and size words must fit
451  if (cat_word + 2 - slave->sii_page.words
452  > slave->sii_page.word_count) {
453  EC_SLAVE_ERR(slave, "Unexpected end of SII data:"
454  " Category header incomplete.\n");
455  return -ENOENT;
456  }
457 
458  cat_type = EC_READ_U16(cat_word) & 0x7FFF;
459  cat_size = EC_READ_U16(cat_word + 1);
460  cat_word += 2;
461 
462  if (cat_word + cat_size - slave->sii_page.words
463  > slave->sii_page.word_count) {
464  EC_SLAVE_WARN(slave, "Unexpected end of SII data:"
465  " Category data incomplete.\n");
466  return -ENOENT;
467  }
468 
469  switch (cat_type) {
470  case 0x000A:
471  ret = ec_slave_fetch_sii_strings(slave, (uint8_t *) cat_word,
472  cat_size * 2);
473  if (ret) {
474  return ret;
475  }
476  break;
477 
478  case 0x001E:
479  ret = ec_slave_fetch_sii_general(slave, (uint8_t *) cat_word,
480  cat_size * 2);
481  if (ret) {
482  return ret;
483  }
484  break;
485 
486  case 0x0028:
487  break;
488 
489  case 0x0029:
490  ret = ec_slave_fetch_sii_syncs(slave, (uint8_t *) cat_word,
491  cat_size * 2);
492  if (ret) {
493  return ret;
494  }
495  break;
496 
497  case 0x0032:
498  ret = ec_slave_fetch_sii_pdos(slave, (uint8_t *) cat_word,
499  cat_size * 2, EC_DIR_INPUT); // TxPDO
500  if (ret) {
501  return ret;
502  }
503  break;
504 
505  case 0x0033:
506  ret = ec_slave_fetch_sii_pdos(slave, (uint8_t *) cat_word,
507  cat_size * 2, EC_DIR_OUTPUT); // RxPDO
508  if (ret) {
509  return ret;
510  }
511  break;
512 
513  default:
514  EC_SLAVE_DBG(slave, 1, "Unknown category type 0x%04X.\n",
515  cat_type);
516  }
517 
518  cat_word += cat_size;
519  if (cat_word - slave->sii_page.words >= slave->sii_page.word_count) {
520  EC_SLAVE_WARN(slave, "Unexpected end of SII data:"
521  " Next category header missing.\n");
522  return -ENOENT;
523  }
524  }
525 
526  return 0;
527 }
528 
529 /****************************************************************************/
530 
538  ec_slave_t *slave,
539  const uint8_t *data,
540  size_t data_size
541  )
542 {
543  int i, err;
544  size_t size;
545  off_t offset;
546 
547  slave->sii.string_count = data[0];
548 
549  if (slave->sii.string_count) {
550  if (!(slave->sii.strings =
551  kmalloc(sizeof(char *) * slave->sii.string_count,
552  GFP_KERNEL))) {
553  EC_SLAVE_ERR(slave, "Failed to allocate string array memory.\n");
554  err = -ENOMEM;
555  goto out_zero;
556  }
557 
558  offset = 1;
559  for (i = 0; i < slave->sii.string_count; i++) {
560  size = data[offset];
561  // allocate memory for string structure and data at a single blow
562  if (!(slave->sii.strings[i] =
563  kmalloc(sizeof(char) * size + 1, GFP_KERNEL))) {
564  EC_SLAVE_ERR(slave, "Failed to allocate string memory.\n");
565  err = -ENOMEM;
566  goto out_free;
567  }
568  memcpy(slave->sii.strings[i], data + offset + 1, size);
569  slave->sii.strings[i][size] = 0x00; // append binary zero
570  offset += 1 + size;
571  }
572  }
573 
574  return 0;
575 
576 out_free:
577  for (i--; i >= 0; i--)
578  kfree(slave->sii.strings[i]);
579  kfree(slave->sii.strings);
580  slave->sii.strings = NULL;
581 out_zero:
582  slave->sii.string_count = 0;
583  return err;
584 }
585 
586 /****************************************************************************/
587 
594  ec_slave_t *slave,
595  const uint8_t *data,
596  size_t data_size
597  )
598 {
599  unsigned int i;
600  uint8_t flags;
601 
602  if (data_size != 32) {
603  EC_SLAVE_ERR(slave, "Wrong size of general category (%zu/32).\n",
604  data_size);
605  return -EINVAL;
606  }
607 
608  slave->sii.group = ec_slave_sii_string(slave, data[0]);
609  slave->sii.image = ec_slave_sii_string(slave, data[1]);
610  slave->sii.order = ec_slave_sii_string(slave, data[2]);
611  slave->sii.name = ec_slave_sii_string(slave, data[3]);
612 
613  for (i = 0; i < 4; i++)
614  slave->sii.physical_layer[i] =
615  (data[4] & (0x03 << (i * 2))) >> (i * 2);
616 
617  // read CoE details
618  flags = EC_READ_U8(data + 5);
619  slave->sii.coe_details.enable_sdo = (flags >> 0) & 0x01;
620  slave->sii.coe_details.enable_sdo_info = (flags >> 1) & 0x01;
621  slave->sii.coe_details.enable_pdo_assign = (flags >> 2) & 0x01;
622  slave->sii.coe_details.enable_pdo_configuration = (flags >> 3) & 0x01;
623  slave->sii.coe_details.enable_upload_at_startup = (flags >> 4) & 0x01;
624  slave->sii.coe_details.enable_sdo_complete_access = (flags >> 5) & 0x01;
625 
626  // read general flags
627  flags = EC_READ_U8(data + 0x000B);
628  slave->sii.general_flags.enable_safeop = (flags >> 0) & 0x01;
629  slave->sii.general_flags.enable_not_lrw = (flags >> 1) & 0x01;
630 
631  slave->sii.current_on_ebus = EC_READ_S16(data + 0x0C);
632  slave->sii.has_general = 1;
633  return 0;
634 }
635 
636 /****************************************************************************/
637 
645  ec_slave_t *slave,
646  const uint8_t *data,
647  size_t data_size
648  )
649 {
650  unsigned int i, count, total_count;
651  ec_sync_t *sync;
652  size_t memsize;
653  ec_sync_t *syncs;
654  uint8_t index;
655 
656  // one sync manager struct is 4 words long
657  if (data_size % 8) {
658  EC_SLAVE_ERR(slave, "Invalid SII sync manager category size %zu.\n",
659  data_size);
660  return -EINVAL;
661  }
662 
663  count = data_size / 8;
664 
665  if (count) {
666  total_count = count + slave->sii.sync_count;
667  if (total_count > EC_MAX_SYNC_MANAGERS) {
668  EC_SLAVE_ERR(slave, "Exceeded maximum number of"
669  " sync managers!\n");
670  return -EOVERFLOW;
671  }
672  memsize = sizeof(ec_sync_t) * total_count;
673  if (!(syncs = kmalloc(memsize, GFP_KERNEL))) {
674  EC_SLAVE_ERR(slave, "Failed to allocate %zu bytes"
675  " for sync managers.\n", memsize);
676  return -ENOMEM;
677  }
678 
679  for (i = 0; i < slave->sii.sync_count; i++)
680  ec_sync_init_copy(syncs + i, slave->sii.syncs + i);
681 
682  // initialize new sync managers
683  for (i = 0; i < count; i++, data += 8) {
684  index = i + slave->sii.sync_count;
685  sync = &syncs[index];
686 
687  ec_sync_init(sync, slave);
688  sync->physical_start_address = EC_READ_U16(data);
689  sync->default_length = EC_READ_U16(data + 2);
690  sync->control_register = EC_READ_U8(data + 4);
691  sync->enable = EC_READ_U8(data + 6);
692  }
693 
694  if (slave->sii.syncs)
695  kfree(slave->sii.syncs);
696  slave->sii.syncs = syncs;
697  slave->sii.sync_count = total_count;
698  }
699 
700  return 0;
701 }
702 
703 /****************************************************************************/
704 
711  ec_slave_t *slave,
712  const uint8_t *data,
713  size_t data_size,
714  ec_direction_t dir
715  )
716 {
717  int ret;
718  ec_pdo_t *pdo;
719  ec_pdo_entry_t *entry;
720  unsigned int entry_count, i;
721 
722  while (data_size >= 8) {
723  if (!(pdo = kmalloc(sizeof(ec_pdo_t), GFP_KERNEL))) {
724  EC_SLAVE_ERR(slave, "Failed to allocate PDO memory.\n");
725  return -ENOMEM;
726  }
727 
728  ec_pdo_init(pdo);
729  pdo->index = EC_READ_U16(data);
730  entry_count = EC_READ_U8(data + 2);
731  pdo->sync_index = EC_READ_U8(data + 3);
732  ret = ec_pdo_set_name(pdo,
733  ec_slave_sii_string(slave, EC_READ_U8(data + 5)));
734  if (ret) {
735  ec_pdo_clear(pdo);
736  kfree(pdo);
737  return ret;
738  }
739  list_add_tail(&pdo->list, &slave->sii.pdos);
740 
741  data_size -= 8;
742  data += 8;
743 
744  for (i = 0; i < entry_count; i++) {
745  if (!(entry = kmalloc(sizeof(ec_pdo_entry_t), GFP_KERNEL))) {
746  EC_SLAVE_ERR(slave, "Failed to allocate PDO entry memory.\n");
747  return -ENOMEM;
748  }
749 
750  ec_pdo_entry_init(entry);
751  entry->index = EC_READ_U16(data);
752  entry->subindex = EC_READ_U8(data + 2);
753  ret = ec_pdo_entry_set_name(entry,
754  ec_slave_sii_string(slave, EC_READ_U8(data + 3)));
755  if (ret) {
756  ec_pdo_entry_clear(entry);
757  kfree(entry);
758  return ret;
759  }
760  entry->bit_length = EC_READ_U8(data + 5);
761  list_add_tail(&entry->list, &pdo->entries);
762 
763  data_size -= 8;
764  data += 8;
765  }
766 
767  // if sync manager index is positive, the PDO is mapped by default
768  if (pdo->sync_index >= 0) {
769  ec_sync_t *sync;
770 
771  if (!(sync = ec_slave_get_sync(slave, pdo->sync_index))) {
772  EC_SLAVE_ERR(slave, "Invalid SM index %i for PDO 0x%04X.",
773  pdo->sync_index, pdo->index);
774  return -ENOENT;
775  }
776 
777  ret = ec_pdo_list_add_pdo_copy(&sync->pdos, pdo);
778  if (ret)
779  return ret;
780  }
781  }
782 
783  return 0;
784 }
785 
786 /****************************************************************************/
787 
794  const ec_slave_t *slave,
795  unsigned int index
796  )
797 {
798  if (!index--)
799  return NULL;
800 
801  if (index >= slave->sii.string_count) {
802  EC_SLAVE_DBG(slave, 1, "String %u not found.\n", index);
803  return NULL;
804  }
805 
806  return slave->sii.strings[index];
807 }
808 
809 /****************************************************************************/
810 
816  ec_slave_t *slave,
817  uint8_t sync_index
818  )
819 {
820  if (sync_index < slave->sii.sync_count) {
821  return &slave->sii.syncs[sync_index];
822  } else {
823  return NULL;
824  }
825 }
826 
827 /****************************************************************************/
828 
834  unsigned int *sdo_count,
835  unsigned int *entry_count
837  )
838 {
839  unsigned int sdos = 0, entries = 0;
840  ec_sdo_t *sdo;
841  ec_sdo_entry_t *entry;
842 
843  list_for_each_entry(sdo, &slave->sdo_dictionary, list) {
844  sdos++;
845  list_for_each_entry(entry, &sdo->entries, list) {
846  entries++;
847  }
848  }
849 
850  *sdo_count = sdos;
851  *entry_count = entries;
852 }
853 
854 /****************************************************************************/
855 
862  ec_slave_t *slave,
863  uint16_t index
864  )
865 {
866  ec_sdo_t *sdo;
867 
868  list_for_each_entry(sdo, &slave->sdo_dictionary, list) {
869  if (sdo->index != index)
870  continue;
871  return sdo;
872  }
873 
874  return NULL;
875 }
876 
877 /****************************************************************************/
878 
888  const ec_slave_t *slave,
889  uint16_t index
890  )
891 {
892  const ec_sdo_t *sdo;
893 
894  list_for_each_entry(sdo, &slave->sdo_dictionary, list) {
895  if (sdo->index != index)
896  continue;
897  return sdo;
898  }
899 
900  return NULL;
901 }
902 
903 /****************************************************************************/
904 
910  const ec_slave_t *slave,
911  uint16_t sdo_position
912  )
913 {
914  const ec_sdo_t *sdo;
915 
916  list_for_each_entry(sdo, &slave->sdo_dictionary, list) {
917  if (sdo_position--)
918  continue;
919  return sdo;
920  }
921 
922  return NULL;
923 }
924 
925 /****************************************************************************/
926 
932  const ec_slave_t *slave
933  )
934 {
935  const ec_sdo_t *sdo;
936  uint16_t count = 0;
937 
938  list_for_each_entry(sdo, &slave->sdo_dictionary, list) {
939  count++;
940  }
941 
942  return count;
943 }
944 
945 /****************************************************************************/
946 
951  const ec_slave_t *slave,
952  uint16_t index
953  )
954 {
955  unsigned int i;
956  const ec_sync_t *sync;
957  const ec_pdo_t *pdo;
958 
959  for (i = 0; i < slave->sii.sync_count; i++) {
960  sync = &slave->sii.syncs[i];
961 
962  if (!(pdo = ec_pdo_list_find_pdo_const(&sync->pdos, index)))
963  continue;
964 
965  return pdo;
966  }
967 
968  return NULL;
969 }
970 
971 /****************************************************************************/
972 
976  ec_slave_t *slave,
977  ec_pdo_t *pdo
978  )
979 {
980  const ec_sdo_t *sdo;
981  ec_pdo_entry_t *pdo_entry;
982  const ec_sdo_entry_t *sdo_entry;
983 
984  list_for_each_entry(sdo, &slave->sdo_dictionary, list) {
985  if (sdo->index == pdo->index) {
986  ec_pdo_set_name(pdo, sdo->name);
987  } else {
988  list_for_each_entry(pdo_entry, &pdo->entries, list) {
989  if (sdo->index == pdo_entry->index) {
990  sdo_entry = ec_sdo_get_entry_const(
991  sdo, pdo_entry->subindex);
992  if (sdo_entry) {
993  ec_pdo_entry_set_name(pdo_entry,
994  sdo_entry->description);
995  }
996  }
997  }
998  }
999  }
1000 }
1001 
1002 /****************************************************************************/
1003 
1007  ec_slave_t *slave
1008  )
1009 {
1010  unsigned int i;
1011  ec_sync_t *sync;
1012  ec_pdo_t *pdo;
1013 
1014  for (i = 0; i < slave->sii.sync_count; i++) {
1015  sync = slave->sii.syncs + i;
1016  list_for_each_entry(pdo, &sync->pdos.list, list) {
1017  ec_slave_find_names_for_pdo(slave, pdo);
1018  }
1019  }
1020 }
1021 
1022 /****************************************************************************/
1023 
1029  const ec_slave_t *slave,
1030  unsigned int port_index
1031  )
1032 {
1033  static const unsigned int prev_table[EC_MAX_PORTS] = {
1034  2, 3, 1, 0
1035  };
1036 
1037  if (port_index >= EC_MAX_PORTS) {
1038  EC_SLAVE_WARN(slave, "%s(port_index=%u): Invalid port index!\n",
1039  __func__, port_index);
1040  }
1041 
1042  do {
1043  port_index = prev_table[port_index];
1044  if (slave->ports[port_index].next_slave) {
1045  return port_index;
1046  }
1047  } while (port_index);
1048 
1049  return 0;
1050 }
1051 
1052 /****************************************************************************/
1053 
1059  const ec_slave_t *slave,
1060  unsigned int port_index
1061  )
1062 {
1063  static const unsigned int next_table[EC_MAX_PORTS] = {
1064  3, 2, 0, 1
1065  };
1066 
1067  if (port_index >= EC_MAX_PORTS) {
1068  EC_SLAVE_WARN(slave, "%s(port_index=%u): Invalid port index!\n",
1069  __func__, port_index);
1070  }
1071 
1072  do {
1073  port_index = next_table[port_index];
1074  if (slave->ports[port_index].next_slave) {
1075  return port_index;
1076  }
1077  } while (port_index);
1078 
1079  return 0;
1080 }
1081 
1082 /****************************************************************************/
1083 
1089  const ec_slave_t *slave
1090  )
1091 {
1092  uint32_t rtt_sum = 0, rtt;
1093  unsigned int port_index = ec_slave_get_next_port(slave, 0);
1094 
1095  while (port_index != 0) {
1096  unsigned int prev_index =
1097  ec_slave_get_previous_port(slave, port_index);
1098 
1099  rtt = slave->ports[port_index].receive_time -
1100  slave->ports[prev_index].receive_time;
1101  rtt_sum += rtt;
1102  port_index = ec_slave_get_next_port(slave, port_index);
1103  }
1104 
1105  return rtt_sum;
1106 }
1107 
1108 /****************************************************************************/
1109 
1115  ec_slave_t *slave
1116  )
1117 {
1118  unsigned int port_index;
1119  ec_slave_t *dc_slave = NULL;
1120 
1121  if (slave->base_dc_supported) {
1122  dc_slave = slave;
1123  } else {
1124  port_index = ec_slave_get_next_port(slave, 0);
1125 
1126  while (port_index != 0) {
1127  ec_slave_t *next = slave->ports[port_index].next_slave;
1128 
1129  if (next) {
1130  dc_slave = ec_slave_find_next_dc_slave(next);
1131 
1132  if (dc_slave) {
1133  break;
1134  }
1135  }
1136  port_index = ec_slave_get_next_port(slave, port_index);
1137  }
1138  }
1139 
1140  return dc_slave;
1141 }
1142 
1143 /****************************************************************************/
1144 
1148  ec_slave_t *slave
1149  )
1150 {
1151  unsigned int port_index;
1152  ec_slave_t *next_slave, *next_dc;
1153  uint32_t rtt, next_rtt_sum;
1154 
1155  if (!slave->base_dc_supported)
1156  return;
1157 
1158  port_index = ec_slave_get_next_port(slave, 0);
1159 
1160  while (port_index != 0) {
1161  next_slave = slave->ports[port_index].next_slave;
1162  next_dc = ec_slave_find_next_dc_slave(next_slave);
1163 
1164  if (next_dc) {
1165  unsigned int prev_port =
1166  ec_slave_get_previous_port(slave, port_index);
1167 
1168  rtt = slave->ports[port_index].receive_time -
1169  slave->ports[prev_port].receive_time;
1170  next_rtt_sum = ec_slave_calc_rtt_sum(next_dc);
1171 
1172  slave->ports[port_index].delay_to_next_dc =
1173  (rtt - next_rtt_sum) / 2; // FIXME
1174  next_dc->ports[0].delay_to_next_dc =
1175  (rtt - next_rtt_sum) / 2;
1176 
1177 #if 0
1178  EC_SLAVE_DBG(slave, 1, "delay %u:%u rtt=%u"
1179  " next_rtt_sum=%u delay=%u\n",
1180  slave->ring_position, port_index, rtt, next_rtt_sum,
1181  slave->ports[port_index].delay_to_next_dc);
1182 #endif
1183  }
1184 
1185  port_index = ec_slave_get_next_port(slave, port_index);
1186  }
1187 }
1188 
1189 /****************************************************************************/
1190 
1194  ec_slave_t *slave,
1195  uint32_t *delay
1196  )
1197 {
1198  unsigned int i;
1199  ec_slave_t *next_dc;
1200 
1201  EC_SLAVE_DBG(slave, 1, "%s(delay = %u ns)\n", __func__, *delay);
1202 
1203  slave->transmission_delay = *delay;
1204 
1205  i = ec_slave_get_next_port(slave, 0);
1206 
1207  while (i != 0) {
1208  ec_slave_port_t *port = &slave->ports[i];
1209  next_dc = ec_slave_find_next_dc_slave(port->next_slave);
1210  if (next_dc) {
1211  *delay = *delay + port->delay_to_next_dc;
1212 #if 0
1213  EC_SLAVE_DBG(slave, 1, "%u:%u %u\n",
1214  slave->ring_position, i, *delay);
1215 #endif
1216  ec_slave_calc_transmission_delays_rec(next_dc, delay);
1217  }
1218 
1219  i = ec_slave_get_next_port(slave, i);
1220  }
1221 
1222  *delay = *delay + slave->ports[0].delay_to_next_dc;
1223 }
1224 
1225 /****************************************************************************/
ec_sii_general_flags_t general_flags
General flags.
Definition: slave.h:154
Slave information interface general flags.
Definition: globals.h:171
ec_internal_request_state_t state
Request state.
Definition: reg_request.h:48
CANopen over EtherCAT.
Definition: globals.h:152
uint16_t ring_position
Ring position.
Definition: slave.h:176
uint32_t revision_number
Revision number.
Definition: slave.h:130
const ec_sdo_entry_t * ec_sdo_get_entry_const(const ec_sdo_t *sdo, uint8_t subindex)
Get an SDO entry from an SDO via its subindex.
Definition: sdo.c:108
uint16_t ec_slave_sdo_count(const ec_slave_t *slave)
Get the number of SDOs in the dictionary.
Definition: slave.c:931
uint16_t boot_rx_mailbox_offset
Bootstrap rx mailbox address.
Definition: slave.h:132
int ec_slave_analyze_sii_data(ec_slave_t *slave)
Analyzes SII data.
Definition: slave.c:323
void ec_fsm_slave_clear(ec_fsm_slave_t *fsm)
Destructor.
Definition: fsm_slave.c:87
ec_sii_t sii
Extracted SII data.
Definition: slave.h:217
size_t word_count
Size of the SII contents in words.
Definition: sii_page.h:61
uint16_t configured_tx_mailbox_size
Configured send mailbox size.
Definition: slave.h:194
uint8_t enable_upload_at_startup
?.
Definition: globals.h:165
void ec_slave_attach_pdo_names(ec_slave_t *slave)
Attach PDO names.
Definition: slave.c:1006
uint16_t base_build
Build number.
Definition: slave.h:199
#define EC_SLAVE_DBG(slave, level, fmt, args...)
Convenience macro for printing slave-specific debug messages to syslog.
Definition: slave.h:99
CANopen SDO entry.
Definition: sdo_entry.h:46
const ec_pdo_t * ec_pdo_list_find_pdo_const(const ec_pdo_list_t *pl, uint16_t index)
Finds a PDO with the given index and returns a const pointer.
Definition: pdo_list.c:257
uint8_t enable_not_lrw
Slave does not support LRW.
Definition: globals.h:173
uint16_t configured_tx_mailbox_offset
Configured send mailbox offset.
Definition: slave.h:192
size_t ec_state_string(uint8_t, char *, uint8_t)
Prints slave states in clear text.
Definition: module.c:405
ec_slave_port_t ports[EC_MAX_PORTS]
Ports.
Definition: slave.h:180
#define EC_SII_WORD_OFFSET_ALIAS
Word offset of alias address.
Definition: globals.h:89
CANopen SDO request.
Definition: sdo_request.h:40
ec_slave_state_t current_state
Current application state.
Definition: slave.h:185
const ec_code_msg_t al_status_messages[]
Application layer status messages.
Definition: fsm_change.c:382
EtherCAT slave structure.
ec_internal_request_state_t state
SDO request state.
Definition: sdo_request.h:55
Register request.
Definition: reg_request.h:40
ec_sdo_t * ec_slave_get_sdo(ec_slave_t *slave, uint16_t index)
Get an SDO from the dictionary.
Definition: slave.c:861
ec_slave_port_link_t link
Port link status.
Definition: slave.h:113
Servo-Profile over EtherCAT.
Definition: globals.h:154
#define EC_SLAVE_WARN(slave, fmt, args...)
Convenience macro for printing slave-specific warnings to syslog.
Definition: slave.h:83
uint8_t enable_sdo
Enable SDO access.
Definition: globals.h:161
struct list_head list
List of PDOs.
Definition: pdo_list.h:42
uint32_t serial_number
Serial number.
Definition: slave.h:131
ec_sii_coe_details_t coe_details
CoE detail flags.
Definition: slave.h:153
char * order
Order number.
Definition: slave.h:150
int ec_pdo_set_name(ec_pdo_t *pdo, const char *name)
Set PDO name.
Definition: pdo.c:117
void ec_slave_find_names_for_pdo(ec_slave_t *, ec_pdo_t *)
Find name for a PDO and its entries.
Definition: slave.c:975
ec_fsm_slave_t fsm
Slave state machine.
Definition: slave.h:229
void ec_slave_set_state(ec_slave_t *slave, ec_slave_state_t new_state)
Sets the application state of a slave.
Definition: slave.c:286
struct list_head reg_requests
Register access requests.
Definition: slave.h:224
struct list_head list
List item.
Definition: sdo.h:42
void ec_pdo_init(ec_pdo_t *pdo)
PDO constructor.
Definition: pdo.c:38
const ec_pdo_t * ec_slave_find_pdo(const ec_slave_t *slave, uint16_t index)
Finds a mapped PDO.
Definition: slave.c:950
CANopen SDO.
Definition: sdo.h:41
uint16_t index
SDO index.
Definition: sdo.h:44
int16_t current_on_ebus
Power consumption in mA.
Definition: slave.h:155
ec_slave_t * ec_slave_find_next_dc_slave(ec_slave_t *)
Finds the next slave supporting DC delay measurement.
Definition: slave.c:1114
uint16_t boot_tx_mailbox_size
Bootstrap transmit mailbox size.
Definition: slave.h:135
int ec_slave_fetch_sii_strings(ec_slave_t *, const uint8_t *, size_t)
Fetches data from a STRING category.
Definition: slave.c:537
uint16_t alias
Configured station alias.
Definition: sii_page.h:56
wait_queue_head_t request_queue
Wait queue for external requests from user space.
Definition: master.h:304
uint16_t station_address
Configured station address.
Definition: slave.h:177
unsigned int sync_count
Number of sync managers.
Definition: slave.h:159
void ec_slave_clear(ec_slave_t *slave)
Slave destructor.
Definition: slave.c:174
struct list_head sdo_dictionary
SDO dictionary list.
Definition: slave.h:219
uint16_t std_rx_mailbox_size
Standard receive mailbox size.
Definition: slave.h:137
uint8_t base_type
Slave type.
Definition: slave.h:197
Global definitions and macros.
uint16_t std_tx_mailbox_offset
Standard transmit mailbox address.
Definition: slave.h:138
PDO entry description.
Definition: pdo_entry.h:40
EtherCAT master structure.
void ec_pdo_clear(ec_pdo_t *pdo)
PDO destructor.
Definition: pdo.c:86
uint16_t index
PDO index.
Definition: pdo.h:43
int8_t sync_index
Assigned sync manager.
Definition: pdo.h:44
uint16_t boot_tx_mailbox_offset
Bootstrap tx mailbox address.
Definition: slave.h:134
uint16_t index
PDO entry index.
Definition: pdo_entry.h:42
void ec_slave_sdo_dict_info(const ec_slave_t *slave, unsigned int *sdo_count, unsigned int *entry_count)
Counts the total number of SDOs and entries in the dictionary.
Definition: slave.c:833
EtherCAT slave.
Definition: slave.h:169
struct list_head sdo_requests
SDO access requests.
Definition: slave.h:223
char * description
Description.
Definition: sdo_entry.h:54
Code/Message pair.
Definition: globals.h:280
struct list_head soe_requests
SoE requests.
Definition: slave.h:226
Slave information interface CANopen over EtherCAT details flags.
Definition: globals.h:160
uint8_t enable_safeop
?.
Definition: globals.h:172
ec_slave_config_t * config
Current configuration.
Definition: slave.h:183
unsigned int ec_slave_get_next_port(const ec_slave_t *, unsigned int)
Returns the next connected port of a given port.
Definition: slave.c:1058
char * ec_slave_sii_string(const ec_slave_t *, unsigned int)
Searches the string list for an index.
Definition: slave.c:793
void ec_pdo_entry_clear(ec_pdo_entry_t *entry)
PDO entry destructor.
Definition: pdo_entry.c:68
void ec_slave_clear_sync_managers(ec_slave_t *slave)
Clear the sync manager array.
Definition: slave.c:267
uint32_t revision_number
Revision number.
Definition: sii_page.h:54
uint8_t enable_sdo_info
SDO information service available.
Definition: globals.h:162
uint8_t enable_sdo_complete_access
Complete access possible.
Definition: globals.h:166
void ec_slave_calc_port_delays(ec_slave_t *slave)
Calculates the port transmission delays.
Definition: slave.c:1147
PDO description.
Definition: pdo.h:41
uint8_t sdo_dictionary_fetched
Dictionary has been fetched.
Definition: slave.h:220
uint16_t mailbox_protocols
Supported mailbox protocols.
Definition: slave.h:140
unsigned int debug_level
Master debug level.
Definition: master.h:277
#define EC_SLAVE_ERR(slave, fmt, args...)
Convenience macro for printing slave-specific errors to syslog.
Definition: slave.h:69
int ec_pdo_list_add_pdo_copy(ec_pdo_list_t *pl, const ec_pdo_t *pdo)
Add the copy of an existing PDO to the list.
Definition: pdo_list.c:133
ec_slave_dc_range_t base_dc_range
DC range.
Definition: slave.h:204
uint8_t bit_length
entry length in bit
Definition: pdo_entry.h:45
Sync manager.
Definition: sync.h:39
uint16_t std_rx_mailbox_offset
Standard receive mailbox address.
Definition: slave.h:136
uint8_t base_fmmu_bit_operation
FMMU bit operation is supported.
Definition: slave.h:202
struct list_head list
List item.
Definition: soe_request.h:41
uint32_t transmission_delay
DC system time transmission delay (offset from reference clock).
Definition: slave.h:208
ec_device_index_t
Master devices.
Definition: globals.h:203
char * name
SDO name.
Definition: sdo.h:46
uint16_t alias
Configured station alias.
Definition: slave.h:127
ec_direction_t
Direction type for PDO assignment functions.
Definition: ecrt.h:522
uint8_t base_fmmu_count
Number of supported FMMUs.
Definition: slave.h:200
void ec_slave_calc_transmission_delays_rec(ec_slave_t *slave, uint32_t *delay)
Recursively calculates transmission delays.
Definition: slave.c:1193
uint16_t configured_rx_mailbox_offset
Configured receive mailbox offset.
Definition: slave.h:188
File-Access over EtherCAT.
Definition: globals.h:153
#define EC_READ_U32(DATA)
Read a 32-bit unsigned value from EtherCAT data.
Definition: ecrt.h:3222
struct list_head entries
List of PDO entries.
Definition: pdo.h:46
ec_slave_port_desc_t desc
Port descriptors.
Definition: slave.h:112
unsigned int string_count
Number of SII strings.
Definition: slave.h:144
ec_master_t * master
Master owning the slave.
Definition: slave.h:171
void ec_pdo_entry_init(ec_pdo_entry_t *entry)
PDO entry constructor.
Definition: pdo_entry.c:37
#define EC_SII_WORD_OFFSET_VENDOR
Word offset of vendor ID.
Definition: globals.h:92
const ec_sdo_t * ec_slave_get_sdo_by_pos_const(const ec_slave_t *slave, uint16_t sdo_position)
Get an SDO from the dictionary, given its position in the list.
Definition: slave.c:909
uint8_t has_dc_system_time
The slave supports the DC system time register.
Definition: slave.h:205
char ** strings
Strings in SII categories.
Definition: slave.h:143
ec_slave_state_t
State of an EtherCAT slave.
Definition: globals.h:127
uint32_t vendor_id
Vendor ID.
Definition: sii_page.h:52
uint8_t subindex
PDO entry subindex.
Definition: pdo_entry.h:43
EtherCAT datagram structure.
uint8_t control_register
Control register value.
Definition: sync.h:43
Values read by the master.
Definition: ecrt.h:525
void ec_sync_clear(ec_sync_t *sync)
Destructor.
Definition: sync.c:73
#define EC_FIRST_SII_CATEGORY_OFFSET
Word offset of first SII category.
Definition: globals.h:86
Port is not implemented.
Definition: ecrt.h:445
uint8_t base_revision
Revision.
Definition: slave.h:198
32 bit.
Definition: globals.h:179
Ethernet-over-EtherCAT set IP parameter request.
Definition: eoe_request.h:41
const ec_sdo_t * ec_slave_get_sdo_const(const ec_slave_t *slave, uint16_t index)
Get an SDO from the dictionary.
Definition: slave.c:887
FoE request.
Definition: foe_request.h:42
uint16_t effective_alias
Effective alias address.
Definition: slave.h:178
void ec_sii_page_clear(ec_sii_page_t *page)
Slave destructor.
Definition: sii_page.c:62
struct list_head entries
List of entries.
Definition: sdo.h:48
ec_internal_request_state_t state
Request state.
Definition: eoe_request.h:43
#define EC_READ_U16(DATA)
Read a 16-bit unsigned value from EtherCAT data.
Definition: ecrt.h:3206
struct list_head foe_requests
FoE requests.
Definition: slave.h:225
uint8_t enable
Enable bit.
Definition: sync.h:44
int ec_slave_fetch_sii_syncs(ec_slave_t *, const uint8_t *, size_t)
Fetches data from a SYNC MANAGER category.
Definition: slave.c:644
#define EC_STATE_STRING_SIZE
Minimum size of a buffer used with ec_state_string().
Definition: globals.h:54
uint16_t boot_rx_mailbox_size
Bootstrap receive mailbox size.
Definition: slave.h:133
#define EC_MAX_PORTS
Maximum number of slave ports.
Definition: ecrt.h:294
uint16_t * words
Complete SII image.
Definition: sii_page.h:60
struct list_head list
List item.
Definition: sdo_request.h:41
void ec_fsm_slave_init(ec_fsm_slave_t *fsm, ec_slave_t *slave)
Constructor.
Definition: fsm_slave.c:56
uint32_t product_code
Vendor-specific product code.
Definition: sii_page.h:53
void ec_slave_init(ec_slave_t *slave, ec_master_t *master, ec_device_index_t dev_idx, uint16_t ring_position, uint16_t station_address)
Slave constructor.
Definition: slave.c:65
ec_slave_t * next_slave
Connected slaves.
Definition: slave.h:114
ec_sii_page_t sii_page
The SII contents, either fetched or taken from the cache.
Definition: slave.h:212
uint32_t receive_time
Port receive times for delay measurement.
Definition: slave.h:115
uint32_t ec_slave_calc_rtt_sum(const ec_slave_t *)
Calculates the sum of round-trip-times of connected ports 1-3.
Definition: slave.c:1088
Slave port.
Definition: slave.h:111
char * image
Image name.
Definition: slave.h:149
ec_pdo_list_t pdos
Current PDO assignment.
Definition: sync.h:45
void ec_slave_request_state(ec_slave_t *slave, ec_slave_state_t state)
Request a slave state and resets the error flag.
Definition: slave.c:308
uint16_t physical_start_address
Physical start address.
Definition: sync.h:41
unsigned long jiffies_preop
Time, the slave went to PREOP.
Definition: slave.h:221
void ec_sii_page_init(ec_sii_page_t *page)
SII page constructor.
Definition: sii_page.c:39
uint16_t configured_rx_mailbox_size
Configured receive mailbox size.
Definition: slave.h:190
uint8_t base_dc_supported
Distributed clocks are supported.
Definition: slave.h:203
void ec_sync_init_copy(ec_sync_t *sync, const ec_sync_t *other)
Copy constructor.
Definition: sync.c:55
char * group
Group name.
Definition: slave.h:148
uint8_t physical_layer[EC_MAX_PORTS]
Port media.
Definition: slave.h:152
struct list_head list
list item
Definition: pdo_entry.h:41
void ec_sdo_clear(ec_sdo_t *sdo)
SDO destructor.
Definition: sdo.c:59
uint8_t base_sync_count
Number of supported sync managers.
Definition: slave.h:201
#define EC_READ_U8(DATA)
Read an 8-bit unsigned value from EtherCAT data.
Definition: ecrt.h:3190
EtherCAT slave configuration structure.
ec_internal_request_state_t state
FoE request state.
Definition: foe_request.h:55
#define EC_READ_S16(DATA)
Read a 16-bit signed value from EtherCAT data.
Definition: ecrt.h:3214
ec_device_index_t device_index
Index of device the slave responds on.
Definition: slave.h:172
void ec_slave_config_detach(ec_slave_config_t *sc)
Detaches the configuration from a slave object.
Definition: slave_config.c:315
unsigned int ec_slave_get_previous_port(const ec_slave_t *, unsigned int)
Returns the previous connected port of a given port.
Definition: slave.c:1028
uint16_t default_length
Data length in bytes.
Definition: sync.h:42
uint32_t product_code
Vendor-specific product code.
Definition: slave.h:129
PREOP state (mailbox communication, no IO)
Definition: globals.h:132
Values written by the master.
Definition: ecrt.h:524
uint32_t serial_number
Serial number.
Definition: sii_page.h:55
struct list_head list
List item.
Definition: pdo.h:42
unsigned int error_flag
Stop processing after an error.
Definition: slave.h:186
ec_sync_t * syncs
SYNC MANAGER categories.
Definition: slave.h:158
uint16_t std_tx_mailbox_size
Standard transmit mailbox size.
Definition: slave.h:139
EtherCAT master.
Definition: master.h:187
uint8_t enable_pdo_configuration
PDO configuration possible.
Definition: globals.h:164
struct list_head list
List item.
Definition: reg_request.h:41
ec_slave_state_t requested_state
Requested application state.
Definition: slave.h:184
struct list_head eoe_requests
EoE set IP parameter requests.
Definition: slave.h:227
Vendor specific.
Definition: globals.h:155
int ec_slave_fetch_sii_pdos(ec_slave_t *, const uint8_t *, size_t, ec_direction_t)
Fetches data from a [RT]xPDO category.
Definition: slave.c:710
#define EC_MAX_SYNC_MANAGERS
Maximum number of sync managers per slave.
Definition: ecrt.h:285
ec_internal_request_state_t state
Request state.
Definition: soe_request.h:52
void ec_sync_init(ec_sync_t *sync, ec_slave_t *slave)
Constructor.
Definition: sync.c:38
struct list_head list
List item.
Definition: eoe_request.h:42
int ec_slave_fetch_sii_general(ec_slave_t *, const uint8_t *, size_t)
Fetches data from a GENERAL category.
Definition: slave.c:593
ADS over EtherCAT.
Definition: globals.h:150
Sercos-over-EtherCAT request.
Definition: soe_request.h:40
char * name
Slave name.
Definition: slave.h:151
int ec_pdo_entry_set_name(ec_pdo_entry_t *entry, const char *name)
Set PDO entry name.
Definition: pdo_entry.c:81
unknown state
Definition: globals.h:128
uint32_t vendor_id
Vendor ID.
Definition: slave.h:128
uint32_t delay_to_next_dc
Delay to next slave with DC support behind this port [ns].
Definition: slave.h:117
struct list_head pdos
SII [RT]XPDO categories.
Definition: slave.h:162
unsigned int force_config
Force (re-)configuration.
Definition: slave.h:187
struct list_head list
List item.
Definition: foe_request.h:43
unsigned int has_general
General category present.
Definition: slave.h:147
ec_sync_t * ec_slave_get_sync(ec_slave_t *slave, uint8_t sync_index)
Get the sync manager given an index.
Definition: slave.c:815
uint8_t enable_pdo_assign
PDO mapping configurable.
Definition: globals.h:163
unsigned int sii_parallel_words
How many SII words the slave can read at once.
Definition: slave.h:214