IgH EtherCAT Master  1.6.1
slave.c
Go to the documentation of this file.
1 /*****************************************************************************
2  *
3  * Copyright (C) 2006-2012 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 
53 /****************************************************************************/
54 
61  ec_slave_t *slave,
62  ec_master_t *master,
63  ec_device_index_t dev_idx,
64  uint16_t ring_position,
65  uint16_t station_address
66  )
67 {
68  unsigned int i;
69 
70  slave->master = master;
71  slave->device_index = dev_idx;
72  slave->ring_position = ring_position;
73  slave->station_address = station_address;
74  slave->effective_alias = 0x0000;
75 
76  slave->config = NULL;
79  slave->error_flag = 0;
80  slave->force_config = 0;
81  slave->configured_rx_mailbox_offset = 0x0000;
82  slave->configured_rx_mailbox_size = 0x0000;
83  slave->configured_tx_mailbox_offset = 0x0000;
84  slave->configured_tx_mailbox_size = 0x0000;
85 
86  slave->base_type = 0;
87  slave->base_revision = 0;
88  slave->base_build = 0;
89  slave->base_fmmu_count = 0;
90  slave->base_sync_count = 0;
91 
92  for (i = 0; i < EC_MAX_PORTS; i++) {
94 
95  slave->ports[i].link.link_up = 0;
96  slave->ports[i].link.loop_closed = 0;
97  slave->ports[i].link.signal_detected = 0;
98  slave->sii.physical_layer[i] = 0xFF;
99 
100  slave->ports[i].receive_time = 0U;
101 
102  slave->ports[i].next_slave = NULL;
103  slave->ports[i].delay_to_next_dc = 0U;
104  }
105 
106  slave->base_fmmu_bit_operation = 0;
107  slave->base_dc_supported = 0;
108  slave->base_dc_range = EC_DC_32;
109  slave->has_dc_system_time = 0;
110  slave->transmission_delay = 0U;
111 
112  slave->sii_words = NULL;
113  slave->sii_nwords = 0;
114 
115  slave->sii.alias = 0x0000;
116  slave->sii.vendor_id = 0x00000000;
117  slave->sii.product_code = 0x00000000;
118  slave->sii.revision_number = 0x00000000;
119  slave->sii.serial_number = 0x00000000;
120  slave->sii.boot_rx_mailbox_offset = 0x0000;
121  slave->sii.boot_rx_mailbox_size = 0x0000;
122  slave->sii.boot_tx_mailbox_offset = 0x0000;
123  slave->sii.boot_tx_mailbox_size = 0x0000;
124  slave->sii.std_rx_mailbox_offset = 0x0000;
125  slave->sii.std_rx_mailbox_size = 0x0000;
126  slave->sii.std_tx_mailbox_offset = 0x0000;
127  slave->sii.std_tx_mailbox_size = 0x0000;
128  slave->sii.mailbox_protocols = 0;
129 
130  slave->sii.strings = NULL;
131  slave->sii.string_count = 0;
132 
133  slave->sii.has_general = 0;
134  slave->sii.group = NULL;
135  slave->sii.image = NULL;
136  slave->sii.order = NULL;
137  slave->sii.name = NULL;
138  memset(&slave->sii.coe_details, 0x00, sizeof(ec_sii_coe_details_t));
139  memset(&slave->sii.general_flags, 0x00, sizeof(ec_sii_general_flags_t));
140  slave->sii.current_on_ebus = 0;
141 
142  slave->sii.syncs = NULL;
143  slave->sii.sync_count = 0;
144 
145  INIT_LIST_HEAD(&slave->sii.pdos);
146 
147  INIT_LIST_HEAD(&slave->sdo_dictionary);
148 
149  slave->sdo_dictionary_fetched = 0;
150  slave->jiffies_preop = 0;
151 
152  INIT_LIST_HEAD(&slave->sdo_requests);
153  INIT_LIST_HEAD(&slave->reg_requests);
154  INIT_LIST_HEAD(&slave->foe_requests);
155  INIT_LIST_HEAD(&slave->soe_requests);
156  INIT_LIST_HEAD(&slave->eoe_requests);
157 
158  // create state machine object
159  ec_fsm_slave_init(&slave->fsm, slave);
160 }
161 
162 /****************************************************************************/
163 
170 {
171  ec_sdo_t *sdo, *next_sdo;
172  unsigned int i;
173  ec_pdo_t *pdo, *next_pdo;
174 
175  // abort all pending requests
176 
177  while (!list_empty(&slave->sdo_requests)) {
178  ec_sdo_request_t *request =
179  list_entry(slave->sdo_requests.next, ec_sdo_request_t, list);
180  list_del_init(&request->list); // dequeue
181  EC_SLAVE_WARN(slave, "Discarding SDO request,"
182  " slave about to be deleted.\n");
183  request->state = EC_INT_REQUEST_FAILURE;
184  }
185 
186  while (!list_empty(&slave->reg_requests)) {
187  ec_reg_request_t *reg =
188  list_entry(slave->reg_requests.next, ec_reg_request_t, list);
189  list_del_init(&reg->list); // dequeue
190  EC_SLAVE_WARN(slave, "Discarding register request,"
191  " slave about to be deleted.\n");
192  reg->state = EC_INT_REQUEST_FAILURE;
193  }
194 
195  while (!list_empty(&slave->foe_requests)) {
196  ec_foe_request_t *request =
197  list_entry(slave->foe_requests.next, ec_foe_request_t, list);
198  list_del_init(&request->list); // dequeue
199  EC_SLAVE_WARN(slave, "Discarding FoE request,"
200  " slave about to be deleted.\n");
201  request->state = EC_INT_REQUEST_FAILURE;
202  }
203 
204  while (!list_empty(&slave->soe_requests)) {
205  ec_soe_request_t *request =
206  list_entry(slave->soe_requests.next, ec_soe_request_t, list);
207  list_del_init(&request->list); // dequeue
208  EC_SLAVE_WARN(slave, "Discarding SoE request,"
209  " slave about to be deleted.\n");
210  request->state = EC_INT_REQUEST_FAILURE;
211  }
212 
213 #ifdef EC_EOE
214  while (!list_empty(&slave->eoe_requests)) {
215  ec_eoe_request_t *request =
216  list_entry(slave->eoe_requests.next, ec_eoe_request_t, list);
217  list_del_init(&request->list); // dequeue
218  EC_SLAVE_WARN(slave, "Discarding EoE request,"
219  " slave about to be deleted.\n");
220  request->state = EC_INT_REQUEST_FAILURE;
221  }
222 #endif
223 
224  wake_up_all(&slave->master->request_queue);
225 
226  if (slave->config) {
228  }
229 
230  // free all SDOs
231  list_for_each_entry_safe(sdo, next_sdo, &slave->sdo_dictionary, list) {
232  list_del(&sdo->list);
233  ec_sdo_clear(sdo);
234  kfree(sdo);
235  }
236 
237  // free all strings
238  if (slave->sii.strings) {
239  for (i = 0; i < slave->sii.string_count; i++)
240  kfree(slave->sii.strings[i]);
241  kfree(slave->sii.strings);
242  }
243 
244  // free all sync managers
246 
247  // free all SII PDOs
248  list_for_each_entry_safe(pdo, next_pdo, &slave->sii.pdos, list) {
249  list_del(&pdo->list);
250  ec_pdo_clear(pdo);
251  kfree(pdo);
252  }
253 
254  if (slave->sii_words) {
255  kfree(slave->sii_words);
256  }
257 
258  ec_fsm_slave_clear(&slave->fsm);
259 }
260 
261 /****************************************************************************/
262 
266 {
267  unsigned int i;
268 
269  if (slave->sii.syncs) {
270  for (i = 0; i < slave->sii.sync_count; i++) {
271  ec_sync_clear(&slave->sii.syncs[i]);
272  }
273  kfree(slave->sii.syncs);
274  slave->sii.syncs = NULL;
275  }
276 }
277 
278 /****************************************************************************/
279 
285  ec_slave_state_t new_state
286  )
287 {
288  if (new_state != slave->current_state) {
289  if (slave->master->debug_level) {
290  char old_state[EC_STATE_STRING_SIZE],
291  cur_state[EC_STATE_STRING_SIZE];
292  ec_state_string(slave->current_state, old_state, 0);
293  ec_state_string(new_state, cur_state, 0);
294  EC_SLAVE_DBG(slave, 0, "%s -> %s.\n", old_state, cur_state);
295  }
296  slave->current_state = new_state;
297  }
298 }
299 
300 /****************************************************************************/
301 
307  ec_slave_state_t state
308  )
309 {
310  slave->requested_state = state;
311  slave->error_flag = 0;
312 }
313 
314 /****************************************************************************/
315 
323  ec_slave_t *slave,
324  const uint8_t *data,
325  size_t data_size
326  )
327 {
328  int i, err;
329  size_t size;
330  off_t offset;
331 
332  slave->sii.string_count = data[0];
333 
334  if (slave->sii.string_count) {
335  if (!(slave->sii.strings =
336  kmalloc(sizeof(char *) * slave->sii.string_count,
337  GFP_KERNEL))) {
338  EC_SLAVE_ERR(slave, "Failed to allocate string array memory.\n");
339  err = -ENOMEM;
340  goto out_zero;
341  }
342 
343  offset = 1;
344  for (i = 0; i < slave->sii.string_count; i++) {
345  size = data[offset];
346  // allocate memory for string structure and data at a single blow
347  if (!(slave->sii.strings[i] =
348  kmalloc(sizeof(char) * size + 1, GFP_KERNEL))) {
349  EC_SLAVE_ERR(slave, "Failed to allocate string memory.\n");
350  err = -ENOMEM;
351  goto out_free;
352  }
353  memcpy(slave->sii.strings[i], data + offset + 1, size);
354  slave->sii.strings[i][size] = 0x00; // append binary zero
355  offset += 1 + size;
356  }
357  }
358 
359  return 0;
360 
361 out_free:
362  for (i--; i >= 0; i--)
363  kfree(slave->sii.strings[i]);
364  kfree(slave->sii.strings);
365  slave->sii.strings = NULL;
366 out_zero:
367  slave->sii.string_count = 0;
368  return err;
369 }
370 
371 /****************************************************************************/
372 
379  ec_slave_t *slave,
380  const uint8_t *data,
381  size_t data_size
382  )
383 {
384  unsigned int i;
385  uint8_t flags;
386 
387  if (data_size != 32) {
388  EC_SLAVE_ERR(slave, "Wrong size of general category (%zu/32).\n",
389  data_size);
390  return -EINVAL;
391  }
392 
393  slave->sii.group = ec_slave_sii_string(slave, data[0]);
394  slave->sii.image = ec_slave_sii_string(slave, data[1]);
395  slave->sii.order = ec_slave_sii_string(slave, data[2]);
396  slave->sii.name = ec_slave_sii_string(slave, data[3]);
397 
398  for (i = 0; i < 4; i++)
399  slave->sii.physical_layer[i] =
400  (data[4] & (0x03 << (i * 2))) >> (i * 2);
401 
402  // read CoE details
403  flags = EC_READ_U8(data + 5);
404  slave->sii.coe_details.enable_sdo = (flags >> 0) & 0x01;
405  slave->sii.coe_details.enable_sdo_info = (flags >> 1) & 0x01;
406  slave->sii.coe_details.enable_pdo_assign = (flags >> 2) & 0x01;
407  slave->sii.coe_details.enable_pdo_configuration = (flags >> 3) & 0x01;
408  slave->sii.coe_details.enable_upload_at_startup = (flags >> 4) & 0x01;
409  slave->sii.coe_details.enable_sdo_complete_access = (flags >> 5) & 0x01;
410 
411  // read general flags
412  flags = EC_READ_U8(data + 0x000B);
413  slave->sii.general_flags.enable_safeop = (flags >> 0) & 0x01;
414  slave->sii.general_flags.enable_not_lrw = (flags >> 1) & 0x01;
415 
416  slave->sii.current_on_ebus = EC_READ_S16(data + 0x0C);
417  slave->sii.has_general = 1;
418  return 0;
419 }
420 
421 /****************************************************************************/
422 
430  ec_slave_t *slave,
431  const uint8_t *data,
432  size_t data_size
433  )
434 {
435  unsigned int i, count, total_count;
436  ec_sync_t *sync;
437  size_t memsize;
438  ec_sync_t *syncs;
439  uint8_t index;
440 
441  // one sync manager struct is 4 words long
442  if (data_size % 8) {
443  EC_SLAVE_ERR(slave, "Invalid SII sync manager category size %zu.\n",
444  data_size);
445  return -EINVAL;
446  }
447 
448  count = data_size / 8;
449 
450  if (count) {
451  total_count = count + slave->sii.sync_count;
452  if (total_count > EC_MAX_SYNC_MANAGERS) {
453  EC_SLAVE_ERR(slave, "Exceeded maximum number of"
454  " sync managers!\n");
455  return -EOVERFLOW;
456  }
457  memsize = sizeof(ec_sync_t) * total_count;
458  if (!(syncs = kmalloc(memsize, GFP_KERNEL))) {
459  EC_SLAVE_ERR(slave, "Failed to allocate %zu bytes"
460  " for sync managers.\n", memsize);
461  return -ENOMEM;
462  }
463 
464  for (i = 0; i < slave->sii.sync_count; i++)
465  ec_sync_init_copy(syncs + i, slave->sii.syncs + i);
466 
467  // initialize new sync managers
468  for (i = 0; i < count; i++, data += 8) {
469  index = i + slave->sii.sync_count;
470  sync = &syncs[index];
471 
472  ec_sync_init(sync, slave);
473  sync->physical_start_address = EC_READ_U16(data);
474  sync->default_length = EC_READ_U16(data + 2);
475  sync->control_register = EC_READ_U8(data + 4);
476  sync->enable = EC_READ_U8(data + 6);
477  }
478 
479  if (slave->sii.syncs)
480  kfree(slave->sii.syncs);
481  slave->sii.syncs = syncs;
482  slave->sii.sync_count = total_count;
483  }
484 
485  return 0;
486 }
487 
488 /****************************************************************************/
489 
496  ec_slave_t *slave,
497  const uint8_t *data,
498  size_t data_size,
499  ec_direction_t dir
500  )
501 {
502  int ret;
503  ec_pdo_t *pdo;
504  ec_pdo_entry_t *entry;
505  unsigned int entry_count, i;
506 
507  while (data_size >= 8) {
508  if (!(pdo = kmalloc(sizeof(ec_pdo_t), GFP_KERNEL))) {
509  EC_SLAVE_ERR(slave, "Failed to allocate PDO memory.\n");
510  return -ENOMEM;
511  }
512 
513  ec_pdo_init(pdo);
514  pdo->index = EC_READ_U16(data);
515  entry_count = EC_READ_U8(data + 2);
516  pdo->sync_index = EC_READ_U8(data + 3);
517  ret = ec_pdo_set_name(pdo,
518  ec_slave_sii_string(slave, EC_READ_U8(data + 5)));
519  if (ret) {
520  ec_pdo_clear(pdo);
521  kfree(pdo);
522  return ret;
523  }
524  list_add_tail(&pdo->list, &slave->sii.pdos);
525 
526  data_size -= 8;
527  data += 8;
528 
529  for (i = 0; i < entry_count; i++) {
530  if (!(entry = kmalloc(sizeof(ec_pdo_entry_t), GFP_KERNEL))) {
531  EC_SLAVE_ERR(slave, "Failed to allocate PDO entry memory.\n");
532  return -ENOMEM;
533  }
534 
535  ec_pdo_entry_init(entry);
536  entry->index = EC_READ_U16(data);
537  entry->subindex = EC_READ_U8(data + 2);
538  ret = ec_pdo_entry_set_name(entry,
539  ec_slave_sii_string(slave, EC_READ_U8(data + 3)));
540  if (ret) {
541  ec_pdo_entry_clear(entry);
542  kfree(entry);
543  return ret;
544  }
545  entry->bit_length = EC_READ_U8(data + 5);
546  list_add_tail(&entry->list, &pdo->entries);
547 
548  data_size -= 8;
549  data += 8;
550  }
551 
552  // if sync manager index is positive, the PDO is mapped by default
553  if (pdo->sync_index >= 0) {
554  ec_sync_t *sync;
555 
556  if (!(sync = ec_slave_get_sync(slave, pdo->sync_index))) {
557  EC_SLAVE_ERR(slave, "Invalid SM index %i for PDO 0x%04X.",
558  pdo->sync_index, pdo->index);
559  return -ENOENT;
560  }
561 
562  ret = ec_pdo_list_add_pdo_copy(&sync->pdos, pdo);
563  if (ret)
564  return ret;
565  }
566  }
567 
568  return 0;
569 }
570 
571 /****************************************************************************/
572 
579  const ec_slave_t *slave,
580  unsigned int index
581  )
582 {
583  if (!index--)
584  return NULL;
585 
586  if (index >= slave->sii.string_count) {
587  EC_SLAVE_DBG(slave, 1, "String %u not found.\n", index);
588  return NULL;
589  }
590 
591  return slave->sii.strings[index];
592 }
593 
594 /****************************************************************************/
595 
601  ec_slave_t *slave,
602  uint8_t sync_index
603  )
604 {
605  if (sync_index < slave->sii.sync_count) {
606  return &slave->sii.syncs[sync_index];
607  } else {
608  return NULL;
609  }
610 }
611 
612 /****************************************************************************/
613 
619  unsigned int *sdo_count,
620  unsigned int *entry_count
622  )
623 {
624  unsigned int sdos = 0, entries = 0;
625  ec_sdo_t *sdo;
626  ec_sdo_entry_t *entry;
627 
628  list_for_each_entry(sdo, &slave->sdo_dictionary, list) {
629  sdos++;
630  list_for_each_entry(entry, &sdo->entries, list) {
631  entries++;
632  }
633  }
634 
635  *sdo_count = sdos;
636  *entry_count = entries;
637 }
638 
639 /****************************************************************************/
640 
647  ec_slave_t *slave,
648  uint16_t index
649  )
650 {
651  ec_sdo_t *sdo;
652 
653  list_for_each_entry(sdo, &slave->sdo_dictionary, list) {
654  if (sdo->index != index)
655  continue;
656  return sdo;
657  }
658 
659  return NULL;
660 }
661 
662 /****************************************************************************/
663 
673  const ec_slave_t *slave,
674  uint16_t index
675  )
676 {
677  const ec_sdo_t *sdo;
678 
679  list_for_each_entry(sdo, &slave->sdo_dictionary, list) {
680  if (sdo->index != index)
681  continue;
682  return sdo;
683  }
684 
685  return NULL;
686 }
687 
688 /****************************************************************************/
689 
695  const ec_slave_t *slave,
696  uint16_t sdo_position
697  )
698 {
699  const ec_sdo_t *sdo;
700 
701  list_for_each_entry(sdo, &slave->sdo_dictionary, list) {
702  if (sdo_position--)
703  continue;
704  return sdo;
705  }
706 
707  return NULL;
708 }
709 
710 /****************************************************************************/
711 
717  const ec_slave_t *slave
718  )
719 {
720  const ec_sdo_t *sdo;
721  uint16_t count = 0;
722 
723  list_for_each_entry(sdo, &slave->sdo_dictionary, list) {
724  count++;
725  }
726 
727  return count;
728 }
729 
730 /****************************************************************************/
731 
736  const ec_slave_t *slave,
737  uint16_t index
738  )
739 {
740  unsigned int i;
741  const ec_sync_t *sync;
742  const ec_pdo_t *pdo;
743 
744  for (i = 0; i < slave->sii.sync_count; i++) {
745  sync = &slave->sii.syncs[i];
746 
747  if (!(pdo = ec_pdo_list_find_pdo_const(&sync->pdos, index)))
748  continue;
749 
750  return pdo;
751  }
752 
753  return NULL;
754 }
755 
756 /****************************************************************************/
757 
761  ec_slave_t *slave,
762  ec_pdo_t *pdo
763  )
764 {
765  const ec_sdo_t *sdo;
766  ec_pdo_entry_t *pdo_entry;
767  const ec_sdo_entry_t *sdo_entry;
768 
769  list_for_each_entry(sdo, &slave->sdo_dictionary, list) {
770  if (sdo->index == pdo->index) {
771  ec_pdo_set_name(pdo, sdo->name);
772  } else {
773  list_for_each_entry(pdo_entry, &pdo->entries, list) {
774  if (sdo->index == pdo_entry->index) {
775  sdo_entry = ec_sdo_get_entry_const(
776  sdo, pdo_entry->subindex);
777  if (sdo_entry) {
778  ec_pdo_entry_set_name(pdo_entry,
779  sdo_entry->description);
780  }
781  }
782  }
783  }
784  }
785 }
786 
787 /****************************************************************************/
788 
792  ec_slave_t *slave
793  )
794 {
795  unsigned int i;
796  ec_sync_t *sync;
797  ec_pdo_t *pdo;
798 
799  for (i = 0; i < slave->sii.sync_count; i++) {
800  sync = slave->sii.syncs + i;
801  list_for_each_entry(pdo, &sync->pdos.list, list) {
802  ec_slave_find_names_for_pdo(slave, pdo);
803  }
804  }
805 }
806 
807 /****************************************************************************/
808 
814  const ec_slave_t *slave,
815  unsigned int port_index
816  )
817 {
818  static const unsigned int prev_table[EC_MAX_PORTS] = {
819  2, 3, 1, 0
820  };
821 
822  if (port_index >= EC_MAX_PORTS) {
823  EC_SLAVE_WARN(slave, "%s(port_index=%u): Invalid port index!\n",
824  __func__, port_index);
825  }
826 
827  do {
828  port_index = prev_table[port_index];
829  if (slave->ports[port_index].next_slave) {
830  return port_index;
831  }
832  } while (port_index);
833 
834  return 0;
835 }
836 
837 /****************************************************************************/
838 
844  const ec_slave_t *slave,
845  unsigned int port_index
846  )
847 {
848  static const unsigned int next_table[EC_MAX_PORTS] = {
849  3, 2, 0, 1
850  };
851 
852  if (port_index >= EC_MAX_PORTS) {
853  EC_SLAVE_WARN(slave, "%s(port_index=%u): Invalid port index!\n",
854  __func__, port_index);
855  }
856 
857  do {
858  port_index = next_table[port_index];
859  if (slave->ports[port_index].next_slave) {
860  return port_index;
861  }
862  } while (port_index);
863 
864  return 0;
865 }
866 
867 /****************************************************************************/
868 
874  const ec_slave_t *slave
875  )
876 {
877  uint32_t rtt_sum = 0, rtt;
878  unsigned int port_index = ec_slave_get_next_port(slave, 0);
879 
880  while (port_index != 0) {
881  unsigned int prev_index =
882  ec_slave_get_previous_port(slave, port_index);
883 
884  rtt = slave->ports[port_index].receive_time -
885  slave->ports[prev_index].receive_time;
886  rtt_sum += rtt;
887  port_index = ec_slave_get_next_port(slave, port_index);
888  }
889 
890  return rtt_sum;
891 }
892 
893 /****************************************************************************/
894 
900  ec_slave_t *slave
901  )
902 {
903  unsigned int port_index;
904  ec_slave_t *dc_slave = NULL;
905 
906  if (slave->base_dc_supported) {
907  dc_slave = slave;
908  } else {
909  port_index = ec_slave_get_next_port(slave, 0);
910 
911  while (port_index != 0) {
912  ec_slave_t *next = slave->ports[port_index].next_slave;
913 
914  if (next) {
915  dc_slave = ec_slave_find_next_dc_slave(next);
916 
917  if (dc_slave) {
918  break;
919  }
920  }
921  port_index = ec_slave_get_next_port(slave, port_index);
922  }
923  }
924 
925  return dc_slave;
926 }
927 
928 /****************************************************************************/
929 
933  ec_slave_t *slave
934  )
935 {
936  unsigned int port_index;
937  ec_slave_t *next_slave, *next_dc;
938  uint32_t rtt, next_rtt_sum;
939 
940  if (!slave->base_dc_supported)
941  return;
942 
943  port_index = ec_slave_get_next_port(slave, 0);
944 
945  while (port_index != 0) {
946  next_slave = slave->ports[port_index].next_slave;
947  next_dc = ec_slave_find_next_dc_slave(next_slave);
948 
949  if (next_dc) {
950  unsigned int prev_port =
951  ec_slave_get_previous_port(slave, port_index);
952 
953  rtt = slave->ports[port_index].receive_time -
954  slave->ports[prev_port].receive_time;
955  next_rtt_sum = ec_slave_calc_rtt_sum(next_dc);
956 
957  slave->ports[port_index].delay_to_next_dc =
958  (rtt - next_rtt_sum) / 2; // FIXME
959  next_dc->ports[0].delay_to_next_dc =
960  (rtt - next_rtt_sum) / 2;
961 
962 #if 0
963  EC_SLAVE_DBG(slave, 1, "delay %u:%u rtt=%u"
964  " next_rtt_sum=%u delay=%u\n",
965  slave->ring_position, port_index, rtt, next_rtt_sum,
966  slave->ports[port_index].delay_to_next_dc);
967 #endif
968  }
969 
970  port_index = ec_slave_get_next_port(slave, port_index);
971  }
972 }
973 
974 /****************************************************************************/
975 
979  ec_slave_t *slave,
980  uint32_t *delay
981  )
982 {
983  unsigned int i;
984  ec_slave_t *next_dc;
985 
986  EC_SLAVE_DBG(slave, 1, "%s(delay = %u ns)\n", __func__, *delay);
987 
988  slave->transmission_delay = *delay;
989 
990  i = ec_slave_get_next_port(slave, 0);
991 
992  while (i != 0) {
993  ec_slave_port_t *port = &slave->ports[i];
994  next_dc = ec_slave_find_next_dc_slave(port->next_slave);
995  if (next_dc) {
996  *delay = *delay + port->delay_to_next_dc;
997 #if 0
998  EC_SLAVE_DBG(slave, 1, "%u:%u %u\n",
999  slave->ring_position, i, *delay);
1000 #endif
1001  ec_slave_calc_transmission_delays_rec(next_dc, delay);
1002  }
1003 
1004  i = ec_slave_get_next_port(slave, i);
1005  }
1006 
1007  *delay = *delay + slave->ports[0].delay_to_next_dc;
1008 }
1009 
1010 /****************************************************************************/
ec_sii_general_flags_t general_flags
General flags.
Definition: slave.h:153
Slave information interface general flags.
Definition: globals.h:165
ec_internal_request_state_t state
Request state.
Definition: reg_request.h:48
uint16_t ring_position
Ring position.
Definition: slave.h:175
uint32_t revision_number
Revision number.
Definition: slave.h:129
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:716
uint16_t boot_rx_mailbox_offset
Bootstrap receive mailbox address.
Definition: slave.h:131
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:215
uint16_t configured_tx_mailbox_size
Configured send mailbox size.
Definition: slave.h:193
uint8_t enable_upload_at_startup
?.
Definition: globals.h:159
void ec_slave_attach_pdo_names(ec_slave_t *slave)
Attach PDO names.
Definition: slave.c:791
uint16_t base_build
Build number.
Definition: slave.h:198
#define EC_SLAVE_DBG(slave, level, fmt, args...)
Convenience macro for printing slave-specific debug messages to syslog.
Definition: slave.h:98
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:167
uint16_t configured_tx_mailbox_offset
Configured send mailbox offset.
Definition: slave.h:191
size_t ec_state_string(uint8_t, char *, uint8_t)
Prints slave states in clear text.
Definition: module.c:401
ec_slave_port_t ports[EC_MAX_PORTS]
Ports.
Definition: slave.h:179
CANopen SDO request.
Definition: sdo_request.h:40
ec_slave_state_t current_state
Current application state.
Definition: slave.h:184
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:646
ec_slave_port_link_t link
Port link status.
Definition: slave.h:112
#define EC_SLAVE_WARN(slave, fmt, args...)
Convenience macro for printing slave-specific warnings to syslog.
Definition: slave.h:82
uint8_t enable_sdo
Enable SDO access.
Definition: globals.h:155
struct list_head list
List of PDOs.
Definition: pdo_list.h:42
uint32_t serial_number
Serial number.
Definition: slave.h:130
ec_sii_coe_details_t coe_details
CoE detail flags.
Definition: slave.h:152
char * order
Order number.
Definition: slave.h:149
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:760
ec_fsm_slave_t fsm
Slave state machine.
Definition: slave.h:227
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:284
struct list_head reg_requests
Register access requests.
Definition: slave.h:222
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:735
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:154
ec_slave_t * ec_slave_find_next_dc_slave(ec_slave_t *)
Finds the next slave supporting DC delay measurement.
Definition: slave.c:899
uint16_t boot_tx_mailbox_size
Bootstrap transmit mailbox size.
Definition: slave.h:134
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:322
wait_queue_head_t request_queue
Wait queue for external requests from user space.
Definition: master.h:301
uint16_t station_address
Configured station address.
Definition: slave.h:176
unsigned int sync_count
Number of sync managers.
Definition: slave.h:158
void ec_slave_clear(ec_slave_t *slave)
Slave destructor.
Definition: slave.c:169
struct list_head sdo_dictionary
SDO dictionary list.
Definition: slave.h:217
uint16_t std_rx_mailbox_size
Standard receive mailbox size.
Definition: slave.h:136
uint8_t base_type
Slave type.
Definition: slave.h:196
Global definitions and macros.
uint16_t std_tx_mailbox_offset
Standard transmit mailbox address.
Definition: slave.h:137
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 transmit mailbox address.
Definition: slave.h:133
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:618
EtherCAT slave.
Definition: slave.h:168
struct list_head sdo_requests
SDO access requests.
Definition: slave.h:221
char * description
Description.
Definition: sdo_entry.h:54
Code/Message pair.
Definition: globals.h:275
struct list_head soe_requests
SoE requests.
Definition: slave.h:224
Slave information interface CANopen over EtherCAT details flags.
Definition: globals.h:154
uint8_t enable_safeop
?.
Definition: globals.h:166
ec_slave_config_t * config
Current configuration.
Definition: slave.h:182
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:843
char * ec_slave_sii_string(const ec_slave_t *, unsigned int)
Searches the string list for an index.
Definition: slave.c:578
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:265
uint8_t enable_sdo_info
SDO information service available.
Definition: globals.h:156
uint8_t enable_sdo_complete_access
Complete access possible.
Definition: globals.h:160
void ec_slave_calc_port_delays(ec_slave_t *slave)
Calculates the port transmission delays.
Definition: slave.c:932
PDO description.
Definition: pdo.h:41
uint8_t sdo_dictionary_fetched
Dictionary has been fetched.
Definition: slave.h:218
uint16_t * sii_words
Complete SII image.
Definition: slave.h:211
uint16_t mailbox_protocols
Supported mailbox protocols.
Definition: slave.h:139
unsigned int debug_level
Master debug level.
Definition: master.h:275
#define EC_SLAVE_ERR(slave, fmt, args...)
Convenience macro for printing slave-specific errors to syslog.
Definition: slave.h:68
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:203
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:135
uint8_t base_fmmu_bit_operation
FMMU bit operation is supported.
Definition: slave.h:201
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:207
ec_device_index_t
Master devices.
Definition: globals.h:198
char * name
SDO name.
Definition: sdo.h:46
uint16_t alias
Configured station alias.
Definition: slave.h:126
ec_direction_t
Direction type for PDO assignment functions.
Definition: ecrt.h:504
uint8_t base_fmmu_count
Number of supported FMMUs.
Definition: slave.h:199
void ec_slave_calc_transmission_delays_rec(ec_slave_t *slave, uint32_t *delay)
Recursively calculates transmission delays.
Definition: slave.c:978
uint16_t configured_rx_mailbox_offset
Configured receive mailbox offset.
Definition: slave.h:187
struct list_head entries
List of PDO entries.
Definition: pdo.h:46
ec_slave_port_desc_t desc
Port descriptors.
Definition: slave.h:111
unsigned int string_count
Number of SII strings.
Definition: slave.h:143
ec_master_t * master
Master owning the slave.
Definition: slave.h:170
void ec_pdo_entry_init(ec_pdo_entry_t *entry)
PDO entry constructor.
Definition: pdo_entry.c:37
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:694
uint8_t has_dc_system_time
The slave supports the DC system time register.
Definition: slave.h:204
char ** strings
Strings in SII categories.
Definition: slave.h:142
ec_slave_state_t
State of an EtherCAT slave.
Definition: globals.h:121
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
void ec_sync_clear(ec_sync_t *sync)
Destructor.
Definition: sync.c:73
Port is not implemented.
Definition: ecrt.h:427
uint8_t base_revision
Revision.
Definition: slave.h:197
32 bit.
Definition: globals.h:173
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:672
FoE request.
Definition: foe_request.h:42
uint16_t effective_alias
Effective alias address.
Definition: slave.h:177
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:3045
struct list_head foe_requests
FoE requests.
Definition: slave.h:223
uint8_t enable
Enable bit.
Definition: sync.h:44
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:429
#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:132
#define EC_MAX_PORTS
Maximum number of slave ports.
Definition: ecrt.h:276
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
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:60
ec_slave_t * next_slave
Connected slaves.
Definition: slave.h:113
uint32_t receive_time
Port receive times for delay measurement.
Definition: slave.h:114
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:873
Slave port.
Definition: slave.h:110
char * image
Image name.
Definition: slave.h:148
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:306
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:219
uint16_t configured_rx_mailbox_size
Configured receive mailbox size.
Definition: slave.h:189
uint8_t base_dc_supported
Distributed clocks are supported.
Definition: slave.h:202
size_t sii_nwords
Size of the SII contents in words.
Definition: slave.h:212
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:147
uint8_t physical_layer[EC_MAX_PORTS]
Port media.
Definition: slave.h:151
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:200
#define EC_READ_U8(DATA)
Read an 8-bit unsigned value from EtherCAT data.
Definition: ecrt.h:3029
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:3053
ec_device_index_t device_index
Index of device the slave responds on.
Definition: slave.h:171
void ec_slave_config_detach(ec_slave_config_t *sc)
Detaches the configuration from a slave object.
Definition: slave_config.c:312
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:813
uint16_t default_length
Data length in bytes.
Definition: sync.h:42
uint32_t product_code
Vendor-specific product code.
Definition: slave.h:128
PREOP state (mailbox communication, no IO)
Definition: globals.h:126
struct list_head list
List item.
Definition: pdo.h:42
unsigned int error_flag
Stop processing after an error.
Definition: slave.h:185
ec_sync_t * syncs
SYNC MANAGER categories.
Definition: slave.h:157
uint16_t std_tx_mailbox_size
Standard transmit mailbox size.
Definition: slave.h:138
EtherCAT master.
Definition: master.h:187
uint8_t enable_pdo_configuration
PDO configuration possible.
Definition: globals.h:158
struct list_head list
List item.
Definition: reg_request.h:41
ec_slave_state_t requested_state
Requested application state.
Definition: slave.h:183
struct list_head eoe_requests
EoE set IP parameter requests.
Definition: slave.h:225
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:495
#define EC_MAX_SYNC_MANAGERS
Maximum number of sync managers per slave.
Definition: ecrt.h:267
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 *slave, const uint8_t *data, size_t data_size)
Fetches data from a GENERAL category.
Definition: slave.c:378
Sercos-over-EtherCAT request.
Definition: soe_request.h:40
char * name
Slave name.
Definition: slave.h:150
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:122
uint32_t vendor_id
Vendor ID.
Definition: slave.h:127
uint32_t delay_to_next_dc
Delay to next slave with DC support behind this port [ns].
Definition: slave.h:116
struct list_head pdos
SII [RT]XPDO categories.
Definition: slave.h:161
unsigned int force_config
Force (re-)configuration.
Definition: slave.h:186
struct list_head list
List item.
Definition: foe_request.h:43
unsigned int has_general
General category present.
Definition: slave.h:146
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:600
uint8_t enable_pdo_assign
PDO mapping configurable.
Definition: globals.h:157