IgH EtherCAT Master  1.5.2
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
50
51/*****************************************************************************/
52
53char *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
351out_free:
352 for (i--; i >= 0; i--)
353 kfree(slave->sii.strings[i]);
354 kfree(slave->sii.strings);
355 slave->sii.strings = NULL;
356out_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);
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];
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/*****************************************************************************/
EtherCAT datagram structure.
void ec_fsm_slave_clear(ec_fsm_slave_t *fsm)
Destructor.
Definition: fsm_slave.c:85
void ec_fsm_slave_init(ec_fsm_slave_t *fsm, ec_slave_t *slave)
Constructor.
Definition: fsm_slave.c:60
Global definitions and macros.
ec_slave_state_t
State of an EtherCAT slave.
Definition: globals.h:115
@ EC_SLAVE_STATE_PREOP
PREOP state (mailbox communication, no IO)
Definition: globals.h:120
@ EC_SLAVE_STATE_UNKNOWN
unknown state
Definition: globals.h:116
#define EC_STATE_STRING_SIZE
Minimum size of a buffer used with ec_state_string().
Definition: globals.h:54
size_t ec_state_string(uint8_t, char *, uint8_t)
Prints slave states in clear text.
Definition: module.c:405
@ EC_DC_32
32 bit.
Definition: globals.h:164
ec_device_index_t
Master devices.
Definition: globals.h:189
#define EC_MAX_PORTS
Maximum number of slave ports.
Definition: ecrt.h:222
#define EC_READ_S16(DATA)
Read a 16-bit signed value from EtherCAT data.
Definition: ecrt.h:2186
ec_direction_t
Direction type for PDO assignment functions.
Definition: ecrt.h:430
#define EC_READ_U16(DATA)
Read a 16-bit unsigned value from EtherCAT data.
Definition: ecrt.h:2178
#define EC_MAX_SYNC_MANAGERS
Maximum number of sync managers per slave.
Definition: ecrt.h:213
#define EC_READ_U8(DATA)
Read an 8-bit unsigned value from EtherCAT data.
Definition: ecrt.h:2162
@ EC_PORT_NOT_IMPLEMENTED
Port is not implemented.
Definition: ecrt.h:353
EtherCAT master structure.
void ec_pdo_init(ec_pdo_t *pdo)
PDO constructor.
Definition: pdo.c:46
void ec_pdo_clear(ec_pdo_t *pdo)
PDO destructor.
Definition: pdo.c:94
int ec_pdo_set_name(ec_pdo_t *pdo, const char *name)
Set PDO name.
Definition: pdo.c:125
void ec_pdo_entry_clear(ec_pdo_entry_t *entry)
PDO entry destructor.
Definition: pdo_entry.c:76
int ec_pdo_entry_set_name(ec_pdo_entry_t *entry, const char *name)
Set PDO entry name.
Definition: pdo_entry.c:89
void ec_pdo_entry_init(ec_pdo_entry_t *entry)
PDO entry constructor.
Definition: pdo_entry.c:45
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
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
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
void ec_sdo_clear(ec_sdo_t *sdo)
SDO destructor.
Definition: sdo.c:67
void ec_slave_calc_port_delays(ec_slave_t *slave)
Calculates the port transmission delays.
Definition: slave.c:922
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
const ec_pdo_t * ec_slave_find_pdo(const ec_slave_t *slave, uint16_t index)
Finds a mapped PDO.
Definition: slave.c:725
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
void ec_slave_clear(ec_slave_t *slave)
Slave destructor.
Definition: slave.c:170
void ec_slave_clear_sync_managers(ec_slave_t *slave)
Clear the sync manager array.
Definition: slave.c:255
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
void ec_slave_calc_transmission_delays_rec(ec_slave_t *slave, uint32_t *delay)
Recursively calculates transmission delays.
Definition: slave.c:968
char * ec_slave_sii_string(ec_slave_t *, unsigned int)
Searches the string list for an index.
Definition: slave.c:568
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
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
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
const ec_code_msg_t al_status_messages[]
Application layer status messages.
Definition: fsm_change.c:346
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
void ec_slave_attach_pdo_names(ec_slave_t *slave)
Attach PDO names.
Definition: slave.c:781
ec_sdo_t * ec_slave_get_sdo(ec_slave_t *slave, uint16_t index)
Get an SDO from the dictionary.
Definition: slave.c:636
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
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
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
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
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
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
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
uint16_t ec_slave_sdo_count(const ec_slave_t *slave)
Get the number of SDOs in the dictionary.
Definition: slave.c:706
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
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
EtherCAT slave structure.
#define EC_SLAVE_DBG(slave, level, fmt, args...)
Convenience macro for printing slave-specific debug messages to syslog.
Definition: slave.h:106
#define EC_SLAVE_ERR(slave, fmt, args...)
Convenience macro for printing slave-specific errors to syslog.
Definition: slave.h:76
#define EC_SLAVE_WARN(slave, fmt, args...)
Convenience macro for printing slave-specific warnings to syslog.
Definition: slave.h:90
void ec_slave_config_detach(ec_slave_config_t *sc)
Detaches the configuration from a slave object.
Definition: slave_config.c:276
EtherCAT slave configuration structure.
Code/Message pair.
Definition: globals.h:266
FoE request.
Definition: foe_request.h:50
struct list_head list
List item.
Definition: foe_request.h:51
ec_internal_request_state_t state
FoE request state.
Definition: foe_request.h:63
EtherCAT master.
Definition: master.h:194
wait_queue_head_t request_queue
Wait queue for external requests from user space.
Definition: master.h:311
unsigned int debug_level
Master debug level.
Definition: master.h:285
PDO entry description.
Definition: pdo_entry.h:48
struct list_head list
list item
Definition: pdo_entry.h:49
uint8_t bit_length
entry length in bit
Definition: pdo_entry.h:53
uint8_t subindex
PDO entry subindex.
Definition: pdo_entry.h:51
uint16_t index
PDO entry index.
Definition: pdo_entry.h:50
struct list_head list
List of PDOs.
Definition: pdo_list.h:50
PDO description.
Definition: pdo.h:49
struct list_head list
List item.
Definition: pdo.h:50
struct list_head entries
List of PDO entries.
Definition: pdo.h:54
int8_t sync_index
Assigned sync manager.
Definition: pdo.h:52
uint16_t index
PDO index.
Definition: pdo.h:51
Register request.
Definition: reg_request.h:48
struct list_head list
List item.
Definition: reg_request.h:49
ec_internal_request_state_t state
Request state.
Definition: reg_request.h:56
CANopen SDO entry.
Definition: sdo_entry.h:54
char * description
Description.
Definition: sdo_entry.h:62
CANopen SDO request.
Definition: sdo_request.h:48
ec_internal_request_state_t state
SDO request state.
Definition: sdo_request.h:63
struct list_head list
List item.
Definition: sdo_request.h:49
CANopen SDO.
Definition: sdo.h:49
uint16_t index
SDO index.
Definition: sdo.h:52
struct list_head list
List item.
Definition: sdo.h:50
char * name
SDO name.
Definition: sdo.h:54
struct list_head entries
List of entries.
Definition: sdo.h:56
Slave information interface CANopen over EtherCAT details flags.
Definition: globals.h:145
uint8_t enable_sdo
Enable SDO access.
Definition: globals.h:146
uint8_t enable_upload_at_startup
?.
Definition: globals.h:150
uint8_t enable_pdo_assign
PDO mapping configurable.
Definition: globals.h:148
uint8_t enable_sdo_complete_access
Complete access possible.
Definition: globals.h:151
uint8_t enable_pdo_configuration
PDO configuration possible.
Definition: globals.h:149
uint8_t enable_sdo_info
SDO information service available.
Definition: globals.h:147
Slave information interface general flags.
Definition: globals.h:156
uint8_t enable_safeop
?.
Definition: globals.h:157
uint8_t enable_not_lrw
Slave does not support LRW.
Definition: globals.h:158
uint16_t std_rx_mailbox_offset
Standard receive mailbox address.
Definition: slave.h:143
char * group
Group name.
Definition: slave.h:155
ec_sync_t * syncs
SYNC MANAGER categories.
Definition: slave.h:165
uint16_t alias
Configured station alias.
Definition: slave.h:134
char * order
Order number.
Definition: slave.h:157
uint32_t serial_number
Serial number.
Definition: slave.h:138
uint16_t std_tx_mailbox_size
Standard transmit mailbox size.
Definition: slave.h:146
unsigned int string_count
Number of SII strings.
Definition: slave.h:151
char * image
Image name.
Definition: slave.h:156
uint16_t boot_tx_mailbox_size
Bootstrap transmit mailbox size.
Definition: slave.h:142
int16_t current_on_ebus
Power consumption in mA.
Definition: slave.h:162
uint32_t product_code
Vendor-specific product code.
Definition: slave.h:136
char ** strings
Strings in SII categories.
Definition: slave.h:150
struct list_head pdos
SII [RT]XPDO categories.
Definition: slave.h:169
uint16_t mailbox_protocols
Supported mailbox protocols.
Definition: slave.h:147
ec_sii_coe_details_t coe_details
CoE detail flags.
Definition: slave.h:160
ec_sii_general_flags_t general_flags
General flags.
Definition: slave.h:161
uint16_t boot_tx_mailbox_offset
Bootstrap transmit mailbox address.
Definition: slave.h:141
uint16_t std_tx_mailbox_offset
Standard transmit mailbox address.
Definition: slave.h:145
uint16_t boot_rx_mailbox_size
Bootstrap receive mailbox size.
Definition: slave.h:140
uint32_t revision_number
Revision number.
Definition: slave.h:137
uint16_t std_rx_mailbox_size
Standard receive mailbox size.
Definition: slave.h:144
uint16_t boot_rx_mailbox_offset
Bootstrap receive mailbox address.
Definition: slave.h:139
unsigned int has_general
General category present.
Definition: slave.h:154
uint32_t vendor_id
Vendor ID.
Definition: slave.h:135
unsigned int sync_count
Number of sync managers.
Definition: slave.h:166
char * name
Slave name.
Definition: slave.h:158
uint8_t physical_layer[EC_MAX_PORTS]
Port media.
Definition: slave.h:159
Slave port.
Definition: slave.h:118
uint32_t receive_time
Port receive times for delay measurement.
Definition: slave.h:122
ec_slave_t * next_slave
Connected slaves.
Definition: slave.h:121
ec_slave_port_link_t link
Port link status.
Definition: slave.h:120
uint32_t delay_to_next_dc
Delay to next slave with DC support behind this port [ns].
Definition: slave.h:124
ec_slave_port_desc_t desc
Port descriptors.
Definition: slave.h:119
EtherCAT slave.
Definition: slave.h:177
uint16_t configured_rx_mailbox_size
Configured receive mailbox size.
Definition: slave.h:197
ec_sii_t sii
Extracted SII data.
Definition: slave.h:223
unsigned int force_config
Force (re-)configuration.
Definition: slave.h:194
ec_slave_port_t ports[EC_MAX_PORTS]
Ports.
Definition: slave.h:187
uint32_t transmission_delay
DC system time transmission delay (offset from reference clock).
Definition: slave.h:215
struct list_head sdo_dictionary
SDO dictionary list.
Definition: slave.h:225
uint8_t base_dc_supported
Distributed clocks are supported.
Definition: slave.h:210
uint16_t ring_position
Ring position.
Definition: slave.h:183
ec_slave_config_t * config
Current configuration.
Definition: slave.h:190
uint16_t configured_tx_mailbox_offset
Configured send mailbox offset.
Definition: slave.h:199
struct list_head foe_requests
FoE write requests.
Definition: slave.h:231
uint16_t * sii_words
Complete SII image.
Definition: slave.h:219
uint8_t base_fmmu_bit_operation
FMMU bit operation is supported.
Definition: slave.h:209
uint8_t base_fmmu_count
Number of supported FMMUs.
Definition: slave.h:207
uint8_t base_revision
Revision.
Definition: slave.h:205
struct list_head reg_requests
Register access requests.
Definition: slave.h:230
ec_slave_state_t current_state
Current application state.
Definition: slave.h:192
uint8_t has_dc_system_time
The slave supports the DC system time register.
Definition: slave.h:212
struct list_head sdo_requests
SDO access requests.
Definition: slave.h:229
uint16_t configured_tx_mailbox_size
Configured send mailbox size.
Definition: slave.h:201
struct list_head soe_requests
SoE write requests.
Definition: slave.h:232
uint16_t configured_rx_mailbox_offset
Configured receive mailbox offset.
Definition: slave.h:195
ec_slave_dc_range_t base_dc_range
DC range.
Definition: slave.h:211
uint8_t base_type
Slave type.
Definition: slave.h:204
uint8_t sdo_dictionary_fetched
Dictionary has been fetched.
Definition: slave.h:226
uint16_t effective_alias
Effective alias address.
Definition: slave.h:185
size_t sii_nwords
Size of the SII contents in words.
Definition: slave.h:220
uint8_t base_sync_count
Number of supported sync managers.
Definition: slave.h:208
ec_device_index_t device_index
Index of device the slave responds on.
Definition: slave.h:179
ec_master_t * master
Master owning the slave.
Definition: slave.h:178
uint16_t station_address
Configured station address.
Definition: slave.h:184
ec_fsm_slave_t fsm
Slave state machine.
Definition: slave.h:234
unsigned int error_flag
Stop processing after an error.
Definition: slave.h:193
unsigned long jiffies_preop
Time, the slave went to PREOP.
Definition: slave.h:227
ec_slave_state_t requested_state
Requested application state.
Definition: slave.h:191
uint16_t base_build
Build number.
Definition: slave.h:206
Sercos-over-EtherCAT request.
Definition: soe_request.h:48
struct list_head list
List item.
Definition: soe_request.h:49
ec_internal_request_state_t state
Request state.
Definition: soe_request.h:58
Sync manager.
Definition: sync.h:47
uint16_t physical_start_address
Physical start address.
Definition: sync.h:49
uint8_t enable
Enable bit.
Definition: sync.h:52
ec_pdo_list_t pdos
Current PDO assignment.
Definition: sync.h:53
uint16_t default_length
Data length in bytes.
Definition: sync.h:50
uint8_t control_register
Control register value.
Definition: sync.h:51
void ec_sync_init_copy(ec_sync_t *sync, const ec_sync_t *other)
Copy constructor.
Definition: sync.c:63
void ec_sync_clear(ec_sync_t *sync)
Destructor.
Definition: sync.c:81
void ec_sync_init(ec_sync_t *sync, ec_slave_t *slave)
Constructor.
Definition: sync.c:46