IgH EtherCAT Master  1.6.0-rc1
slave.c
Go to the documentation of this file.
1 /******************************************************************************
2  *
3  * $Id$
4  *
5  * Copyright (C) 2006-2012 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 #include <linux/delay.h>
39 
40 #include "globals.h"
41 #include "datagram.h"
42 #include "master.h"
43 #include "slave_config.h"
44 
45 #include "slave.h"
46 
47 /*****************************************************************************/
48 
49 extern const ec_code_msg_t al_status_messages[];
50 
51 /*****************************************************************************/
52 
53 char *ec_slave_sii_string(ec_slave_t *, unsigned int);
54 
55 /*****************************************************************************/
56 
63  ec_slave_t *slave,
64  ec_master_t *master,
65  ec_device_index_t dev_idx,
66  uint16_t ring_position,
67  uint16_t station_address
68  )
69 {
70  unsigned int i;
71 
72  slave->master = master;
73  slave->device_index = dev_idx;
74  slave->ring_position = ring_position;
75  slave->station_address = station_address;
76  slave->effective_alias = 0x0000;
77 
78  slave->config = NULL;
81  slave->error_flag = 0;
82  slave->force_config = 0;
83  slave->configured_rx_mailbox_offset = 0x0000;
84  slave->configured_rx_mailbox_size = 0x0000;
85  slave->configured_tx_mailbox_offset = 0x0000;
86  slave->configured_tx_mailbox_size = 0x0000;
87 
88  slave->base_type = 0;
89  slave->base_revision = 0;
90  slave->base_build = 0;
91  slave->base_fmmu_count = 0;
92  slave->base_sync_count = 0;
93 
94  for (i = 0; i < EC_MAX_PORTS; i++) {
96 
97  slave->ports[i].link.link_up = 0;
98  slave->ports[i].link.loop_closed = 1;
99  slave->ports[i].link.signal_detected = 0;
100  slave->sii.physical_layer[i] = 0xFF;
101 
102  slave->ports[i].receive_time = 0U;
103 
104  slave->ports[i].next_slave = NULL;
105  slave->ports[i].delay_to_next_dc = 0U;
106 
107 #ifdef EC_LOOP_CONTROL
108  slave->ports[i].state = EC_SLAVE_PORT_DOWN;
109  slave->ports[i].link_detection_jiffies = 0;
110 #endif
111  }
112 
113  slave->base_fmmu_bit_operation = 0;
114  slave->base_dc_supported = 0;
115  slave->base_dc_range = EC_DC_32;
116  slave->has_dc_system_time = 0;
117  slave->transmission_delay = 0U;
118 
119  slave->sii_words = NULL;
120  slave->sii_nwords = 0;
121 
122  slave->sii.alias = 0x0000;
123  slave->sii.vendor_id = 0x00000000;
124  slave->sii.product_code = 0x00000000;
125  slave->sii.revision_number = 0x00000000;
126  slave->sii.serial_number = 0x00000000;
127  slave->sii.boot_rx_mailbox_offset = 0x0000;
128  slave->sii.boot_rx_mailbox_size = 0x0000;
129  slave->sii.boot_tx_mailbox_offset = 0x0000;
130  slave->sii.boot_tx_mailbox_size = 0x0000;
131  slave->sii.std_rx_mailbox_offset = 0x0000;
132  slave->sii.std_rx_mailbox_size = 0x0000;
133  slave->sii.std_tx_mailbox_offset = 0x0000;
134  slave->sii.std_tx_mailbox_size = 0x0000;
135  slave->sii.mailbox_protocols = 0;
136 
137  slave->sii.strings = NULL;
138  slave->sii.string_count = 0;
139 
140  slave->sii.has_general = 0;
141  slave->sii.group = NULL;
142  slave->sii.image = NULL;
143  slave->sii.order = NULL;
144  slave->sii.name = NULL;
145  memset(&slave->sii.coe_details, 0x00, sizeof(ec_sii_coe_details_t));
146  memset(&slave->sii.general_flags, 0x00, sizeof(ec_sii_general_flags_t));
147  slave->sii.current_on_ebus = 0;
148 
149  slave->sii.syncs = NULL;
150  slave->sii.sync_count = 0;
151 
152  INIT_LIST_HEAD(&slave->sii.pdos);
153 
154  INIT_LIST_HEAD(&slave->sdo_dictionary);
155 
156  slave->sdo_dictionary_fetched = 0;
157  slave->jiffies_preop = 0;
158 
159  INIT_LIST_HEAD(&slave->sdo_requests);
160  INIT_LIST_HEAD(&slave->reg_requests);
161  INIT_LIST_HEAD(&slave->foe_requests);
162  INIT_LIST_HEAD(&slave->soe_requests);
163  INIT_LIST_HEAD(&slave->eoe_requests);
164  INIT_LIST_HEAD(&slave->dict_requests);
165 
166  // create state machine object
167  ec_fsm_slave_init(&slave->fsm, slave);
168 
169  slave->read_mbox_busy = 0;
170  rt_mutex_init(&slave->mbox_sem);
171 
172 #ifdef EC_EOE
175 #endif
180 
181  slave->valid_mbox_data = 0;
182 }
183 
184 
185 /*****************************************************************************/
186 
191 {
192  rt_mutex_lock(&slave->mbox_sem);
193  slave->read_mbox_busy = 0;
194  rt_mutex_unlock(&slave->mbox_sem);
195 }
196 
197 
198 /*****************************************************************************/
199 
204 {
205  int rc;
206 
207  rt_mutex_lock(&slave->mbox_sem);
208  rc = slave->read_mbox_busy;
209  if (!slave->read_mbox_busy) {
210  slave->read_mbox_busy = 1;
211  }
212  rt_mutex_unlock(&slave->mbox_sem);
213  return rc;
214 }
215 
216 
217 /*****************************************************************************/
218 
225 {
226  ec_sdo_t *sdo, *next_sdo;
227  unsigned int i;
228  ec_pdo_t *pdo, *next_pdo;
229 
230  // abort all pending requests
231 
232  while (!list_empty(&slave->sdo_requests)) {
233  ec_sdo_request_t *request =
234  list_entry(slave->sdo_requests.next, ec_sdo_request_t, list);
235  list_del_init(&request->list); // dequeue
236  EC_SLAVE_WARN(slave, "Discarding SDO request,"
237  " slave about to be deleted.\n");
238  request->state = EC_INT_REQUEST_FAILURE;
239  }
240 
241  while (!list_empty(&slave->reg_requests)) {
242  ec_reg_request_t *reg =
243  list_entry(slave->reg_requests.next, ec_reg_request_t, list);
244  list_del_init(&reg->list); // dequeue
245  EC_SLAVE_WARN(slave, "Discarding register request,"
246  " slave about to be deleted.\n");
247  reg->state = EC_INT_REQUEST_FAILURE;
248  }
249 
250  while (!list_empty(&slave->foe_requests)) {
251  ec_foe_request_t *request =
252  list_entry(slave->foe_requests.next, ec_foe_request_t, list);
253  list_del_init(&request->list); // dequeue
254  EC_SLAVE_WARN(slave, "Discarding FoE request,"
255  " slave about to be deleted.\n");
256  request->state = EC_INT_REQUEST_FAILURE;
257  }
258 
259  while (!list_empty(&slave->soe_requests)) {
260  ec_soe_request_t *request =
261  list_entry(slave->soe_requests.next, ec_soe_request_t, list);
262  list_del_init(&request->list); // dequeue
263  EC_SLAVE_WARN(slave, "Discarding SoE request,"
264  " slave about to be deleted.\n");
265  request->state = EC_INT_REQUEST_FAILURE;
266  }
267 
268  while (!list_empty(&slave->eoe_requests)) {
269  ec_eoe_request_t *request =
270  list_entry(slave->eoe_requests.next, ec_eoe_request_t, list);
271  list_del_init(&request->list); // dequeue
272  EC_SLAVE_WARN(slave, "Discarding EoE request,"
273  " slave about to be deleted.\n");
274  request->state = EC_INT_REQUEST_FAILURE;
275  }
276 
277  while (!list_empty(&slave->dict_requests)) {
278  ec_dict_request_t *request =
279  list_entry(slave->dict_requests.next, ec_dict_request_t, list);
280  list_del_init(&request->list); // dequeue
281  EC_SLAVE_WARN(slave, "Discarding dictionary request,"
282  " slave about to be deleted.\n");
283  request->state = EC_INT_REQUEST_FAILURE;
284  }
285 
286  wake_up_all(&slave->master->request_queue);
287 
288  if (slave->config) {
290  }
291 
292  // free all SDOs
293  list_for_each_entry_safe(sdo, next_sdo, &slave->sdo_dictionary, list) {
294  list_del(&sdo->list);
295  ec_sdo_clear(sdo);
296  kfree(sdo);
297  }
298 
299  // free all strings
300  if (slave->sii.strings) {
301  for (i = 0; i < slave->sii.string_count; i++)
302  kfree(slave->sii.strings[i]);
303  kfree(slave->sii.strings);
304  }
305 
306  // free all sync managers
308 
309  // free all SII PDOs
310  list_for_each_entry_safe(pdo, next_pdo, &slave->sii.pdos, list) {
311  list_del(&pdo->list);
312  ec_pdo_clear(pdo);
313  kfree(pdo);
314  }
315 
316  if (slave->sii_words) {
317  kfree(slave->sii_words);
318  }
319 
320  // free mailbox response data
321 #ifdef EC_EOE
324 #endif
329 
330  ec_fsm_slave_clear(&slave->fsm);
331 }
332 
333 /*****************************************************************************/
334 
338 {
339  unsigned int i;
340 
341  if (slave->sii.syncs) {
342  for (i = 0; i < slave->sii.sync_count; i++) {
343  ec_sync_clear(&slave->sii.syncs[i]);
344  }
345  kfree(slave->sii.syncs);
346  slave->sii.syncs = NULL;
347  }
348 }
349 
350 /*****************************************************************************/
351 
357  uint16_t new_state
358  )
359 {
360  unsigned int i;
361  uint8_t state;
362 
363  for (i = 0; i < EC_MAX_PORTS; i++) {
364  // link status
365  state = new_state & (1 << (4 + i)) ? 1 : 0;
366  if (slave->ports[i].link.link_up != state) {
367  EC_SLAVE_DBG(slave, 1, "Port %u link status changed to %s.\n",
368  i, state ? "up" : "down");
369  slave->ports[i].link.link_up = state;
370  }
371 
372  // loop status
373  state = new_state & (1 << (8 + i * 2)) ? 1 : 0;
374  if (slave->ports[i].link.loop_closed != state) {
375  EC_SLAVE_DBG(slave, 1, "Port %u loop status changed to %s.\n",
376  i, state ? "closed" : "open");
377  slave->ports[i].link.loop_closed = state;
378  }
379 
380  // signal detection
381  state = new_state & (1 << (9 + i * 2)) ? 1 : 0;
382  if (slave->ports[i].link.signal_detected != state) {
383  EC_SLAVE_DBG(slave, 1, "Port %u signal status changed to %s.\n",
384  i, state ? "yes" : "no");
385  slave->ports[i].link.signal_detected = state;
386  }
387  }
388 }
389 
390 /*****************************************************************************/
391 
397  ec_slave_state_t new_state
398  )
399 {
400  if (new_state != slave->current_state) {
401  if (slave->master->debug_level) {
402  char old_state[EC_STATE_STRING_SIZE],
403  cur_state[EC_STATE_STRING_SIZE];
404  ec_state_string(slave->current_state, old_state, 0);
405  ec_state_string(new_state, cur_state, 0);
406  EC_SLAVE_DBG(slave, 0, "%s -> %s.\n", old_state, cur_state);
407  }
408  slave->current_state = new_state;
409  }
410 }
411 
412 /*****************************************************************************/
413 
419  ec_slave_state_t state
420  )
421 {
422  slave->requested_state = state;
423  slave->error_flag = 0;
424 }
425 
426 /*****************************************************************************/
427 
435  ec_slave_t *slave,
436  const uint8_t *data,
437  size_t data_size
438  )
439 {
440  int i, err;
441  size_t size;
442  off_t offset;
443 
444  slave->sii.string_count = data[0];
445 
446  if (slave->sii.string_count) {
447  if (!(slave->sii.strings =
448  kmalloc(sizeof(char *) * slave->sii.string_count,
449  GFP_KERNEL))) {
450  EC_SLAVE_ERR(slave, "Failed to allocate string array memory.\n");
451  err = -ENOMEM;
452  goto out_zero;
453  }
454 
455  offset = 1;
456  for (i = 0; i < slave->sii.string_count; i++) {
457  size = data[offset];
458  // allocate memory for string structure and data at a single blow
459  if (!(slave->sii.strings[i] =
460  kmalloc(sizeof(char) * size + 1, GFP_KERNEL))) {
461  EC_SLAVE_ERR(slave, "Failed to allocate string memory.\n");
462  err = -ENOMEM;
463  goto out_free;
464  }
465  memcpy(slave->sii.strings[i], data + offset + 1, size);
466  slave->sii.strings[i][size] = 0x00; // append binary zero
467  offset += 1 + size;
468  }
469  }
470 
471  return 0;
472 
473 out_free:
474  for (i--; i >= 0; i--)
475  kfree(slave->sii.strings[i]);
476  kfree(slave->sii.strings);
477  slave->sii.strings = NULL;
478 out_zero:
479  slave->sii.string_count = 0;
480  return err;
481 }
482 
483 /*****************************************************************************/
484 
491  ec_slave_t *slave,
492  const uint8_t *data,
493  size_t data_size
494  )
495 {
496  unsigned int i;
497  uint8_t flags;
498 
499  if (data_size != 32) {
500  EC_SLAVE_ERR(slave, "Wrong size of general category (%zu/32).\n",
501  data_size);
502  return -EINVAL;
503  }
504 
505  slave->sii.group = ec_slave_sii_string(slave, data[0]);
506  slave->sii.image = ec_slave_sii_string(slave, data[1]);
507  slave->sii.order = ec_slave_sii_string(slave, data[2]);
508  slave->sii.name = ec_slave_sii_string(slave, data[3]);
509 
510  for (i = 0; i < 4; i++)
511  slave->sii.physical_layer[i] =
512  (data[4] & (0x03 << (i * 2))) >> (i * 2);
513 
514  // read CoE details
515  flags = EC_READ_U8(data + 5);
516  slave->sii.coe_details.enable_sdo = (flags >> 0) & 0x01;
517  slave->sii.coe_details.enable_sdo_info = (flags >> 1) & 0x01;
518  slave->sii.coe_details.enable_pdo_assign = (flags >> 2) & 0x01;
519  slave->sii.coe_details.enable_pdo_configuration = (flags >> 3) & 0x01;
520  slave->sii.coe_details.enable_upload_at_startup = (flags >> 4) & 0x01;
521  slave->sii.coe_details.enable_sdo_complete_access = (flags >> 5) & 0x01;
522 
523  // read general flags
524  flags = EC_READ_U8(data + 0x000B);
525  slave->sii.general_flags.enable_safeop = (flags >> 0) & 0x01;
526  slave->sii.general_flags.enable_not_lrw = (flags >> 1) & 0x01;
527 
528  slave->sii.current_on_ebus = EC_READ_S16(data + 0x0C);
529  slave->sii.has_general = 1;
530  return 0;
531 }
532 
533 /*****************************************************************************/
534 
542  ec_slave_t *slave,
543  const uint8_t *data,
544  size_t data_size
545  )
546 {
547  unsigned int i, count, total_count;
548  ec_sync_t *sync;
549  size_t memsize;
550  ec_sync_t *syncs;
551  uint8_t index;
552 
553  // one sync manager struct is 4 words long
554  if (data_size % 8) {
555  EC_SLAVE_ERR(slave, "Invalid SII sync manager category size %zu.\n",
556  data_size);
557  return -EINVAL;
558  }
559 
560  count = data_size / 8;
561 
562  if (count) {
563  total_count = count + slave->sii.sync_count;
564  if (total_count > EC_MAX_SYNC_MANAGERS) {
565  EC_SLAVE_ERR(slave, "Exceeded maximum number of"
566  " sync managers!\n");
567  return -EOVERFLOW;
568  }
569  memsize = sizeof(ec_sync_t) * total_count;
570  if (!(syncs = kmalloc(memsize, GFP_KERNEL))) {
571  EC_SLAVE_ERR(slave, "Failed to allocate %zu bytes"
572  " for sync managers.\n", memsize);
573  return -ENOMEM;
574  }
575 
576  for (i = 0; i < slave->sii.sync_count; i++)
577  ec_sync_init_copy(syncs + i, slave->sii.syncs + i);
578 
579  // initialize new sync managers
580  for (i = 0; i < count; i++, data += 8) {
581  index = i + slave->sii.sync_count;
582  sync = &syncs[index];
583 
584  ec_sync_init(sync, slave);
585  sync->physical_start_address = EC_READ_U16(data);
586  sync->default_length = EC_READ_U16(data + 2);
587  sync->control_register = EC_READ_U8(data + 4);
588  sync->enable = EC_READ_U8(data + 6);
589  }
590 
591  if (slave->sii.syncs)
592  kfree(slave->sii.syncs);
593  slave->sii.syncs = syncs;
594  slave->sii.sync_count = total_count;
595  }
596 
597  return 0;
598 }
599 
600 /*****************************************************************************/
601 
608  ec_slave_t *slave,
609  const uint8_t *data,
610  size_t data_size,
611  ec_direction_t dir
612  )
613 {
614  int ret;
615  ec_pdo_t *pdo;
616  ec_pdo_entry_t *entry;
617  unsigned int entry_count, i;
618 
619  while (data_size >= 8) {
620  if (!(pdo = kmalloc(sizeof(ec_pdo_t), GFP_KERNEL))) {
621  EC_SLAVE_ERR(slave, "Failed to allocate PDO memory.\n");
622  return -ENOMEM;
623  }
624 
625  ec_pdo_init(pdo);
626  pdo->index = EC_READ_U16(data);
627  entry_count = EC_READ_U8(data + 2);
628  pdo->sync_index = EC_READ_U8(data + 3);
629  ret = ec_pdo_set_name(pdo,
630  ec_slave_sii_string(slave, EC_READ_U8(data + 5)));
631  if (ret) {
632  ec_pdo_clear(pdo);
633  kfree(pdo);
634  return ret;
635  }
636  list_add_tail(&pdo->list, &slave->sii.pdos);
637 
638  data_size -= 8;
639  data += 8;
640 
641  for (i = 0; i < entry_count; i++) {
642  if (!(entry = kmalloc(sizeof(ec_pdo_entry_t), GFP_KERNEL))) {
643  EC_SLAVE_ERR(slave, "Failed to allocate PDO entry memory.\n");
644  return -ENOMEM;
645  }
646 
647  ec_pdo_entry_init(entry);
648  entry->index = EC_READ_U16(data);
649  entry->subindex = EC_READ_U8(data + 2);
650  ret = ec_pdo_entry_set_name(entry,
651  ec_slave_sii_string(slave, EC_READ_U8(data + 3)));
652  if (ret) {
653  ec_pdo_entry_clear(entry);
654  kfree(entry);
655  return ret;
656  }
657  entry->bit_length = EC_READ_U8(data + 5);
658  list_add_tail(&entry->list, &pdo->entries);
659 
660  data_size -= 8;
661  data += 8;
662  }
663 
664  // if sync manager index is positive, the PDO is mapped by default
665  if (pdo->sync_index >= 0) {
666  ec_sync_t *sync;
667 
668  if (!(sync = ec_slave_get_sync(slave, pdo->sync_index))) {
669  EC_SLAVE_ERR(slave, "Invalid SM index %i for PDO 0x%04X.",
670  pdo->sync_index, pdo->index);
671  return -ENOENT;
672  }
673 
674  ret = ec_pdo_list_add_pdo_copy(&sync->pdos, pdo);
675  if (ret)
676  return ret;
677  }
678  }
679 
680  return 0;
681 }
682 
683 /*****************************************************************************/
684 
691  ec_slave_t *slave,
692  unsigned int index
693  )
694 {
695  if (!index--)
696  return NULL;
697 
698  if (index >= slave->sii.string_count) {
699  EC_SLAVE_DBG(slave, 1, "String %u not found.\n", index);
700  return NULL;
701  }
702 
703  return slave->sii.strings[index];
704 }
705 
706 /*****************************************************************************/
707 
713  ec_slave_t *slave,
714  uint8_t sync_index
715  )
716 {
717  if (sync_index < slave->sii.sync_count) {
718  return &slave->sii.syncs[sync_index];
719  } else {
720  return NULL;
721  }
722 }
723 
724 /*****************************************************************************/
725 
731  unsigned int *sdo_count,
732  unsigned int *entry_count
734  )
735 {
736  unsigned int sdos = 0, entries = 0;
737  ec_sdo_t *sdo;
738  ec_sdo_entry_t *entry;
739 
740  list_for_each_entry(sdo, &slave->sdo_dictionary, list) {
741  sdos++;
742  list_for_each_entry(entry, &sdo->entries, list) {
743  entries++;
744  }
745  }
746 
747  *sdo_count = sdos;
748  *entry_count = entries;
749 }
750 
751 /*****************************************************************************/
752 
759  ec_slave_t *slave,
760  uint16_t index
761  )
762 {
763  ec_sdo_t *sdo;
764 
765  list_for_each_entry(sdo, &slave->sdo_dictionary, list) {
766  if (sdo->index != index)
767  continue;
768  return sdo;
769  }
770 
771  return NULL;
772 }
773 
774 /*****************************************************************************/
775 
785  const ec_slave_t *slave,
786  uint16_t index
787  )
788 {
789  const ec_sdo_t *sdo;
790 
791  list_for_each_entry(sdo, &slave->sdo_dictionary, list) {
792  if (sdo->index != index)
793  continue;
794  return sdo;
795  }
796 
797  return NULL;
798 }
799 
800 /*****************************************************************************/
801 
807  const ec_slave_t *slave,
808  uint16_t sdo_position
809  )
810 {
811  const ec_sdo_t *sdo;
812 
813  list_for_each_entry(sdo, &slave->sdo_dictionary, list) {
814  if (sdo_position--)
815  continue;
816  return sdo;
817  }
818 
819  return NULL;
820 }
821 
822 /*****************************************************************************/
823 
829  const ec_slave_t *slave
830  )
831 {
832  const ec_sdo_t *sdo;
833  uint16_t count = 0;
834 
835  list_for_each_entry(sdo, &slave->sdo_dictionary, list) {
836  count++;
837  }
838 
839  return count;
840 }
841 
842 /*****************************************************************************/
843 
848  const ec_slave_t *slave,
849  uint16_t index
850  )
851 {
852  unsigned int i;
853  const ec_sync_t *sync;
854  const ec_pdo_t *pdo;
855 
856  for (i = 0; i < slave->sii.sync_count; i++) {
857  sync = &slave->sii.syncs[i];
858 
859  if (!(pdo = ec_pdo_list_find_pdo_const(&sync->pdos, index)))
860  continue;
861 
862  return pdo;
863  }
864 
865  return NULL;
866 }
867 
868 /*****************************************************************************/
869 
873  ec_slave_t *slave,
874  ec_pdo_t *pdo
875  )
876 {
877  const ec_sdo_t *sdo;
878  ec_pdo_entry_t *pdo_entry;
879  const ec_sdo_entry_t *sdo_entry;
880 
881  list_for_each_entry(sdo, &slave->sdo_dictionary, list) {
882  if (sdo->index == pdo->index) {
883  ec_pdo_set_name(pdo, sdo->name);
884  } else {
885  list_for_each_entry(pdo_entry, &pdo->entries, list) {
886  if (sdo->index == pdo_entry->index) {
887  sdo_entry = ec_sdo_get_entry_const(
888  sdo, pdo_entry->subindex);
889  if (sdo_entry) {
890  ec_pdo_entry_set_name(pdo_entry,
891  sdo_entry->description);
892  }
893  }
894  }
895  }
896  }
897 }
898 
899 /*****************************************************************************/
900 
904  ec_slave_t *slave
905  )
906 {
907  unsigned int i;
908  ec_sync_t *sync;
909  ec_pdo_t *pdo;
910 
911  for (i = 0; i < slave->sii.sync_count; i++) {
912  sync = slave->sii.syncs + i;
913  list_for_each_entry(pdo, &sync->pdos.list, list) {
914  ec_slave_find_names_for_pdo(slave, pdo);
915  }
916  }
917 }
918 
919 /*****************************************************************************/
920 
926  ec_slave_t *slave,
927  unsigned int port_index
928  )
929 {
930  static const unsigned int prev_table[EC_MAX_PORTS] = {
931  2, 3, 1, 0
932  };
933 
934  if (port_index >= EC_MAX_PORTS) {
935  EC_SLAVE_WARN(slave, "%s(port_index=%u): Invalid port index!\n",
936  __func__, port_index);
937  }
938 
939  do {
940  port_index = prev_table[port_index];
941  if (slave->ports[port_index].next_slave) {
942  return port_index;
943  }
944  } while (port_index);
945 
946  return 0;
947 }
948 
949 /*****************************************************************************/
950 
956  ec_slave_t *slave,
957  unsigned int port_index
958  )
959 {
960  static const unsigned int next_table[EC_MAX_PORTS] = {
961  3, 2, 0, 1
962  };
963 
964  if (port_index >= EC_MAX_PORTS) {
965  EC_SLAVE_WARN(slave, "%s(port_index=%u): Invalid port index!\n",
966  __func__, port_index);
967  }
968 
969  do {
970  port_index = next_table[port_index];
971  if (slave->ports[port_index].next_slave) {
972  return port_index;
973  }
974  } while (port_index);
975 
976  return 0;
977 }
978 
979 /*****************************************************************************/
980 
986  ec_slave_t *slave
987  )
988 {
989  uint32_t rtt_sum = 0, rtt;
990  unsigned int port_index = ec_slave_get_next_port(slave, 0);
991 
992  while (port_index != 0) {
993  unsigned int prev_index =
994  ec_slave_get_previous_port(slave, port_index);
995 
996  rtt = slave->ports[port_index].receive_time -
997  slave->ports[prev_index].receive_time;
998  rtt_sum += rtt;
999  port_index = ec_slave_get_next_port(slave, port_index);
1000  }
1001 
1002  return rtt_sum;
1003 }
1004 
1005 /*****************************************************************************/
1006 
1012  ec_slave_t *slave
1013  )
1014 {
1015  unsigned int port_index;
1016  ec_slave_t *dc_slave = NULL;
1017 
1018  if (slave->base_dc_supported) {
1019  dc_slave = slave;
1020  } else {
1021  port_index = ec_slave_get_next_port(slave, 0);
1022 
1023  while (port_index != 0) {
1024  ec_slave_t *next = slave->ports[port_index].next_slave;
1025 
1026  if (next) {
1027  dc_slave = ec_slave_find_next_dc_slave(next);
1028 
1029  if (dc_slave) {
1030  break;
1031  }
1032  }
1033  port_index = ec_slave_get_next_port(slave, port_index);
1034  }
1035  }
1036 
1037  return dc_slave;
1038 }
1039 
1040 /*****************************************************************************/
1041 
1045  ec_slave_t *slave
1046  )
1047 {
1048  unsigned int port_index;
1049  ec_slave_t *next_slave, *next_dc;
1050  uint32_t rtt, next_rtt_sum;
1051 
1052  if (!slave->base_dc_supported)
1053  return;
1054 
1055  port_index = ec_slave_get_next_port(slave, 0);
1056 
1057  while (port_index != 0) {
1058  next_slave = slave->ports[port_index].next_slave;
1059  next_dc = ec_slave_find_next_dc_slave(next_slave);
1060 
1061  if (next_dc) {
1062  unsigned int prev_port =
1063  ec_slave_get_previous_port(slave, port_index);
1064 
1065  rtt = slave->ports[port_index].receive_time -
1066  slave->ports[prev_port].receive_time;
1067  next_rtt_sum = ec_slave_calc_rtt_sum(next_dc);
1068 
1069  slave->ports[port_index].delay_to_next_dc =
1070  (rtt - next_rtt_sum) / 2; // FIXME
1071  next_dc->ports[0].delay_to_next_dc =
1072  (rtt - next_rtt_sum) / 2;
1073 
1074 #if 0
1075  EC_SLAVE_DBG(slave, 1, "delay %u:%u rtt=%u"
1076  " next_rtt_sum=%u delay=%u\n",
1077  slave->ring_position, port_index, rtt, next_rtt_sum,
1078  slave->ports[port_index].delay_to_next_dc);
1079 #endif
1080  }
1081 
1082  port_index = ec_slave_get_next_port(slave, port_index);
1083  }
1084 }
1085 
1086 /*****************************************************************************/
1087 
1091  ec_slave_t *slave,
1092  uint32_t *delay
1093  )
1094 {
1095  unsigned int i;
1096  ec_slave_t *next_dc;
1097 
1098  EC_SLAVE_DBG(slave, 1, "%s(delay = %u ns)\n", __func__, *delay);
1099 
1100  slave->transmission_delay = *delay;
1101 
1102  i = ec_slave_get_next_port(slave, 0);
1103 
1104  while (i != 0) {
1105  ec_slave_port_t *port = &slave->ports[i];
1106  next_dc = ec_slave_find_next_dc_slave(port->next_slave);
1107  if (next_dc) {
1108  *delay = *delay + port->delay_to_next_dc;
1109 #if 0
1110  EC_SLAVE_DBG(slave, 1, "%u:%u %u\n",
1111  slave->ring_position, i, *delay);
1112 #endif
1113  ec_slave_calc_transmission_delays_rec(next_dc, delay);
1114  }
1115 
1116  i = ec_slave_get_next_port(slave, i);
1117  }
1118 
1119  *delay = *delay + slave->ports[0].delay_to_next_dc;
1120 }
1121 
1122 /*****************************************************************************/
ec_sii_general_flags_t general_flags
General flags.
Definition: slave.h:184
ec_mbox_data_t mbox_eoe_frag_data
Received mailbox data for EoE, type frame fragment.
Definition: slave.h:265
Slave information interface general flags.
Definition: globals.h:171
ec_internal_request_state_t state
Request state.
Definition: reg_request.h:56
uint16_t ring_position
Ring position.
Definition: slave.h:206
uint32_t revision_number
Revision number.
Definition: slave.h:160
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:116
uint16_t ec_slave_sdo_count(const ec_slave_t *slave)
Get the number of SDOs in the dictionary.
Definition: slave.c:828
struct rt_mutex mbox_sem
Semaphore protecting the check_mbox variable.
Definition: slave.h:262
uint16_t boot_rx_mailbox_offset
Bootstrap receive mailbox address.
Definition: slave.h:162
void ec_fsm_slave_clear(ec_fsm_slave_t *fsm)
Destructor.
Definition: fsm_slave.c:97
ec_sii_t sii
Extracted SII data.
Definition: slave.h:246
uint16_t configured_tx_mailbox_size
Configured send mailbox size.
Definition: slave.h:224
unsigned int ec_slave_get_previous_port(ec_slave_t *slave, unsigned int port_index)
Returns the previous connected port of a given port.
Definition: slave.c:925
void ec_mbox_data_init(ec_mbox_data_t *mbox_data)
Initialize mailbox response data.
Definition: datagram.c:661
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:903
uint16_t base_build
Build number.
Definition: slave.h:229
struct list_head list
List item.
Definition: soe_request.h:49
#define EC_SLAVE_DBG(slave, level, fmt, args...)
Convenience macro for printing slave-specific debug messages to syslog.
Definition: slave.h:107
CANopen SDO entry.
Definition: sdo_entry.h:54
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:265
ec_mbox_data_t mbox_eoe_init_data
Received mailbox data for EoE, type eoe init reponse.
Definition: slave.h:266
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:222
size_t ec_state_string(uint8_t, char *, uint8_t)
Prints slave states in clear text.
Definition: module.c:402
ec_slave_port_t ports[EC_MAX_PORTS]
Ports.
Definition: slave.h:210
CANopen SDO request.
Definition: sdo_request.h:48
ec_slave_state_t current_state
Current application state.
Definition: slave.h:215
const ec_code_msg_t al_status_messages[]
Application layer status messages.
Definition: fsm_change.c:346
EtherCAT slave structure.
ec_internal_request_state_t state
SDO request state.
Definition: sdo_request.h:63
Register request.
Definition: reg_request.h:48
ec_mbox_data_t mbox_foe_data
Received mailbox data for FoE.
Definition: slave.h:269
ec_sdo_t * ec_slave_get_sdo(ec_slave_t *slave, uint16_t index)
Get an SDO from the dictionary.
Definition: slave.c:758
ec_slave_port_link_t link
Port link status.
Definition: slave.h:139
#define EC_SLAVE_WARN(slave, fmt, args...)
Convenience macro for printing slave-specific warnings to syslog.
Definition: slave.h:91
uint8_t enable_sdo
Enable SDO access.
Definition: globals.h:161
struct list_head list
List of PDOs.
Definition: pdo_list.h:50
uint32_t serial_number
Serial number.
Definition: slave.h:161
ec_sii_coe_details_t coe_details
CoE detail flags.
Definition: slave.h:183
char * order
Order number.
Definition: slave.h:180
int ec_pdo_set_name(ec_pdo_t *pdo, const char *name)
Set PDO name.
Definition: pdo.c:125
ec_internal_request_state_t state
Request state.
Definition: soe_request.h:58
void ec_slave_find_names_for_pdo(ec_slave_t *slave, ec_pdo_t *pdo)
Find name for a PDO and its entries.
Definition: slave.c:872
ec_fsm_slave_t fsm
Slave state machine.
Definition: slave.h:259
struct list_head reg_requests
Register access requests.
Definition: slave.h:253
struct list_head list
List item.
Definition: sdo.h:50
void ec_pdo_init(ec_pdo_t *pdo)
PDO constructor.
Definition: pdo.c:46
const ec_pdo_t * ec_slave_find_pdo(const ec_slave_t *slave, uint16_t index)
Finds a mapped PDO.
Definition: slave.c:847
CANopen SDO.
Definition: sdo.h:49
uint16_t index
SDO index.
Definition: sdo.h:52
int16_t current_on_ebus
Power consumption in mA.
Definition: slave.h:185
uint16_t boot_tx_mailbox_size
Bootstrap transmit mailbox size.
Definition: slave.h:165
int ec_slave_fetch_sii_strings(ec_slave_t *slave, const uint8_t *data, size_t data_size)
Fetches data from a STRING category.
Definition: slave.c:434
void ec_slave_set_dl_status(ec_slave_t *slave, uint16_t new_state)
Sets the data-link state of a slave.
Definition: slave.c:356
wait_queue_head_t request_queue
Wait queue for external requests from user space.
Definition: master.h:308
uint16_t station_address
Configured station address.
Definition: slave.h:207
unsigned int sync_count
Number of sync managers.
Definition: slave.h:189
char * ec_slave_sii_string(ec_slave_t *, unsigned int)
Searches the string list for an index.
Definition: slave.c:690
void ec_slave_clear(ec_slave_t *slave)
Slave destructor.
Definition: slave.c:224
struct list_head sdo_dictionary
SDO dictionary list.
Definition: slave.h:248
uint16_t std_rx_mailbox_size
Standard receive mailbox size.
Definition: slave.h:167
uint8_t base_type
Slave type.
Definition: slave.h:227
Global definitions and macros.
uint16_t std_tx_mailbox_offset
Standard transmit mailbox address.
Definition: slave.h:168
PDO entry description.
Definition: pdo_entry.h:48
EtherCAT master structure.
void ec_pdo_clear(ec_pdo_t *pdo)
PDO destructor.
Definition: pdo.c:94
uint16_t index
PDO index.
Definition: pdo.h:51
int8_t sync_index
Assigned sync manager.
Definition: pdo.h:52
uint16_t boot_tx_mailbox_offset
Bootstrap transmit mailbox address.
Definition: slave.h:164
uint16_t index
PDO entry index.
Definition: pdo_entry.h:50
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:730
EtherCAT slave.
Definition: slave.h:199
struct list_head sdo_requests
SDO access requests.
Definition: slave.h:252
char * description
Description.
Definition: sdo_entry.h:62
Code/Message pair.
Definition: globals.h:281
struct list_head soe_requests
SoE requests.
Definition: slave.h:255
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:213
void ec_pdo_entry_clear(ec_pdo_entry_t *entry)
PDO entry destructor.
Definition: pdo_entry.c:76
void ec_slave_clear_sync_managers(ec_slave_t *slave)
Clear the sync manager array.
Definition: slave.c:337
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:1044
PDO description.
Definition: pdo.h:49
uint8_t sdo_dictionary_fetched
Dictionary has been fetched.
Definition: slave.h:249
uint16_t * sii_words
Complete SII image.
Definition: slave.h:242
uint16_t mailbox_protocols
Supported mailbox protocols.
Definition: slave.h:170
unsigned int debug_level
Master debug level.
Definition: master.h:285
#define EC_SLAVE_ERR(slave, fmt, args...)
Convenience macro for printing slave-specific errors to syslog.
Definition: slave.h:77
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:141
ec_slave_dc_range_t base_dc_range
DC range.
Definition: slave.h:234
uint8_t bit_length
entry length in bit
Definition: pdo_entry.h:53
Sync manager.
Definition: sync.h:47
uint16_t std_rx_mailbox_offset
Standard receive mailbox address.
Definition: slave.h:166
uint8_t base_fmmu_bit_operation
FMMU bit operation is supported.
Definition: slave.h:232
uint32_t transmission_delay
DC system time transmission delay (offset from reference clock).
Definition: slave.h:238
ec_device_index_t
Master devices.
Definition: globals.h:204
char * name
SDO name.
Definition: sdo.h:54
uint16_t alias
Configured station alias.
Definition: slave.h:157
ec_direction_t
Direction type for PDO assignment functions.
Definition: ecrt.h:435
uint8_t base_fmmu_count
Number of supported FMMUs.
Definition: slave.h:230
void ec_slave_calc_transmission_delays_rec(ec_slave_t *slave, uint32_t *delay)
Recursively calculates transmission delays.
Definition: slave.c:1090
uint16_t configured_rx_mailbox_offset
Configured receive mailbox offset.
Definition: slave.h:218
struct list_head entries
List of PDO entries.
Definition: pdo.h:54
ec_slave_port_desc_t desc
Port descriptors.
Definition: slave.h:138
unsigned int string_count
Number of SII strings.
Definition: slave.h:174
ec_master_t * master
Master owning the slave.
Definition: slave.h:201
void ec_pdo_entry_init(ec_pdo_entry_t *entry)
PDO entry constructor.
Definition: pdo_entry.c:45
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:806
uint8_t has_dc_system_time
The slave supports the DC system time register.
Definition: slave.h:235
char ** strings
Strings in SII categories.
Definition: slave.h:173
ec_slave_state_t
State of an EtherCAT slave.
Definition: globals.h:127
uint8_t subindex
PDO entry subindex.
Definition: pdo_entry.h:51
EtherCAT datagram structure.
uint8_t control_register
Control register value.
Definition: sync.h:51
int ec_read_mbox_locked(ec_slave_t *slave)
Return the current mailbox lock status and lock it if not locked.
Definition: slave.c:203
CANopen dictionary request.
Definition: dict_request.h:48
void ec_sync_clear(ec_sync_t *sync)
Destructor.
Definition: sync.c:81
Port is not implemented.
Definition: ecrt.h:358
uint8_t base_revision
Revision.
Definition: slave.h:228
32 bit.
Definition: globals.h:179
struct list_head list
List item.
Definition: dict_request.h:49
Ethernet-over-EtherCAT set IP parameter request.
Definition: eoe_request.h:49
void ec_read_mbox_lock_clear(ec_slave_t *slave)
Clears the mailbox lock.
Definition: slave.c:190
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:784
uint8_t valid_mbox_data
Received mailbox data is valid.
Definition: slave.h:273
FoE request.
Definition: foe_request.h:50
ec_slave_t * ec_slave_find_next_dc_slave(ec_slave_t *slave)
Finds the next slave supporting DC delay measurement.
Definition: slave.c:1011
uint16_t effective_alias
Effective alias address.
Definition: slave.h:208
struct list_head entries
List of entries.
Definition: sdo.h:56
ec_internal_request_state_t state
Request state.
Definition: eoe_request.h:51
#define EC_READ_U16(DATA)
Read a 16-bit unsigned value from EtherCAT data.
Definition: ecrt.h:2250
struct list_head foe_requests
FoE requests.
Definition: slave.h:254
void ec_mbox_data_clear(ec_mbox_data_t *mbox_data)
Free internal memory for mailbox response data.
Definition: datagram.c:676
uint8_t enable
Enable bit.
Definition: sync.h:52
int ec_slave_fetch_sii_syncs(ec_slave_t *slave, const uint8_t *data, size_t data_size)
Fetches data from a SYNC MANAGER category.
Definition: slave.c:541
#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:163
#define EC_MAX_PORTS
Maximum number of slave ports.
Definition: ecrt.h:227
struct list_head list
List item.
Definition: sdo_request.h:49
void ec_fsm_slave_init(ec_fsm_slave_t *fsm, ec_slave_t *slave)
Constructor.
Definition: fsm_slave.c:66
uint8_t read_mbox_busy
Flag set during a mailbox read request.
Definition: slave.h:261
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:62
ec_slave_t * next_slave
Connected slaves.
Definition: slave.h:140
uint32_t receive_time
Port receive times for delay measurement.
Definition: slave.h:141
Slave port.
Definition: slave.h:137
char * image
Image name.
Definition: slave.h:179
ec_pdo_list_t pdos
Current PDO assignment.
Definition: sync.h:53
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:418
uint16_t physical_start_address
Physical start address.
Definition: sync.h:49
ec_mbox_data_t mbox_voe_data
Received mailbox data for VoE.
Definition: slave.h:271
unsigned long jiffies_preop
Time, the slave went to PREOP.
Definition: slave.h:250
uint16_t configured_rx_mailbox_size
Configured receive mailbox size.
Definition: slave.h:220
uint8_t base_dc_supported
Distributed clocks are supported.
Definition: slave.h:233
uint32_t ec_slave_calc_rtt_sum(ec_slave_t *slave)
Calculates the sum of round-trip-times of connected ports 1-3.
Definition: slave.c:985
size_t sii_nwords
Size of the SII contents in words.
Definition: slave.h:243
void ec_sync_init_copy(ec_sync_t *sync, const ec_sync_t *other)
Copy constructor.
Definition: sync.c:63
char * group
Group name.
Definition: slave.h:178
uint8_t physical_layer[EC_MAX_PORTS]
Port media.
Definition: slave.h:182
struct list_head list
list item
Definition: pdo_entry.h:49
void ec_sdo_clear(ec_sdo_t *sdo)
SDO destructor.
Definition: sdo.c:67
uint8_t base_sync_count
Number of supported sync managers.
Definition: slave.h:231
#define EC_READ_U8(DATA)
Read an 8-bit unsigned value from EtherCAT data.
Definition: ecrt.h:2234
struct list_head dict_requests
Dictionary read requests.
Definition: slave.h:257
unsigned int ec_slave_get_next_port(ec_slave_t *slave, unsigned int port_index)
Returns the next connected port of a given port.
Definition: slave.c:955
EtherCAT slave configuration structure.
ec_internal_request_state_t state
FoE request state.
Definition: foe_request.h:63
#define EC_READ_S16(DATA)
Read a 16-bit signed value from EtherCAT data.
Definition: ecrt.h:2258
ec_device_index_t device_index
Index of device the slave responds on.
Definition: slave.h:202
void ec_slave_config_detach(ec_slave_config_t *sc)
Detaches the configuration from a slave object.
Definition: slave_config.c:308
uint16_t default_length
Data length in bytes.
Definition: sync.h:50
uint32_t product_code
Vendor-specific product code.
Definition: slave.h:159
PREOP state (mailbox communication, no IO)
Definition: globals.h:132
struct list_head list
List item.
Definition: pdo.h:50
unsigned int error_flag
Stop processing after an error.
Definition: slave.h:216
ec_sync_t * syncs
SYNC MANAGER categories.
Definition: slave.h:188
uint16_t std_tx_mailbox_size
Standard transmit mailbox size.
Definition: slave.h:169
EtherCAT master.
Definition: master.h:189
uint8_t enable_pdo_configuration
PDO configuration possible.
Definition: globals.h:164
struct list_head list
List item.
Definition: reg_request.h:49
ec_slave_state_t requested_state
Requested application state.
Definition: slave.h:214
struct list_head eoe_requests
EoE set IP parameter requests.
Definition: slave.h:256
int ec_slave_fetch_sii_pdos(ec_slave_t *slave, const uint8_t *data, size_t data_size, ec_direction_t dir)
Fetches data from a [RT]xPDO category.
Definition: slave.c:607
#define EC_MAX_SYNC_MANAGERS
Maximum number of sync managers per slave.
Definition: ecrt.h:218
void ec_sync_init(ec_sync_t *sync, ec_slave_t *slave)
Constructor.
Definition: sync.c:46
struct list_head list
List item.
Definition: eoe_request.h:50
int ec_slave_fetch_sii_general(ec_slave_t *slave, const uint8_t *data, size_t data_size)
Fetches data from a GENERAL category.
Definition: slave.c:490
void ec_slave_set_al_status(ec_slave_t *slave, ec_slave_state_t new_state)
Sets the application state of a slave.
Definition: slave.c:396
char * name
Slave name.
Definition: slave.h:181
ec_mbox_data_t mbox_coe_data
Received mailbox data for CoE.
Definition: slave.h:268
int ec_pdo_entry_set_name(ec_pdo_entry_t *entry, const char *name)
Set PDO entry name.
Definition: pdo_entry.c:89
unknown state
Definition: globals.h:128
ec_mbox_data_t mbox_soe_data
Received mailbox data for SoE.
Definition: slave.h:270
uint32_t vendor_id
Vendor ID.
Definition: slave.h:158
uint32_t delay_to_next_dc
Delay to next slave with DC support behind this port [ns].
Definition: slave.h:143
struct list_head pdos
SII [RT]XPDO categories.
Definition: slave.h:192
unsigned int force_config
Force (re-)configuration.
Definition: slave.h:217
struct list_head list
List item.
Definition: foe_request.h:51
unsigned int has_general
General category present.
Definition: slave.h:177
Sercos-over-EtherCAT request.
Definition: soe_request.h:48
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:712
uint8_t enable_pdo_assign
PDO mapping configurable.
Definition: globals.h:163
ec_internal_request_state_t state
SDO request state.
Definition: dict_request.h:50