IgH EtherCAT Master  1.5.2
fsm_master.c
Go to the documentation of this file.
1/******************************************************************************
2 *
3 * $Id$
4 *
5 * Copyright (C) 2006-2012 Florian Pose, Ingenieurgemeinschaft IgH
6 *
7 * This file is part of the IgH EtherCAT Master.
8 *
9 * The IgH EtherCAT Master is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License version 2, as
11 * published by the Free Software Foundation.
12 *
13 * The IgH EtherCAT Master is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
16 * Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License along
19 * with the IgH EtherCAT Master; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
21 *
22 * ---
23 *
24 * The license mentioned above concerns the source code only. Using the
25 * EtherCAT technology and brand is only permitted in compliance with the
26 * industrial property and similar rights of Beckhoff Automation GmbH.
27 *
28 *****************************************************************************/
29
34/*****************************************************************************/
35
36#include "globals.h"
37#include "master.h"
38#include "mailbox.h"
39#include "slave_config.h"
40#ifdef EC_EOE
41#include "ethernet.h"
42#endif
43
44#include "fsm_master.h"
45#include "fsm_foe.h"
46
47/*****************************************************************************/
48
51#define EC_SYSTEM_TIME_TOLERANCE_NS 1000000
52
53/*****************************************************************************/
54
69
72
73/*****************************************************************************/
74
78 ec_fsm_master_t *fsm,
79 ec_master_t *master,
80 ec_datagram_t *datagram
81 )
82{
83 fsm->master = master;
84 fsm->datagram = datagram;
85
87
88 // init sub-state-machines
91 ec_fsm_pdo_init(&fsm->fsm_pdo, &fsm->fsm_coe);
94 &fsm->fsm_change, &fsm->fsm_coe, &fsm->fsm_soe, &fsm->fsm_pdo);
96 &fsm->fsm_slave_config, &fsm->fsm_pdo);
97 ec_fsm_sii_init(&fsm->fsm_sii, fsm->datagram);
98}
99
100/*****************************************************************************/
101
105 ec_fsm_master_t *fsm
106 )
107{
108 // clear sub-state machines
116}
117
118/*****************************************************************************/
119
123 ec_fsm_master_t *fsm
124 )
125{
126 ec_device_index_t dev_idx;
127
129 fsm->idle = 0;
130 fsm->dev_idx = EC_DEVICE_MAIN;
131
132 for (dev_idx = EC_DEVICE_MAIN;
133 dev_idx < ec_master_num_devices(fsm->master); dev_idx++) {
134 fsm->link_state[dev_idx] = 0;
135 fsm->slaves_responding[dev_idx] = 0;
136 fsm->slave_states[dev_idx] = EC_SLAVE_STATE_UNKNOWN;
137 }
138
139 fsm->rescan_required = 0;
140}
141
142/*****************************************************************************/
143
152 ec_fsm_master_t *fsm
153 )
154{
155 if (fsm->datagram->state == EC_DATAGRAM_SENT
156 || fsm->datagram->state == EC_DATAGRAM_QUEUED) {
157 // datagram was not sent or received yet.
158 return 0;
159 }
160
161 fsm->state(fsm);
162 return 1;
163}
164
165/*****************************************************************************/
166
171 const ec_fsm_master_t *fsm
172 )
173{
174 return fsm->idle;
175}
176
177/*****************************************************************************/
178
182 ec_fsm_master_t *fsm
183 )
184{
185 fsm->dev_idx = EC_DEVICE_MAIN;
187 fsm->state(fsm); // execute immediately
188}
189
190/******************************************************************************
191 * Master state machine
192 *****************************************************************************/
193
199 ec_fsm_master_t *fsm
200 )
201{
202 ec_master_t *master = fsm->master;
203
204 fsm->idle = 1;
205
206 // check for emergency requests
207 if (!list_empty(&master->emerg_reg_requests)) {
208 ec_reg_request_t *request;
209
210 // get first request
211 request = list_entry(master->emerg_reg_requests.next,
212 ec_reg_request_t, list);
213 list_del_init(&request->list); // dequeue
214 request->state = EC_INT_REQUEST_BUSY;
215
216 if (request->transfer_size > fsm->datagram->mem_size) {
217 EC_MASTER_ERR(master, "Emergency request data too large!\n");
218 request->state = EC_INT_REQUEST_FAILURE;
219 wake_up_all(&master->request_queue);
220 fsm->state(fsm); // continue
221 return;
222 }
223
224 if (request->dir != EC_DIR_OUTPUT) {
225 EC_MASTER_ERR(master, "Emergency requests must be"
226 " write requests!\n");
227 request->state = EC_INT_REQUEST_FAILURE;
228 wake_up_all(&master->request_queue);
229 fsm->state(fsm); // continue
230 return;
231 }
232
233 EC_MASTER_DBG(master, 1, "Writing emergency register request...\n");
235 request->address, request->transfer_size);
236 memcpy(fsm->datagram->data, request->data, request->transfer_size);
238 request->state = EC_INT_REQUEST_SUCCESS;
239 wake_up_all(&master->request_queue);
240 return;
241 }
242
243 ec_datagram_brd(fsm->datagram, 0x0130, 2);
245 fsm->datagram->device_index = fsm->dev_idx;
246 fsm->retries = EC_FSM_RETRIES;
248}
249
250/*****************************************************************************/
251
257 ec_fsm_master_t *fsm
258 )
259{
260 ec_datagram_t *datagram = fsm->datagram;
261 unsigned int i, size;
262 ec_slave_t *slave;
263 ec_master_t *master = fsm->master;
264
265 if (datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--) {
266 return;
267 }
268
269 // bus topology change?
270 if (datagram->working_counter != fsm->slaves_responding[fsm->dev_idx]) {
271 fsm->rescan_required = 1;
272 fsm->slaves_responding[fsm->dev_idx] = datagram->working_counter;
273 EC_MASTER_INFO(master, "%u slave(s) responding on %s device.\n",
274 fsm->slaves_responding[fsm->dev_idx],
275 ec_device_names[fsm->dev_idx != 0]);
276 }
277
278 if (fsm->link_state[fsm->dev_idx] &&
279 !master->devices[fsm->dev_idx].link_state) {
280 ec_device_index_t dev_idx;
281
282 EC_MASTER_DBG(master, 1, "Master state machine detected "
283 "link down on %s device. Clearing slave list.\n",
284 ec_device_names[fsm->dev_idx != 0]);
285
286#ifdef EC_EOE
287 ec_master_eoe_stop(master);
289#endif
291
292 for (dev_idx = EC_DEVICE_MAIN;
293 dev_idx < ec_master_num_devices(master); dev_idx++) {
294 fsm->slave_states[dev_idx] = 0x00;
295 fsm->slaves_responding[dev_idx] = 0; /* Reset to trigger rescan on
296 next link up. */
297 }
298 }
299 fsm->link_state[fsm->dev_idx] = master->devices[fsm->dev_idx].link_state;
300
301 if (datagram->state == EC_DATAGRAM_RECEIVED &&
302 fsm->slaves_responding[fsm->dev_idx]) {
303 uint8_t states = EC_READ_U8(datagram->data);
304 if (states != fsm->slave_states[fsm->dev_idx]) {
305 // slave states changed
306 char state_str[EC_STATE_STRING_SIZE];
307 fsm->slave_states[fsm->dev_idx] = states;
308 ec_state_string(states, state_str, 1);
309 EC_MASTER_INFO(master, "Slave states on %s device: %s.\n",
310 ec_device_names[fsm->dev_idx != 0], state_str);
311 }
312 } else {
313 fsm->slave_states[fsm->dev_idx] = 0x00;
314 }
315
316 fsm->dev_idx++;
317 if (fsm->dev_idx < ec_master_num_devices(master)) {
318 // check number of responding slaves on next device
320 fsm->state(fsm); // execute immediately
321 return;
322 }
323
324 if (fsm->rescan_required) {
325 down(&master->scan_sem);
326 if (!master->allow_scan) {
327 up(&master->scan_sem);
328 } else {
329 unsigned int count = 0, next_dev_slave, ring_position;
330 ec_device_index_t dev_idx;
331
332 master->scan_busy = 1;
333 up(&master->scan_sem);
334
335 // clear all slaves and scan the bus
336 fsm->rescan_required = 0;
337 fsm->idle = 0;
338 fsm->scan_jiffies = jiffies;
339
340#ifdef EC_EOE
341 ec_master_eoe_stop(master);
343#endif
345
346 for (dev_idx = EC_DEVICE_MAIN;
347 dev_idx < ec_master_num_devices(master); dev_idx++) {
348 count += fsm->slaves_responding[dev_idx];
349 }
350
351 if (!count) {
352 // no slaves present -> finish state machine.
353 master->scan_busy = 0;
354 wake_up_interruptible(&master->scan_queue);
356 return;
357 }
358
359 size = sizeof(ec_slave_t) * count;
360 if (!(master->slaves =
361 (ec_slave_t *) kmalloc(size, GFP_KERNEL))) {
362 EC_MASTER_ERR(master, "Failed to allocate %u bytes"
363 " of slave memory!\n", size);
364 master->scan_busy = 0;
365 wake_up_interruptible(&master->scan_queue);
367 return;
368 }
369
370 // init slaves
371 dev_idx = EC_DEVICE_MAIN;
372 next_dev_slave = fsm->slaves_responding[dev_idx];
373 ring_position = 0;
374 for (i = 0; i < count; i++, ring_position++) {
375 slave = master->slaves + i;
376 while (i >= next_dev_slave) {
377 dev_idx++;
378 next_dev_slave += fsm->slaves_responding[dev_idx];
379 ring_position = 0;
380 }
381
382 ec_slave_init(slave, master, dev_idx, ring_position, i + 1);
383
384 // do not force reconfiguration in operation phase to avoid
385 // unnecesssary process data interruptions
386 if (master->phase != EC_OPERATION) {
387 slave->force_config = 1;
388 }
389 }
390 master->slave_count = count;
391 master->fsm_slave = master->slaves;
392
393 /* start with first device with slaves responding; at least one
394 * has responding slaves, otherwise count would be zero. */
395 fsm->dev_idx = EC_DEVICE_MAIN;
396 while (!fsm->slaves_responding[fsm->dev_idx]) {
397 fsm->dev_idx++;
398 }
399
401 return;
402 }
403 }
404
405 if (master->slave_count) {
406
407 // application applied configurations
408 if (master->config_changed) {
409 master->config_changed = 0;
410
411 EC_MASTER_DBG(master, 1, "Configuration changed.\n");
412
413 fsm->slave = master->slaves; // begin with first slave
415
416 } else {
417 // fetch state from first slave
418 fsm->slave = master->slaves;
420 0x0130, 2);
421 ec_datagram_zero(datagram);
423 fsm->retries = EC_FSM_RETRIES;
425 }
426 } else {
428 }
429}
430
431/*****************************************************************************/
432
438 ec_fsm_master_t *fsm
439 )
440{
441 ec_master_t *master = fsm->master;
442 ec_sii_write_request_t *request;
443 ec_slave_config_t *config;
444 ec_flag_t *flag;
445 int assign_to_pdi;
446
447 // search the first request to be processed
448 while (1) {
449 if (list_empty(&master->sii_requests))
450 break;
451
452 // get first request
453 request = list_entry(master->sii_requests.next,
455 list_del_init(&request->list); // dequeue
456 request->state = EC_INT_REQUEST_BUSY;
457
458 assign_to_pdi = 0;
459 config = request->slave->config;
460 if (config) {
461 flag = ec_slave_config_find_flag(config, "AssignToPdi");
462 if (flag) {
463 assign_to_pdi = flag->value;
464 }
465 }
466
467 if (assign_to_pdi) {
468 fsm->sii_request = request;
469 EC_SLAVE_DBG(request->slave, 1,
470 "Assigning SII back to EtherCAT.\n");
472 0x0500, 0x01);
473 EC_WRITE_U8(fsm->datagram->data, 0x00); // EtherCAT
474 fsm->retries = EC_FSM_RETRIES;
476 return 1;
477 }
478
479 // found pending SII write operation. execute it!
480 EC_SLAVE_DBG(request->slave, 1, "Writing SII data...\n");
481 fsm->sii_request = request;
482 fsm->sii_index = 0;
483 ec_fsm_sii_write(&fsm->fsm_sii, request->slave, request->offset,
486 fsm->state(fsm); // execute immediately
487 return 1;
488 }
489
490 return 0;
491}
492
493/*****************************************************************************/
494
500 ec_fsm_master_t *fsm
501 )
502{
503 ec_master_t *master = fsm->master;
504 ec_slave_t *slave;
505 ec_sdo_request_t *req;
506
507 // search for internal requests to be processed
508 for (slave = master->slaves;
509 slave < master->slaves + master->slave_count;
510 slave++) {
511
512 if (!slave->config) {
513 continue;
514 }
515
516 list_for_each_entry(req, &slave->config->sdo_requests, list) {
517 if (req->state == EC_INT_REQUEST_QUEUED) {
518
519 if (ec_sdo_request_timed_out(req)) {
520 req->state = EC_INT_REQUEST_FAILURE;
521 EC_SLAVE_DBG(slave, 1, "Internal SDO request"
522 " timed out.\n");
523 continue;
524 }
525
526 if (slave->current_state == EC_SLAVE_STATE_INIT) {
527 req->state = EC_INT_REQUEST_FAILURE;
528 continue;
529 }
530
531 req->state = EC_INT_REQUEST_BUSY;
532 EC_SLAVE_DBG(slave, 1, "Processing internal"
533 " SDO request...\n");
534 fsm->idle = 0;
535 fsm->sdo_request = req;
536 fsm->slave = slave;
538 ec_fsm_coe_transfer(&fsm->fsm_coe, slave, req);
539 ec_fsm_coe_exec(&fsm->fsm_coe, fsm->datagram);
540 return 1;
541 }
542 }
543 }
544 return 0;
545}
546
547/*****************************************************************************/
548
554 ec_fsm_master_t *fsm
555 )
556{
557 ec_master_t *master = fsm->master;
558 ec_slave_t *slave;
559
560 // Check for pending internal SDO requests
562 return;
563 }
564
565 // enable processing of requests
566 for (slave = master->slaves;
567 slave < master->slaves + master->slave_count;
568 slave++) {
570 }
571
572 // check, if slaves have an SDO dictionary to read out.
573 for (slave = master->slaves;
574 slave < master->slaves + master->slave_count;
575 slave++) {
576 if (!(slave->sii.mailbox_protocols & EC_MBOX_COE)
577 || (slave->sii.has_general
579 || slave->sdo_dictionary_fetched
582 || jiffies - slave->jiffies_preop < EC_WAIT_SDO_DICT * HZ
583 ) continue;
584
585 EC_SLAVE_DBG(slave, 1, "Fetching SDO dictionary.\n");
586
587 slave->sdo_dictionary_fetched = 1;
588
589 // start fetching SDO dictionary
590 fsm->idle = 0;
591 fsm->slave = slave;
593 ec_fsm_coe_dictionary(&fsm->fsm_coe, slave);
594 ec_fsm_coe_exec(&fsm->fsm_coe, fsm->datagram); // execute immediately
596 return;
597 }
598
599 // check for pending SII write operations.
601 return; // SII write request found
602 }
603
605}
606
607/*****************************************************************************/
608
612 ec_fsm_master_t *fsm
613 )
614{
615 ec_master_t *master = fsm->master;
616
617 // is there another slave to query?
618 fsm->slave++;
619 if (fsm->slave < master->slaves + master->slave_count) {
620 // fetch state from next slave
621 fsm->idle = 1;
623 fsm->slave->station_address, 0x0130, 2);
626 fsm->retries = EC_FSM_RETRIES;
628 return;
629 }
630
631 // all slaves processed
633}
634
635/*****************************************************************************/
636
640 ec_fsm_master_t *fsm
641 )
642{
643 ec_master_t *master = fsm->master;
644 ec_slave_t *slave = fsm->slave;
645
646 if (master->config_changed) {
647 master->config_changed = 0;
648
649 // abort iterating through slaves,
650 // first compensate DC system time offsets,
651 // then begin configuring at slave 0
652 EC_MASTER_DBG(master, 1, "Configuration changed"
653 " (aborting state check).\n");
654
655 fsm->slave = master->slaves; // begin with first slave
657 return;
658 }
659
660 // Does the slave have to be configured?
661 if ((slave->current_state != slave->requested_state
662 || slave->force_config) && !slave->error_flag) {
663
664 // Start slave configuration
665 down(&master->config_sem);
666 master->config_busy = 1;
667 up(&master->config_sem);
668
669 if (master->debug_level) {
670 char old_state[EC_STATE_STRING_SIZE],
671 new_state[EC_STATE_STRING_SIZE];
672 ec_state_string(slave->current_state, old_state, 0);
673 ec_state_string(slave->requested_state, new_state, 0);
674 EC_SLAVE_DBG(slave, 1, "Changing state from %s to %s%s.\n",
675 old_state, new_state,
676 slave->force_config ? " (forced)" : "");
677 }
678
679 fsm->idle = 0;
682 fsm->state(fsm); // execute immediately
684 return;
685 }
686
687 // process next slave
689}
690
691/*****************************************************************************/
692
698 ec_fsm_master_t *fsm
699 )
700{
701 ec_slave_t *slave = fsm->slave;
702 ec_datagram_t *datagram = fsm->datagram;
703
704 if (datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--) {
705 return;
706 }
707
708 if (datagram->state != EC_DATAGRAM_RECEIVED) {
709 EC_SLAVE_ERR(slave, "Failed to receive AL state datagram: ");
710 ec_datagram_print_state(datagram);
712 return;
713 }
714
715 // did the slave not respond to its station address?
716 if (datagram->working_counter != 1) {
717 if (!slave->error_flag) {
718 slave->error_flag = 1;
719 EC_SLAVE_DBG(slave, 1, "Slave did not respond to state query.\n");
720 }
721 fsm->rescan_required = 1;
723 return;
724 }
725
726 // A single slave responded
727 ec_slave_set_state(slave, EC_READ_U8(datagram->data));
728
729 if (!slave->error_flag) {
730 // Check, if new slave state has to be acknowledged
732 fsm->idle = 0;
734 ec_fsm_change_ack(&fsm->fsm_change, slave);
735 fsm->state(fsm); // execute immediately
736 return;
737 }
738
739 // No acknowlegde necessary; check for configuration
741 return;
742 }
743
744 // slave has error flag set; process next one
746}
747
748/*****************************************************************************/
749
753 ec_fsm_master_t *fsm
754 )
755{
756 ec_slave_t *slave = fsm->slave;
757
758 if (ec_fsm_change_exec(&fsm->fsm_change)) {
759 return;
760 }
761
762 if (!ec_fsm_change_success(&fsm->fsm_change)) {
763 fsm->slave->error_flag = 1;
764 EC_SLAVE_ERR(slave, "Failed to acknowledge state change.\n");
765 }
766
768}
769
770/*****************************************************************************/
771
775 ec_fsm_master_t *fsm
776 )
777{
778 // broadcast clear all station addresses
779 ec_datagram_bwr(fsm->datagram, 0x0010, 2);
780 EC_WRITE_U16(fsm->datagram->data, 0x0000);
781 fsm->datagram->device_index = fsm->dev_idx;
782 fsm->retries = EC_FSM_RETRIES;
784}
785
786/*****************************************************************************/
787
791 ec_fsm_master_t *fsm
792 )
793{
794 ec_master_t *master = fsm->master;
795 ec_datagram_t *datagram = fsm->datagram;
796
797 if (datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--) {
798 return;
799 }
800
801 if (datagram->state != EC_DATAGRAM_RECEIVED) {
802 EC_MASTER_ERR(master, "Failed to receive address"
803 " clearing datagram on %s link: ",
804 ec_device_names[fsm->dev_idx != 0]);
805 ec_datagram_print_state(datagram);
806 master->scan_busy = 0;
807 wake_up_interruptible(&master->scan_queue);
809 return;
810 }
811
812 if (datagram->working_counter != fsm->slaves_responding[fsm->dev_idx]) {
813 EC_MASTER_WARN(master, "Failed to clear station addresses on %s link:"
814 " Cleared %u of %u",
815 ec_device_names[fsm->dev_idx != 0], datagram->working_counter,
816 fsm->slaves_responding[fsm->dev_idx]);
817 }
818
819 EC_MASTER_DBG(master, 1, "Sending broadcast-write"
820 " to measure transmission delays on %s link.\n",
821 ec_device_names[fsm->dev_idx != 0]);
822
823 ec_datagram_bwr(datagram, 0x0900, 1);
824 ec_datagram_zero(datagram);
825 fsm->datagram->device_index = fsm->dev_idx;
826 fsm->retries = EC_FSM_RETRIES;
828}
829
830/*****************************************************************************/
831
835 ec_fsm_master_t *fsm
836 )
837{
838 ec_master_t *master = fsm->master;
839 ec_datagram_t *datagram = fsm->datagram;
840
841 if (datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--) {
842 return;
843 }
844
845 if (datagram->state != EC_DATAGRAM_RECEIVED) {
846 EC_MASTER_ERR(master, "Failed to receive delay measuring datagram"
847 " on %s link: ", ec_device_names[fsm->dev_idx != 0]);
848 ec_datagram_print_state(datagram);
849 master->scan_busy = 0;
850 wake_up_interruptible(&master->scan_queue);
852 return;
853 }
854
855 EC_MASTER_DBG(master, 1, "%u slaves responded to delay measuring"
856 " on %s link.\n",
857 datagram->working_counter, ec_device_names[fsm->dev_idx != 0]);
858
859 do {
860 fsm->dev_idx++;
861 } while (fsm->dev_idx < ec_master_num_devices(master) &&
862 !fsm->slaves_responding[fsm->dev_idx]);
863 if (fsm->dev_idx < ec_master_num_devices(master)) {
865 return;
866 }
867
868 EC_MASTER_INFO(master, "Scanning bus.\n");
869
870 // begin scanning of slaves
871 fsm->slave = master->slaves;
872 EC_MASTER_DBG(master, 1, "Scanning slave %u on %s link.\n",
873 fsm->slave->ring_position,
877 ec_fsm_slave_scan_exec(&fsm->fsm_slave_scan); // execute immediately
879}
880
881/*****************************************************************************/
882
888 ec_fsm_master_t *fsm
889 )
890{
891 ec_master_t *master = fsm->master;
892#ifdef EC_EOE
893 ec_slave_t *slave = fsm->slave;
894#endif
895
897 return;
898 }
899
900#ifdef EC_EOE
901 if (slave->sii.mailbox_protocols & EC_MBOX_EOE) {
902 // create EoE handler for this slave
903 ec_eoe_t *eoe;
904 if (!(eoe = kmalloc(sizeof(ec_eoe_t), GFP_KERNEL))) {
905 EC_SLAVE_ERR(slave, "Failed to allocate EoE handler memory!\n");
906 } else if (ec_eoe_init(eoe, slave)) {
907 EC_SLAVE_ERR(slave, "Failed to init EoE handler!\n");
908 kfree(eoe);
909 } else {
910 list_add_tail(&eoe->list, &master->eoe_handlers);
911 }
912 }
913#endif
914
915 // another slave to fetch?
916 fsm->slave++;
917 if (fsm->slave < master->slaves + master->slave_count) {
918 EC_MASTER_DBG(master, 1, "Scanning slave %u on %s link.\n",
919 fsm->slave->ring_position,
922 ec_fsm_slave_scan_exec(&fsm->fsm_slave_scan); // execute immediately
924 return;
925 }
926
927 EC_MASTER_INFO(master, "Bus scanning completed in %lu ms.\n",
928 (jiffies - fsm->scan_jiffies) * 1000 / HZ);
929
930 master->scan_busy = 0;
931 wake_up_interruptible(&master->scan_queue);
932
933 ec_master_calc_dc(master);
934
935 // Attach slave configurations
937
938#ifdef EC_EOE
939 // check if EoE processing has to be started
940 ec_master_eoe_start(master);
941#endif
942
943 if (master->slave_count) {
944 master->config_changed = 0;
945
946 fsm->slave = master->slaves; // begin with first slave
948 } else {
950 }
951}
952
953/*****************************************************************************/
954
960 ec_fsm_master_t *fsm
961 )
962{
963 ec_master_t *master = fsm->master;
964
966 return;
967 }
968
969 fsm->slave->force_config = 0;
970
971 // configuration finished
972 master->config_busy = 0;
973 wake_up_interruptible(&master->config_queue);
974
976 // TODO: mark slave_config as failed.
977 }
978
979 fsm->idle = 1;
981}
982
983/*****************************************************************************/
984
988 ec_fsm_master_t *fsm
989 )
990{
991 ec_master_t *master = fsm->master;
992
993 if (master->dc_ref_time) {
994
995 while (fsm->slave < master->slaves + master->slave_count) {
996 if (!fsm->slave->base_dc_supported
997 || !fsm->slave->has_dc_system_time) {
998 fsm->slave++;
999 continue;
1000 }
1001
1002 EC_SLAVE_DBG(fsm->slave, 1, "Checking system time offset.\n");
1003
1004 // read DC system time (0x0910, 64 bit)
1005 // gap (64 bit)
1006 // and time offset (0x0920, 64 bit)
1008 0x0910, 24);
1010 fsm->retries = EC_FSM_RETRIES;
1012 return;
1013 }
1014
1015 } else {
1016 if (master->active) {
1017 EC_MASTER_WARN(master, "No application time received up to now,"
1018 " but master already active.\n");
1019 } else {
1020 EC_MASTER_DBG(master, 1, "No app_time received up to now.\n");
1021 }
1022 }
1023
1024 // scanning and setting system times complete
1025 ec_master_request_op(master);
1027}
1028
1029/*****************************************************************************/
1030
1036 ec_fsm_master_t *fsm,
1037 u64 system_time,
1038 u64 old_offset,
1039 unsigned long jiffies_since_read
1040 )
1041{
1042 ec_slave_t *slave = fsm->slave;
1043 u32 correction, system_time32, old_offset32, new_offset;
1044 s32 time_diff;
1045
1046 system_time32 = (u32) system_time;
1047 old_offset32 = (u32) old_offset;
1048
1049 // correct read system time by elapsed time since read operation
1050 correction = jiffies_since_read * 1000 / HZ * 1000000;
1051 system_time32 += correction;
1052 time_diff = (u32) slave->master->app_time - system_time32;
1053
1054 EC_SLAVE_DBG(slave, 1, "DC 32 bit system time offset calculation:"
1055 " system_time=%u (corrected with %u),"
1056 " app_time=%llu, diff=%i\n",
1057 system_time32, correction,
1058 slave->master->app_time, time_diff);
1059
1060 if (EC_ABS(time_diff) > EC_SYSTEM_TIME_TOLERANCE_NS) {
1061 new_offset = time_diff + old_offset32;
1062 EC_SLAVE_DBG(slave, 1, "Setting time offset to %u (was %u)\n",
1063 new_offset, old_offset32);
1064 return (u64) new_offset;
1065 } else {
1066 EC_SLAVE_DBG(slave, 1, "Not touching time offset.\n");
1067 return old_offset;
1068 }
1069}
1070
1071/*****************************************************************************/
1072
1078 ec_fsm_master_t *fsm,
1079 u64 system_time,
1080 u64 old_offset,
1081 unsigned long jiffies_since_read
1082 )
1083{
1084 ec_slave_t *slave = fsm->slave;
1085 u64 new_offset, correction;
1086 s64 time_diff;
1087
1088 // correct read system time by elapsed time since read operation
1089 correction = (u64) (jiffies_since_read * 1000 / HZ) * 1000000;
1090 system_time += correction;
1091 time_diff = fsm->slave->master->app_time - system_time;
1092
1093 EC_SLAVE_DBG(slave, 1, "DC 64 bit system time offset calculation:"
1094 " system_time=%llu (corrected with %llu),"
1095 " app_time=%llu, diff=%lli\n",
1096 system_time, correction,
1097 slave->master->app_time, time_diff);
1098
1099 if (EC_ABS(time_diff) > EC_SYSTEM_TIME_TOLERANCE_NS) {
1100 new_offset = time_diff + old_offset;
1101 EC_SLAVE_DBG(slave, 1, "Setting time offset to %llu (was %llu)\n",
1102 new_offset, old_offset);
1103 } else {
1104 new_offset = old_offset;
1105 EC_SLAVE_DBG(slave, 1, "Not touching time offset.\n");
1106 }
1107
1108 return new_offset;
1109}
1110
1111/*****************************************************************************/
1112
1116 ec_fsm_master_t *fsm
1117 )
1118{
1119 ec_datagram_t *datagram = fsm->datagram;
1120 ec_slave_t *slave = fsm->slave;
1121 u64 system_time, old_offset, new_offset;
1122 unsigned long jiffies_since_read;
1123
1124 if (datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--)
1125 return;
1126
1127 if (datagram->state != EC_DATAGRAM_RECEIVED) {
1128 EC_SLAVE_ERR(slave, "Failed to receive DC times datagram: ");
1129 ec_datagram_print_state(datagram);
1130 fsm->slave++;
1132 return;
1133 }
1134
1135 if (datagram->working_counter != 1) {
1136 EC_SLAVE_WARN(slave, "Failed to get DC times: ");
1138 fsm->slave++;
1140 return;
1141 }
1142
1143 system_time = EC_READ_U64(datagram->data); // 0x0910
1144 old_offset = EC_READ_U64(datagram->data + 16); // 0x0920
1145 jiffies_since_read = jiffies - datagram->jiffies_sent;
1146
1147 if (slave->base_dc_range == EC_DC_32) {
1148 new_offset = ec_fsm_master_dc_offset32(fsm,
1149 system_time, old_offset, jiffies_since_read);
1150 } else {
1151 new_offset = ec_fsm_master_dc_offset64(fsm,
1152 system_time, old_offset, jiffies_since_read);
1153 }
1154
1155 // set DC system time offset and transmission delay
1156 ec_datagram_fpwr(datagram, slave->station_address, 0x0920, 12);
1157 EC_WRITE_U64(datagram->data, new_offset);
1158 EC_WRITE_U32(datagram->data + 8, slave->transmission_delay);
1159 fsm->datagram->device_index = slave->device_index;
1160 fsm->retries = EC_FSM_RETRIES;
1162}
1163
1164/*****************************************************************************/
1165
1169 ec_fsm_master_t *fsm
1170 )
1171{
1172 ec_datagram_t *datagram = fsm->datagram;
1173 ec_slave_t *slave = fsm->slave;
1174
1175 if (datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--)
1176 return;
1177
1178 if (datagram->state != EC_DATAGRAM_RECEIVED) {
1179 EC_SLAVE_ERR(slave,
1180 "Failed to receive DC system time offset datagram: ");
1181 ec_datagram_print_state(datagram);
1182 fsm->slave++;
1184 return;
1185 }
1186
1187 if (datagram->working_counter != 1) {
1188 EC_SLAVE_ERR(slave, "Failed to set DC system time offset: ");
1190 fsm->slave++;
1192 return;
1193 }
1194
1195 fsm->slave++;
1197}
1198
1199/*****************************************************************************/
1200
1204 ec_fsm_master_t *fsm
1205 )
1206{
1207 ec_datagram_t *datagram = fsm->datagram;
1208 ec_sii_write_request_t *request = fsm->sii_request;
1209 ec_slave_t *slave = request->slave;
1210
1211 if (datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--)
1212 return;
1213
1214 if (datagram->state != EC_DATAGRAM_RECEIVED) {
1215 EC_SLAVE_ERR(slave, "Failed to receive SII assignment datagram: ");
1216 ec_datagram_print_state(datagram);
1217 goto cont;
1218 }
1219
1220 if (datagram->working_counter != 1) {
1221 EC_SLAVE_ERR(slave, "Failed to assign SII back to EtherCAT: ");
1223 goto cont;
1224 }
1225
1226cont:
1227 // found pending SII write operation. execute it!
1228 EC_SLAVE_DBG(slave, 1, "Writing SII data (after assignment)...\n");
1229 fsm->sii_index = 0;
1230 ec_fsm_sii_write(&fsm->fsm_sii, slave, request->offset,
1233 fsm->state(fsm); // execute immediately
1234}
1235
1236/*****************************************************************************/
1237
1241 ec_fsm_master_t *fsm
1242 )
1243{
1244 ec_master_t *master = fsm->master;
1245 ec_sii_write_request_t *request = fsm->sii_request;
1246 ec_slave_t *slave = request->slave;
1247
1248 if (ec_fsm_sii_exec(&fsm->fsm_sii)) return;
1249
1250 if (!ec_fsm_sii_success(&fsm->fsm_sii)) {
1251 EC_SLAVE_ERR(slave, "Failed to write SII data.\n");
1252 request->state = EC_INT_REQUEST_FAILURE;
1253 wake_up_all(&master->request_queue);
1255 return;
1256 }
1257
1258 fsm->sii_index++;
1259 if (fsm->sii_index < request->nwords) {
1260 ec_fsm_sii_write(&fsm->fsm_sii, slave,
1261 request->offset + fsm->sii_index,
1262 request->words + fsm->sii_index,
1264 ec_fsm_sii_exec(&fsm->fsm_sii); // execute immediately
1265 return;
1266 }
1267
1268 // finished writing SII
1269 EC_SLAVE_DBG(slave, 1, "Finished writing %zu words of SII data.\n",
1270 request->nwords);
1271
1272 if (request->offset <= 4 && request->offset + request->nwords > 4) {
1273 // alias was written
1274 slave->sii.alias = EC_READ_U16(request->words + 4);
1275 // TODO: read alias from register 0x0012
1276 slave->effective_alias = slave->sii.alias;
1277 }
1278 // TODO: Evaluate other SII contents!
1279
1280 request->state = EC_INT_REQUEST_SUCCESS;
1281 wake_up_all(&master->request_queue);
1282
1283 // check for another SII write request
1285 return; // processing another request
1286
1288}
1289
1290/*****************************************************************************/
1291
1295 ec_fsm_master_t *fsm
1296 )
1297{
1298 ec_slave_t *slave = fsm->slave;
1299 ec_master_t *master = fsm->master;
1300
1301 if (ec_fsm_coe_exec(&fsm->fsm_coe, fsm->datagram)) {
1302 return;
1303 }
1304
1305 if (!ec_fsm_coe_success(&fsm->fsm_coe)) {
1307 return;
1308 }
1309
1310 // SDO dictionary fetching finished
1311
1312 if (master->debug_level) {
1313 unsigned int sdo_count, entry_count;
1314 ec_slave_sdo_dict_info(slave, &sdo_count, &entry_count);
1315 EC_SLAVE_DBG(slave, 1, "Fetched %u SDOs and %u entries.\n",
1316 sdo_count, entry_count);
1317 }
1318
1319 // attach pdo names from dictionary
1321
1323}
1324
1325/*****************************************************************************/
1326
1330 ec_fsm_master_t *fsm
1331 )
1332{
1333 ec_sdo_request_t *request = fsm->sdo_request;
1334
1335 if (!request) {
1336 // configuration was cleared in the meantime
1338 return;
1339 }
1340
1341 if (ec_fsm_coe_exec(&fsm->fsm_coe, fsm->datagram)) {
1342 return;
1343 }
1344
1345 if (!ec_fsm_coe_success(&fsm->fsm_coe)) {
1346 EC_SLAVE_DBG(fsm->slave, 1,
1347 "Failed to process internal SDO request.\n");
1348 request->state = EC_INT_REQUEST_FAILURE;
1349 wake_up_all(&fsm->master->request_queue);
1351 return;
1352 }
1353
1354 // SDO request finished
1355 request->state = EC_INT_REQUEST_SUCCESS;
1356 wake_up_all(&fsm->master->request_queue);
1357
1358 EC_SLAVE_DBG(fsm->slave, 1, "Finished internal SDO request.\n");
1359
1360 // check for another SDO request
1362 return; // processing another request
1363 }
1364
1366}
1367
1368/*****************************************************************************/
void ec_datagram_print_wc_error(const ec_datagram_t *datagram)
Evaluates the working counter of a single-cast datagram.
Definition: datagram.c:602
void ec_datagram_zero(ec_datagram_t *datagram)
Fills the datagram payload memory with zeros.
Definition: datagram.c:178
int ec_datagram_apwr(ec_datagram_t *datagram, uint16_t ring_position, uint16_t mem_address, size_t data_size)
Initializes an EtherCAT APWR datagram.
Definition: datagram.c:210
int ec_datagram_brd(ec_datagram_t *datagram, uint16_t mem_address, size_t data_size)
Initializes an EtherCAT BRD datagram.
Definition: datagram.c:373
int ec_datagram_bwr(ec_datagram_t *datagram, uint16_t mem_address, size_t data_size)
Initializes an EtherCAT BWR datagram.
Definition: datagram.c:393
void ec_datagram_print_state(const ec_datagram_t *datagram)
Prints the state of a datagram.
Definition: datagram.c:565
int ec_datagram_fpwr(ec_datagram_t *datagram, uint16_t configured_address, uint16_t mem_address, size_t data_size)
Initializes an EtherCAT FPWR datagram.
Definition: datagram.c:298
int ec_datagram_fprd(ec_datagram_t *datagram, uint16_t configured_address, uint16_t mem_address, size_t data_size)
Initializes an EtherCAT FPRD datagram.
Definition: datagram.c:273
@ EC_DATAGRAM_RECEIVED
Received (dequeued).
Definition: datagram.h:78
@ EC_DATAGRAM_TIMED_OUT
Timed out (dequeued).
Definition: datagram.h:79
@ EC_DATAGRAM_SENT
Sent (still in the queue).
Definition: datagram.h:77
@ EC_DATAGRAM_QUEUED
Queued for sending.
Definition: datagram.h:76
int ec_eoe_init(ec_eoe_t *eoe, ec_slave_t *slave)
EoE constructor.
Definition: ethernet.c:104
Ethernet over EtherCAT (EoE)
int ec_fsm_change_success(ec_fsm_change_t *fsm)
Returns, if the state machine terminated with success.
Definition: fsm_change.c:139
void ec_fsm_change_init(ec_fsm_change_t *fsm, ec_datagram_t *datagram)
Constructor.
Definition: fsm_change.c:65
void ec_fsm_change_ack(ec_fsm_change_t *fsm, ec_slave_t *slave)
Starts the change state machine to only acknowlegde a slave's state.
Definition: fsm_change.c:107
void ec_fsm_change_clear(ec_fsm_change_t *fsm)
Destructor.
Definition: fsm_change.c:80
int ec_fsm_change_exec(ec_fsm_change_t *fsm)
Executes the current state of the state machine.
Definition: fsm_change.c:124
void ec_fsm_coe_dictionary(ec_fsm_coe_t *fsm, ec_slave_t *slave)
Starts reading a slaves' SDO dictionary.
Definition: fsm_coe.c:192
int ec_fsm_coe_success(const ec_fsm_coe_t *fsm)
Returns, if the state machine terminated with success.
Definition: fsm_coe.c:262
void ec_fsm_coe_transfer(ec_fsm_coe_t *fsm, ec_slave_t *slave, ec_sdo_request_t *request)
Starts to transfer an SDO to/from a slave.
Definition: fsm_coe.c:205
void ec_fsm_coe_init(ec_fsm_coe_t *fsm)
Constructor.
Definition: fsm_coe.c:170
int ec_fsm_coe_exec(ec_fsm_coe_t *fsm, ec_datagram_t *datagram)
Executes the current state of the state machine.
Definition: fsm_coe.c:228
void ec_fsm_coe_clear(ec_fsm_coe_t *fsm)
Destructor.
Definition: fsm_coe.c:182
EtherCAT FoE state machines.
int ec_fsm_master_exec(ec_fsm_master_t *fsm)
Executes the current state of the state machine.
Definition: fsm_master.c:151
void ec_fsm_master_state_scan_slave(ec_fsm_master_t *)
Master state: SCAN SLAVE.
Definition: fsm_master.c:887
void ec_fsm_master_state_dc_measure_delays(ec_fsm_master_t *)
Master state: DC MEASURE DELAYS.
Definition: fsm_master.c:834
void ec_fsm_master_state_acknowledge(ec_fsm_master_t *)
Master state: ACKNOWLEDGE.
Definition: fsm_master.c:752
void ec_fsm_master_state_sdo_request(ec_fsm_master_t *)
Master state: SDO REQUEST.
Definition: fsm_master.c:1329
int ec_fsm_master_action_process_sdo(ec_fsm_master_t *fsm)
Check for pending SDO requests and process one.
Definition: fsm_master.c:499
void ec_fsm_master_state_dc_write_offset(ec_fsm_master_t *)
Master state: DC WRITE OFFSET.
Definition: fsm_master.c:1168
void ec_fsm_master_init(ec_fsm_master_t *fsm, ec_master_t *master, ec_datagram_t *datagram)
Constructor.
Definition: fsm_master.c:77
void ec_fsm_master_action_next_slave_state(ec_fsm_master_t *fsm)
Master action: Get state of next slave.
Definition: fsm_master.c:611
void ec_fsm_master_state_sdo_dictionary(ec_fsm_master_t *)
Master state: SDO DICTIONARY.
Definition: fsm_master.c:1294
int ec_fsm_master_idle(const ec_fsm_master_t *fsm)
Definition: fsm_master.c:170
void ec_fsm_master_state_clear_addresses(ec_fsm_master_t *)
Master state: CLEAR ADDRESSES.
Definition: fsm_master.c:790
void ec_fsm_master_enter_write_system_times(ec_fsm_master_t *)
Start writing DC system times.
Definition: fsm_master.c:987
void ec_fsm_master_action_configure(ec_fsm_master_t *fsm)
Master action: Configure.
Definition: fsm_master.c:639
void ec_fsm_master_state_read_state(ec_fsm_master_t *)
Master state: READ STATE.
Definition: fsm_master.c:697
int ec_fsm_master_action_process_sii(ec_fsm_master_t *fsm)
Check for pending SII write requests and process one.
Definition: fsm_master.c:437
void ec_fsm_master_restart(ec_fsm_master_t *fsm)
Restarts the master state machine.
Definition: fsm_master.c:181
u64 ec_fsm_master_dc_offset32(ec_fsm_master_t *fsm, u64 system_time, u64 old_offset, unsigned long jiffies_since_read)
Configure 32 bit time offset.
Definition: fsm_master.c:1035
void ec_fsm_master_enter_clear_addresses(ec_fsm_master_t *)
Start clearing slave addresses.
Definition: fsm_master.c:774
#define EC_SYSTEM_TIME_TOLERANCE_NS
Time difference [ns] to tolerate without setting a new system time offset.
Definition: fsm_master.c:51
void ec_fsm_master_state_broadcast(ec_fsm_master_t *)
Master state: BROADCAST.
Definition: fsm_master.c:256
void ec_fsm_master_state_configure_slave(ec_fsm_master_t *)
Master state: CONFIGURE SLAVE.
Definition: fsm_master.c:959
void ec_fsm_master_state_write_sii(ec_fsm_master_t *)
Master state: WRITE SII.
Definition: fsm_master.c:1240
u64 ec_fsm_master_dc_offset64(ec_fsm_master_t *fsm, u64 system_time, u64 old_offset, unsigned long jiffies_since_read)
Configure 64 bit time offset.
Definition: fsm_master.c:1077
void ec_fsm_master_state_dc_read_offset(ec_fsm_master_t *)
Master state: DC READ OFFSET.
Definition: fsm_master.c:1115
void ec_fsm_master_clear(ec_fsm_master_t *fsm)
Destructor.
Definition: fsm_master.c:104
void ec_fsm_master_state_start(ec_fsm_master_t *)
Master state: START.
Definition: fsm_master.c:198
void ec_fsm_master_state_assign_sii(ec_fsm_master_t *)
Master state: ASSIGN SII.
Definition: fsm_master.c:1203
void ec_fsm_master_action_idle(ec_fsm_master_t *fsm)
Master action: IDLE.
Definition: fsm_master.c:553
void ec_fsm_master_reset(ec_fsm_master_t *fsm)
Reset state machine.
Definition: fsm_master.c:122
EtherCAT master state machine.
void ec_fsm_pdo_clear(ec_fsm_pdo_t *fsm)
Destructor.
Definition: fsm_pdo.c:90
void ec_fsm_pdo_init(ec_fsm_pdo_t *fsm, ec_fsm_coe_t *fsm_coe)
Constructor.
Definition: fsm_pdo.c:74
int ec_fsm_sii_success(ec_fsm_sii_t *fsm)
Returns, if the master startup state machine terminated with success.
Definition: fsm_sii.c:152
void ec_fsm_sii_clear(ec_fsm_sii_t *fsm)
Destructor.
Definition: fsm_sii.c:88
int ec_fsm_sii_exec(ec_fsm_sii_t *fsm)
Executes the SII state machine.
Definition: fsm_sii.c:137
void ec_fsm_sii_write(ec_fsm_sii_t *fsm, ec_slave_t *slave, uint16_t word_offset, const uint16_t *value, ec_fsm_sii_addressing_t mode)
Initializes the SII write state machine.
Definition: fsm_sii.c:116
void ec_fsm_sii_init(ec_fsm_sii_t *fsm, ec_datagram_t *datagram)
Constructor.
Definition: fsm_sii.c:74
@ EC_FSM_SII_USE_CONFIGURED_ADDRESS
Use configured addresses.
Definition: fsm_sii.h:50
void ec_fsm_slave_set_ready(ec_fsm_slave_t *fsm)
Sets the current state of the state machine to READY.
Definition: fsm_slave.c:148
void ec_fsm_slave_config_init(ec_fsm_slave_config_t *fsm, ec_datagram_t *datagram, ec_fsm_change_t *fsm_change, ec_fsm_coe_t *fsm_coe, ec_fsm_soe_t *fsm_soe, ec_fsm_pdo_t *fsm_pdo)
Constructor.
int ec_fsm_slave_config_success(const ec_fsm_slave_config_t *fsm)
void ec_fsm_slave_config_start(ec_fsm_slave_config_t *fsm, ec_slave_t *slave)
Start slave configuration state machine.
void ec_fsm_slave_config_clear(ec_fsm_slave_config_t *fsm)
Destructor.
int ec_fsm_slave_config_exec(ec_fsm_slave_config_t *fsm)
Executes the current state of the state machine.
void ec_fsm_slave_scan_start(ec_fsm_slave_scan_t *fsm, ec_slave_t *slave)
Start slave scan state machine.
void ec_fsm_slave_scan_init(ec_fsm_slave_scan_t *fsm, ec_datagram_t *datagram, ec_fsm_slave_config_t *fsm_slave_config, ec_fsm_pdo_t *fsm_pdo)
Constructor.
void ec_fsm_slave_scan_clear(ec_fsm_slave_scan_t *fsm)
Destructor.
int ec_fsm_slave_scan_exec(ec_fsm_slave_scan_t *fsm)
Executes the current state of the state machine.
void ec_fsm_soe_init(ec_fsm_soe_t *fsm)
Constructor.
Definition: fsm_soe.c:105
void ec_fsm_soe_clear(ec_fsm_soe_t *fsm)
Destructor.
Definition: fsm_soe.c:118
Global definitions and macros.
@ EC_SLAVE_STATE_UNKNOWN
unknown state
Definition: globals.h:116
@ EC_SLAVE_STATE_INIT
INIT state (no mailbox communication, no IO)
Definition: globals.h:118
@ EC_SLAVE_STATE_ACK_ERR
Acknowledge/Error bit (no actual state)
Definition: globals.h:128
#define EC_ABS(X)
Absolute value.
Definition: globals.h:242
#define EC_STATE_STRING_SIZE
Minimum size of a buffer used with ec_state_string().
Definition: globals.h:54
#define EC_FSM_RETRIES
Number of state machine retries on datagram timeout.
Definition: globals.h:47
#define EC_WAIT_SDO_DICT
Seconds to wait before fetching SDO dictionary after slave entered PREOP state.
Definition: globals.h:51
size_t ec_state_string(uint8_t, char *, uint8_t)
Prints slave states in clear text.
Definition: module.c:405
@ EC_DC_32
32 bit.
Definition: globals.h:164
struct ec_slave ec_slave_t
Definition: globals.h:301
const char * ec_device_names[2]
Device names.
Definition: module.c:469
ec_device_index_t
Master devices.
Definition: globals.h:189
@ EC_DEVICE_MAIN
Main device.
Definition: globals.h:190
@ EC_MBOX_COE
CANopen over EtherCAT.
Definition: globals.h:137
@ EC_MBOX_EOE
Ethernet over EtherCAT.
Definition: globals.h:136
#define EC_WRITE_U8(DATA, VAL)
Write an 8-bit unsigned value to EtherCAT data.
Definition: ecrt.h:2266
#define EC_WRITE_U32(DATA, VAL)
Write a 32-bit unsigned value to EtherCAT data.
Definition: ecrt.h:2300
#define EC_READ_U16(DATA)
Read a 16-bit unsigned value from EtherCAT data.
Definition: ecrt.h:2178
#define EC_READ_U64(DATA)
Read a 64-bit unsigned value from EtherCAT data.
Definition: ecrt.h:2210
#define EC_READ_U8(DATA)
Read an 8-bit unsigned value from EtherCAT data.
Definition: ecrt.h:2162
#define EC_WRITE_U64(DATA, VAL)
Write a 64-bit unsigned value to EtherCAT data.
Definition: ecrt.h:2317
#define EC_WRITE_U16(DATA, VAL)
Write a 16-bit unsigned value to EtherCAT data.
Definition: ecrt.h:2283
@ EC_DIR_OUTPUT
Values written by the master.
Definition: ecrt.h:432
Mailbox functionality.
void ec_master_request_op(ec_master_t *master)
Request OP state for configured slaves.
Definition: master.c:2240
void ec_master_eoe_start(ec_master_t *master)
Starts Ethernet over EtherCAT processing on demand.
Definition: master.c:1694
void ec_master_attach_slave_configs(ec_master_t *master)
Attaches the slave configurations to the slaves.
Definition: master.c:1808
void ec_master_calc_dc(ec_master_t *master)
Distributed-clocks calculations.
Definition: master.c:2223
void ec_master_clear_eoe_handlers(ec_master_t *master)
Clear and free all EoE handlers.
Definition: master.c:442
void ec_master_clear_slaves(ec_master_t *master)
Clear all slaves.
Definition: master.c:478
void ec_master_eoe_stop(ec_master_t *master)
Stops the Ethernet over EtherCAT processing.
Definition: master.c:1728
EtherCAT master structure.
#define ec_master_num_devices(MASTER)
Number of Ethernet devices.
Definition: master.h:330
#define EC_MASTER_INFO(master, fmt, args...)
Convenience macro for printing master-specific information to syslog.
Definition: master.h:73
#define EC_MASTER_DBG(master, level, fmt, args...)
Convenience macro for printing master-specific debug messages to syslog.
Definition: master.h:111
@ EC_OPERATION
Operation phase.
Definition: master.h:135
#define EC_MASTER_ERR(master, fmt, args...)
Convenience macro for printing master-specific errors to syslog.
Definition: master.h:85
#define EC_MASTER_WARN(master, fmt, args...)
Convenience macro for printing master-specific warnings to syslog.
Definition: master.h:97
int ec_sdo_request_timed_out(const ec_sdo_request_t *req)
Checks, if the timeout was exceeded.
Definition: sdo_request.c:177
void ec_slave_attach_pdo_names(ec_slave_t *slave)
Attach PDO names.
Definition: slave.c:781
void ec_slave_set_state(ec_slave_t *slave, ec_slave_state_t new_state)
Sets the application state of a slave.
Definition: slave.c:274
void ec_slave_sdo_dict_info(const ec_slave_t *slave, unsigned int *sdo_count, unsigned int *entry_count)
Counts the total number of SDOs and entries in the dictionary.
Definition: slave.c:608
void ec_slave_init(ec_slave_t *slave, ec_master_t *master, ec_device_index_t dev_idx, uint16_t ring_position, uint16_t station_address)
Slave constructor.
Definition: slave.c:62
#define EC_SLAVE_DBG(slave, level, fmt, args...)
Convenience macro for printing slave-specific debug messages to syslog.
Definition: slave.h:106
#define EC_SLAVE_ERR(slave, fmt, args...)
Convenience macro for printing slave-specific errors to syslog.
Definition: slave.h:76
#define EC_SLAVE_WARN(slave, fmt, args...)
Convenience macro for printing slave-specific warnings to syslog.
Definition: slave.h:90
ec_flag_t * ec_slave_config_find_flag(ec_slave_config_t *sc, const char *key)
Finds a flag.
Definition: slave_config.c:580
EtherCAT slave configuration structure.
EtherCAT datagram.
Definition: datagram.h:87
size_t mem_size
Datagram data memory size.
Definition: datagram.h:96
uint16_t working_counter
Working counter.
Definition: datagram.h:99
unsigned long jiffies_sent
Jiffies, when the datagram was sent.
Definition: datagram.h:104
ec_datagram_state_t state
State.
Definition: datagram.h:100
ec_device_index_t device_index
Device via which the datagram shall be / was sent.
Definition: datagram.h:90
uint8_t * data
Datagram payload.
Definition: datagram.h:94
uint8_t link_state
device link state
Definition: device.h:88
Ethernet over EtherCAT (EoE) handler.
Definition: ethernet.h:77
struct list_head list
list item
Definition: ethernet.h:78
Slave configutation feature flag.
Definition: flag.h:38
int32_t value
Flag value (meaning depends on key).
Definition: flag.h:41
Finite state machine of an EtherCAT master.
Definition: fsm_master.h:68
unsigned int slaves_responding[EC_MAX_NUM_DEVICES]
Number of responding slaves for every device.
Definition: fsm_master.h:80
ec_sii_write_request_t * sii_request
SII write request.
Definition: fsm_master.h:88
unsigned int rescan_required
A bus rescan is required.
Definition: fsm_master.h:83
ec_fsm_coe_t fsm_coe
CoE state machine.
Definition: fsm_master.h:92
void(* state)(ec_fsm_master_t *)
master state function
Definition: fsm_master.h:73
ec_sdo_request_t * sdo_request
SDO request to process.
Definition: fsm_master.h:90
ec_datagram_t * datagram
datagram used in the state machine
Definition: fsm_master.h:70
ec_fsm_change_t fsm_change
State change state machine.
Definition: fsm_master.h:95
uint8_t link_state[EC_MAX_NUM_DEVICES]
Last link state for every device.
Definition: fsm_master.h:78
unsigned int retries
retries on datagram timeout.
Definition: fsm_master.h:71
ec_slave_state_t slave_states[EC_MAX_NUM_DEVICES]
AL states of responding slaves for every device.
Definition: fsm_master.h:84
ec_fsm_pdo_t fsm_pdo
PDO configuration state machine.
Definition: fsm_master.h:94
int idle
state machine is in idle phase
Definition: fsm_master.h:76
ec_slave_t * slave
current slave
Definition: fsm_master.h:87
ec_device_index_t dev_idx
Current device index (for scanning etc.).
Definition: fsm_master.h:74
ec_fsm_soe_t fsm_soe
SoE state machine.
Definition: fsm_master.h:93
ec_fsm_slave_config_t fsm_slave_config
slave state machine
Definition: fsm_master.h:96
unsigned long scan_jiffies
beginning of slave scanning
Definition: fsm_master.h:77
off_t sii_index
index to SII write request data
Definition: fsm_master.h:89
ec_fsm_sii_t fsm_sii
SII state machine.
Definition: fsm_master.h:98
ec_fsm_slave_scan_t fsm_slave_scan
slave state machine
Definition: fsm_master.h:97
ec_master_t * master
master the FSM runs on
Definition: fsm_master.h:69
EtherCAT master.
Definition: master.h:194
struct list_head eoe_handlers
Ethernet over EtherCAT handlers.
Definition: master.h:293
struct list_head emerg_reg_requests
Emergency register access requests.
Definition: master.h:308
wait_queue_head_t request_queue
Wait queue for external requests from user space.
Definition: master.h:311
struct list_head sii_requests
SII write requests.
Definition: master.h:307
u64 app_time
Time of the last ecrt_master_sync() call.
Definition: master.h:238
wait_queue_head_t scan_queue
Queue for processes that wait for slave scanning.
Definition: master.h:254
unsigned int scan_busy
Current scan state.
Definition: master.h:250
unsigned int slave_count
Number of slaves on the bus.
Definition: master.h:232
unsigned int config_busy
State of slave configuration.
Definition: master.h:257
struct semaphore config_sem
Semaphore protecting the config_busy variable and the allow_config flag.
Definition: master.h:258
u64 dc_ref_time
Common reference timestamp for DC start times.
Definition: master.h:239
ec_slave_t * fsm_slave
Slave that is queried next for FSM exec.
Definition: master.h:281
wait_queue_head_t config_queue
Queue for processes that wait for slave configuration.
Definition: master.h:260
struct semaphore scan_sem
Semaphore protecting the scan_busy variable and the allow_scan flag.
Definition: master.h:252
ec_slave_t * slaves
Array of slaves on the bus.
Definition: master.h:231
unsigned int active
Master has been activated.
Definition: master.h:224
unsigned int debug_level
Master debug level.
Definition: master.h:285
unsigned int allow_scan
True, if slave scanning is allowed.
Definition: master.h:251
unsigned int config_changed
The configuration changed.
Definition: master.h:225
ec_master_phase_t phase
Master phase.
Definition: master.h:223
ec_device_t devices[EC_MAX_NUM_DEVICES]
EtherCAT devices.
Definition: master.h:211
Register request.
Definition: reg_request.h:48
uint8_t * data
Pointer to data memory.
Definition: reg_request.h:51
struct list_head list
List item.
Definition: reg_request.h:49
uint16_t address
Register address.
Definition: reg_request.h:54
uint16_t ring_position
Ring position for emergency requests.
Definition: reg_request.h:57
ec_direction_t dir
Direction.
Definition: reg_request.h:52
ec_internal_request_state_t state
Request state.
Definition: reg_request.h:56
size_t transfer_size
Size of the data to transfer.
Definition: reg_request.h:55
CANopen SDO request.
Definition: sdo_request.h:48
ec_internal_request_state_t state
SDO request state.
Definition: sdo_request.h:63
uint8_t enable_sdo_info
SDO information service available.
Definition: globals.h:147
uint16_t alias
Configured station alias.
Definition: slave.h:134
uint16_t mailbox_protocols
Supported mailbox protocols.
Definition: slave.h:147
ec_sii_coe_details_t coe_details
CoE detail flags.
Definition: slave.h:160
unsigned int has_general
General category present.
Definition: slave.h:154
SII write request.
Definition: fsm_master.h:53
struct list_head list
List head.
Definition: fsm_master.h:54
ec_slave_t * slave
EtherCAT slave.
Definition: fsm_master.h:55
ec_internal_request_state_t state
State of the request.
Definition: fsm_master.h:59
const uint16_t * words
Pointer to the data words.
Definition: fsm_master.h:58
size_t nwords
Number of words.
Definition: fsm_master.h:57
uint16_t offset
SII word offset.
Definition: fsm_master.h:56
EtherCAT slave configuration.
Definition: slave_config.h:119
struct list_head sdo_requests
List of SDO requests.
Definition: slave_config.h:145
EtherCAT slave.
Definition: slave.h:177
ec_sii_t sii
Extracted SII data.
Definition: slave.h:223
unsigned int force_config
Force (re-)configuration.
Definition: slave.h:194
uint32_t transmission_delay
DC system time transmission delay (offset from reference clock).
Definition: slave.h:215
uint8_t base_dc_supported
Distributed clocks are supported.
Definition: slave.h:210
uint16_t ring_position
Ring position.
Definition: slave.h:183
ec_slave_config_t * config
Current configuration.
Definition: slave.h:190
ec_slave_state_t current_state
Current application state.
Definition: slave.h:192
uint8_t has_dc_system_time
The slave supports the DC system time register.
Definition: slave.h:212
ec_slave_dc_range_t base_dc_range
DC range.
Definition: slave.h:211
uint8_t sdo_dictionary_fetched
Dictionary has been fetched.
Definition: slave.h:226
uint16_t effective_alias
Effective alias address.
Definition: slave.h:185
ec_device_index_t device_index
Index of device the slave responds on.
Definition: slave.h:179
ec_master_t * master
Master owning the slave.
Definition: slave.h:178
uint16_t station_address
Configured station address.
Definition: slave.h:184
ec_fsm_slave_t fsm
Slave state machine.
Definition: slave.h:234
unsigned int error_flag
Stop processing after an error.
Definition: slave.h:193
unsigned long jiffies_preop
Time, the slave went to PREOP.
Definition: slave.h:227
ec_slave_state_t requested_state
Requested application state.
Definition: slave.h:191