IgH EtherCAT Master  1.6.9
slave_config.c
Go to the documentation of this file.
1/*****************************************************************************
2 *
3 * Copyright (C) 2006-2024 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 * vim: expandtab
21 *
22 ****************************************************************************/
23
28
29/****************************************************************************/
30
31#include "slave_config.h"
32
33#include "globals.h"
34#include "master.h"
35#include "voe_handler.h"
36#include "flag.h"
37#include "ioctl.h"
38
39#ifdef EC_EOE
40#include "eoe_request.h"
41#endif
42
43#include <linux/module.h>
44#include <linux/slab.h>
45
46/****************************************************************************/
47
48// prototypes for private methods
52 ec_pdo_t *);
53
54/****************************************************************************/
55
58typedef struct {
59 struct list_head list;
62 unsigned int timeout_ms;
64
65/****************************************************************************/
66
74 ec_master_t *master,
75 uint16_t alias,
76 uint16_t position,
77 uint32_t vendor_id,
78 uint32_t product_code
79 )
80{
81 unsigned int i;
82
83 sc->master = master;
84
85 sc->alias = alias;
86 sc->position = position;
87 sc->vendor_id = vendor_id;
88 sc->product_code = product_code;
89 sc->watchdog_divider = 0; // use default
90 sc->watchdog_intervals = 0; // use default
91
92 sc->slave = NULL;
93
94 for (i = 0; i < EC_MAX_SYNC_MANAGERS; i++)
96
97 sc->used_fmmus = 0;
98 sc->dc_assign_activate = 0x0000;
99 sc->dc_sync[0].cycle_time = 0U;
100 sc->dc_sync[1].cycle_time = 0;
101 sc->dc_sync[0].shift_time = 0U;
102 sc->dc_sync[1].shift_time = 0;
103
104 INIT_LIST_HEAD(&sc->sdo_configs);
105 INIT_LIST_HEAD(&sc->sdo_requests);
106 INIT_LIST_HEAD(&sc->soe_requests);
107 INIT_LIST_HEAD(&sc->reg_requests);
108 INIT_LIST_HEAD(&sc->voe_handlers);
109 INIT_LIST_HEAD(&sc->soe_configs);
110 INIT_LIST_HEAD(&sc->flags);
111 INIT_LIST_HEAD(&sc->al_timeouts);
112
113#ifdef EC_EOE
115#endif
116
118}
119
120/****************************************************************************/
121
128 )
129{
130 unsigned int i;
131 ec_sdo_request_t *req, *next_req;
132 ec_voe_handler_t *voe, *next_voe;
133 ec_reg_request_t *reg, *next_reg;
134 ec_soe_request_t *soe, *next_soe;
135 ec_flag_t *flag, *next_flag;
136 ec_al_timeout_t *timeout, *next_timeout;
137
139
140 // Free sync managers
141 for (i = 0; i < EC_MAX_SYNC_MANAGERS; i++)
143
144 // free all SDO configurations
145 list_for_each_entry_safe(req, next_req, &sc->sdo_configs, list) {
146 list_del(&req->list);
148 kfree(req);
149 }
150
151 // free all SDO requests
152 list_for_each_entry_safe(req, next_req, &sc->sdo_requests, list) {
153 list_del(&req->list);
155 kfree(req);
156 }
157
158 // free all SoE requests
159 list_for_each_entry_safe(soe, next_soe, &sc->soe_requests, list) {
160 list_del(&soe->list);
162 kfree(soe);
163 }
164
165 // free all register requests
166 list_for_each_entry_safe(reg, next_reg, &sc->reg_requests, list) {
167 list_del(&reg->list);
169 kfree(reg);
170 }
171
172 // free all VoE handlers
173 list_for_each_entry_safe(voe, next_voe, &sc->voe_handlers, list) {
174 list_del(&voe->list);
176 kfree(voe);
177 }
178
179 // free all SoE configurations
180 list_for_each_entry_safe(soe, next_soe, &sc->soe_configs, list) {
181 list_del(&soe->list);
183 kfree(soe);
184 }
185
186 // free all flags
187 list_for_each_entry_safe(flag, next_flag, &sc->flags, list) {
188 list_del(&flag->list);
189 ec_flag_clear(flag);
190 kfree(flag);
191 }
192
193 // free all AL timeouts
194 list_for_each_entry_safe(timeout, next_timeout, &sc->al_timeouts, list) {
195 list_del(&timeout->list);
196 kfree(timeout);
197 }
198
200}
201
202/****************************************************************************/
203
218 ec_domain_t *domain,
219 uint8_t sync_index,
220 ec_direction_t dir
221 )
222{
223 unsigned int i;
224 ec_fmmu_config_t *fmmu;
225
226 // FMMU configuration already prepared?
227 for (i = 0; i < sc->used_fmmus; i++) {
228 fmmu = &sc->fmmu_configs[i];
229 if (fmmu->domain == domain && fmmu->sync_index == sync_index)
230 return fmmu->logical_start_address;
231 }
232
233 if (sc->used_fmmus == EC_MAX_FMMUS) {
234 EC_CONFIG_ERR(sc, "FMMU limit reached!\n");
235 return -EOVERFLOW;
236 }
237
238 fmmu = &sc->fmmu_configs[sc->used_fmmus++];
239
240 down(&sc->master->master_sem);
241 ec_fmmu_config_init(fmmu, sc, domain, sync_index, dir);
242 up(&sc->master->master_sem);
243
244 return fmmu->logical_start_address;
245}
246
247/****************************************************************************/
248
256 )
257{
258 ec_slave_t *slave;
259
260 if (sc->slave)
261 return 0; // already attached
262
263 if (!(slave = ec_master_find_slave(
264 sc->master, sc->alias, sc->position))) {
265 EC_CONFIG_DBG(sc, 1, "Failed to find slave for configuration.\n");
266 return -ENOENT;
267 }
268
269 if (slave->config) {
270 EC_CONFIG_DBG(sc, 1, "Failed to attach configuration. Slave %u"
271 " already has a configuration!\n", slave->ring_position);
272 return -EEXIST;
273 }
274
275 if (
276#ifdef EC_IDENT_WILDCARDS
277 sc->vendor_id != 0xffffffff &&
278#endif
279 slave->sii.vendor_id != sc->vendor_id
280 ) {
281 EC_CONFIG_DBG(sc, 1, "Slave %u has no matching vendor ID (0x%08X)"
282 " for configuration (0x%08X).\n",
283 slave->ring_position, slave->sii.vendor_id, sc->vendor_id);
284 return -EINVAL;
285 }
286
287 if (
288#ifdef EC_IDENT_WILDCARDS
289 sc->product_code != 0xffffffff &&
290#endif
291 slave->sii.product_code != sc->product_code
292 ) {
293 EC_CONFIG_DBG(sc, 1, "Slave %u has no matching product code (0x%08X)"
294 " for configuration (0x%08X).\n",
295 slave->ring_position, slave->sii.product_code,
296 sc->product_code);
297 return -EINVAL;
298 }
299
300 // attach slave
301 slave->config = sc;
302 sc->slave = slave;
303
304 EC_CONFIG_DBG(sc, 1, "Attached slave %u.\n", slave->ring_position);
305 return 0;
306}
307
308/****************************************************************************/
309
314 )
315{
316 if (sc->slave) {
317 ec_reg_request_t *reg;
318
319 sc->slave->config = NULL;
320
321 // invalidate processing register request
322 list_for_each_entry(reg, &sc->reg_requests, list) {
323 if (sc->slave->fsm.reg_request == reg) {
324 sc->slave->fsm.reg_request = NULL;
325 break;
326 }
327 }
328
329 sc->slave = NULL;
330 }
331}
332
333/****************************************************************************/
334
338{
339 uint8_t sync_index;
340 ec_sync_config_t *sync_config;
341 const ec_sync_t *sync;
342
343 if (!sc->slave)
344 return;
345
346 for (sync_index = 0; sync_index < EC_MAX_SYNC_MANAGERS; sync_index++) {
347 sync_config = &sc->sync_configs[sync_index];
348 if ((sync = ec_slave_get_sync(sc->slave, sync_index))) {
349 sync_config->dir = ec_sync_default_direction(sync);
350 if (sync_config->dir == EC_DIR_INVALID)
352 "SM%u has an invalid direction field!\n", sync_index);
353 ec_pdo_list_copy(&sync_config->pdos, &sync->pdos);
354 }
355 }
356}
357
358/****************************************************************************/
359
363 const ec_slave_config_t *sc,
364 ec_pdo_t *pdo
365 )
366{
367 unsigned int i;
368 const ec_sync_t *sync;
369 const ec_pdo_t *default_pdo;
370
371 if (!sc->slave)
372 return;
373
374 EC_CONFIG_DBG(sc, 1, "Loading default mapping for PDO 0x%04X.\n",
375 pdo->index);
376
377 // find PDO in any sync manager (it could be reassigned later)
378 for (i = 0; i < sc->slave->sii.sync_count; i++) {
379 sync = &sc->slave->sii.syncs[i];
380
381 list_for_each_entry(default_pdo, &sync->pdos.list, list) {
382 if (default_pdo->index != pdo->index)
383 continue;
384
385 if (default_pdo->name) {
386 EC_CONFIG_DBG(sc, 1, "Found PDO name \"%s\".\n",
387 default_pdo->name);
388
389 // take PDO name from assigned one
390 ec_pdo_set_name(pdo, default_pdo->name);
391 }
392
393 // copy entries (= default PDO mapping)
394 if (ec_pdo_copy_entries(pdo, default_pdo))
395 return;
396
397 if (sc->master->debug_level) {
398 const ec_pdo_entry_t *entry;
399 list_for_each_entry(entry, &pdo->entries, list) {
400 EC_CONFIG_DBG(sc, 1, "Entry 0x%04X:%02X.\n",
401 entry->index, entry->subindex);
402 }
403 }
404
405 return;
406 }
407 }
408
409 EC_CONFIG_DBG(sc, 1, "No default mapping found.\n");
410}
411
412/****************************************************************************/
413
419 const ec_slave_config_t *sc
420 )
421{
422 const ec_sdo_request_t *req;
423 unsigned int count = 0;
424
425 list_for_each_entry(req, &sc->sdo_configs, list) {
426 count++;
427 }
428
429 return count;
430}
431
432/****************************************************************************/
433
441 const ec_slave_config_t *sc,
442 unsigned int pos
443 )
444{
445 const ec_sdo_request_t *req;
446
447 list_for_each_entry(req, &sc->sdo_configs, list) {
448 if (pos--)
449 continue;
450 return req;
451 }
452
453 return NULL;
454}
455
456/****************************************************************************/
457
463 const ec_slave_config_t *sc
464 )
465{
466 const ec_soe_request_t *req;
467 unsigned int count = 0;
468
469 list_for_each_entry(req, &sc->soe_configs, list) {
470 count++;
471 }
472
473 return count;
474}
475
476/****************************************************************************/
477
485 const ec_slave_config_t *sc,
486 unsigned int pos
487 )
488{
489 const ec_soe_request_t *req;
490
491 list_for_each_entry(req, &sc->soe_configs, list) {
492 if (pos--)
493 continue;
494 return req;
495 }
496
497 return NULL;
498}
499
500/****************************************************************************/
501
507 const ec_slave_config_t *sc
508 )
509{
510 const ec_flag_t *flag;
511 unsigned int count = 0;
512
513 list_for_each_entry(flag, &sc->flags, list) {
514 count++;
515 }
516
517 return count;
518}
519
520/****************************************************************************/
521
529 const ec_slave_config_t *sc,
530 unsigned int pos
531 )
532{
533 const ec_flag_t *flag;
534
535 list_for_each_entry(flag, &sc->flags, list) {
536 if (pos--)
537 continue;
538 return flag;
539 }
540
541 return NULL;
542}
543
544/****************************************************************************/
545
552 unsigned int pos
553 )
554{
555 ec_sdo_request_t *req;
556
557 list_for_each_entry(req, &sc->sdo_requests, list) {
558 if (pos--)
559 continue;
560 return req;
561 }
562
563 return NULL;
564}
565
566/****************************************************************************/
567
574 unsigned int pos
575 )
576{
577 ec_soe_request_t *req;
578
579 list_for_each_entry(req, &sc->soe_requests, list) {
580 if (pos--)
581 continue;
582 return req;
583 }
584
585 return NULL;
586}
587
588/****************************************************************************/
589
596 unsigned int pos
597 )
598{
599 ec_reg_request_t *reg;
600
601 list_for_each_entry(reg, &sc->reg_requests, list) {
602 if (pos--)
603 continue;
604 return reg;
605 }
606
607 return NULL;
608}
609
610/****************************************************************************/
611
618 unsigned int pos
619 )
620{
621 ec_voe_handler_t *voe;
622
623 list_for_each_entry(voe, &sc->voe_handlers, list) {
624 if (pos--)
625 continue;
626 return voe;
627 }
628
629 return NULL;
630}
631
632/****************************************************************************/
633
640 const char *key
641 )
642{
643 if (sc) {
644 ec_flag_t *flag;
645 list_for_each_entry(flag, &sc->flags, list) {
646 if (!strcmp(flag->key, key)) {
647 return flag;
648 }
649 }
650 }
651
652 return NULL;
653}
654
655/****************************************************************************/
656
663{
664 ec_al_timeout_t *timeout;
665
666 list_for_each_entry(timeout, &sc->al_timeouts, list) {
667 if (timeout->from == from && timeout->to == to) {
668 return timeout->timeout_ms;
669 }
670 }
671
672 return 0;
673}
674
675/*****************************************************************************
676 * Application interface
677 ****************************************************************************/
678
680 ec_direction_t dir, ec_watchdog_mode_t watchdog_mode)
681{
682 ec_sync_config_t *sync_config;
683
684 EC_CONFIG_DBG(sc, 1, "ecrt_slave_config_sync_manager(sc = 0x%p,"
685 " sync_index = %u, dir = %i, watchdog_mode = %i)\n",
686 sc, sync_index, dir, watchdog_mode);
687
688 if (sync_index >= EC_MAX_SYNC_MANAGERS) {
689 EC_CONFIG_ERR(sc, "Invalid sync manager index %u!\n", sync_index);
690 return -ENOENT;
691 }
692
693 if (dir != EC_DIR_OUTPUT && dir != EC_DIR_INPUT) {
694 EC_CONFIG_ERR(sc, "Invalid direction %u!\n", (unsigned int) dir);
695 return -EINVAL;
696 }
697
698 sync_config = &sc->sync_configs[sync_index];
699 sync_config->dir = dir;
700 sync_config->watchdog_mode = watchdog_mode;
701 return 0;
702}
703
704/****************************************************************************/
705
707 uint16_t divider, uint16_t intervals)
708{
709 EC_CONFIG_DBG(sc, 1, "%s(sc = 0x%p, divider = %u, intervals = %u)\n",
710 __func__, sc, divider, intervals);
711
712 sc->watchdog_divider = divider;
713 sc->watchdog_intervals = intervals;
714 return 0;
715}
716
717/****************************************************************************/
718
720 uint8_t sync_index, uint16_t pdo_index)
721{
722 ec_pdo_t *pdo;
723
724 EC_CONFIG_DBG(sc, 1, "%s(sc = 0x%p, sync_index = %u, "
725 "pdo_index = 0x%04X)\n", __func__, sc, sync_index, pdo_index);
726
727 if (sync_index >= EC_MAX_SYNC_MANAGERS) {
728 EC_CONFIG_ERR(sc, "Invalid sync manager index %u!\n", sync_index);
729 return -EINVAL;
730 }
731
732 down(&sc->master->master_sem);
733
734 pdo = ec_pdo_list_add_pdo(&sc->sync_configs[sync_index].pdos, pdo_index);
735 if (IS_ERR(pdo)) {
736 up(&sc->master->master_sem);
737 return PTR_ERR(pdo);
738 }
739 pdo->sync_index = sync_index;
740
742
743 up(&sc->master->master_sem);
744 return 0;
745}
746
747/****************************************************************************/
748
750 uint8_t sync_index)
751{
752 EC_CONFIG_DBG(sc, 1, "%s(sc = 0x%p, sync_index = %u)\n",
753 __func__, sc, sync_index);
754
755 if (sync_index >= EC_MAX_SYNC_MANAGERS) {
756 EC_CONFIG_ERR(sc, "Invalid sync manager index %u!\n", sync_index);
757 return -EINVAL;
758 }
759
760 down(&sc->master->master_sem);
761 ec_pdo_list_clear_pdos(&sc->sync_configs[sync_index].pdos);
762 up(&sc->master->master_sem);
763 return 0;
764}
765
766/****************************************************************************/
767
769 uint16_t pdo_index, uint16_t entry_index, uint8_t entry_subindex,
770 uint8_t entry_bit_length)
771{
772 uint8_t sync_index;
773 ec_pdo_t *pdo = NULL;
774 ec_pdo_entry_t *entry;
775 int retval = 0;
776
777 EC_CONFIG_DBG(sc, 1, "%s(sc = 0x%p, "
778 "pdo_index = 0x%04X, entry_index = 0x%04X, "
779 "entry_subindex = 0x%02X, entry_bit_length = %u)\n",
780 __func__, sc, pdo_index, entry_index, entry_subindex,
781 entry_bit_length);
782
783 for (sync_index = 0; sync_index < EC_MAX_SYNC_MANAGERS; sync_index++)
784 if ((pdo = ec_pdo_list_find_pdo(
785 &sc->sync_configs[sync_index].pdos, pdo_index)))
786 break;
787
788 if (pdo) {
789 down(&sc->master->master_sem);
790 entry = ec_pdo_add_entry(pdo, entry_index, entry_subindex,
791 entry_bit_length);
792 up(&sc->master->master_sem);
793 if (IS_ERR(entry))
794 retval = PTR_ERR(entry);
795 } else {
796 EC_CONFIG_ERR(sc, "PDO 0x%04X is not assigned.\n", pdo_index);
797 retval = -ENOENT;
798 }
799
800 return retval;
801}
802
803/****************************************************************************/
804
806 uint16_t pdo_index)
807{
808 uint8_t sync_index;
809 ec_pdo_t *pdo = NULL;
810
811 EC_CONFIG_DBG(sc, 1, "%s(sc = 0x%p, pdo_index = 0x%04X)\n",
812 __func__, sc, pdo_index);
813
814 for (sync_index = 0; sync_index < EC_MAX_SYNC_MANAGERS; sync_index++)
815 if ((pdo = ec_pdo_list_find_pdo(
816 &sc->sync_configs[sync_index].pdos, pdo_index)))
817 break;
818
819 if (pdo) {
820 down(&sc->master->master_sem);
822 up(&sc->master->master_sem);
823 } else {
824 EC_CONFIG_WARN(sc, "PDO 0x%04X is not assigned.\n", pdo_index);
825 }
826 return 0;
827}
828
829/****************************************************************************/
830
832 unsigned int n_syncs, const ec_sync_info_t syncs[])
833{
834 int ret;
835 unsigned int i, j, k;
836 const ec_sync_info_t *sync_info;
837 const ec_pdo_info_t *pdo_info;
838 const ec_pdo_entry_info_t *entry_info;
839
840 EC_CONFIG_DBG(sc, 1, "%s(sc = 0x%p, n_syncs = %u, syncs = 0x%p)\n",
841 __func__, sc, n_syncs, syncs);
842
843 if (!syncs)
844 return 0;
845
846 for (i = 0; i < n_syncs; i++) {
847 sync_info = &syncs[i];
848
849 if (sync_info->index == (uint8_t) EC_END)
850 break;
851
852 if (sync_info->index >= EC_MAX_SYNC_MANAGERS) {
853 EC_CONFIG_ERR(sc, "Invalid sync manager index %u!\n",
854 sync_info->index);
855 return -ENOENT;
856 }
857
858 ret = ecrt_slave_config_sync_manager(sc, sync_info->index,
859 sync_info->dir, sync_info->watchdog_mode);
860 if (ret)
861 return ret;
862
864
865 if (sync_info->n_pdos && sync_info->pdos) {
866
867 for (j = 0; j < sync_info->n_pdos; j++) {
868 pdo_info = &sync_info->pdos[j];
869
871 sc, sync_info->index, pdo_info->index);
872 if (ret)
873 return ret;
874
876
877 if (pdo_info->n_entries && pdo_info->entries) {
878 for (k = 0; k < pdo_info->n_entries; k++) {
879 entry_info = &pdo_info->entries[k];
880
882 pdo_info->index, entry_info->index,
883 entry_info->subindex,
884 entry_info->bit_length);
885 if (ret)
886 return ret;
887 }
888 }
889 }
890 }
891 }
892
893 return 0;
894}
895
896/****************************************************************************/
897
900 uint16_t index,
901 uint8_t subindex,
902 ec_domain_t *domain,
903 unsigned int *bit_position
904 )
905{
906 uint8_t sync_index;
907 const ec_sync_config_t *sync_config;
908 unsigned int bit_offset, bit_pos;
909 ec_pdo_t *pdo;
910 ec_pdo_entry_t *entry;
911 int sync_offset;
912
913 EC_CONFIG_DBG(sc, 1, "%s(sc = 0x%p, index = 0x%04X, "
914 "subindex = 0x%02X, domain = 0x%p, bit_position = 0x%p)\n",
915 __func__, sc, index, subindex, domain, bit_position);
916
917 for (sync_index = 0; sync_index < EC_MAX_SYNC_MANAGERS; sync_index++) {
918 sync_config = &sc->sync_configs[sync_index];
919 bit_offset = 0;
920
921 list_for_each_entry(pdo, &sync_config->pdos.list, list) {
922 list_for_each_entry(entry, &pdo->entries, list) {
923 if (entry->index != index || entry->subindex != subindex) {
924 bit_offset += entry->bit_length;
925 } else {
926 bit_pos = bit_offset % 8;
927 if (bit_position) {
928 *bit_position = bit_pos;
929 } else if (bit_pos) {
930 EC_CONFIG_ERR(sc, "PDO entry 0x%04X:%02X does"
931 " not byte-align.\n", index, subindex);
932 return -EFAULT;
933 }
934
935 sync_offset = ec_slave_config_prepare_fmmu(
936 sc, domain, sync_index, sync_config->dir);
937 if (sync_offset < 0)
938 return sync_offset;
939
940 return sync_offset + bit_offset / 8;
941 }
942 }
943 }
944 }
945
946 EC_CONFIG_ERR(sc, "PDO entry 0x%04X:%02X is not mapped.\n",
947 index, subindex);
948 return -ENOENT;
949}
950
951/****************************************************************************/
952
955 uint8_t sync_index,
956 unsigned int pdo_pos,
957 unsigned int entry_pos,
958 ec_domain_t *domain,
959 unsigned int *bit_position
960 )
961{
962 const ec_sync_config_t *sync_config;
963 unsigned int bit_offset, pp, ep;
964 ec_pdo_t *pdo;
965 ec_pdo_entry_t *entry;
966
967 EC_CONFIG_DBG(sc, 1, "%s(sc = 0x%p, sync_index = %u, pdo_pos = %u,"
968 " entry_pos = %u, domain = 0x%p, bit_position = 0x%p)\n",
969 __func__, sc, sync_index, pdo_pos, entry_pos,
970 domain, bit_position);
971
972 if (sync_index >= EC_MAX_SYNC_MANAGERS) {
973 EC_CONFIG_ERR(sc, "Invalid syncmanager position %u.\n", sync_index);
974 return -EINVAL;
975 }
976
977 sync_config = &sc->sync_configs[sync_index];
978 bit_offset = 0;
979 pp = 0;
980
981 list_for_each_entry(pdo, &sync_config->pdos.list, list) {
982 ep = 0;
983 list_for_each_entry(entry, &pdo->entries, list) {
984 if (pp != pdo_pos || ep != entry_pos) {
985 bit_offset += entry->bit_length;
986 } else {
987 unsigned int bit_pos = bit_offset % 8;
988 int sync_offset;
989
990 if (bit_position) {
991 *bit_position = bit_pos;
992 } else if (bit_pos) {
993 EC_CONFIG_ERR(sc, "PDO entry 0x%04X:%02X does"
994 " not byte-align.\n",
995 pdo->index, entry->subindex);
996 return -EFAULT;
997 }
998
999 sync_offset = ec_slave_config_prepare_fmmu(
1000 sc, domain, sync_index, sync_config->dir);
1001 if (sync_offset < 0)
1002 return sync_offset;
1003
1004 return sync_offset + bit_offset / 8;
1005 }
1006 ep++;
1007 }
1008 pp++;
1009 }
1010
1011 EC_CONFIG_ERR(sc, "PDO entry specification %u/%u/%u out of range.\n",
1012 sync_index, pdo_pos, entry_pos);
1013 return -ENOENT;
1014}
1015
1016/****************************************************************************/
1017
1018int ecrt_slave_config_dc(ec_slave_config_t *sc, uint16_t assign_activate,
1019 uint32_t sync0_cycle_time, int32_t sync0_shift_time,
1020 uint32_t sync1_cycle_time, int32_t sync1_shift_time)
1021{
1022 EC_CONFIG_DBG(sc, 1, "%s(sc = 0x%p, assign_activate = 0x%04X,"
1023 " sync0_cycle = %u, sync0_shift = %i,"
1024 " sync1_cycle = %u, sync1_shift = %i\n",
1025 __func__, sc, assign_activate, sync0_cycle_time, sync0_shift_time,
1026 sync1_cycle_time, sync1_shift_time);
1027
1028 sc->dc_assign_activate = assign_activate;
1029 sc->dc_sync[0].cycle_time = sync0_cycle_time;
1030 sc->dc_sync[0].shift_time = sync0_shift_time;
1031 sc->dc_sync[1].cycle_time = sync1_cycle_time;
1032 sc->dc_sync[1].shift_time = sync1_shift_time;
1033 return 0;
1034}
1035
1036/****************************************************************************/
1037
1039 uint8_t subindex, const uint8_t *data, size_t size)
1040{
1041 ec_slave_t *slave = sc->slave;
1042 ec_sdo_request_t *req;
1043 int ret;
1044
1045 EC_CONFIG_DBG(sc, 1, "%s(sc = 0x%p, index = 0x%04X, "
1046 "subindex = 0x%02X, data = 0x%p, size = %zu)\n",
1047 __func__, sc, index, subindex, data, size);
1048
1049 if (slave && !(slave->sii.mailbox_protocols & EC_MBOX_COE)) {
1050 EC_CONFIG_WARN(sc, "Attached slave does not support CoE!\n");
1051 }
1052
1053 if (!(req = (ec_sdo_request_t *)
1054 kmalloc(sizeof(ec_sdo_request_t), GFP_KERNEL))) {
1055 EC_CONFIG_ERR(sc, "Failed to allocate memory for"
1056 " SDO configuration!\n");
1057 return -ENOMEM;
1058 }
1059
1061 ecrt_sdo_request_index(req, index, subindex);
1062
1063 ret = ec_sdo_request_copy_data(req, data, size);
1064 if (ret < 0) {
1066 kfree(req);
1067 return ret;
1068 }
1069
1070 down(&sc->master->master_sem);
1071 list_add_tail(&req->list, &sc->sdo_configs);
1072 up(&sc->master->master_sem);
1073 return 0;
1074}
1075
1076/****************************************************************************/
1077
1079 uint8_t subindex, uint8_t value)
1080{
1081 uint8_t data[1];
1082
1083 EC_CONFIG_DBG(sc, 1, "%s(sc = 0x%p, index = 0x%04X, "
1084 "subindex = 0x%02X, value = %u)\n",
1085 __func__, sc, index, subindex, (unsigned int) value);
1086
1087 EC_WRITE_U8(data, value);
1088 return ecrt_slave_config_sdo(sc, index, subindex, data, 1);
1089}
1090
1091/****************************************************************************/
1092
1094 uint8_t subindex, uint16_t value)
1095{
1096 uint8_t data[2];
1097
1098 EC_CONFIG_DBG(sc, 1, "%s(sc = 0x%p, index = 0x%04X, "
1099 "subindex = 0x%02X, value = %u)\n",
1100 __func__, sc, index, subindex, value);
1101
1102 EC_WRITE_U16(data, value);
1103 return ecrt_slave_config_sdo(sc, index, subindex, data, 2);
1104}
1105
1106/****************************************************************************/
1107
1109 uint8_t subindex, uint32_t value)
1110{
1111 uint8_t data[4];
1112
1113 EC_CONFIG_DBG(sc, 1, "%s(sc = 0x%p, index = 0x%04X, "
1114 "subindex = 0x%02X, value = %u)\n",
1115 __func__, sc, index, subindex, value);
1116
1117 EC_WRITE_U32(data, value);
1118 return ecrt_slave_config_sdo(sc, index, subindex, data, 4);
1119}
1120
1121/****************************************************************************/
1122
1124 const uint8_t *data, size_t size)
1125{
1126 ec_slave_t *slave = sc->slave;
1127 ec_sdo_request_t *req;
1128 int ret;
1129
1130 EC_CONFIG_DBG(sc, 1, "%s(sc = 0x%p, index = 0x%04X, "
1131 "data = 0x%p, size = %zu)\n", __func__, sc, index, data, size);
1132
1133 if (slave && !(slave->sii.mailbox_protocols & EC_MBOX_COE)) {
1134 EC_CONFIG_WARN(sc, "Attached slave does not support CoE!\n");
1135 }
1136
1137 if (!(req = (ec_sdo_request_t *)
1138 kmalloc(sizeof(ec_sdo_request_t), GFP_KERNEL))) {
1139 EC_CONFIG_ERR(sc, "Failed to allocate memory for"
1140 " SDO configuration!\n");
1141 return -ENOMEM;
1142 }
1143
1145 ecrt_sdo_request_index(req, index, 0);
1146 req->complete_access = 1;
1147
1148 ret = ec_sdo_request_copy_data(req, data, size);
1149 if (ret < 0) {
1151 kfree(req);
1152 return ret;
1153 }
1154
1155 down(&sc->master->master_sem);
1156 list_add_tail(&req->list, &sc->sdo_configs);
1157 up(&sc->master->master_sem);
1158 return 0;
1159}
1160
1161/****************************************************************************/
1162
1164{
1165 return ec_coe_emerg_ring_size(&sc->emerg_ring, elements);
1166}
1167
1168/****************************************************************************/
1169
1171{
1172 return ec_coe_emerg_ring_pop(&sc->emerg_ring, target);
1173}
1174
1175/****************************************************************************/
1176
1181
1182/****************************************************************************/
1183
1188
1189/****************************************************************************/
1190
1195 ec_slave_config_t *sc, uint16_t index, uint8_t subindex, size_t size)
1196{
1197 ec_sdo_request_t *req;
1198 int ret;
1199
1200 EC_CONFIG_DBG(sc, 1, "%s(sc = 0x%p, "
1201 "index = 0x%04X, subindex = 0x%02X, size = %zu)\n",
1202 __func__, sc, index, subindex, size);
1203
1204 if (!(req = (ec_sdo_request_t *)
1205 kmalloc(sizeof(ec_sdo_request_t), GFP_KERNEL))) {
1206 EC_CONFIG_ERR(sc, "Failed to allocate SDO request memory!\n");
1207 return ERR_PTR(-ENOMEM);
1208 }
1209
1211 ecrt_sdo_request_index(req, index, subindex);
1212
1213 ret = ec_sdo_request_alloc(req, size);
1214 if (ret < 0) {
1216 kfree(req);
1217 return ERR_PTR(ret);
1218 }
1219
1220 // prepare data for optional writing
1221 memset(req->data, 0x00, size);
1222 req->data_size = size;
1223
1224 down(&sc->master->master_sem);
1225 list_add_tail(&req->list, &sc->sdo_requests);
1226 up(&sc->master->master_sem);
1227
1228 return req;
1229}
1230
1231/****************************************************************************/
1232
1234 ec_slave_config_t *sc, uint16_t index, uint8_t subindex, size_t size)
1235{
1237 subindex, size);
1238 return IS_ERR(s) ? NULL : s;
1239}
1240
1241/****************************************************************************/
1242
1247 ec_slave_config_t *sc, uint8_t drive_no, uint16_t idn, size_t size)
1248{
1249 ec_soe_request_t *req;
1250 int ret;
1251
1252 EC_CONFIG_DBG(sc, 1, "%s(sc = 0x%p, "
1253 "drive_no = 0x%02X, idn = 0x%04X, size = %zu)\n",
1254 __func__, sc, drive_no, idn, size);
1255
1256 if (!(req = (ec_soe_request_t *)
1257 kmalloc(sizeof(ec_soe_request_t), GFP_KERNEL))) {
1258 EC_CONFIG_ERR(sc, "Failed to allocate IDN request memory!\n");
1259 return ERR_PTR(-ENOMEM);
1260 }
1261
1263 ecrt_soe_request_idn(req, drive_no, idn);
1264
1265 ret = ec_soe_request_alloc(req, size);
1266 if (ret < 0) {
1268 kfree(req);
1269 return ERR_PTR(ret);
1270 }
1271
1272 // prepare data for optional writing
1273 memset(req->data, 0x00, size);
1274 req->data_size = size;
1275
1276 down(&sc->master->master_sem);
1277 list_add_tail(&req->list, &sc->soe_requests);
1278 up(&sc->master->master_sem);
1279
1280 return req;
1281}
1282
1283/****************************************************************************/
1284
1286 ec_slave_config_t *sc, uint8_t drive_no, uint16_t idn, size_t size)
1287{
1289 drive_no, idn, size);
1290 return IS_ERR(req) ? NULL : req;
1291}
1292
1293/****************************************************************************/
1294
1299 ec_slave_config_t *sc, size_t size)
1300{
1301 ec_reg_request_t *reg;
1302 int ret;
1303
1304 EC_CONFIG_DBG(sc, 1, "%s(sc = 0x%p, size = %zu)\n",
1305 __func__, sc, size);
1306
1307 if (!(reg = (ec_reg_request_t *)
1308 kmalloc(sizeof(ec_reg_request_t), GFP_KERNEL))) {
1309 EC_CONFIG_ERR(sc, "Failed to allocate register request memory!\n");
1310 return ERR_PTR(-ENOMEM);
1311 }
1312
1313 ret = ec_reg_request_init(reg, size);
1314 if (ret) {
1315 kfree(reg);
1316 return ERR_PTR(ret);
1317 }
1318
1319 down(&sc->master->master_sem);
1320 list_add_tail(&reg->list, &sc->reg_requests);
1321 up(&sc->master->master_sem);
1322
1323 return reg;
1324}
1325
1326/****************************************************************************/
1327
1329 ec_slave_config_t *sc, size_t size)
1330{
1331 ec_reg_request_t *reg =
1333 return IS_ERR(reg) ? NULL : reg;
1334}
1335
1336/****************************************************************************/
1337
1342 ec_slave_config_t *sc, size_t size)
1343{
1344 ec_voe_handler_t *voe;
1345 int ret;
1346
1347 EC_CONFIG_DBG(sc, 1, "%s(sc = 0x%p, size = %zu)\n", __func__, sc, size);
1348
1349 if (!(voe = (ec_voe_handler_t *)
1350 kmalloc(sizeof(ec_voe_handler_t), GFP_KERNEL))) {
1351 EC_CONFIG_ERR(sc, "Failed to allocate VoE request memory!\n");
1352 return ERR_PTR(-ENOMEM);
1353 }
1354
1355 ret = ec_voe_handler_init(voe, sc, size);
1356 if (ret < 0) {
1357 kfree(voe);
1358 return ERR_PTR(ret);
1359 }
1360
1361 down(&sc->master->master_sem);
1362 list_add_tail(&voe->list, &sc->voe_handlers);
1363 up(&sc->master->master_sem);
1364
1365 return voe;
1366}
1367
1368/****************************************************************************/
1369
1371 ec_slave_config_t *sc, size_t size)
1372{
1374 size);
1375 return IS_ERR(voe) ? NULL : voe;
1376}
1377
1378/****************************************************************************/
1379
1382{
1383 const ec_slave_t *slave = sc->slave;
1384
1385 state->online = slave ? 1 : 0;
1386 if (state->online) {
1387 state->operational =
1388 slave->current_state == EC_SLAVE_STATE_OP && !slave->force_config;
1389 state->al_state = slave->current_state;
1390 } else {
1391 state->operational = 0;
1393 }
1394 return 0;
1395}
1396
1397/****************************************************************************/
1398
1400 uint16_t idn, ec_al_state_t state, const uint8_t *data,
1401 size_t size)
1402{
1403 ec_slave_t *slave = sc->slave;
1404 ec_soe_request_t *req;
1405 int ret;
1406
1407 EC_CONFIG_DBG(sc, 1, "%s(sc = 0x%p, drive_no = %u, idn = 0x%04X, "
1408 "state = %u, data = 0x%p, size = %zu)\n",
1409 __func__, sc, drive_no, idn, state, data, size);
1410
1411 if (drive_no > 7) {
1412 EC_CONFIG_ERR(sc, "Invalid drive number %u!\n",
1413 (unsigned int) drive_no);
1414 return -EINVAL;
1415 }
1416
1417 if (state != EC_AL_STATE_PREOP && state != EC_AL_STATE_SAFEOP) {
1418 EC_CONFIG_ERR(sc, "AL state for IDN config"
1419 " must be PREOP or SAFEOP!\n");
1420 return -EINVAL;
1421 }
1422
1423 if (slave && !(slave->sii.mailbox_protocols & EC_MBOX_SOE)) {
1424 EC_CONFIG_WARN(sc, "Attached slave does not support SoE!\n");
1425 }
1426
1427 if (!(req = (ec_soe_request_t *)
1428 kmalloc(sizeof(ec_soe_request_t), GFP_KERNEL))) {
1429 EC_CONFIG_ERR(sc, "Failed to allocate memory for"
1430 " IDN configuration!\n");
1431 return -ENOMEM;
1432 }
1433
1435 ec_soe_request_set_drive_no(req, drive_no);
1436 ec_soe_request_set_idn(req, idn);
1437 req->al_state = state;
1438
1439 ret = ec_soe_request_copy_data(req, data, size);
1440 if (ret < 0) {
1442 kfree(req);
1443 return ret;
1444 }
1445
1446 down(&sc->master->master_sem);
1447 list_add_tail(&req->list, &sc->soe_configs);
1448 up(&sc->master->master_sem);
1449 return 0;
1450}
1451
1452/****************************************************************************/
1453
1455 int32_t value)
1456{
1457 ec_flag_t *flag;
1458
1459 EC_CONFIG_DBG(sc, 1, "%s(sc = 0x%p, key = %s, value = %i)\n",
1460 __func__, sc, key, value);
1461
1462
1463 flag = ec_slave_config_find_flag(sc, key);
1464 if (flag) {
1465 flag->value = value; // overwrite value
1466 }
1467 else { // new flag
1468 int ret;
1469
1470 if (!(flag = (ec_flag_t *) kmalloc(sizeof(ec_flag_t), GFP_KERNEL))) {
1471 EC_CONFIG_ERR(sc, "Failed to allocate memory for flag!\n");
1472 return -ENOMEM;
1473 }
1474
1475 ret = ec_flag_init(flag, key, value);
1476 if (ret) {
1477 kfree(flag);
1478 return ret;
1479 }
1480
1481 down(&sc->master->master_sem);
1482 list_add_tail(&flag->list, &sc->flags);
1483 up(&sc->master->master_sem);
1484 }
1485 return 0;
1486}
1487
1488/****************************************************************************/
1489
1490#ifdef EC_EOE
1491
1493 const unsigned char *mac_address)
1494{
1495 memcpy(sc->eoe_ip_param_request.mac_address, mac_address, EC_ETH_ALEN);
1496 sc->eoe_ip_param_request.mac_address_included = 1;
1497 return 0;
1498}
1499
1500/****************************************************************************/
1501
1503 struct in_addr ip_address)
1504{
1505 sc->eoe_ip_param_request.ip_address = ip_address;
1506 sc->eoe_ip_param_request.ip_address_included = 1;
1507 return 0;
1508}
1509
1510/****************************************************************************/
1511
1513 struct in_addr subnet_mask)
1514{
1515 sc->eoe_ip_param_request.subnet_mask = subnet_mask;
1516 sc->eoe_ip_param_request.subnet_mask_included = 1;
1517 return 0;
1518}
1519
1520/****************************************************************************/
1521
1523 struct in_addr gateway_address)
1524{
1525 sc->eoe_ip_param_request.gateway = gateway_address;
1526 sc->eoe_ip_param_request.gateway_included = 1;
1527 return 0;
1528}
1529
1530/****************************************************************************/
1531
1533 struct in_addr dns_address)
1534{
1535 sc->eoe_ip_param_request.dns = dns_address;
1536 sc->eoe_ip_param_request.dns_included = 1;
1537 return 0;
1538}
1539
1540/****************************************************************************/
1541
1543 const char *name)
1544{
1545 strncpy(sc->eoe_ip_param_request.name, name, EC_MAX_HOSTNAME_SIZE - 1);
1546 sc->eoe_ip_param_request.name_included = 1;
1547 return 0;
1548}
1549
1550#endif
1551
1552/****************************************************************************/
1553
1555 ec_al_state_t from, ec_al_state_t to, unsigned int timeout_ms)
1556{
1557 ec_al_timeout_t *timeout;
1558 ec_slave_state_t from_state, to_state;
1559
1560 if (from != EC_AL_STATE_INIT && from != EC_AL_STATE_PREOP &&
1561 from != EC_AL_STATE_SAFEOP && from != EC_AL_STATE_OP) {
1562 EC_CONFIG_ERR(sc, "Invalid from state %i.\n", from);
1563 return -EINVAL;
1564 }
1565 if (to != EC_AL_STATE_INIT && to != EC_AL_STATE_PREOP &&
1566 to != EC_AL_STATE_SAFEOP && to != EC_AL_STATE_OP) {
1567 EC_CONFIG_ERR(sc, "Invalid to state %i.\n", to);
1568 return -EINVAL;
1569 }
1570
1571 from_state = (ec_slave_state_t) from;
1572 to_state = (ec_slave_state_t) to;
1573
1574 /* try to find an already configured timeout. */
1575 list_for_each_entry(timeout, &sc->al_timeouts, list) {
1576 if (timeout->from == from_state && timeout->to == to_state) {
1577 if (timeout_ms == 0) {
1578 // delete configured value
1579 list_del(&timeout->list);
1580 kfree(timeout);
1581 return 0;
1582 }
1583 timeout->timeout_ms = timeout_ms;
1584 return 0;
1585 }
1586 }
1587
1588 if (timeout_ms == 0) {
1589 return 0;
1590 }
1591
1592 /* no timeout found. create one. */
1593 if (!(timeout = (ec_al_timeout_t *)
1594 kmalloc(sizeof(ec_al_timeout_t), GFP_KERNEL))) {
1595 EC_CONFIG_ERR(sc, "Failed to allocate memory for"
1596 " AL timeout configuration!\n");
1597 return -ENOMEM;
1598 }
1599
1600 timeout->from = from_state;
1601 timeout->to = to_state;
1602 timeout->timeout_ms = timeout_ms;
1603
1604 down(&sc->master->master_sem);
1605 list_add_tail(&timeout->list, &sc->al_timeouts);
1606 up(&sc->master->master_sem);
1607 return 0;
1608}
1609
1610/****************************************************************************/
1611
1613
1614EXPORT_SYMBOL(ecrt_slave_config_sync_manager);
1615EXPORT_SYMBOL(ecrt_slave_config_watchdog);
1620EXPORT_SYMBOL(ecrt_slave_config_pdos);
1621EXPORT_SYMBOL(ecrt_slave_config_reg_pdo_entry);
1623EXPORT_SYMBOL(ecrt_slave_config_dc);
1624EXPORT_SYMBOL(ecrt_slave_config_sdo);
1625EXPORT_SYMBOL(ecrt_slave_config_sdo8);
1626EXPORT_SYMBOL(ecrt_slave_config_sdo16);
1627EXPORT_SYMBOL(ecrt_slave_config_sdo32);
1628EXPORT_SYMBOL(ecrt_slave_config_complete_sdo);
1629EXPORT_SYMBOL(ecrt_slave_config_emerg_size);
1630EXPORT_SYMBOL(ecrt_slave_config_emerg_pop);
1631EXPORT_SYMBOL(ecrt_slave_config_emerg_clear);
1637EXPORT_SYMBOL(ecrt_slave_config_state);
1638EXPORT_SYMBOL(ecrt_slave_config_idn);
1639EXPORT_SYMBOL(ecrt_slave_config_flag);
1640#ifdef EOE
1646EXPORT_SYMBOL(ecrt_slave_config_eoe_hostname);
1647#endif
1648EXPORT_SYMBOL(ecrt_slave_config_state_timeout);
1649
1651
1652/****************************************************************************/
int ec_coe_emerg_ring_overruns(const ec_coe_emerg_ring_t *ring)
Read the number of overruns.
void ec_coe_emerg_ring_init(ec_coe_emerg_ring_t *ring, ec_slave_config_t *sc)
Emergency ring buffer constructor.
int ec_coe_emerg_ring_pop(ec_coe_emerg_ring_t *ring, u8 *msg)
Remove an emergency message from the ring.
int ec_coe_emerg_ring_clear_ring(ec_coe_emerg_ring_t *ring)
Clear the ring.
int ec_coe_emerg_ring_size(ec_coe_emerg_ring_t *ring, size_t size)
Set the ring size.
void ec_coe_emerg_ring_clear(ec_coe_emerg_ring_t *ring)
Emergency ring buffer destructor.
void ec_eoe_request_init(ec_eoe_request_t *req)
EoE request constructor.
Definition eoe_request.c:38
EtherCAT EoE request structure.
int ec_flag_init(ec_flag_t *flag, const char *key, int32_t value)
SDO request constructor.
Definition flag.c:36
void ec_flag_clear(ec_flag_t *flag)
SDO request destructor.
Definition flag.c:59
EtherCAT Slave Configuration Feature Flag.
void ec_fmmu_config_init(ec_fmmu_config_t *fmmu, ec_slave_config_t *sc, ec_domain_t *domain, uint8_t sync_index, ec_direction_t dir)
FMMU configuration constructor.
Definition fmmu_config.c:42
Global definitions and macros.
ec_slave_state_t
State of an EtherCAT slave.
Definition globals.h:121
@ EC_SLAVE_STATE_OP
OP (mailbox communication and input/output update)
Definition globals.h:132
@ EC_SLAVE_STATE_UNKNOWN
unknown state
Definition globals.h:122
@ EC_MBOX_COE
CANopen over EtherCAT.
Definition globals.h:146
@ EC_MBOX_SOE
Servo-Profile over EtherCAT.
Definition globals.h:148
#define EC_MAX_FMMUS
Maximum number of FMMUs per slave.
Definition globals.h:92
struct ec_slave ec_slave_t
Definition globals.h:310
#define EC_MAX_HOSTNAME_SIZE
Maximum hostname size.
Definition globals.h:110
int ecrt_slave_config_pdos(ec_slave_config_t *sc, unsigned int n_syncs, const ec_sync_info_t syncs[])
Specify a complete PDO configuration.
struct ec_soe_request ec_soe_request_t
Definition ecrt.h:312
int ecrt_slave_config_emerg_clear(ec_slave_config_t *sc)
Clears CoE emergency ring buffer and the overrun counter.
int ecrt_slave_config_sync_manager(ec_slave_config_t *sc, uint8_t sync_index, ec_direction_t dir, ec_watchdog_mode_t watchdog_mode)
Configure a sync manager.
int ecrt_soe_request_idn(ec_soe_request_t *req, uint8_t drive_no, uint16_t idn)
Set the request's drive and Sercos ID numbers.
ec_al_state_t
Application-layer state.
Definition ecrt.h:615
ec_sdo_request_t * ecrt_slave_config_create_sdo_request(ec_slave_config_t *sc, uint16_t index, uint8_t subindex, size_t size)
Create an SDO request to exchange SDOs during realtime operation.
int ecrt_slave_config_reg_pdo_entry_pos(ec_slave_config_t *sc, uint8_t sync_index, unsigned int pdo_pos, unsigned int entry_pos, ec_domain_t *domain, unsigned int *bit_position)
Registers a PDO entry using its position.
int ecrt_slave_config_watchdog(ec_slave_config_t *sc, uint16_t divider, uint16_t intervals)
Configure a slave's watchdog times.
ec_soe_request_t * ecrt_slave_config_create_soe_request(ec_slave_config_t *sc, uint8_t drive_no, uint16_t idn, size_t size)
Create an SoE request to exchange SoE IDNs during realtime operation.
int ecrt_slave_config_idn(ec_slave_config_t *sc, uint8_t drive_no, uint16_t idn, ec_al_state_t state, const uint8_t *data, size_t size)
Add an SoE IDN configuration.
int ecrt_slave_config_eoe_subnet_mask(ec_slave_config_t *sc, struct in_addr subnet_mask)
Sets the subnet mask for Ethernet-over-EtherCAT (EoE) operation.
int ecrt_slave_config_sdo32(ec_slave_config_t *sc, uint16_t index, uint8_t subindex, uint32_t value)
Add a configuration value for a 32-bit SDO.
int ecrt_slave_config_emerg_overruns(const ec_slave_config_t *sc)
Read the number of CoE emergency overruns.
#define EC_WRITE_U8(DATA, VAL)
Write an 8-bit unsigned value to EtherCAT data.
Definition ecrt.h:3040
struct ec_voe_handler ec_voe_handler_t
Definition ecrt.h:315
int ecrt_slave_config_state(const ec_slave_config_t *sc, ec_slave_config_state_t *state)
Outputs the state of the slave configuration.
ec_voe_handler_t * ecrt_slave_config_create_voe_handler(ec_slave_config_t *sc, size_t size)
Create an VoE handler to exchange vendor-specific data during realtime operation.
int ecrt_slave_config_pdo_assign_clear(ec_slave_config_t *sc, uint8_t sync_index)
Clear a sync manager's PDO assignment.
struct ec_sdo_request ec_sdo_request_t
Definition ecrt.h:309
int ecrt_slave_config_dc(ec_slave_config_t *sc, uint16_t assign_activate, uint32_t sync0_cycle_time, int32_t sync0_shift_time, uint32_t sync1_cycle_time, int32_t sync1_shift_time)
Configure distributed clocks.
int ecrt_slave_config_flag(ec_slave_config_t *sc, const char *key, int32_t value)
Adds a feature flag to a slave configuration.
struct ec_master ec_master_t
Definition ecrt.h:300
int ecrt_slave_config_eoe_default_gateway(ec_slave_config_t *sc, struct in_addr gateway_address)
Sets the gateway address for Ethernet-over-EtherCAT (EoE) operation.
int ecrt_slave_config_pdo_mapping_add(ec_slave_config_t *sc, uint16_t pdo_index, uint16_t entry_index, uint8_t entry_subindex, uint8_t entry_bit_length)
Add a PDO entry to the given PDO's mapping.
ec_direction_t
Direction type for PDO assignment functions.
Definition ecrt.h:504
int ecrt_slave_config_sdo(ec_slave_config_t *sc, uint16_t index, uint8_t subindex, const uint8_t *data, size_t size)
Add an SDO configuration.
struct ec_domain ec_domain_t
Definition ecrt.h:306
struct ec_slave_config ec_slave_config_t
Definition ecrt.h:303
struct ec_reg_request ec_reg_request_t
Definition ecrt.h:318
int ecrt_slave_config_reg_pdo_entry(ec_slave_config_t *sc, uint16_t index, uint8_t subindex, ec_domain_t *domain, unsigned int *bit_position)
Registers a PDO entry for process data exchange in a domain.
#define EC_WRITE_U32(DATA, VAL)
Write a 32-bit unsigned value to EtherCAT data.
Definition ecrt.h:3074
int ecrt_slave_config_eoe_mac_address(ec_slave_config_t *sc, const unsigned char *mac_address)
Sets the link/MAC address for Ethernet-over-EtherCAT (EoE) operation.
int ecrt_slave_config_complete_sdo(ec_slave_config_t *sc, uint16_t index, const uint8_t *data, size_t size)
Add configuration data for a complete SDO.
ec_watchdog_mode_t
Watchdog mode for sync manager configuration.
Definition ecrt.h:517
int ecrt_slave_config_eoe_ip_address(ec_slave_config_t *sc, struct in_addr ip_address)
Sets the IP address for Ethernet-over-EtherCAT (EoE) operation.
int ecrt_slave_config_eoe_dns_address(ec_slave_config_t *sc, struct in_addr dns_address)
Sets the IPv4 address of the DNS server for Ethernet-over-EtherCAT (EoE) operation.
int ecrt_slave_config_eoe_hostname(ec_slave_config_t *sc, const char *name)
Sets the host name for Ethernet-over-EtherCAT (EoE) operation.
#define EC_END
End of list marker.
Definition ecrt.h:263
int ecrt_slave_config_pdo_mapping_clear(ec_slave_config_t *sc, uint16_t pdo_index)
Clear the mapping of a given PDO.
int ecrt_slave_config_sdo8(ec_slave_config_t *sc, uint16_t index, uint8_t subindex, uint8_t value)
Add a configuration value for an 8-bit SDO.
#define EC_MAX_SYNC_MANAGERS
Maximum number of sync managers per slave.
Definition ecrt.h:267
ec_reg_request_t * ecrt_slave_config_create_reg_request(ec_slave_config_t *sc, size_t size)
Create a register request to exchange EtherCAT register contents during realtime operation.
int ecrt_slave_config_sdo16(ec_slave_config_t *sc, uint16_t index, uint8_t subindex, uint16_t value)
Add a configuration value for a 16-bit SDO.
#define EC_WRITE_U16(DATA, VAL)
Write a 16-bit unsigned value to EtherCAT data.
Definition ecrt.h:3057
int ecrt_slave_config_pdo_assign_add(ec_slave_config_t *sc, uint8_t sync_index, uint16_t pdo_index)
Add a PDO to a sync manager's PDO assignment.
int ecrt_sdo_request_index(ec_sdo_request_t *req, uint16_t index, uint8_t subindex)
Set the SDO index and subindex.
int ecrt_slave_config_state_timeout(ec_slave_config_t *sc, ec_al_state_t from, ec_al_state_t to, unsigned int timeout_ms)
Sets the application-layer state transition timeout in ms.
int ecrt_slave_config_emerg_pop(ec_slave_config_t *sc, uint8_t *target)
Read and remove one record from the CoE emergency ring buffer.
int ecrt_slave_config_emerg_size(ec_slave_config_t *sc, size_t elements)
Set the size of the CoE emergency ring buffer.
@ EC_AL_STATE_INIT
Init.
Definition ecrt.h:616
@ EC_AL_STATE_OP
Operational.
Definition ecrt.h:619
@ EC_AL_STATE_PREOP
Pre-operational.
Definition ecrt.h:617
@ EC_AL_STATE_SAFEOP
Safe-operational.
Definition ecrt.h:618
@ EC_DIR_INVALID
Invalid direction.
Definition ecrt.h:505
@ EC_DIR_INPUT
Values read by the master.
Definition ecrt.h:507
@ EC_DIR_OUTPUT
Values written by the master.
Definition ecrt.h:506
EtherCAT master character device IOCTL commands.
ec_slave_t * ec_master_find_slave(ec_master_t *master, uint16_t alias, uint16_t position)
Finds a slave in the bus, given the alias and position.
Definition master.c:1842
EtherCAT master structure.
int ec_pdo_copy_entries(ec_pdo_t *pdo, const ec_pdo_t *other)
Copy PDO entries from another PDO.
Definition pdo.c:178
void ec_pdo_clear_entries(ec_pdo_t *pdo)
Clear PDO entry list.
Definition pdo.c:98
ec_pdo_entry_t * ec_pdo_add_entry(ec_pdo_t *pdo, uint16_t index, uint8_t subindex, uint8_t bit_length)
Add a new PDO entry to the configuration.
Definition pdo.c:149
int ec_pdo_set_name(ec_pdo_t *pdo, const char *name)
Set PDO name.
Definition pdo.c:117
ec_pdo_t * ec_pdo_list_add_pdo(ec_pdo_list_t *pl, uint16_t index)
Add a new PDO to the list.
Definition pdo_list.c:109
ec_pdo_t * ec_pdo_list_find_pdo(const ec_pdo_list_t *pl, uint16_t index)
Finds a PDO with the given index.
Definition pdo_list.c:235
int ec_pdo_list_copy(ec_pdo_list_t *pl, const ec_pdo_list_t *other)
Makes a deep copy of another PDO list.
Definition pdo_list.c:169
void ec_pdo_list_clear_pdos(ec_pdo_list_t *pl)
Clears the list of mapped PDOs.
Definition pdo_list.c:62
void ec_reg_request_clear(ec_reg_request_t *reg)
Register request destructor.
Definition reg_request.c:65
int ec_reg_request_init(ec_reg_request_t *reg, size_t size)
Register request constructor.
Definition reg_request.c:40
void ec_sdo_request_init(ec_sdo_request_t *req)
SDO request constructor.
Definition sdo_request.c:48
int ec_sdo_request_alloc(ec_sdo_request_t *req, size_t size)
Pre-allocates the data memory.
void ec_sdo_request_clear(ec_sdo_request_t *req)
SDO request destructor.
Definition sdo_request.c:70
int ec_sdo_request_copy_data(ec_sdo_request_t *req, const uint8_t *source, size_t size)
Copies SDO data from an external source.
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
#define EC_SLAVE_WARN(slave, fmt, args...)
Convenience macro for printing slave-specific warnings to syslog.
Definition slave.h:82
ec_voe_handler_t * ec_slave_config_find_voe_handler(ec_slave_config_t *sc, unsigned int pos)
Finds a VoE handler via its position in the list.
ec_sdo_request_t * ecrt_slave_config_create_sdo_request_err(ec_slave_config_t *sc, uint16_t index, uint8_t subindex, size_t size)
Same as ecrt_slave_config_create_sdo_request(), but with ERR_PTR() return value.
ec_soe_request_t * ec_slave_config_find_soe_request(ec_slave_config_t *sc, unsigned int pos)
Finds a SoE request via its position in the list.
void ec_slave_config_load_default_sync_config(ec_slave_config_t *sc)
Loads the default PDO assignment from the slave object.
const ec_sdo_request_t * ec_slave_config_get_sdo_by_pos_const(const ec_slave_config_t *sc, unsigned int pos)
Finds an SDO configuration via its position in the list.
ec_voe_handler_t * ecrt_slave_config_create_voe_handler_err(ec_slave_config_t *sc, size_t size)
Same as ecrt_slave_config_create_voe_handler(), but with ERR_PTR() return value.
int ec_slave_config_prepare_fmmu(ec_slave_config_t *, ec_domain_t *, uint8_t, ec_direction_t)
Prepares an FMMU configuration.
void ec_slave_config_clear(ec_slave_config_t *sc)
Slave configuration destructor.
unsigned int ec_slave_config_idn_count(const ec_slave_config_t *sc)
Get the number of IDN configurations.
const ec_flag_t * ec_slave_config_get_flag_by_pos_const(const ec_slave_config_t *sc, unsigned int pos)
Finds a flag via its position in the list.
void ec_slave_config_init(ec_slave_config_t *sc, ec_master_t *master, uint16_t alias, uint16_t position, uint32_t vendor_id, uint32_t product_code)
Slave configuration constructor.
ec_reg_request_t * ec_slave_config_find_reg_request(ec_slave_config_t *sc, unsigned int pos)
Finds a register handler via its position in the list.
ec_soe_request_t * ecrt_slave_config_create_soe_request_err(ec_slave_config_t *sc, uint8_t drive_no, uint16_t idn, size_t size)
Same as ecrt_slave_config_create_soe_request(), but with ERR_PTR() return value.
ec_sdo_request_t * ec_slave_config_find_sdo_request(ec_slave_config_t *sc, unsigned int pos)
Finds a CoE SDO request via its position in the list.
void ec_slave_config_load_default_mapping(const ec_slave_config_t *, ec_pdo_t *)
Loads the default mapping for a PDO from the slave object.
int ec_slave_config_attach(ec_slave_config_t *sc)
Attaches the configuration to the addressed slave object.
unsigned int ec_slave_config_sdo_count(const ec_slave_config_t *sc)
Get the number of SDO configurations.
ec_flag_t * ec_slave_config_find_flag(ec_slave_config_t *sc, const char *key)
Finds a flag.
unsigned int ec_slave_config_flag_count(const ec_slave_config_t *sc)
Get the number of feature flags.
unsigned int ec_slave_config_al_timeout(const ec_slave_config_t *sc, ec_slave_state_t from, ec_slave_state_t to)
Return an AL state timeout.
const ec_soe_request_t * ec_slave_config_get_idn_by_pos_const(const ec_slave_config_t *sc, unsigned int pos)
Finds an IDN configuration via its position in the list.
void ec_slave_config_detach(ec_slave_config_t *sc)
Detaches the configuration from a slave object.
ec_reg_request_t * ecrt_slave_config_create_reg_request_err(ec_slave_config_t *sc, size_t size)
Same as ecrt_slave_config_create_reg_request(), but with ERR_PTR() return value.
EtherCAT slave configuration structure.
#define EC_CONFIG_ERR(sc, fmt, args...)
Convenience macro for printing configuration-specific errors to syslog.
#define EC_CONFIG_WARN(sc, fmt, args...)
Convenience macro for printing configuration-specific warnings to syslog.
#define EC_CONFIG_DBG(sc, level, fmt, args...)
Convenience macro for printing configuration-specific debug messages to syslog.
void ec_soe_request_set_idn(ec_soe_request_t *req, uint16_t idn)
Set IDN.
void ec_soe_request_set_drive_no(ec_soe_request_t *req, uint8_t drive_no)
Set drive number.
Definition soe_request.c:99
int ec_soe_request_copy_data(ec_soe_request_t *req, const uint8_t *source, size_t size)
Copies SoE data from an external source.
void ec_soe_request_init(ec_soe_request_t *req)
SoE request constructor.
Definition soe_request.c:48
int ec_soe_request_alloc(ec_soe_request_t *req, size_t size)
Pre-allocates the data memory.
void ec_soe_request_clear(ec_soe_request_t *req)
SoE request destructor.
Definition soe_request.c:71
EtherCAT application-layer transition timeout.
Slave configutation feature flag.
Definition flag.h:38
char * key
Flag key (null-terminated ASCII string.
Definition flag.h:40
struct list_head list
List item.
Definition flag.h:39
int32_t value
Flag value (meaning depends on key).
Definition flag.h:41
FMMU configuration.
Definition fmmu_config.h:38
uint32_t logical_start_address
Logical start address.
Definition fmmu_config.h:44
const ec_domain_t * domain
Domain.
Definition fmmu_config.h:41
uint8_t sync_index
Index of sync manager to use.
Definition fmmu_config.h:42
ec_reg_request_t * reg_request
Register request to process.
Definition fsm_slave.h:59
struct semaphore master_sem
Master semaphore.
Definition master.h:198
unsigned int debug_level
Master debug level.
Definition master.h:275
PDO entry configuration information.
Definition ecrt.h:531
uint8_t subindex
PDO entry subindex.
Definition ecrt.h:533
uint8_t bit_length
Size of the PDO entry in bit.
Definition ecrt.h:534
uint16_t index
PDO entry index.
Definition ecrt.h:532
PDO entry description.
Definition pdo_entry.h:40
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
PDO configuration information.
Definition ecrt.h:545
unsigned int n_entries
Number of PDO entries in entries to map.
Definition ecrt.h:547
uint16_t index
PDO index.
Definition ecrt.h:546
ec_pdo_entry_info_t const * entries
Array of PDO entries to map.
Definition ecrt.h:551
struct list_head list
List of PDOs.
Definition pdo_list.h:42
PDO description.
Definition pdo.h:41
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
char * name
PDO name.
Definition pdo.h:45
struct list_head list
List item.
Definition reg_request.h:41
struct list_head list
List item.
Definition sdo_request.h:41
uint8_t complete_access
SDO shall be transferred completely.
Definition sdo_request.h:47
size_t data_size
Size of SDO data.
Definition sdo_request.h:46
uint8_t * data
Pointer to SDO data.
Definition sdo_request.h:44
ec_sync_t * syncs
SYNC MANAGER categories.
Definition slave.h:157
uint32_t product_code
Vendor-specific product code.
Definition slave.h:128
uint16_t mailbox_protocols
Supported mailbox protocols.
Definition slave.h:139
uint32_t vendor_id
Vendor ID.
Definition slave.h:127
unsigned int sync_count
Number of sync managers.
Definition slave.h:158
Slave configuration state.
Definition ecrt.h:376
unsigned int online
The slave is online.
Definition ecrt.h:377
unsigned int operational
The slave was brought into OP state using the specified configuration.
Definition ecrt.h:378
unsigned int al_state
The application-layer state of the slave.
Definition ecrt.h:380
uint32_t product_code
Slave product code.
ec_sync_config_t sync_configs[EC_MAX_SYNC_MANAGERS]
Sync manager configurations.
struct list_head flags
List of feature flags.
struct list_head reg_requests
List of register requests.
uint16_t dc_assign_activate
Vendor-specific AssignActivate word.
struct list_head sdo_requests
List of SDO requests.
uint16_t watchdog_intervals
Process data watchdog intervals (see spec.
uint16_t alias
Slave alias.
ec_fmmu_config_t fmmu_configs[EC_MAX_FMMUS]
FMMU configurations.
ec_coe_emerg_ring_t emerg_ring
CoE emergency ring buffer.
ec_sync_signal_t dc_sync[EC_SYNC_SIGNAL_COUNT]
DC sync signals.
struct list_head soe_requests
List of SoE requests.
struct list_head soe_configs
List of SoE configurations.
struct list_head sdo_configs
List of SDO configurations.
uint16_t watchdog_divider
Watchdog divider as a number of 40ns intervals (see spec.
uint8_t used_fmmus
Number of FMMUs used.
ec_master_t * master
Master owning the slave configuration.
ec_slave_t * slave
Slave pointer.
struct list_head al_timeouts
List of specific AL state timeouts.
uint32_t vendor_id
Slave vendor ID.
uint16_t position
Index after alias.
ec_eoe_request_t eoe_ip_param_request
EoE IP parameters.
struct list_head voe_handlers
List of VoE handlers.
ec_sii_t sii
Extracted SII data.
Definition slave.h:215
unsigned int force_config
Force (re-)configuration.
Definition slave.h:186
uint16_t ring_position
Ring position.
Definition slave.h:175
ec_slave_config_t * config
Current configuration.
Definition slave.h:182
ec_slave_state_t current_state
Current application state.
Definition slave.h:184
ec_fsm_slave_t fsm
Slave state machine.
Definition slave.h:227
ec_al_state_t al_state
AL state (only valid for IDN config).
Definition soe_request.h:44
size_t data_size
Size of SDO data.
Definition soe_request.h:47
uint8_t * data
Pointer to SDO data.
Definition soe_request.h:45
struct list_head list
List item.
Definition soe_request.h:41
Sync manager configuration.
Definition sync_config.h:38
ec_direction_t dir
Sync manager direction.
Definition sync_config.h:39
ec_watchdog_mode_t watchdog_mode
Watchdog mode.
Definition sync_config.h:40
ec_pdo_list_t pdos
Current PDO assignment.
Definition sync_config.h:41
Sync manager configuration information.
Definition ecrt.h:564
unsigned int n_pdos
Number of PDOs in pdos.
Definition ecrt.h:569
ec_direction_t dir
Sync manager direction.
Definition ecrt.h:568
uint8_t index
Sync manager index.
Definition ecrt.h:565
ec_pdo_info_t const * pdos
Array with PDOs to assign.
Definition ecrt.h:570
ec_watchdog_mode_t watchdog_mode
Watchdog mode.
Definition ecrt.h:572
uint32_t cycle_time
Cycle time [ns].
Definition globals.h:181
int32_t shift_time
Shift time [ns].
Definition globals.h:182
Sync manager.
Definition sync.h:39
ec_pdo_list_t pdos
Current PDO assignment.
Definition sync.h:45
struct list_head list
List item.
Definition voe_handler.h:42
ec_direction_t ec_sync_default_direction(const ec_sync_t *sync)
Determines the default direction from the control register.
Definition sync.c:159
void ec_sync_config_clear(ec_sync_config_t *sync_config)
Destructor.
Definition sync_config.c:48
void ec_sync_config_init(ec_sync_config_t *sync_config)
Constructor.
Definition sync_config.c:35
void ec_voe_handler_clear(ec_voe_handler_t *voe)
VoE handler destructor.
Definition voe_handler.c:87
int ec_voe_handler_init(ec_voe_handler_t *voe, ec_slave_config_t *sc, size_t size)
VoE handler constructor.
Definition voe_handler.c:64
Vendor specific over EtherCAT protocol handler.