IgH EtherCAT Master  1.5.3
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 = 0;
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 
108  slave->base_fmmu_bit_operation = 0;
109  slave->base_dc_supported = 0;
110  slave->base_dc_range = EC_DC_32;
111  slave->has_dc_system_time = 0;
112  slave->transmission_delay = 0U;
113 
114  slave->sii_words = NULL;
115  slave->sii_nwords = 0;
116 
117  slave->sii.alias = 0x0000;
118  slave->sii.vendor_id = 0x00000000;
119  slave->sii.product_code = 0x00000000;
120  slave->sii.revision_number = 0x00000000;
121  slave->sii.serial_number = 0x00000000;
122  slave->sii.boot_rx_mailbox_offset = 0x0000;
123  slave->sii.boot_rx_mailbox_size = 0x0000;
124  slave->sii.boot_tx_mailbox_offset = 0x0000;
125  slave->sii.boot_tx_mailbox_size = 0x0000;
126  slave->sii.std_rx_mailbox_offset = 0x0000;
127  slave->sii.std_rx_mailbox_size = 0x0000;
128  slave->sii.std_tx_mailbox_offset = 0x0000;
129  slave->sii.std_tx_mailbox_size = 0x0000;
130  slave->sii.mailbox_protocols = 0;
131 
132  slave->sii.strings = NULL;
133  slave->sii.string_count = 0;
134 
135  slave->sii.has_general = 0;
136  slave->sii.group = NULL;
137  slave->sii.image = NULL;
138  slave->sii.order = NULL;
139  slave->sii.name = NULL;
140  memset(&slave->sii.coe_details, 0x00, sizeof(ec_sii_coe_details_t));
141  memset(&slave->sii.general_flags, 0x00, sizeof(ec_sii_general_flags_t));
142  slave->sii.current_on_ebus = 0;
143 
144  slave->sii.syncs = NULL;
145  slave->sii.sync_count = 0;
146 
147  INIT_LIST_HEAD(&slave->sii.pdos);
148 
149  INIT_LIST_HEAD(&slave->sdo_dictionary);
150 
151  slave->sdo_dictionary_fetched = 0;
152  slave->jiffies_preop = 0;
153 
154  INIT_LIST_HEAD(&slave->sdo_requests);
155  INIT_LIST_HEAD(&slave->reg_requests);
156  INIT_LIST_HEAD(&slave->foe_requests);
157  INIT_LIST_HEAD(&slave->soe_requests);
158 
159  // create state machine object
160  ec_fsm_slave_init(&slave->fsm, slave);
161 }
162 
163 /*****************************************************************************/
164 
171 {
172  ec_sdo_t *sdo, *next_sdo;
173  unsigned int i;
174  ec_pdo_t *pdo, *next_pdo;
175 
176  // abort all pending requests
177 
178  while (!list_empty(&slave->sdo_requests)) {
179  ec_sdo_request_t *request =
180  list_entry(slave->sdo_requests.next, ec_sdo_request_t, list);
181  list_del_init(&request->list); // dequeue
182  EC_SLAVE_WARN(slave, "Discarding SDO request,"
183  " slave about to be deleted.\n");
184  request->state = EC_INT_REQUEST_FAILURE;
185  }
186 
187  while (!list_empty(&slave->reg_requests)) {
188  ec_reg_request_t *reg =
189  list_entry(slave->reg_requests.next, ec_reg_request_t, list);
190  list_del_init(&reg->list); // dequeue
191  EC_SLAVE_WARN(slave, "Discarding register request,"
192  " slave about to be deleted.\n");
193  reg->state = EC_INT_REQUEST_FAILURE;
194  }
195 
196  while (!list_empty(&slave->foe_requests)) {
197  ec_foe_request_t *request =
198  list_entry(slave->foe_requests.next, ec_foe_request_t, list);
199  list_del_init(&request->list); // dequeue
200  EC_SLAVE_WARN(slave, "Discarding FoE request,"
201  " slave about to be deleted.\n");
202  request->state = EC_INT_REQUEST_FAILURE;
203  }
204 
205  while (!list_empty(&slave->soe_requests)) {
206  ec_soe_request_t *request =
207  list_entry(slave->soe_requests.next, ec_soe_request_t, list);
208  list_del_init(&request->list); // dequeue
209  EC_SLAVE_WARN(slave, "Discarding SoE request,"
210  " slave about to be deleted.\n");
211  request->state = EC_INT_REQUEST_FAILURE;
212  }
213 
214  wake_up_all(&slave->master->request_queue);
215 
216  if (slave->config) {
218  }
219 
220  // free all SDOs
221  list_for_each_entry_safe(sdo, next_sdo, &slave->sdo_dictionary, list) {
222  list_del(&sdo->list);
223  ec_sdo_clear(sdo);
224  kfree(sdo);
225  }
226 
227  // free all strings
228  if (slave->sii.strings) {
229  for (i = 0; i < slave->sii.string_count; i++)
230  kfree(slave->sii.strings[i]);
231  kfree(slave->sii.strings);
232  }
233 
234  // free all sync managers
236 
237  // free all SII PDOs
238  list_for_each_entry_safe(pdo, next_pdo, &slave->sii.pdos, list) {
239  list_del(&pdo->list);
240  ec_pdo_clear(pdo);
241  kfree(pdo);
242  }
243 
244  if (slave->sii_words) {
245  kfree(slave->sii_words);
246  }
247 
248  ec_fsm_slave_clear(&slave->fsm);
249 }
250 
251 /*****************************************************************************/
252 
256 {
257  unsigned int i;
258 
259  if (slave->sii.syncs) {
260  for (i = 0; i < slave->sii.sync_count; i++) {
261  ec_sync_clear(&slave->sii.syncs[i]);
262  }
263  kfree(slave->sii.syncs);
264  slave->sii.syncs = NULL;
265  }
266 }
267 
268 /*****************************************************************************/
269 
275  ec_slave_state_t new_state
276  )
277 {
278  if (new_state != slave->current_state) {
279  if (slave->master->debug_level) {
280  char old_state[EC_STATE_STRING_SIZE],
281  cur_state[EC_STATE_STRING_SIZE];
282  ec_state_string(slave->current_state, old_state, 0);
283  ec_state_string(new_state, cur_state, 0);
284  EC_SLAVE_DBG(slave, 0, "%s -> %s.\n", old_state, cur_state);
285  }
286  slave->current_state = new_state;
287  }
288 }
289 
290 /*****************************************************************************/
291 
297  ec_slave_state_t state
298  )
299 {
300  slave->requested_state = state;
301  slave->error_flag = 0;
302 }
303 
304 /*****************************************************************************/
305 
313  ec_slave_t *slave,
314  const uint8_t *data,
315  size_t data_size
316  )
317 {
318  int i, err;
319  size_t size;
320  off_t offset;
321 
322  slave->sii.string_count = data[0];
323 
324  if (slave->sii.string_count) {
325  if (!(slave->sii.strings =
326  kmalloc(sizeof(char *) * slave->sii.string_count,
327  GFP_KERNEL))) {
328  EC_SLAVE_ERR(slave, "Failed to allocate string array memory.\n");
329  err = -ENOMEM;
330  goto out_zero;
331  }
332 
333  offset = 1;
334  for (i = 0; i < slave->sii.string_count; i++) {
335  size = data[offset];
336  // allocate memory for string structure and data at a single blow
337  if (!(slave->sii.strings[i] =
338  kmalloc(sizeof(char) * size + 1, GFP_KERNEL))) {
339  EC_SLAVE_ERR(slave, "Failed to allocate string memory.\n");
340  err = -ENOMEM;
341  goto out_free;
342  }
343  memcpy(slave->sii.strings[i], data + offset + 1, size);
344  slave->sii.strings[i][size] = 0x00; // append binary zero
345  offset += 1 + size;
346  }
347  }
348 
349  return 0;
350 
351 out_free:
352  for (i--; i >= 0; i--)
353  kfree(slave->sii.strings[i]);
354  kfree(slave->sii.strings);
355  slave->sii.strings = NULL;
356 out_zero:
357  slave->sii.string_count = 0;
358  return err;
359 }
360 
361 /*****************************************************************************/
362 
369  ec_slave_t *slave,
370  const uint8_t *data,
371  size_t data_size
372  )
373 {
374  unsigned int i;
375  uint8_t flags;
376 
377  if (data_size != 32) {
378  EC_SLAVE_ERR(slave, "Wrong size of general category (%zu/32).\n",
379  data_size);
380  return -EINVAL;
381  }
382 
383  slave->sii.group = ec_slave_sii_string(slave, data[0]);
384  slave->sii.image = ec_slave_sii_string(slave, data[1]);
385  slave->sii.order = ec_slave_sii_string(slave, data[2]);
386  slave->sii.name = ec_slave_sii_string(slave, data[3]);
387 
388  for (i = 0; i < 4; i++)
389  slave->sii.physical_layer[i] =
390  (data[4] & (0x03 << (i * 2))) >> (i * 2);
391 
392  // read CoE details
393  flags = EC_READ_U8(data + 5);
394  slave->sii.coe_details.enable_sdo = (flags >> 0) & 0x01;
395  slave->sii.coe_details.enable_sdo_info = (flags >> 1) & 0x01;
396  slave->sii.coe_details.enable_pdo_assign = (flags >> 2) & 0x01;
397  slave->sii.coe_details.enable_pdo_configuration = (flags >> 3) & 0x01;
398  slave->sii.coe_details.enable_upload_at_startup = (flags >> 4) & 0x01;
399  slave->sii.coe_details.enable_sdo_complete_access = (flags >> 5) & 0x01;
400 
401  // read general flags
402  flags = EC_READ_U8(data + 0x000B);
403  slave->sii.general_flags.enable_safeop = (flags >> 0) & 0x01;
404  slave->sii.general_flags.enable_not_lrw = (flags >> 1) & 0x01;
405 
406  slave->sii.current_on_ebus = EC_READ_S16(data + 0x0C);
407  slave->sii.has_general = 1;
408  return 0;
409 }
410 
411 /*****************************************************************************/
412 
420  ec_slave_t *slave,
421  const uint8_t *data,
422  size_t data_size
423  )
424 {
425  unsigned int i, count, total_count;
426  ec_sync_t *sync;
427  size_t memsize;
428  ec_sync_t *syncs;
429  uint8_t index;
430 
431  // one sync manager struct is 4 words long
432  if (data_size % 8) {
433  EC_SLAVE_ERR(slave, "Invalid SII sync manager category size %zu.\n",
434  data_size);
435  return -EINVAL;
436  }
437 
438  count = data_size / 8;
439 
440  if (count) {
441  total_count = count + slave->sii.sync_count;
442  if (total_count > EC_MAX_SYNC_MANAGERS) {
443  EC_SLAVE_ERR(slave, "Exceeded maximum number of"
444  " sync managers!\n");
445  return -EOVERFLOW;
446  }
447  memsize = sizeof(ec_sync_t) * total_count;
448  if (!(syncs = kmalloc(memsize, GFP_KERNEL))) {
449  EC_SLAVE_ERR(slave, "Failed to allocate %zu bytes"
450  " for sync managers.\n", memsize);
451  return -ENOMEM;
452  }
453 
454  for (i = 0; i < slave->sii.sync_count; i++)
455  ec_sync_init_copy(syncs + i, slave->sii.syncs + i);
456 
457  // initialize new sync managers
458  for (i = 0; i < count; i++, data += 8) {
459  index = i + slave->sii.sync_count;
460  sync = &syncs[index];
461 
462  ec_sync_init(sync, slave);
463  sync->physical_start_address = EC_READ_U16(data);
464  sync->default_length = EC_READ_U16(data + 2);
465  sync->control_register = EC_READ_U8(data + 4);
466  sync->enable = EC_READ_U8(data + 6);
467  }
468 
469  if (slave->sii.syncs)
470  kfree(slave->sii.syncs);
471  slave->sii.syncs = syncs;
472  slave->sii.sync_count = total_count;
473  }
474 
475  return 0;
476 }
477 
478 /*****************************************************************************/
479 
486  ec_slave_t *slave,
487  const uint8_t *data,
488  size_t data_size,
489  ec_direction_t dir
490  )
491 {
492  int ret;
493  ec_pdo_t *pdo;
494  ec_pdo_entry_t *entry;
495  unsigned int entry_count, i;
496 
497  while (data_size >= 8) {
498  if (!(pdo = kmalloc(sizeof(ec_pdo_t), GFP_KERNEL))) {
499  EC_SLAVE_ERR(slave, "Failed to allocate PDO memory.\n");
500  return -ENOMEM;
501  }
502 
503  ec_pdo_init(pdo);
504  pdo->index = EC_READ_U16(data);
505  entry_count = EC_READ_U8(data + 2);
506  pdo->sync_index = EC_READ_U8(data + 3);
507  ret = ec_pdo_set_name(pdo,
508  ec_slave_sii_string(slave, EC_READ_U8(data + 5)));
509  if (ret) {
510  ec_pdo_clear(pdo);
511  kfree(pdo);
512  return ret;
513  }
514  list_add_tail(&pdo->list, &slave->sii.pdos);
515 
516  data_size -= 8;
517  data += 8;
518 
519  for (i = 0; i < entry_count; i++) {
520  if (!(entry = kmalloc(sizeof(ec_pdo_entry_t), GFP_KERNEL))) {
521  EC_SLAVE_ERR(slave, "Failed to allocate PDO entry memory.\n");
522  return -ENOMEM;
523  }
524 
525  ec_pdo_entry_init(entry);
526  entry->index = EC_READ_U16(data);
527  entry->subindex = EC_READ_U8(data + 2);
528  ret = ec_pdo_entry_set_name(entry,
529  ec_slave_sii_string(slave, EC_READ_U8(data + 3)));
530  if (ret) {
531  ec_pdo_entry_clear(entry);
532  kfree(entry);
533  return ret;
534  }
535  entry->bit_length = EC_READ_U8(data + 5);
536  list_add_tail(&entry->list, &pdo->entries);
537 
538  data_size -= 8;
539  data += 8;
540  }
541 
542  // if sync manager index is positive, the PDO is mapped by default
543  if (pdo->sync_index >= 0) {
544  ec_sync_t *sync;
545 
546  if (!(sync = ec_slave_get_sync(slave, pdo->sync_index))) {
547  EC_SLAVE_ERR(slave, "Invalid SM index %i for PDO 0x%04X.",
548  pdo->sync_index, pdo->index);
549  return -ENOENT;
550  }
551 
552  ret = ec_pdo_list_add_pdo_copy(&sync->pdos, pdo);
553  if (ret)
554  return ret;
555  }
556  }
557 
558  return 0;
559 }
560 
561 /*****************************************************************************/
562 
569  ec_slave_t *slave,
570  unsigned int index
571  )
572 {
573  if (!index--)
574  return NULL;
575 
576  if (index >= slave->sii.string_count) {
577  EC_SLAVE_DBG(slave, 1, "String %u not found.\n", index);
578  return NULL;
579  }
580 
581  return slave->sii.strings[index];
582 }
583 
584 /*****************************************************************************/
585 
591  ec_slave_t *slave,
592  uint8_t sync_index
593  )
594 {
595  if (sync_index < slave->sii.sync_count) {
596  return &slave->sii.syncs[sync_index];
597  } else {
598  return NULL;
599  }
600 }
601 
602 /*****************************************************************************/
603 
609  unsigned int *sdo_count,
610  unsigned int *entry_count
612  )
613 {
614  unsigned int sdos = 0, entries = 0;
615  ec_sdo_t *sdo;
616  ec_sdo_entry_t *entry;
617 
618  list_for_each_entry(sdo, &slave->sdo_dictionary, list) {
619  sdos++;
620  list_for_each_entry(entry, &sdo->entries, list) {
621  entries++;
622  }
623  }
624 
625  *sdo_count = sdos;
626  *entry_count = entries;
627 }
628 
629 /*****************************************************************************/
630 
637  ec_slave_t *slave,
638  uint16_t index
639  )
640 {
641  ec_sdo_t *sdo;
642 
643  list_for_each_entry(sdo, &slave->sdo_dictionary, list) {
644  if (sdo->index != index)
645  continue;
646  return sdo;
647  }
648 
649  return NULL;
650 }
651 
652 /*****************************************************************************/
653 
663  const ec_slave_t *slave,
664  uint16_t index
665  )
666 {
667  const ec_sdo_t *sdo;
668 
669  list_for_each_entry(sdo, &slave->sdo_dictionary, list) {
670  if (sdo->index != index)
671  continue;
672  return sdo;
673  }
674 
675  return NULL;
676 }
677 
678 /*****************************************************************************/
679 
685  const ec_slave_t *slave,
686  uint16_t sdo_position
687  )
688 {
689  const ec_sdo_t *sdo;
690 
691  list_for_each_entry(sdo, &slave->sdo_dictionary, list) {
692  if (sdo_position--)
693  continue;
694  return sdo;
695  }
696 
697  return NULL;
698 }
699 
700 /*****************************************************************************/
701 
707  const ec_slave_t *slave
708  )
709 {
710  const ec_sdo_t *sdo;
711  uint16_t count = 0;
712 
713  list_for_each_entry(sdo, &slave->sdo_dictionary, list) {
714  count++;
715  }
716 
717  return count;
718 }
719 
720 /*****************************************************************************/
721 
726  const ec_slave_t *slave,
727  uint16_t index
728  )
729 {
730  unsigned int i;
731  const ec_sync_t *sync;
732  const ec_pdo_t *pdo;
733 
734  for (i = 0; i < slave->sii.sync_count; i++) {
735  sync = &slave->sii.syncs[i];
736 
737  if (!(pdo = ec_pdo_list_find_pdo_const(&sync->pdos, index)))
738  continue;
739 
740  return pdo;
741  }
742 
743  return NULL;
744 }
745 
746 /*****************************************************************************/
747 
751  ec_slave_t *slave,
752  ec_pdo_t *pdo
753  )
754 {
755  const ec_sdo_t *sdo;
756  ec_pdo_entry_t *pdo_entry;
757  const ec_sdo_entry_t *sdo_entry;
758 
759  list_for_each_entry(sdo, &slave->sdo_dictionary, list) {
760  if (sdo->index == pdo->index) {
761  ec_pdo_set_name(pdo, sdo->name);
762  } else {
763  list_for_each_entry(pdo_entry, &pdo->entries, list) {
764  if (sdo->index == pdo_entry->index) {
765  sdo_entry = ec_sdo_get_entry_const(
766  sdo, pdo_entry->subindex);
767  if (sdo_entry) {
768  ec_pdo_entry_set_name(pdo_entry,
769  sdo_entry->description);
770  }
771  }
772  }
773  }
774  }
775 }
776 
777 /*****************************************************************************/
778 
782  ec_slave_t *slave
783  )
784 {
785  unsigned int i;
786  ec_sync_t *sync;
787  ec_pdo_t *pdo;
788 
789  for (i = 0; i < slave->sii.sync_count; i++) {
790  sync = slave->sii.syncs + i;
791  list_for_each_entry(pdo, &sync->pdos.list, list) {
792  ec_slave_find_names_for_pdo(slave, pdo);
793  }
794  }
795 }
796 
797 /*****************************************************************************/
798 
804  ec_slave_t *slave,
805  unsigned int port_index
806  )
807 {
808  static const unsigned int prev_table[EC_MAX_PORTS] = {
809  2, 3, 1, 0
810  };
811 
812  if (port_index >= EC_MAX_PORTS) {
813  EC_SLAVE_WARN(slave, "%s(port_index=%u): Invalid port index!\n",
814  __func__, port_index);
815  }
816 
817  do {
818  port_index = prev_table[port_index];
819  if (slave->ports[port_index].next_slave) {
820  return port_index;
821  }
822  } while (port_index);
823 
824  return 0;
825 }
826 
827 /*****************************************************************************/
828 
834  ec_slave_t *slave,
835  unsigned int port_index
836  )
837 {
838  static const unsigned int next_table[EC_MAX_PORTS] = {
839  3, 2, 0, 1
840  };
841 
842  if (port_index >= EC_MAX_PORTS) {
843  EC_SLAVE_WARN(slave, "%s(port_index=%u): Invalid port index!\n",
844  __func__, port_index);
845  }
846 
847  do {
848  port_index = next_table[port_index];
849  if (slave->ports[port_index].next_slave) {
850  return port_index;
851  }
852  } while (port_index);
853 
854  return 0;
855 }
856 
857 /*****************************************************************************/
858 
864  ec_slave_t *slave
865  )
866 {
867  uint32_t rtt_sum = 0, rtt;
868  unsigned int port_index = ec_slave_get_next_port(slave, 0);
869 
870  while (port_index != 0) {
871  unsigned int prev_index =
872  ec_slave_get_previous_port(slave, port_index);
873 
874  rtt = slave->ports[port_index].receive_time -
875  slave->ports[prev_index].receive_time;
876  rtt_sum += rtt;
877  port_index = ec_slave_get_next_port(slave, port_index);
878  }
879 
880  return rtt_sum;
881 }
882 
883 /*****************************************************************************/
884 
890  ec_slave_t *slave
891  )
892 {
893  unsigned int port_index;
894  ec_slave_t *dc_slave = NULL;
895 
896  if (slave->base_dc_supported) {
897  dc_slave = slave;
898  } else {
899  port_index = ec_slave_get_next_port(slave, 0);
900 
901  while (port_index != 0) {
902  ec_slave_t *next = slave->ports[port_index].next_slave;
903 
904  if (next) {
905  dc_slave = ec_slave_find_next_dc_slave(next);
906 
907  if (dc_slave) {
908  break;
909  }
910  }
911  port_index = ec_slave_get_next_port(slave, port_index);
912  }
913  }
914 
915  return dc_slave;
916 }
917 
918 /*****************************************************************************/
919 
923  ec_slave_t *slave
924  )
925 {
926  unsigned int port_index;
927  ec_slave_t *next_slave, *next_dc;
928  uint32_t rtt, next_rtt_sum;
929 
930  if (!slave->base_dc_supported)
931  return;
932 
933  port_index = ec_slave_get_next_port(slave, 0);
934 
935  while (port_index != 0) {
936  next_slave = slave->ports[port_index].next_slave;
937  next_dc = ec_slave_find_next_dc_slave(next_slave);
938 
939  if (next_dc) {
940  unsigned int prev_port =
941  ec_slave_get_previous_port(slave, port_index);
942 
943  rtt = slave->ports[port_index].receive_time -
944  slave->ports[prev_port].receive_time;
945  next_rtt_sum = ec_slave_calc_rtt_sum(next_dc);
946 
947  slave->ports[port_index].delay_to_next_dc =
948  (rtt - next_rtt_sum) / 2; // FIXME
949  next_dc->ports[0].delay_to_next_dc =
950  (rtt - next_rtt_sum) / 2;
951 
952 #if 0
953  EC_SLAVE_DBG(slave, 1, "delay %u:%u rtt=%u"
954  " next_rtt_sum=%u delay=%u\n",
955  slave->ring_position, port_index, rtt, next_rtt_sum,
956  slave->ports[port_index].delay_to_next_dc);
957 #endif
958  }
959 
960  port_index = ec_slave_get_next_port(slave, port_index);
961  }
962 }
963 
964 /*****************************************************************************/
965 
969  ec_slave_t *slave,
970  uint32_t *delay
971  )
972 {
973  unsigned int i;
974  ec_slave_t *next_dc;
975 
976  EC_SLAVE_DBG(slave, 1, "%s(delay = %u ns)\n", __func__, *delay);
977 
978  slave->transmission_delay = *delay;
979 
980  i = ec_slave_get_next_port(slave, 0);
981 
982  while (i != 0) {
983  ec_slave_port_t *port = &slave->ports[i];
984  next_dc = ec_slave_find_next_dc_slave(port->next_slave);
985  if (next_dc) {
986  *delay = *delay + port->delay_to_next_dc;
987 #if 0
988  EC_SLAVE_DBG(slave, 1, "%u:%u %u\n",
989  slave->ring_position, i, *delay);
990 #endif
992  }
993 
994  i = ec_slave_get_next_port(slave, i);
995  }
996 
997  *delay = *delay + slave->ports[0].delay_to_next_dc;
998 }
999 
1000 /*****************************************************************************/
ec_sii_general_flags_t general_flags
General flags.
Definition: slave.h:161
Slave information interface general flags.
Definition: globals.h:156
ec_internal_request_state_t state
Request state.
Definition: reg_request.h:56
uint16_t ring_position
Ring position.
Definition: slave.h:183
uint32_t revision_number
Revision number.
Definition: slave.h:137
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:706
uint16_t boot_rx_mailbox_offset
Bootstrap receive mailbox address.
Definition: slave.h:139
void ec_fsm_slave_clear(ec_fsm_slave_t *fsm)
Destructor.
Definition: fsm_slave.c:83
ec_sii_t sii
Extracted SII data.
Definition: slave.h:223
uint16_t configured_tx_mailbox_size
Configured send mailbox size.
Definition: slave.h:201
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:803
uint8_t enable_upload_at_startup
?.
Definition: globals.h:150
void ec_slave_attach_pdo_names(ec_slave_t *slave)
Attach PDO names.
Definition: slave.c:781
uint16_t base_build
Build number.
Definition: slave.h:206
#define EC_SLAVE_DBG(slave, level, fmt, args...)
Convenience macro for printing slave-specific debug messages to syslog.
Definition: slave.h:106
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
uint8_t enable_not_lrw
Slave does not support LRW.
Definition: globals.h:158
uint16_t configured_tx_mailbox_offset
Configured send mailbox offset.
Definition: slave.h:199
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:187
CANopen SDO request.
Definition: sdo_request.h:46
ec_slave_state_t current_state
Current application state.
Definition: slave.h:192
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:61
Register request.
Definition: reg_request.h:48
ec_sdo_t * ec_slave_get_sdo(ec_slave_t *slave, uint16_t index)
Get an SDO from the dictionary.
Definition: slave.c:636
ec_slave_port_link_t link
Port link status.
Definition: slave.h:120
#define EC_SLAVE_WARN(slave, fmt, args...)
Convenience macro for printing slave-specific warnings to syslog.
Definition: slave.h:90
uint8_t enable_sdo
Enable SDO access.
Definition: globals.h:146
struct list_head list
List of PDOs.
Definition: pdo_list.h:50
uint32_t serial_number
Serial number.
Definition: slave.h:138
ec_sii_coe_details_t coe_details
CoE detail flags.
Definition: slave.h:160
char * order
Order number.
Definition: slave.h:157
int ec_pdo_set_name(ec_pdo_t *pdo, const char *name)
Set PDO name.
Definition: pdo.c:125
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:750
ec_fsm_slave_t fsm
Slave state machine.
Definition: slave.h:234
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:274
struct list_head reg_requests
Register access requests.
Definition: slave.h:230
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:725
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:162
uint16_t boot_tx_mailbox_size
Bootstrap transmit mailbox size.
Definition: slave.h:142
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:312
wait_queue_head_t request_queue
Wait queue for external requests from user space.
Definition: master.h:311
uint16_t station_address
Configured station address.
Definition: slave.h:184
unsigned int sync_count
Number of sync managers.
Definition: slave.h:166
void ec_slave_clear(ec_slave_t *slave)
Slave destructor.
Definition: slave.c:170
struct list_head sdo_dictionary
SDO dictionary list.
Definition: slave.h:225
uint16_t std_rx_mailbox_size
Standard receive mailbox size.
Definition: slave.h:144
uint8_t base_type
Slave type.
Definition: slave.h:204
Global definitions and macros.
uint16_t std_tx_mailbox_offset
Standard transmit mailbox address.
Definition: slave.h:145
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:141
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:608
EtherCAT slave.
Definition: slave.h:176
struct list_head sdo_requests
SDO access requests.
Definition: slave.h:229
char * description
Description.
Definition: sdo_entry.h:62
Code/Message pair.
Definition: globals.h:266
struct list_head soe_requests
SoE write requests.
Definition: slave.h:232
Slave information interface CANopen over EtherCAT details flags.
Definition: globals.h:145
uint8_t enable_safeop
?.
Definition: globals.h:157
ec_slave_config_t * config
Current configuration.
Definition: slave.h:190
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:255
uint8_t enable_sdo_info
SDO information service available.
Definition: globals.h:147
uint8_t enable_sdo_complete_access
Complete access possible.
Definition: globals.h:151
void ec_slave_calc_port_delays(ec_slave_t *slave)
Calculates the port transmission delays.
Definition: slave.c:922
PDO description.
Definition: pdo.h:49
uint8_t sdo_dictionary_fetched
Dictionary has been fetched.
Definition: slave.h:226
uint16_t * sii_words
Complete SII image.
Definition: slave.h:219
uint16_t mailbox_protocols
Supported mailbox protocols.
Definition: slave.h:147
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:76
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:211
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:143
uint8_t base_fmmu_bit_operation
FMMU bit operation is supported.
Definition: slave.h:209
struct list_head list
List item.
Definition: soe_request.h:49
uint32_t transmission_delay
DC system time transmission delay (offset from reference clock).
Definition: slave.h:215
ec_device_index_t
Master devices.
Definition: globals.h:189
char * name
SDO name.
Definition: sdo.h:54
uint16_t alias
Configured station alias.
Definition: slave.h:134
ec_direction_t
Direction type for PDO assignment functions.
Definition: ecrt.h:446
uint8_t base_fmmu_count
Number of supported FMMUs.
Definition: slave.h:207
void ec_slave_calc_transmission_delays_rec(ec_slave_t *slave, uint32_t *delay)
Recursively calculates transmission delays.
Definition: slave.c:968
uint16_t configured_rx_mailbox_offset
Configured receive mailbox offset.
Definition: slave.h:195
struct list_head entries
List of PDO entries.
Definition: pdo.h:54
ec_slave_port_desc_t desc
Port descriptors.
Definition: slave.h:119
unsigned int string_count
Number of SII strings.
Definition: slave.h:151
ec_master_t * master
Master owning the slave.
Definition: slave.h:178
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:684
uint8_t has_dc_system_time
The slave supports the DC system time register.
Definition: slave.h:212
char ** strings
Strings in SII categories.
Definition: slave.h:150
ec_slave_state_t
State of an EtherCAT slave.
Definition: globals.h:115
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
void ec_sync_clear(ec_sync_t *sync)
Destructor.
Definition: sync.c:81
Port is not implemented.
Definition: ecrt.h:369
uint8_t base_revision
Revision.
Definition: slave.h:205
32 bit.
Definition: globals.h:164
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:662
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:889
uint16_t effective_alias
Effective alias address.
Definition: slave.h:185
struct list_head entries
List of entries.
Definition: sdo.h:56
#define EC_READ_U16(DATA)
Read a 16-bit unsigned value from EtherCAT data.
Definition: ecrt.h:2313
struct list_head foe_requests
FoE write requests.
Definition: slave.h:231
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:419
#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:140
#define EC_MAX_PORTS
Maximum number of slave ports.
Definition: ecrt.h:235
struct list_head list
List item.
Definition: sdo_request.h:47
void ec_fsm_slave_init(ec_fsm_slave_t *fsm, ec_slave_t *slave)
Constructor.
Definition: fsm_slave.c:58
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:121
uint32_t receive_time
Port receive times for delay measurement.
Definition: slave.h:122
Slave port.
Definition: slave.h:118
char * image
Image name.
Definition: slave.h:156
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:296
uint16_t physical_start_address
Physical start address.
Definition: sync.h:49
unsigned long jiffies_preop
Time, the slave went to PREOP.
Definition: slave.h:227
uint16_t configured_rx_mailbox_size
Configured receive mailbox size.
Definition: slave.h:197
uint8_t base_dc_supported
Distributed clocks are supported.
Definition: slave.h:210
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:863
char * ec_slave_sii_string(ec_slave_t *, unsigned int)
Searches the string list for an index.
Definition: slave.c:568
size_t sii_nwords
Size of the SII contents in words.
Definition: slave.h:220
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:155
uint8_t physical_layer[EC_MAX_PORTS]
Port media.
Definition: slave.h:159
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:208
#define EC_READ_U8(DATA)
Read an 8-bit unsigned value from EtherCAT data.
Definition: ecrt.h:2297
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:833
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:2321
ec_device_index_t device_index
Index of device the slave responds on.
Definition: slave.h:179
void ec_slave_config_detach(ec_slave_config_t *sc)
Detaches the configuration from a slave object.
Definition: slave_config.c:282
uint16_t default_length
Data length in bytes.
Definition: sync.h:50
uint32_t product_code
Vendor-specific product code.
Definition: slave.h:136
PREOP state (mailbox communication, no IO)
Definition: globals.h:120
struct list_head list
List item.
Definition: pdo.h:50
unsigned int error_flag
Stop processing after an error.
Definition: slave.h:193
ec_sync_t * syncs
SYNC MANAGER categories.
Definition: slave.h:165
uint16_t std_tx_mailbox_size
Standard transmit mailbox size.
Definition: slave.h:146
EtherCAT master.
Definition: master.h:194
uint8_t enable_pdo_configuration
PDO configuration possible.
Definition: globals.h:149
struct list_head list
List item.
Definition: reg_request.h:49
ec_slave_state_t requested_state
Requested application state.
Definition: slave.h:191
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:485
#define EC_MAX_SYNC_MANAGERS
Maximum number of sync managers per slave.
Definition: ecrt.h:226
ec_internal_request_state_t state
Request state.
Definition: soe_request.h:60
void ec_sync_init(ec_sync_t *sync, ec_slave_t *slave)
Constructor.
Definition: sync.c:46
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:368
Sercos-over-EtherCAT request.
Definition: soe_request.h:48
char * name
Slave name.
Definition: slave.h:158
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:116
uint32_t vendor_id
Vendor ID.
Definition: slave.h:135
uint32_t delay_to_next_dc
Delay to next slave with DC support behind this port [ns].
Definition: slave.h:124
struct list_head pdos
SII [RT]XPDO categories.
Definition: slave.h:169
unsigned int force_config
Force (re-)configuration.
Definition: slave.h:194
struct list_head list
List item.
Definition: foe_request.h:51
unsigned int has_general
General category present.
Definition: slave.h:154
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:590
uint8_t enable_pdo_assign
PDO mapping configurable.
Definition: globals.h:148