IgH EtherCAT Master  1.6.9
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
26
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
42
43/****************************************************************************/
44
45// prototypes for private methods
46char *ec_slave_sii_string(const ec_slave_t *, unsigned int);
48unsigned int ec_slave_get_previous_port(const ec_slave_t *, unsigned int);
49unsigned int ec_slave_get_next_port(const ec_slave_t *, unsigned int);
50uint32_t ec_slave_calc_rtt_sum(const ec_slave_t *);
52
53/****************************************************************************/
54
59
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
168
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
283
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
305
307 ec_slave_state_t state
308 )
309{
310 slave->requested_state = state;
311 slave->error_flag = 0;
312}
313
314/****************************************************************************/
315
321
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
361out_free:
362 for (i--; i >= 0; i--)
363 kfree(slave->sii.strings[i]);
364 kfree(slave->sii.strings);
365 slave->sii.strings = NULL;
366out_zero:
367 slave->sii.string_count = 0;
368 return err;
369}
370
371/****************************************************************************/
372
377
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);
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
494
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
577
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
617
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
645
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
671
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
693
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
715
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];
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
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/****************************************************************************/
EtherCAT datagram structure.
const ec_code_msg_t al_status_messages[]
Application layer status messages.
Definition fsm_change.c:382
void ec_fsm_slave_clear(ec_fsm_slave_t *fsm)
Destructor.
Definition fsm_slave.c:87
void ec_fsm_slave_init(ec_fsm_slave_t *fsm, ec_slave_t *slave)
Constructor.
Definition fsm_slave.c:56
Global definitions and macros.
ec_slave_state_t
State of an EtherCAT slave.
Definition globals.h:121
@ EC_SLAVE_STATE_PREOP
PREOP state (mailbox communication, no IO)
Definition globals.h:126
@ EC_SLAVE_STATE_UNKNOWN
unknown state
Definition globals.h:122
#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:401
@ EC_DC_32
32 bit.
Definition globals.h:173
struct ec_slave ec_slave_t
Definition globals.h:310
ec_device_index_t
Master devices.
Definition globals.h:198
struct ec_soe_request ec_soe_request_t
Definition ecrt.h:312
#define EC_MAX_PORTS
Maximum number of slave ports.
Definition ecrt.h:276
#define EC_READ_S16(DATA)
Read a 16-bit signed value from EtherCAT data.
Definition ecrt.h:2956
struct ec_sdo_request ec_sdo_request_t
Definition ecrt.h:309
struct ec_master ec_master_t
Definition ecrt.h:300
ec_direction_t
Direction type for PDO assignment functions.
Definition ecrt.h:504
struct ec_reg_request ec_reg_request_t
Definition ecrt.h:318
#define EC_READ_U16(DATA)
Read a 16-bit unsigned value from EtherCAT data.
Definition ecrt.h:2948
#define EC_MAX_SYNC_MANAGERS
Maximum number of sync managers per slave.
Definition ecrt.h:267
#define EC_READ_U8(DATA)
Read an 8-bit unsigned value from EtherCAT data.
Definition ecrt.h:2932
@ EC_PORT_NOT_IMPLEMENTED
Port is not implemented.
Definition ecrt.h:427
EtherCAT master structure.
void ec_pdo_init(ec_pdo_t *pdo)
PDO constructor.
Definition pdo.c:38
void ec_pdo_clear(ec_pdo_t *pdo)
PDO destructor.
Definition pdo.c:86
int ec_pdo_set_name(ec_pdo_t *pdo, const char *name)
Set PDO name.
Definition pdo.c:117
void ec_pdo_entry_clear(ec_pdo_entry_t *entry)
PDO entry destructor.
Definition pdo_entry.c:68
int ec_pdo_entry_set_name(ec_pdo_entry_t *entry, const char *name)
Set PDO entry name.
Definition pdo_entry.c:81
void ec_pdo_entry_init(ec_pdo_entry_t *entry)
PDO entry constructor.
Definition pdo_entry.c:37
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
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
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
void ec_sdo_clear(ec_sdo_t *sdo)
SDO destructor.
Definition sdo.c:59
struct ec_sdo ec_sdo_t
Definition sdo_entry.h:40
void ec_slave_calc_port_delays(ec_slave_t *slave)
Calculates the port transmission delays.
Definition slave.c:932
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
const ec_pdo_t * ec_slave_find_pdo(const ec_slave_t *slave, uint16_t index)
Finds a mapped PDO.
Definition slave.c:735
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
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
void ec_slave_clear(ec_slave_t *slave)
Slave destructor.
Definition slave.c:169
void ec_slave_clear_sync_managers(ec_slave_t *slave)
Clear the sync manager array.
Definition slave.c:265
void ec_slave_calc_transmission_delays_rec(ec_slave_t *slave, uint32_t *delay)
Recursively calculates transmission delays.
Definition slave.c:978
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
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
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
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
void ec_slave_attach_pdo_names(ec_slave_t *slave)
Attach PDO names.
Definition slave.c:791
ec_sdo_t * ec_slave_get_sdo(ec_slave_t *slave, uint16_t index)
Get an SDO from the dictionary.
Definition slave.c:646
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
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
char * ec_slave_sii_string(const ec_slave_t *, unsigned int)
Searches the string list for an index.
Definition slave.c:578
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
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
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
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
uint16_t ec_slave_sdo_count(const ec_slave_t *slave)
Get the number of SDOs in the dictionary.
Definition slave.c:716
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
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
ec_slave_t * ec_slave_find_next_dc_slave(ec_slave_t *)
Finds the next slave supporting DC delay measurement.
Definition slave.c:899
EtherCAT slave structure.
#define EC_SLAVE_DBG(slave, level, fmt, args...)
Convenience macro for printing slave-specific debug messages to syslog.
Definition slave.h:98
#define EC_SLAVE_ERR(slave, fmt, args...)
Convenience macro for printing slave-specific errors to syslog.
Definition slave.h:68
#define EC_SLAVE_WARN(slave, fmt, args...)
Convenience macro for printing slave-specific warnings to syslog.
Definition slave.h:82
void ec_slave_config_detach(ec_slave_config_t *sc)
Detaches the configuration from a slave object.
EtherCAT slave configuration structure.
Code/Message pair.
Definition globals.h:275
Ethernet-over-EtherCAT set IP parameter request.
Definition eoe_request.h:41
ec_internal_request_state_t state
Request state.
Definition eoe_request.h:43
struct list_head list
List item.
Definition eoe_request.h:42
FoE request.
Definition foe_request.h:42
struct list_head list
List item.
Definition foe_request.h:43
ec_internal_request_state_t state
FoE request state.
Definition foe_request.h:55
wait_queue_head_t request_queue
Wait queue for external requests from user space.
Definition master.h:301
unsigned int debug_level
Master debug level.
Definition master.h:275
PDO entry description.
Definition pdo_entry.h:40
struct list_head list
list item
Definition pdo_entry.h:41
uint8_t bit_length
entry length in bit
Definition pdo_entry.h:45
uint8_t subindex
PDO entry subindex.
Definition pdo_entry.h:43
uint16_t index
PDO entry index.
Definition pdo_entry.h:42
struct list_head list
List of PDOs.
Definition pdo_list.h:42
PDO description.
Definition pdo.h:41
struct list_head list
List item.
Definition pdo.h:42
struct list_head entries
List of PDO entries.
Definition pdo.h:46
int8_t sync_index
Assigned sync manager.
Definition pdo.h:44
uint16_t index
PDO index.
Definition pdo.h:43
struct list_head list
List item.
Definition reg_request.h:41
ec_internal_request_state_t state
Request state.
Definition reg_request.h:48
CANopen SDO entry.
Definition sdo_entry.h:46
char * description
Description.
Definition sdo_entry.h:54
ec_internal_request_state_t state
SDO request state.
Definition sdo_request.h:55
struct list_head list
List item.
Definition sdo_request.h:41
uint16_t index
SDO index.
Definition sdo.h:44
struct list_head list
List item.
Definition sdo.h:42
char * name
SDO name.
Definition sdo.h:46
struct list_head entries
List of entries.
Definition sdo.h:48
Slave information interface CANopen over EtherCAT details flags.
Definition globals.h:154
uint8_t enable_sdo
Enable SDO access.
Definition globals.h:155
uint8_t enable_upload_at_startup
?
Definition globals.h:159
uint8_t enable_pdo_assign
PDO mapping configurable.
Definition globals.h:157
uint8_t enable_sdo_complete_access
Complete access possible.
Definition globals.h:160
uint8_t enable_pdo_configuration
PDO configuration possible.
Definition globals.h:158
uint8_t enable_sdo_info
SDO information service available.
Definition globals.h:156
Slave information interface general flags.
Definition globals.h:165
uint8_t enable_not_lrw
Slave does not support LRW.
Definition globals.h:167
uint16_t std_rx_mailbox_offset
Standard receive mailbox address.
Definition slave.h:135
char * group
Group name.
Definition slave.h:147
ec_sync_t * syncs
SYNC MANAGER categories.
Definition slave.h:157
uint16_t alias
Configured station alias.
Definition slave.h:126
char * order
Order number.
Definition slave.h:149
uint32_t serial_number
Serial number.
Definition slave.h:130
uint16_t std_tx_mailbox_size
Standard transmit mailbox size.
Definition slave.h:138
unsigned int string_count
Number of SII strings.
Definition slave.h:143
char * image
Image name.
Definition slave.h:148
uint16_t boot_tx_mailbox_size
Bootstrap transmit mailbox size.
Definition slave.h:134
int16_t current_on_ebus
Power consumption in mA.
Definition slave.h:154
uint32_t product_code
Vendor-specific product code.
Definition slave.h:128
char ** strings
Strings in SII categories.
Definition slave.h:142
struct list_head pdos
SII [RT]XPDO categories.
Definition slave.h:161
uint16_t mailbox_protocols
Supported mailbox protocols.
Definition slave.h:139
ec_sii_coe_details_t coe_details
CoE detail flags.
Definition slave.h:152
ec_sii_general_flags_t general_flags
General flags.
Definition slave.h:153
uint16_t boot_tx_mailbox_offset
Bootstrap transmit mailbox address.
Definition slave.h:133
uint16_t std_tx_mailbox_offset
Standard transmit mailbox address.
Definition slave.h:137
uint16_t boot_rx_mailbox_size
Bootstrap receive mailbox size.
Definition slave.h:132
uint32_t revision_number
Revision number.
Definition slave.h:129
uint16_t std_rx_mailbox_size
Standard receive mailbox size.
Definition slave.h:136
uint16_t boot_rx_mailbox_offset
Bootstrap receive mailbox address.
Definition slave.h:131
unsigned int has_general
General category present.
Definition slave.h:146
uint32_t vendor_id
Vendor ID.
Definition slave.h:127
unsigned int sync_count
Number of sync managers.
Definition slave.h:158
char * name
Slave name.
Definition slave.h:150
uint8_t physical_layer[EC_MAX_PORTS]
Port media.
Definition slave.h:151
Slave port.
Definition slave.h:110
uint32_t receive_time
Port receive times for delay measurement.
Definition slave.h:114
ec_slave_t * next_slave
Connected slaves.
Definition slave.h:113
ec_slave_port_link_t link
Port link status.
Definition slave.h:112
uint32_t delay_to_next_dc
Delay to next slave with DC support behind this port [ns].
Definition slave.h:116
ec_slave_port_desc_t desc
Port descriptors.
Definition slave.h:111
uint16_t configured_rx_mailbox_size
Configured receive mailbox size.
Definition slave.h:189
ec_sii_t sii
Extracted SII data.
Definition slave.h:215
unsigned int force_config
Force (re-)configuration.
Definition slave.h:186
ec_slave_port_t ports[EC_MAX_PORTS]
Ports.
Definition slave.h:179
uint32_t transmission_delay
DC system time transmission delay (offset from reference clock).
Definition slave.h:207
struct list_head sdo_dictionary
SDO dictionary list.
Definition slave.h:217
uint8_t base_dc_supported
Distributed clocks are supported.
Definition slave.h:202
uint16_t ring_position
Ring position.
Definition slave.h:175
ec_slave_config_t * config
Current configuration.
Definition slave.h:182
uint16_t configured_tx_mailbox_offset
Configured send mailbox offset.
Definition slave.h:191
struct list_head foe_requests
FoE requests.
Definition slave.h:223
uint16_t * sii_words
Complete SII image.
Definition slave.h:211
uint8_t base_fmmu_bit_operation
FMMU bit operation is supported.
Definition slave.h:201
uint8_t base_fmmu_count
Number of supported FMMUs.
Definition slave.h:199
uint8_t base_revision
Revision.
Definition slave.h:197
struct list_head reg_requests
Register access requests.
Definition slave.h:222
ec_slave_state_t current_state
Current application state.
Definition slave.h:184
uint8_t has_dc_system_time
The slave supports the DC system time register.
Definition slave.h:204
struct list_head eoe_requests
EoE set IP parameter requests.
Definition slave.h:225
struct list_head sdo_requests
SDO access requests.
Definition slave.h:221
uint16_t configured_tx_mailbox_size
Configured send mailbox size.
Definition slave.h:193
struct list_head soe_requests
SoE requests.
Definition slave.h:224
uint16_t configured_rx_mailbox_offset
Configured receive mailbox offset.
Definition slave.h:187
ec_slave_dc_range_t base_dc_range
DC range.
Definition slave.h:203
uint8_t base_type
Slave type.
Definition slave.h:196
uint8_t sdo_dictionary_fetched
Dictionary has been fetched.
Definition slave.h:218
uint16_t effective_alias
Effective alias address.
Definition slave.h:177
size_t sii_nwords
Size of the SII contents in words.
Definition slave.h:212
uint8_t base_sync_count
Number of supported sync managers.
Definition slave.h:200
ec_device_index_t device_index
Index of device the slave responds on.
Definition slave.h:171
ec_master_t * master
Master owning the slave.
Definition slave.h:170
uint16_t station_address
Configured station address.
Definition slave.h:176
ec_fsm_slave_t fsm
Slave state machine.
Definition slave.h:227
unsigned int error_flag
Stop processing after an error.
Definition slave.h:185
unsigned long jiffies_preop
Time, the slave went to PREOP.
Definition slave.h:219
ec_slave_state_t requested_state
Requested application state.
Definition slave.h:183
uint16_t base_build
Build number.
Definition slave.h:198
ec_internal_request_state_t state
Request state.
Definition soe_request.h:52
struct list_head list
List item.
Definition soe_request.h:41
Sync manager.
Definition sync.h:39
uint16_t physical_start_address
Physical start address.
Definition sync.h:41
uint8_t enable
Enable bit.
Definition sync.h:44
ec_pdo_list_t pdos
Current PDO assignment.
Definition sync.h:45
uint16_t default_length
Data length in bytes.
Definition sync.h:42
uint8_t control_register
Control register value.
Definition sync.h:43
void ec_sync_init_copy(ec_sync_t *sync, const ec_sync_t *other)
Copy constructor.
Definition sync.c:55
void ec_sync_clear(ec_sync_t *sync)
Destructor.
Definition sync.c:73
void ec_sync_init(ec_sync_t *sync, ec_slave_t *slave)
Constructor.
Definition sync.c:38