IgH EtherCAT Master  1.6.9
fsm_master.c
Go to the documentation of this file.
1/*****************************************************************************
2 *
3 * Copyright (C) 2006-2023 Florian Pose, Ingenieurgemeinschaft IgH
4 *
5 * This file is part of the IgH EtherCAT Master.
6 *
7 * The IgH EtherCAT Master is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License version 2, as
9 * published by the Free Software Foundation.
10 *
11 * The IgH EtherCAT Master is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
14 * Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with the IgH EtherCAT Master; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 *
20 ****************************************************************************/
21
25
26/****************************************************************************/
27
28#include "globals.h"
29#include "master.h"
30#include "mailbox.h"
31#include "slave_config.h"
32#ifdef EC_EOE
33#include "ethernet.h"
34#endif
35
36#include "fsm_master.h"
37#include "fsm_foe.h"
38
39/****************************************************************************/
40
43#define EC_SYSTEM_TIME_TOLERANCE_NS 1000000
44
45/****************************************************************************/
46
47// prototypes for private methods
54u64 ec_fsm_master_dc_offset32(ec_fsm_master_t *, u64, u64, unsigned long);
55u64 ec_fsm_master_dc_offset64(ec_fsm_master_t *, u64, u64, unsigned long);
56
57/****************************************************************************/
58
74
77
78/****************************************************************************/
79
83 ec_fsm_master_t *fsm,
84 ec_master_t *master,
85 ec_datagram_t *datagram
86 )
87{
88 fsm->master = master;
89 fsm->datagram = datagram;
90
91 // inits the member variables state, idle, dev_idx, link_state,
92 // slaves_responding, slave_states and rescan_required
94
95 fsm->retries = 0;
96 fsm->scan_jiffies = 0;
97 fsm->slave = NULL;
98 fsm->sii_request = NULL;
99 fsm->sii_index = 0;
100 fsm->sdo_request = NULL;
101 fsm->soe_request = NULL;
102
103 // init sub-state-machines
106 ec_fsm_pdo_init(&fsm->fsm_pdo, &fsm->fsm_coe);
107#ifdef EC_EOE
109#endif
112 &fsm->fsm_change, &fsm->fsm_coe, &fsm->fsm_soe, &fsm->fsm_pdo,
113 &fsm->fsm_eoe);
115 &fsm->fsm_slave_config, &fsm->fsm_pdo);
116 ec_fsm_sii_init(&fsm->fsm_sii, fsm->datagram);
117}
118
119/****************************************************************************/
120
124 ec_fsm_master_t *fsm
125 )
126{
127 // clear sub-state machines
131#ifdef EC_EOE
133#endif
138}
139
140/****************************************************************************/
141
145 ec_fsm_master_t *fsm
146 )
147{
148 ec_device_index_t dev_idx;
149
151 fsm->idle = 0;
152 fsm->dev_idx = EC_DEVICE_MAIN;
153
154 for (dev_idx = EC_DEVICE_MAIN;
155 dev_idx < ec_master_num_devices(fsm->master); dev_idx++) {
156 fsm->link_state[dev_idx] = 0;
157 fsm->slaves_responding[dev_idx] = 0;
158 fsm->slave_states[dev_idx] = EC_SLAVE_STATE_UNKNOWN;
159 }
160
161 fsm->rescan_required = 0;
162}
163
164/****************************************************************************/
165
174 ec_fsm_master_t *fsm
175 )
176{
177 if (fsm->datagram->state == EC_DATAGRAM_SENT
178 || fsm->datagram->state == EC_DATAGRAM_QUEUED) {
179 // datagram was not sent or received yet.
180 return 0;
181 }
182
183 fsm->state(fsm);
184 return 1;
185}
186
187/****************************************************************************/
188
193 const ec_fsm_master_t *fsm
194 )
195{
196 return fsm->idle;
197}
198
199/****************************************************************************/
200
204 ec_fsm_master_t *fsm
205 )
206{
207 fsm->dev_idx = EC_DEVICE_MAIN;
209 fsm->state(fsm); // execute immediately
210}
211
212/*****************************************************************************
213 * Master state machine
214 ****************************************************************************/
215
221 ec_fsm_master_t *fsm
222 )
223{
224 ec_master_t *master = fsm->master;
225
226 fsm->idle = 1;
227
228 // check for emergency requests
229 if (!list_empty(&master->emerg_reg_requests)) {
230 ec_reg_request_t *request;
231
232 // get first request
233 request = list_entry(master->emerg_reg_requests.next,
234 ec_reg_request_t, list);
235 list_del_init(&request->list); // dequeue
236 request->state = EC_INT_REQUEST_BUSY;
237
238 if (request->transfer_size > fsm->datagram->mem_size) {
239 EC_MASTER_ERR(master, "Emergency request data too large!\n");
240 request->state = EC_INT_REQUEST_FAILURE;
241 wake_up_all(&master->request_queue);
242 fsm->state(fsm); // continue
243 return;
244 }
245
246 if (request->dir != EC_DIR_OUTPUT) {
247 EC_MASTER_ERR(master, "Emergency requests must be"
248 " write requests!\n");
249 request->state = EC_INT_REQUEST_FAILURE;
250 wake_up_all(&master->request_queue);
251 fsm->state(fsm); // continue
252 return;
253 }
254
255 EC_MASTER_DBG(master, 1, "Writing emergency register request...\n");
257 request->address, request->transfer_size);
258 memcpy(fsm->datagram->data, request->data, request->transfer_size);
260 request->state = EC_INT_REQUEST_SUCCESS;
261 wake_up_all(&master->request_queue);
262 return;
263 }
264
265 ec_datagram_brd(fsm->datagram, 0x0130, 2);
267 fsm->datagram->device_index = fsm->dev_idx;
268 fsm->retries = EC_FSM_RETRIES;
270}
271
272/****************************************************************************/
273
279 ec_fsm_master_t *fsm
280 )
281{
282 ec_datagram_t *datagram = fsm->datagram;
283 unsigned int i, size;
284 ec_slave_t *slave;
285 ec_master_t *master = fsm->master;
286
287 if (datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--) {
288 return;
289 }
290
291 // bus topology change?
292 if (datagram->working_counter != fsm->slaves_responding[fsm->dev_idx]) {
293 fsm->rescan_required = 1;
294 fsm->slaves_responding[fsm->dev_idx] = datagram->working_counter;
295 EC_MASTER_INFO(master, "%u slave(s) responding on %s device. "
296 "Re-scanning on next possibility.\n",
297 fsm->slaves_responding[fsm->dev_idx],
298 ec_device_names[fsm->dev_idx != 0]);
299 }
300
301 if (fsm->link_state[fsm->dev_idx] &&
302 !master->devices[fsm->dev_idx].link_state) {
303 ec_device_index_t dev_idx;
304
305 EC_MASTER_DBG(master, 1, "Master state machine detected "
306 "link down on %s device. Clearing slave list.\n",
307 ec_device_names[fsm->dev_idx != 0]);
308
309#ifdef EC_EOE
310 ec_master_eoe_stop(master);
312#endif
314
315 for (dev_idx = EC_DEVICE_MAIN;
316 dev_idx < ec_master_num_devices(master); dev_idx++) {
317 fsm->slave_states[dev_idx] = 0x00;
318 fsm->slaves_responding[dev_idx] = 0; /* Reset to trigger rescan on
319 next link up. */
320 }
321 }
322 fsm->link_state[fsm->dev_idx] = master->devices[fsm->dev_idx].link_state;
323
324 if (datagram->state == EC_DATAGRAM_RECEIVED &&
325 fsm->slaves_responding[fsm->dev_idx]) {
326 uint8_t states = EC_READ_U8(datagram->data);
327 if (states != fsm->slave_states[fsm->dev_idx]) {
328 // slave states changed
329 char state_str[EC_STATE_STRING_SIZE];
330 fsm->slave_states[fsm->dev_idx] = states;
331 ec_state_string(states, state_str, 1);
332 EC_MASTER_INFO(master, "Slave states on %s device: %s.\n",
333 ec_device_names[fsm->dev_idx != 0], state_str);
334 }
335 } else {
336 fsm->slave_states[fsm->dev_idx] = 0x00;
337 }
338
339 fsm->dev_idx++;
340 if (fsm->dev_idx < ec_master_num_devices(master)) {
341 // check number of responding slaves on next device
343 fsm->state(fsm); // execute immediately
344 return;
345 }
346
347 if (fsm->rescan_required) {
348 down(&master->scan_sem);
349 if (!master->allow_scan) {
350 up(&master->scan_sem);
351 } else {
352 unsigned int count = 0, next_dev_slave, ring_position;
353 ec_device_index_t dev_idx;
354
355 master->scan_busy = 1;
356 master->scan_index = 0;
357 up(&master->scan_sem);
358
359 EC_MASTER_INFO(master, "Re-scanning now.\n");
360
361 // clear all slaves and scan the bus
362 fsm->rescan_required = 0;
363 fsm->idle = 0;
364 fsm->scan_jiffies = jiffies;
365
366#ifdef EC_EOE
367 ec_master_eoe_stop(master);
369#endif
371
372 for (dev_idx = EC_DEVICE_MAIN;
373 dev_idx < ec_master_num_devices(master); dev_idx++) {
374 count += fsm->slaves_responding[dev_idx];
375 }
376
377 if (!count) {
378 // no slaves present -> finish state machine.
379 master->scan_busy = 0;
380 wake_up_interruptible(&master->scan_queue);
382 return;
383 }
384
385 size = sizeof(ec_slave_t) * count;
386 if (!(master->slaves =
387 (ec_slave_t *) kmalloc(size, GFP_KERNEL))) {
388 EC_MASTER_ERR(master, "Failed to allocate %u bytes"
389 " of slave memory!\n", size);
390 master->scan_busy = 0;
391 wake_up_interruptible(&master->scan_queue);
393 return;
394 }
395
396 // init slaves
397 dev_idx = EC_DEVICE_MAIN;
398 next_dev_slave = fsm->slaves_responding[dev_idx];
399 ring_position = 0;
400 for (i = 0; i < count; i++, ring_position++) {
401 slave = master->slaves + i;
402 while (i >= next_dev_slave) {
403 dev_idx++;
404 next_dev_slave += fsm->slaves_responding[dev_idx];
405 ring_position = 0;
406 }
407
408 ec_slave_init(slave, master, dev_idx, ring_position, i + 1);
409
410 // do not force reconfiguration in operation phase to avoid
411 // unnecesssary process data interruptions
412 if (master->phase != EC_OPERATION) {
413 slave->force_config = 1;
414 }
415 }
416 master->slave_count = count;
417 master->fsm_slave = master->slaves;
418
419 /* start with first device with slaves responding; at least one
420 * has responding slaves, otherwise count would be zero. */
421 fsm->dev_idx = EC_DEVICE_MAIN;
422 while (!fsm->slaves_responding[fsm->dev_idx]) {
423 fsm->dev_idx++;
424 }
425
427 return;
428 }
429 }
430
431 if (master->slave_count) {
432
433 // application applied configurations
434 if (master->config_changed) {
435 master->config_changed = 0;
436
437 EC_MASTER_DBG(master, 1, "Configuration changed.\n");
438
439 fsm->slave = master->slaves; // begin with first slave
441
442 } else {
443 // fetch state from first slave
444 fsm->slave = master->slaves;
446 0x0130, 2);
447 ec_datagram_zero(datagram);
449 fsm->retries = EC_FSM_RETRIES;
451 }
452 } else {
454 }
455}
456
457/****************************************************************************/
458
464 ec_fsm_master_t *fsm
465 )
466{
467 ec_master_t *master = fsm->master;
468 ec_sii_write_request_t *request;
469 ec_slave_config_t *config;
470 ec_flag_t *flag;
471 int assign_to_pdi;
472
473 // search the first request to be processed
474 while (1) {
475 if (list_empty(&master->sii_requests))
476 break;
477
478 // get first request
479 request = list_entry(master->sii_requests.next,
481 list_del_init(&request->list); // dequeue
482 request->state = EC_INT_REQUEST_BUSY;
483
484 assign_to_pdi = 0;
485 config = request->slave->config;
486 if (config) {
487 flag = ec_slave_config_find_flag(config, "AssignToPdi");
488 if (flag) {
489 assign_to_pdi = flag->value;
490 }
491 }
492
493 if (assign_to_pdi) {
494 fsm->sii_request = request;
495 EC_SLAVE_DBG(request->slave, 1,
496 "Assigning SII back to EtherCAT.\n");
498 0x0500, 0x01);
499 EC_WRITE_U8(fsm->datagram->data, 0x00); // EtherCAT
500 fsm->retries = EC_FSM_RETRIES;
502 return 1;
503 }
504
505 // found pending SII write operation. execute it!
506 EC_SLAVE_DBG(request->slave, 1, "Writing SII data...\n");
507 fsm->sii_request = request;
508 fsm->sii_index = 0;
509 ec_fsm_sii_write(&fsm->fsm_sii, request->slave, request->offset,
512 fsm->state(fsm); // execute immediately
513 return 1;
514 }
515
516 return 0;
517}
518
519/****************************************************************************/
520
526 ec_fsm_master_t *fsm
527 )
528{
529 ec_master_t *master = fsm->master;
530 ec_slave_t *slave;
531 ec_sdo_request_t *sdo_req;
532 ec_soe_request_t *soe_req;
533
534 // search for internal requests to be processed
535 for (slave = master->slaves;
536 slave < master->slaves + master->slave_count;
537 slave++) {
538
539 if (!slave->config) {
540 continue;
541 }
542
543 list_for_each_entry(sdo_req, &slave->config->sdo_requests, list) {
544 if (sdo_req->state == EC_INT_REQUEST_QUEUED) {
545
546 if (ec_sdo_request_timed_out(sdo_req)) {
547 sdo_req->state = EC_INT_REQUEST_FAILURE;
548 EC_SLAVE_DBG(slave, 1, "Internal SDO request"
549 " timed out.\n");
550 continue;
551 }
552
553 if (slave->current_state == EC_SLAVE_STATE_INIT) {
554 sdo_req->state = EC_INT_REQUEST_FAILURE;
555 continue;
556 }
557
558 sdo_req->state = EC_INT_REQUEST_BUSY;
559 EC_SLAVE_DBG(slave, 1, "Processing internal"
560 " SDO request...\n");
561 fsm->idle = 0;
562 fsm->sdo_request = sdo_req;
563 fsm->slave = slave;
565 ec_fsm_coe_transfer(&fsm->fsm_coe, slave, sdo_req);
566 ec_fsm_coe_exec(&fsm->fsm_coe, fsm->datagram);
567 return 1;
568 }
569 }
570
571 list_for_each_entry(soe_req, &slave->config->soe_requests, list) {
572 if (soe_req->state == EC_INT_REQUEST_QUEUED) {
573
574 if (ec_soe_request_timed_out(soe_req)) {
575 soe_req->state = EC_INT_REQUEST_FAILURE;
576 EC_SLAVE_DBG(slave, 1, "Internal SoE request"
577 " timed out.\n");
578 continue;
579 }
580
581 if (slave->current_state == EC_SLAVE_STATE_INIT) {
582 soe_req->state = EC_INT_REQUEST_FAILURE;
583 continue;
584 }
585
586 soe_req->state = EC_INT_REQUEST_BUSY;
587 EC_SLAVE_DBG(slave, 1, "Processing internal"
588 " SoE request...\n");
589 fsm->idle = 0;
590 fsm->soe_request = soe_req;
591 fsm->slave = slave;
593 ec_fsm_soe_transfer(&fsm->fsm_soe, slave, soe_req);
594 ec_fsm_soe_exec(&fsm->fsm_soe, fsm->datagram);
595 return 1;
596 }
597 }
598 }
599 return 0;
600}
601
602/****************************************************************************/
603
609 ec_fsm_master_t *fsm
610 )
611{
612 ec_master_t *master = fsm->master;
613 ec_slave_t *slave;
614
615 // Check for pending internal SDO or SoE requests
617 return;
618 }
619
620 // enable processing of requests
621 for (slave = master->slaves;
622 slave < master->slaves + master->slave_count;
623 slave++) {
625 }
626
627 // check, if slaves have an SDO dictionary to read out.
628 for (slave = master->slaves;
629 slave < master->slaves + master->slave_count;
630 slave++) {
631 if (!(slave->sii.mailbox_protocols & EC_MBOX_COE)
632 || (slave->sii.has_general
634 || slave->sdo_dictionary_fetched
637 || jiffies - slave->jiffies_preop < EC_WAIT_SDO_DICT * HZ
638 ) continue;
639
640 EC_SLAVE_DBG(slave, 1, "Fetching SDO dictionary.\n");
641
642 slave->sdo_dictionary_fetched = 1;
643
644 // start fetching SDO dictionary
645 fsm->idle = 0;
646 fsm->slave = slave;
648 ec_fsm_coe_dictionary(&fsm->fsm_coe, slave);
649 ec_fsm_coe_exec(&fsm->fsm_coe, fsm->datagram); // execute immediately
651 return;
652 }
653
654 // check for pending SII write operations.
656 return; // SII write request found
657 }
658
660}
661
662/****************************************************************************/
663
667 ec_fsm_master_t *fsm
668 )
669{
670 ec_master_t *master = fsm->master;
671
672 // is there another slave to query?
673 fsm->slave++;
674 if (fsm->slave < master->slaves + master->slave_count) {
675 // fetch state from next slave
676 fsm->idle = 1;
678 fsm->slave->station_address, 0x0130, 2);
681 fsm->retries = EC_FSM_RETRIES;
683 return;
684 }
685
686 // all slaves processed
688}
689
690/****************************************************************************/
691
695 ec_fsm_master_t *fsm
696 )
697{
698 ec_master_t *master = fsm->master;
699 ec_slave_t *slave = fsm->slave;
700
701 if (master->config_changed) {
702 master->config_changed = 0;
703
704 // abort iterating through slaves,
705 // first compensate DC system time offsets,
706 // then begin configuring at slave 0
707 EC_MASTER_DBG(master, 1, "Configuration changed"
708 " (aborting state check).\n");
709
710 fsm->slave = master->slaves; // begin with first slave
712 return;
713 }
714
715 // Does the slave have to be configured?
716 if ((slave->current_state != slave->requested_state
717 || slave->force_config) && !slave->error_flag) {
718
719 // Start slave configuration
720 down(&master->config_sem);
721 master->config_busy = 1;
722 up(&master->config_sem);
723
724 if (master->debug_level) {
725 char old_state[EC_STATE_STRING_SIZE],
726 new_state[EC_STATE_STRING_SIZE];
727 ec_state_string(slave->current_state, old_state, 0);
728 ec_state_string(slave->requested_state, new_state, 0);
729 EC_SLAVE_DBG(slave, 1, "Changing state from %s to %s%s.\n",
730 old_state, new_state,
731 slave->force_config ? " (forced)" : "");
732 }
733
734 fsm->idle = 0;
737 fsm->state(fsm); // execute immediately
739 return;
740 }
741
742 // process next slave
744}
745
746/****************************************************************************/
747
753 ec_fsm_master_t *fsm
754 )
755{
756 ec_slave_t *slave = fsm->slave;
757 ec_datagram_t *datagram = fsm->datagram;
758
759 if (datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--) {
760 return;
761 }
762
763 if (datagram->state != EC_DATAGRAM_RECEIVED) {
764 EC_SLAVE_ERR(slave, "Failed to receive AL state datagram: ");
765 ec_datagram_print_state(datagram);
767 return;
768 }
769
770 // did the slave not respond to its station address?
771 if (datagram->working_counter != 1) {
772 if (!slave->error_flag) {
773 slave->error_flag = 1;
774 EC_SLAVE_DBG(slave, 1, "Slave did not respond to state query.\n");
775 }
777 return;
778 }
779
780 // A single slave responded
781 ec_slave_set_state(slave, EC_READ_U8(datagram->data));
782
783 if (!slave->error_flag) {
784 // Check, if new slave state has to be acknowledged
786 fsm->idle = 0;
788 ec_fsm_change_ack(&fsm->fsm_change, slave);
789 fsm->state(fsm); // execute immediately
790 return;
791 }
792
793 // No acknowlegde necessary; check for configuration
795 return;
796 }
797
798 // slave has error flag set; process next one
800}
801
802/****************************************************************************/
803
807 ec_fsm_master_t *fsm
808 )
809{
810 ec_slave_t *slave = fsm->slave;
811
812 if (ec_fsm_change_exec(&fsm->fsm_change)) {
813 return;
814 }
815
816 if (!ec_fsm_change_success(&fsm->fsm_change)) {
817 fsm->slave->error_flag = 1;
818 EC_SLAVE_ERR(slave, "Failed to acknowledge state change.\n");
819 }
820
822}
823
824/****************************************************************************/
825
829 ec_fsm_master_t *fsm
830 )
831{
832 // broadcast clear all station addresses
833 ec_datagram_bwr(fsm->datagram, 0x0010, 2);
834 EC_WRITE_U16(fsm->datagram->data, 0x0000);
835 fsm->datagram->device_index = fsm->dev_idx;
836 fsm->retries = EC_FSM_RETRIES;
838}
839
840/****************************************************************************/
841
845 ec_fsm_master_t *fsm
846 )
847{
848 ec_master_t *master = fsm->master;
849 ec_datagram_t *datagram = fsm->datagram;
850
851 if (datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--) {
852 return;
853 }
854
855 if (datagram->state != EC_DATAGRAM_RECEIVED) {
856 EC_MASTER_ERR(master, "Failed to receive address"
857 " clearing datagram on %s link: ",
858 ec_device_names[fsm->dev_idx != 0]);
859 ec_datagram_print_state(datagram);
860 master->scan_busy = 0;
861 master->scan_index = master->slave_count;
862 wake_up_interruptible(&master->scan_queue);
864 return;
865 }
866
867 if (datagram->working_counter != fsm->slaves_responding[fsm->dev_idx]) {
868 EC_MASTER_WARN(master, "Failed to clear station addresses on %s link:"
869 " Cleared %u of %u",
870 ec_device_names[fsm->dev_idx != 0], datagram->working_counter,
871 fsm->slaves_responding[fsm->dev_idx]);
872 }
873
874 EC_MASTER_DBG(master, 1, "Sending broadcast-write"
875 " to measure transmission delays on %s link.\n",
876 ec_device_names[fsm->dev_idx != 0]);
877
878 ec_datagram_bwr(datagram, 0x0900, 1);
879 ec_datagram_zero(datagram);
880 fsm->datagram->device_index = fsm->dev_idx;
881 fsm->retries = EC_FSM_RETRIES;
883}
884
885/****************************************************************************/
886
890 ec_fsm_master_t *fsm
891 )
892{
893 ec_master_t *master = fsm->master;
894 ec_datagram_t *datagram = fsm->datagram;
895
896 if (datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--) {
897 return;
898 }
899
900 if (datagram->state != EC_DATAGRAM_RECEIVED) {
901 EC_MASTER_ERR(master, "Failed to receive delay measuring datagram"
902 " on %s link: ", ec_device_names[fsm->dev_idx != 0]);
903 ec_datagram_print_state(datagram);
904 master->scan_busy = 0;
905 master->scan_index = master->slave_count;
906 wake_up_interruptible(&master->scan_queue);
908 return;
909 }
910
911 EC_MASTER_DBG(master, 1, "%u slaves responded to delay measuring"
912 " on %s link.\n",
913 datagram->working_counter, ec_device_names[fsm->dev_idx != 0]);
914
915 do {
916 fsm->dev_idx++;
917 } while (fsm->dev_idx < ec_master_num_devices(master) &&
918 !fsm->slaves_responding[fsm->dev_idx]);
919 if (fsm->dev_idx < ec_master_num_devices(master)) {
921 return;
922 }
923
924 EC_MASTER_INFO(master, "Scanning bus.\n");
925
926 // begin scanning of slaves
927 fsm->slave = master->slaves;
928 master->scan_index = 0;
929 EC_MASTER_DBG(master, 1, "Scanning slave %u on %s link.\n",
930 fsm->slave->ring_position,
934 ec_fsm_slave_scan_exec(&fsm->fsm_slave_scan); // execute immediately
936}
937
938/****************************************************************************/
939
945 ec_fsm_master_t *fsm
946 )
947{
948 ec_master_t *master = fsm->master;
949#ifdef EC_EOE
950 ec_slave_t *slave = fsm->slave;
951#endif
952
954 return;
955 }
956
957#ifdef EC_EOE
958 if (slave->sii.mailbox_protocols & EC_MBOX_EOE) {
959 // create EoE handler for this slave
960 ec_eoe_t *eoe;
961 if (!(eoe = kmalloc(sizeof(ec_eoe_t), GFP_KERNEL))) {
962 EC_SLAVE_ERR(slave, "Failed to allocate EoE handler memory!\n");
963 } else if (ec_eoe_init(eoe, slave)) {
964 EC_SLAVE_ERR(slave, "Failed to init EoE handler!\n");
965 kfree(eoe);
966 } else {
967 list_add_tail(&eoe->list, &master->eoe_handlers);
968 }
969 }
970#endif
971
972 // another slave to fetch?
973 fsm->slave++;
974 master->scan_index++;
975 if (fsm->slave < master->slaves + master->slave_count) {
976 EC_MASTER_DBG(master, 1, "Scanning slave %u on %s link.\n",
977 fsm->slave->ring_position,
980 ec_fsm_slave_scan_exec(&fsm->fsm_slave_scan); // execute immediately
982 return;
983 }
984
985 EC_MASTER_INFO(master, "Bus scanning completed in %lu ms.\n",
986 (jiffies - fsm->scan_jiffies) * 1000 / HZ);
987
988 master->scan_busy = 0;
989 master->scan_index = master->slave_count;
990 wake_up_interruptible(&master->scan_queue);
991
992 // Attach slave configurations
994
995 // Calculate DC (needs attached slaves due to reference clock selection)
996 ec_master_calc_dc(master);
997
998#ifdef EC_EOE
999 // check if EoE processing has to be started
1000 ec_master_eoe_start(master);
1001#endif
1002
1003 if (master->slave_count) {
1004 master->config_changed = 0;
1005
1006 fsm->slave = master->slaves; // begin with first slave
1008 } else {
1010 }
1011}
1012
1013/****************************************************************************/
1014
1020 ec_fsm_master_t *fsm
1021 )
1022{
1023 ec_master_t *master = fsm->master;
1024
1026 return;
1027 }
1028
1029 fsm->slave->force_config = 0;
1030
1031 // configuration finished
1032 master->config_busy = 0;
1033 wake_up_interruptible(&master->config_queue);
1034
1036 // TODO: mark slave_config as failed.
1037 }
1038
1039 fsm->idle = 1;
1041}
1042
1043/****************************************************************************/
1044
1048 ec_fsm_master_t *fsm
1049 )
1050{
1051 ec_master_t *master = fsm->master;
1052
1053 if (master->dc_ref_time) {
1054
1055 while (fsm->slave < master->slaves + master->slave_count) {
1056 if (!fsm->slave->base_dc_supported
1057 || !fsm->slave->has_dc_system_time) {
1058 fsm->slave++;
1059 continue;
1060 }
1061
1062 EC_SLAVE_DBG(fsm->slave, 1, "Checking system time offset.\n");
1063
1064 // read DC system time (0x0910, 64 bit)
1065 // gap (64 bit)
1066 // and time offset (0x0920, 64 bit)
1068 0x0910, 24);
1070 fsm->retries = EC_FSM_RETRIES;
1072 return;
1073 }
1074
1075 } else {
1076 if (master->active) {
1077 EC_MASTER_WARN(master, "No application time received up to now,"
1078 " but master already active.\n");
1079 } else {
1080 EC_MASTER_DBG(master, 1, "No app_time received up to now.\n");
1081 }
1082 }
1083
1084 // scanning and setting system times complete
1085 ec_master_request_op(master);
1086 EC_MASTER_DBG(master, 1, "After requesting OP, rescan_required is %u.\n",
1087 fsm->rescan_required);
1089}
1090
1091/****************************************************************************/
1092
1098 ec_fsm_master_t *fsm,
1099 u64 system_time,
1100 u64 old_offset,
1101 unsigned long jiffies_since_read
1102 )
1103{
1104 ec_slave_t *slave = fsm->slave;
1105 u32 correction, system_time32, old_offset32, new_offset;
1106 s32 time_diff;
1107
1108 system_time32 = (u32) system_time;
1109 old_offset32 = (u32) old_offset;
1110
1111 // correct read system time by elapsed time since read operation
1112 correction = jiffies_since_read * 1000 / HZ * 1000000;
1113 system_time32 += correction;
1114 time_diff = (u32) slave->master->app_time - system_time32;
1115
1116 EC_SLAVE_DBG(slave, 1, "DC 32 bit system time offset calculation:"
1117 " system_time=%u (corrected with %u),"
1118 " app_time=%llu, diff=%i\n",
1119 system_time32, correction,
1120 slave->master->app_time, time_diff);
1121
1122 if (EC_ABS(time_diff) > EC_SYSTEM_TIME_TOLERANCE_NS) {
1123 new_offset = time_diff + old_offset32;
1124 EC_SLAVE_DBG(slave, 1, "Setting time offset to %u (was %u)\n",
1125 new_offset, old_offset32);
1126 return (u64) new_offset;
1127 } else {
1128 EC_SLAVE_DBG(slave, 1, "Not touching time offset.\n");
1129 return old_offset;
1130 }
1131}
1132
1133/****************************************************************************/
1134
1140 ec_fsm_master_t *fsm,
1141 u64 system_time,
1142 u64 old_offset,
1143 unsigned long jiffies_since_read
1144 )
1145{
1146 ec_slave_t *slave = fsm->slave;
1147 u64 new_offset, correction;
1148 s64 time_diff;
1149
1150 // correct read system time by elapsed time since read operation
1151 correction = (u64) (jiffies_since_read * 1000 / HZ) * 1000000;
1152 system_time += correction;
1153 time_diff = fsm->slave->master->app_time - system_time;
1154
1155 EC_SLAVE_DBG(slave, 1, "DC 64 bit system time offset calculation:"
1156 " system_time=%llu (corrected with %llu),"
1157 " app_time=%llu, diff=%lli\n",
1158 system_time, correction,
1159 slave->master->app_time, time_diff);
1160
1161 if (EC_ABS(time_diff) > EC_SYSTEM_TIME_TOLERANCE_NS) {
1162 new_offset = time_diff + old_offset;
1163 EC_SLAVE_DBG(slave, 1, "Setting time offset to %llu (was %llu)\n",
1164 new_offset, old_offset);
1165 } else {
1166 new_offset = old_offset;
1167 EC_SLAVE_DBG(slave, 1, "Not touching time offset.\n");
1168 }
1169
1170 return new_offset;
1171}
1172
1173/****************************************************************************/
1174
1178 ec_fsm_master_t *fsm
1179 )
1180{
1181 ec_datagram_t *datagram = fsm->datagram;
1182 ec_slave_t *slave = fsm->slave;
1183 u64 system_time, old_offset, new_offset;
1184 unsigned long jiffies_since_read;
1185
1186 if (datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--)
1187 return;
1188
1189 if (datagram->state != EC_DATAGRAM_RECEIVED) {
1190 EC_SLAVE_ERR(slave, "Failed to receive DC times datagram: ");
1191 ec_datagram_print_state(datagram);
1192 fsm->slave++;
1194 return;
1195 }
1196
1197 if (datagram->working_counter != 1) {
1198 EC_SLAVE_WARN(slave, "Failed to get DC times: ");
1200 fsm->slave++;
1202 return;
1203 }
1204
1205 system_time = EC_READ_U64(datagram->data); // 0x0910
1206 old_offset = EC_READ_U64(datagram->data + 16); // 0x0920
1207 jiffies_since_read = jiffies - datagram->jiffies_sent;
1208
1209 if (slave->base_dc_range == EC_DC_32) {
1210 new_offset = ec_fsm_master_dc_offset32(fsm,
1211 system_time, old_offset, jiffies_since_read);
1212 } else {
1213 new_offset = ec_fsm_master_dc_offset64(fsm,
1214 system_time, old_offset, jiffies_since_read);
1215 }
1216
1217 // set DC system time offset and transmission delay
1218 ec_datagram_fpwr(datagram, slave->station_address, 0x0920, 12);
1219 EC_WRITE_U64(datagram->data, new_offset);
1220 EC_WRITE_U32(datagram->data + 8, slave->transmission_delay);
1221 fsm->datagram->device_index = slave->device_index;
1222 fsm->retries = EC_FSM_RETRIES;
1224}
1225
1226/****************************************************************************/
1227
1231 ec_fsm_master_t *fsm
1232 )
1233{
1234 ec_datagram_t *datagram = fsm->datagram;
1235 ec_slave_t *slave = fsm->slave;
1236
1237 if (datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--)
1238 return;
1239
1240 if (datagram->state != EC_DATAGRAM_RECEIVED) {
1241 EC_SLAVE_ERR(slave,
1242 "Failed to receive DC system time offset datagram: ");
1243 ec_datagram_print_state(datagram);
1244 fsm->slave++;
1246 return;
1247 }
1248
1249 if (datagram->working_counter != 1) {
1250 EC_SLAVE_ERR(slave, "Failed to set DC system time offset: ");
1252 fsm->slave++;
1254 return;
1255 }
1256
1257 fsm->slave++;
1259}
1260
1261/****************************************************************************/
1262
1266 ec_fsm_master_t *fsm
1267 )
1268{
1269 ec_datagram_t *datagram = fsm->datagram;
1270 ec_sii_write_request_t *request = fsm->sii_request;
1271 ec_slave_t *slave = request->slave;
1272
1273 if (datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--)
1274 return;
1275
1276 if (datagram->state != EC_DATAGRAM_RECEIVED) {
1277 EC_SLAVE_ERR(slave, "Failed to receive SII assignment datagram: ");
1278 ec_datagram_print_state(datagram);
1279 goto cont;
1280 }
1281
1282 if (datagram->working_counter != 1) {
1283 EC_SLAVE_ERR(slave, "Failed to assign SII back to EtherCAT: ");
1285 goto cont;
1286 }
1287
1288cont:
1289 // found pending SII write operation. execute it!
1290 EC_SLAVE_DBG(slave, 1, "Writing SII data (after assignment)...\n");
1291 fsm->sii_index = 0;
1292 ec_fsm_sii_write(&fsm->fsm_sii, slave, request->offset,
1295 fsm->state(fsm); // execute immediately
1296}
1297
1298/****************************************************************************/
1299
1303 ec_fsm_master_t *fsm
1304 )
1305{
1306 ec_master_t *master = fsm->master;
1307 ec_sii_write_request_t *request = fsm->sii_request;
1308 ec_slave_t *slave = request->slave;
1309
1310 if (ec_fsm_sii_exec(&fsm->fsm_sii)) return;
1311
1312 if (!ec_fsm_sii_success(&fsm->fsm_sii)) {
1313 EC_SLAVE_ERR(slave, "Failed to write SII data.\n");
1314 request->state = EC_INT_REQUEST_FAILURE;
1315 wake_up_all(&master->request_queue);
1317 return;
1318 }
1319
1320 fsm->sii_index++;
1321 if (fsm->sii_index < request->nwords) {
1322 ec_fsm_sii_write(&fsm->fsm_sii, slave,
1323 request->offset + fsm->sii_index,
1324 request->words + fsm->sii_index,
1326 ec_fsm_sii_exec(&fsm->fsm_sii); // execute immediately
1327 return;
1328 }
1329
1330 // finished writing SII
1331 EC_SLAVE_DBG(slave, 1, "Finished writing %zu words of SII data.\n",
1332 request->nwords);
1333
1334 if (request->offset <= 4 && request->offset + request->nwords > 4) {
1335 // alias was written
1336 slave->sii.alias = EC_READ_U16(request->words + 4);
1337 // TODO: read alias from register 0x0012
1338 slave->effective_alias = slave->sii.alias;
1339 }
1340 // TODO: Evaluate other SII contents!
1341
1342 request->state = EC_INT_REQUEST_SUCCESS;
1343 wake_up_all(&master->request_queue);
1344
1345 // check for another SII write request
1347 return; // processing another request
1348
1350}
1351
1352/****************************************************************************/
1353
1357 ec_fsm_master_t *fsm
1358 )
1359{
1360 ec_slave_t *slave = fsm->slave;
1361 ec_master_t *master = fsm->master;
1362
1363 if (ec_fsm_coe_exec(&fsm->fsm_coe, fsm->datagram)) {
1364 return;
1365 }
1366
1367 if (!ec_fsm_coe_success(&fsm->fsm_coe)) {
1369 return;
1370 }
1371
1372 // SDO dictionary fetching finished
1373
1374 if (master->debug_level) {
1375 unsigned int sdo_count, entry_count;
1376 ec_slave_sdo_dict_info(slave, &sdo_count, &entry_count);
1377 EC_SLAVE_DBG(slave, 1, "Fetched %u SDOs and %u entries.\n",
1378 sdo_count, entry_count);
1379 }
1380
1381 // attach pdo names from dictionary
1383
1385}
1386
1387/****************************************************************************/
1388
1392 ec_fsm_master_t *fsm
1393 )
1394{
1395 ec_sdo_request_t *request = fsm->sdo_request;
1396
1397 if (!request) {
1398 // configuration was cleared in the meantime
1400 return;
1401 }
1402
1403 if (ec_fsm_coe_exec(&fsm->fsm_coe, fsm->datagram)) {
1404 return;
1405 }
1406
1407 if (!ec_fsm_coe_success(&fsm->fsm_coe)) {
1408 EC_SLAVE_DBG(fsm->slave, 1,
1409 "Failed to process internal SDO request.\n");
1410 request->state = EC_INT_REQUEST_FAILURE;
1411 wake_up_all(&fsm->master->request_queue);
1413 return;
1414 }
1415
1416 // SDO request finished
1417 request->state = EC_INT_REQUEST_SUCCESS;
1418 wake_up_all(&fsm->master->request_queue);
1419
1420 EC_SLAVE_DBG(fsm->slave, 1, "Finished internal SDO request.\n");
1421
1422 // check for another SDO/SoE request
1424 return; // processing another request
1425 }
1426
1428}
1429
1430/****************************************************************************/
1431
1435 ec_fsm_master_t *fsm
1436 )
1437{
1438 ec_soe_request_t *request = fsm->soe_request;
1439
1440 if (!request) {
1441 // configuration was cleared in the meantime
1443 return;
1444 }
1445
1446 if (ec_fsm_soe_exec(&fsm->fsm_soe, fsm->datagram)) {
1447 return;
1448 }
1449
1450 if (!ec_fsm_soe_success(&fsm->fsm_soe)) {
1451 EC_SLAVE_DBG(fsm->slave, 1,
1452 "Failed to process internal SoE request.\n");
1453 request->state = EC_INT_REQUEST_FAILURE;
1454 wake_up_all(&fsm->master->request_queue);
1456 return;
1457 }
1458
1459 // SoE request finished
1460 request->state = EC_INT_REQUEST_SUCCESS;
1461 wake_up_all(&fsm->master->request_queue);
1462
1463 EC_SLAVE_DBG(fsm->slave, 1, "Finished internal SoE request.\n");
1464
1465 // check for another CoE/SoE request
1467 return; // processing another request
1468 }
1469
1471}
1472
1473/****************************************************************************/
void ec_datagram_print_wc_error(const ec_datagram_t *datagram)
Evaluates the working counter of a single-cast datagram.
Definition datagram.c:594
void ec_datagram_zero(ec_datagram_t *datagram)
Fills the datagram payload memory with zeros.
Definition datagram.c:170
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:202
int ec_datagram_brd(ec_datagram_t *datagram, uint16_t mem_address, size_t data_size)
Initializes an EtherCAT BRD datagram.
Definition datagram.c:365
int ec_datagram_bwr(ec_datagram_t *datagram, uint16_t mem_address, size_t data_size)
Initializes an EtherCAT BWR datagram.
Definition datagram.c:385
void ec_datagram_print_state(const ec_datagram_t *datagram)
Prints the state of a datagram.
Definition datagram.c:557
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:290
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:265
@ EC_DATAGRAM_RECEIVED
Received (dequeued).
Definition datagram.h:70
@ EC_DATAGRAM_TIMED_OUT
Timed out (dequeued).
Definition datagram.h:71
@ EC_DATAGRAM_SENT
Sent (still in the queue).
Definition datagram.h:69
@ EC_DATAGRAM_QUEUED
Queued for sending.
Definition datagram.h:68
int ec_eoe_init(ec_eoe_t *eoe, ec_slave_t *slave)
EoE constructor.
Definition ethernet.c:111
Ethernet over EtherCAT (EoE)
struct ec_eoe ec_eoe_t
Definition ethernet.h:66
int ec_fsm_change_success(ec_fsm_change_t *fsm)
Returns, if the state machine terminated with success.
Definition fsm_change.c:172
void ec_fsm_change_init(ec_fsm_change_t *fsm, ec_datagram_t *datagram)
Constructor.
Definition fsm_change.c:54
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:140
void ec_fsm_change_clear(ec_fsm_change_t *fsm)
Destructor.
Definition fsm_change.c:69
int ec_fsm_change_exec(ec_fsm_change_t *fsm)
Executes the current state of the state machine.
Definition fsm_change.c:157
void ec_fsm_coe_dictionary(ec_fsm_coe_t *fsm, ec_slave_t *slave)
Starts reading a slaves' SDO dictionary.
Definition fsm_coe.c:197
int ec_fsm_coe_success(const ec_fsm_coe_t *fsm)
Returns, if the state machine terminated with success.
Definition fsm_coe.c:267
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:210
void ec_fsm_coe_init(ec_fsm_coe_t *fsm)
Constructor.
Definition fsm_coe.c:175
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:233
void ec_fsm_coe_clear(ec_fsm_coe_t *fsm)
Destructor.
Definition fsm_coe.c:187
void ec_fsm_eoe_clear(ec_fsm_eoe_t *fsm)
Destructor.
Definition fsm_eoe.c:94
void ec_fsm_eoe_init(ec_fsm_eoe_t *fsm)
Constructor.
Definition fsm_eoe.c:77
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:173
void ec_fsm_master_state_scan_slave(ec_fsm_master_t *)
Master state: SCAN SLAVE.
Definition fsm_master.c:944
int ec_fsm_master_action_process_int_request(ec_fsm_master_t *)
Check for pending internal SDO/SoE requests and process one.
Definition fsm_master.c:525
void ec_fsm_master_state_dc_measure_delays(ec_fsm_master_t *)
Master state: DC MEASURE DELAYS.
Definition fsm_master.c:889
void ec_fsm_master_state_acknowledge(ec_fsm_master_t *)
Master state: ACKNOWLEDGE.
Definition fsm_master.c:806
void ec_fsm_master_state_sdo_request(ec_fsm_master_t *)
Master state: SDO REQUEST.
void ec_fsm_master_state_dc_write_offset(ec_fsm_master_t *)
Master state: DC WRITE OFFSET.
void ec_fsm_master_init(ec_fsm_master_t *fsm, ec_master_t *master, ec_datagram_t *datagram)
Constructor.
Definition fsm_master.c:82
void ec_fsm_master_action_next_slave_state(ec_fsm_master_t *)
Master action: Get state of next slave.
Definition fsm_master.c:666
void ec_fsm_master_state_soe_request(ec_fsm_master_t *)
Master state: SoE REQUEST.
void ec_fsm_master_state_sdo_dictionary(ec_fsm_master_t *)
Master state: SDO DICTIONARY.
int ec_fsm_master_idle(const ec_fsm_master_t *fsm)
Definition fsm_master.c:192
void ec_fsm_master_state_clear_addresses(ec_fsm_master_t *)
Master state: CLEAR ADDRESSES.
Definition fsm_master.c:844
void ec_fsm_master_enter_write_system_times(ec_fsm_master_t *)
Start writing DC system times.
void ec_fsm_master_action_configure(ec_fsm_master_t *)
Master action: Configure.
Definition fsm_master.c:694
void ec_fsm_master_state_read_state(ec_fsm_master_t *)
Master state: READ STATE.
Definition fsm_master.c:752
int ec_fsm_master_action_process_sii(ec_fsm_master_t *)
Check for pending SII write requests and process one.
Definition fsm_master.c:463
void ec_fsm_master_restart(ec_fsm_master_t *)
Restarts the master state machine.
Definition fsm_master.c:203
u64 ec_fsm_master_dc_offset32(ec_fsm_master_t *, u64, u64, unsigned long)
Configure 32 bit time offset.
void ec_fsm_master_enter_clear_addresses(ec_fsm_master_t *)
Start clearing slave addresses.
Definition fsm_master.c:828
#define EC_SYSTEM_TIME_TOLERANCE_NS
Time difference [ns] to tolerate without setting a new system time offset.
Definition fsm_master.c:43
void ec_fsm_master_state_broadcast(ec_fsm_master_t *)
Master state: BROADCAST.
Definition fsm_master.c:278
void ec_fsm_master_state_configure_slave(ec_fsm_master_t *)
Master state: CONFIGURE SLAVE.
void ec_fsm_master_state_write_sii(ec_fsm_master_t *)
Master state: WRITE SII.
u64 ec_fsm_master_dc_offset64(ec_fsm_master_t *, u64, u64, unsigned long)
Configure 64 bit time offset.
void ec_fsm_master_state_dc_read_offset(ec_fsm_master_t *)
Master state: DC READ OFFSET.
void ec_fsm_master_clear(ec_fsm_master_t *fsm)
Destructor.
Definition fsm_master.c:123
void ec_fsm_master_state_start(ec_fsm_master_t *)
Master state: START.
Definition fsm_master.c:220
void ec_fsm_master_state_assign_sii(ec_fsm_master_t *)
Master state: ASSIGN SII.
void ec_fsm_master_action_idle(ec_fsm_master_t *)
Master action: IDLE.
Definition fsm_master.c:608
void ec_fsm_master_reset(ec_fsm_master_t *fsm)
Reset state machine.
Definition fsm_master.c:144
EtherCAT master state machine.
struct ec_fsm_master ec_fsm_master_t
Definition fsm_master.h:56
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:144
void ec_fsm_sii_clear(ec_fsm_sii_t *fsm)
Destructor.
Definition fsm_sii.c:80
int ec_fsm_sii_exec(ec_fsm_sii_t *fsm)
Executes the SII state machine.
Definition fsm_sii.c:129
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:108
void ec_fsm_sii_init(ec_fsm_sii_t *fsm, ec_datagram_t *datagram)
Constructor.
Definition fsm_sii.c:66
@ EC_FSM_SII_USE_CONFIGURED_ADDRESS
Use configured addresses.
Definition fsm_sii.h:42
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:160
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_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, ec_fsm_eoe_t *fsm_eoe)
Constructor.
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:107
int ec_fsm_soe_exec(ec_fsm_soe_t *fsm, ec_datagram_t *datagram)
Executes the current state of the state machine.
Definition fsm_soe.c:152
void ec_fsm_soe_transfer(ec_fsm_soe_t *fsm, ec_slave_t *slave, ec_soe_request_t *request)
Starts to transfer an IDN to/from a slave.
Definition fsm_soe.c:130
void ec_fsm_soe_clear(ec_fsm_soe_t *fsm)
Destructor.
Definition fsm_soe.c:120
int ec_fsm_soe_success(const ec_fsm_soe_t *fsm)
Returns, if the state machine terminated with success.
Definition fsm_soe.c:187
Global definitions and macros.
@ EC_SLAVE_STATE_UNKNOWN
unknown state
Definition globals.h:122
@ EC_SLAVE_STATE_INIT
INIT state (no mailbox communication, no IO)
Definition globals.h:124
@ EC_SLAVE_STATE_ACK_ERR
Acknowledge/Error bit (no actual state)
Definition globals.h:134
#define EC_ABS(X)
Absolute value.
Definition globals.h:251
#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
@ EC_MBOX_COE
CANopen over EtherCAT.
Definition globals.h:146
@ EC_MBOX_EOE
Ethernet over EtherCAT.
Definition globals.h:145
#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:401
@ EC_DC_32
32 bit.
Definition globals.h:173
struct ec_slave ec_slave_t
Definition globals.h:310
const char * ec_device_names[2]
Device names.
Definition module.c:465
ec_device_index_t
Master devices.
Definition globals.h:198
@ EC_DEVICE_MAIN
Main device.
Definition globals.h:199
struct ec_soe_request ec_soe_request_t
Definition ecrt.h:312
#define EC_WRITE_U8(DATA, VAL)
Write an 8-bit unsigned value to EtherCAT data.
Definition ecrt.h:3040
struct ec_sdo_request ec_sdo_request_t
Definition ecrt.h:309
struct ec_master ec_master_t
Definition ecrt.h:300
struct ec_slave_config ec_slave_config_t
Definition ecrt.h:303
struct ec_reg_request ec_reg_request_t
Definition ecrt.h:318
#define EC_WRITE_U32(DATA, VAL)
Write a 32-bit unsigned value to EtherCAT data.
Definition ecrt.h:3074
#define EC_READ_U16(DATA)
Read a 16-bit unsigned value from EtherCAT data.
Definition ecrt.h:2948
#define EC_READ_U64(DATA)
Read a 64-bit unsigned value from EtherCAT data.
Definition ecrt.h:2980
#define EC_READ_U8(DATA)
Read an 8-bit unsigned value from EtherCAT data.
Definition ecrt.h:2932
#define EC_WRITE_U64(DATA, VAL)
Write a 64-bit unsigned value to EtherCAT data.
Definition ecrt.h:3091
#define EC_WRITE_U16(DATA, VAL)
Write a 16-bit unsigned value to EtherCAT data.
Definition ecrt.h:3057
@ EC_DIR_OUTPUT
Values written by the master.
Definition ecrt.h:506
Mailbox functionality.
void ec_master_request_op(ec_master_t *master)
Request OP state for configured slaves.
Definition master.c:2234
void ec_master_eoe_start(ec_master_t *master)
Starts Ethernet over EtherCAT processing on demand.
Definition master.c:1690
void ec_master_attach_slave_configs(ec_master_t *master)
Attaches the slave configurations to the slaves.
Definition master.c:1802
void ec_master_calc_dc(ec_master_t *master)
Distributed-clocks calculations.
Definition master.c:2217
void ec_master_clear_eoe_handlers(ec_master_t *master)
Clear and free all EoE handlers.
Definition master.c:461
void ec_master_clear_slaves(ec_master_t *master)
Clear all slaves.
Definition master.c:497
void ec_master_eoe_stop(ec_master_t *master)
Stops the Ethernet over EtherCAT processing.
Definition master.c:1724
EtherCAT master structure.
#define ec_master_num_devices(MASTER)
Number of Ethernet devices.
Definition master.h:323
#define EC_MASTER_INFO(master, fmt, args...)
Convenience macro for printing master-specific information to syslog.
Definition master.h:62
#define EC_MASTER_DBG(master, level, fmt, args...)
Convenience macro for printing master-specific debug messages to syslog.
Definition master.h:100
@ EC_OPERATION
Operation phase.
Definition master.h:128
#define EC_MASTER_ERR(master, fmt, args...)
Convenience macro for printing master-specific errors to syslog.
Definition master.h:74
#define EC_MASTER_WARN(master, fmt, args...)
Convenience macro for printing master-specific warnings to syslog.
Definition master.h:86
int ec_sdo_request_timed_out(const ec_sdo_request_t *req)
Checks, if the timeout was exceeded.
void ec_slave_attach_pdo_names(ec_slave_t *slave)
Attach PDO names.
Definition slave.c:791
void ec_slave_set_state(ec_slave_t *slave, ec_slave_state_t new_state)
Sets the application state of a slave.
Definition slave.c:284
void ec_slave_sdo_dict_info(const ec_slave_t *slave, unsigned int *sdo_count, unsigned int *entry_count)
Counts the total number of SDOs and entries in the dictionary.
Definition slave.c:618
void ec_slave_init(ec_slave_t *slave, ec_master_t *master, ec_device_index_t dev_idx, uint16_t ring_position, uint16_t station_address)
Slave constructor.
Definition slave.c:60
#define EC_SLAVE_DBG(slave, level, fmt, args...)
Convenience macro for printing slave-specific debug messages to syslog.
Definition slave.h:98
#define EC_SLAVE_ERR(slave, fmt, args...)
Convenience macro for printing slave-specific errors to syslog.
Definition slave.h:68
#define EC_SLAVE_WARN(slave, fmt, args...)
Convenience macro for printing slave-specific warnings to syslog.
Definition slave.h:82
ec_flag_t * ec_slave_config_find_flag(ec_slave_config_t *sc, const char *key)
Finds a flag.
EtherCAT slave configuration structure.
int ec_soe_request_timed_out(const ec_soe_request_t *req)
Checks, if the timeout was exceeded.
EtherCAT datagram.
Definition datagram.h:79
size_t mem_size
Datagram data memory size.
Definition datagram.h:90
uint16_t working_counter
Working counter.
Definition datagram.h:93
unsigned long jiffies_sent
Jiffies, when the datagram was sent.
Definition datagram.h:98
ec_datagram_state_t state
State.
Definition datagram.h:94
ec_device_index_t device_index
Device via which the datagram shall be / was sent.
Definition datagram.h:84
uint8_t * data
Datagram payload.
Definition datagram.h:88
uint8_t link_state
device link state
Definition device.h:80
struct list_head list
list item
Definition ethernet.h:76
Slave configutation feature flag.
Definition flag.h:38
int32_t value
Flag value (meaning depends on key).
Definition flag.h:41
unsigned int slaves_responding[EC_MAX_NUM_DEVICES]
Number of responding slaves for every device.
Definition fsm_master.h:72
ec_sii_write_request_t * sii_request
SII write request.
Definition fsm_master.h:80
unsigned int rescan_required
A bus rescan is required.
Definition fsm_master.h:75
ec_fsm_coe_t fsm_coe
CoE state machine.
Definition fsm_master.h:85
void(* state)(ec_fsm_master_t *)
master state function
Definition fsm_master.h:65
ec_sdo_request_t * sdo_request
SDO request to process.
Definition fsm_master.h:82
ec_datagram_t * datagram
datagram used in the state machine
Definition fsm_master.h:62
ec_soe_request_t * soe_request
SoE request to process.
Definition fsm_master.h:83
ec_fsm_change_t fsm_change
State change state machine.
Definition fsm_master.h:89
uint8_t link_state[EC_MAX_NUM_DEVICES]
Last link state for every device.
Definition fsm_master.h:70
unsigned int retries
retries on datagram timeout.
Definition fsm_master.h:63
ec_slave_state_t slave_states[EC_MAX_NUM_DEVICES]
AL states of responding slaves for every device.
Definition fsm_master.h:76
ec_fsm_pdo_t fsm_pdo
PDO configuration state machine.
Definition fsm_master.h:87
int idle
state machine is in idle phase
Definition fsm_master.h:68
ec_slave_t * slave
current slave
Definition fsm_master.h:79
ec_fsm_eoe_t fsm_eoe
EoE state machine.
Definition fsm_master.h:88
ec_device_index_t dev_idx
Current device index (for scanning etc.).
Definition fsm_master.h:66
ec_fsm_soe_t fsm_soe
SoE state machine.
Definition fsm_master.h:86
ec_fsm_slave_config_t fsm_slave_config
slave state machine
Definition fsm_master.h:90
unsigned long scan_jiffies
beginning of slave scanning
Definition fsm_master.h:69
off_t sii_index
index to SII write request data
Definition fsm_master.h:81
ec_fsm_sii_t fsm_sii
SII state machine.
Definition fsm_master.h:92
ec_fsm_slave_scan_t fsm_slave_scan
slave state machine
Definition fsm_master.h:91
ec_master_t * master
master the FSM runs on
Definition fsm_master.h:61
struct list_head eoe_handlers
Ethernet over EtherCAT handlers.
Definition master.h:283
struct list_head emerg_reg_requests
Emergency register access requests.
Definition master.h:298
wait_queue_head_t request_queue
Wait queue for external requests from user space.
Definition master.h:301
struct list_head sii_requests
SII write requests.
Definition master.h:297
u64 app_time
Time of the last ecrt_master_sync() call.
Definition master.h:227
wait_queue_head_t scan_queue
Queue for processes that wait for slave scanning.
Definition master.h:244
unsigned int scan_busy
Current scan state.
Definition master.h:239
unsigned int slave_count
Number of slaves on the bus.
Definition master.h:221
unsigned int config_busy
State of slave configuration.
Definition master.h:247
struct semaphore config_sem
Semaphore protecting the config_busy variable and the allow_config flag.
Definition master.h:248
u64 dc_ref_time
Common reference timestamp for DC start times.
Definition master.h:228
ec_slave_t * fsm_slave
Slave that is queried next for FSM exec.
Definition master.h:271
wait_queue_head_t config_queue
Queue for processes that wait for slave configuration.
Definition master.h:250
struct semaphore scan_sem
Semaphore protecting the scan_busy variable and the allow_scan flag.
Definition master.h:242
ec_slave_t * slaves
Array of slaves on the bus.
Definition master.h:220
unsigned int active
Master has been activated.
Definition master.h:213
unsigned int debug_level
Master debug level.
Definition master.h:275
unsigned int allow_scan
True, if slave scanning is allowed.
Definition master.h:241
unsigned int config_changed
The configuration changed.
Definition master.h:214
unsigned int scan_index
Index of slave currently scanned.
Definition master.h:240
ec_master_phase_t phase
Master phase.
Definition master.h:212
ec_device_t devices[EC_MAX_NUM_DEVICES]
EtherCAT devices.
Definition master.h:200
uint8_t * data
Pointer to data memory.
Definition reg_request.h:43
struct list_head list
List item.
Definition reg_request.h:41
uint16_t address
Register address.
Definition reg_request.h:46
uint16_t ring_position
Ring position for emergency requests.
Definition reg_request.h:49
ec_direction_t dir
Direction.
Definition reg_request.h:44
ec_internal_request_state_t state
Request state.
Definition reg_request.h:48
size_t transfer_size
Size of the data to transfer.
Definition reg_request.h:47
ec_internal_request_state_t state
SDO request state.
Definition sdo_request.h:55
uint8_t enable_sdo_info
SDO information service available.
Definition globals.h:156
uint16_t alias
Configured station alias.
Definition slave.h:126
uint16_t mailbox_protocols
Supported mailbox protocols.
Definition slave.h:139
ec_sii_coe_details_t coe_details
CoE detail flags.
Definition slave.h:152
unsigned int has_general
General category present.
Definition slave.h:146
SII write request.
Definition fsm_master.h:45
struct list_head list
List head.
Definition fsm_master.h:46
ec_slave_t * slave
EtherCAT slave.
Definition fsm_master.h:47
ec_internal_request_state_t state
State of the request.
Definition fsm_master.h:51
const uint16_t * words
Pointer to the data words.
Definition fsm_master.h:50
size_t nwords
Number of words.
Definition fsm_master.h:49
uint16_t offset
SII word offset.
Definition fsm_master.h:48
struct list_head sdo_requests
List of SDO requests.
struct list_head soe_requests
List of SoE requests.
ec_sii_t sii
Extracted SII data.
Definition slave.h:215
unsigned int force_config
Force (re-)configuration.
Definition slave.h:186
uint32_t transmission_delay
DC system time transmission delay (offset from reference clock).
Definition slave.h:207
uint8_t base_dc_supported
Distributed clocks are supported.
Definition slave.h:202
uint16_t ring_position
Ring position.
Definition slave.h:175
ec_slave_config_t * config
Current configuration.
Definition slave.h:182
ec_slave_state_t current_state
Current application state.
Definition slave.h:184
uint8_t has_dc_system_time
The slave supports the DC system time register.
Definition slave.h:204
ec_slave_dc_range_t base_dc_range
DC range.
Definition slave.h:203
uint8_t sdo_dictionary_fetched
Dictionary has been fetched.
Definition slave.h:218
uint16_t effective_alias
Effective alias address.
Definition slave.h:177
ec_device_index_t device_index
Index of device the slave responds on.
Definition slave.h:171
ec_master_t * master
Master owning the slave.
Definition slave.h:170
uint16_t station_address
Configured station address.
Definition slave.h:176
ec_fsm_slave_t fsm
Slave state machine.
Definition slave.h:227
unsigned int error_flag
Stop processing after an error.
Definition slave.h:185
unsigned long jiffies_preop
Time, the slave went to PREOP.
Definition slave.h:219
ec_slave_state_t requested_state
Requested application state.
Definition slave.h:183
ec_internal_request_state_t state
Request state.
Definition soe_request.h:52