IgH EtherCAT Master  1.6.12
fsm_master.c
Go to the documentation of this file.
1/*****************************************************************************
2 *
3 * Copyright (C) 2006-2026 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#include "smp.h"
36
37#include "fsm_master.h"
38#include "fsm_foe.h"
39
40/****************************************************************************/
41
44#define EC_SYSTEM_TIME_TOLERANCE_NS 1000000
45
46/****************************************************************************/
47
48// prototypes for private methods
55u64 ec_fsm_master_dc_offset32(ec_fsm_master_t *, u64, u64, unsigned long);
56u64 ec_fsm_master_dc_offset64(ec_fsm_master_t *, u64, u64, unsigned long);
57
58/****************************************************************************/
59
75
78
79/****************************************************************************/
80
84 ec_fsm_master_t *fsm,
85 ec_master_t *master,
86 ec_datagram_t *datagram
87 )
88{
89 fsm->master = master;
90 fsm->datagram = datagram;
91
92 // inits the member variables state, idle, dev_idx, link_state,
93 // slaves_responding, slave_states and rescan_required
95
96 fsm->retries = 0;
97 fsm->scan_jiffies = 0;
98 fsm->slave = NULL;
99 fsm->sii_request = NULL;
100 fsm->sii_index = 0;
101 fsm->sdo_request = NULL;
102 fsm->soe_request = NULL;
103
104 // init sub-state-machines
107 ec_fsm_pdo_init(&fsm->fsm_pdo, &fsm->fsm_coe);
108#ifdef EC_EOE
110#endif
113 &fsm->fsm_change, &fsm->fsm_coe, &fsm->fsm_soe, &fsm->fsm_pdo,
114 &fsm->fsm_eoe);
116 &fsm->fsm_slave_config, &fsm->fsm_pdo);
117 ec_fsm_sii_init(&fsm->fsm_sii, fsm->datagram);
118}
119
120/****************************************************************************/
121
125 ec_fsm_master_t *fsm
126 )
127{
128 // clear sub-state machines
132#ifdef EC_EOE
134#endif
139}
140
141/****************************************************************************/
142
146 ec_fsm_master_t *fsm
147 )
148{
149 ec_device_index_t dev_idx;
150
152 fsm->idle = 0;
153 fsm->dev_idx = EC_DEVICE_MAIN;
154
155 for (dev_idx = EC_DEVICE_MAIN;
156 dev_idx < ec_master_num_devices(fsm->master); dev_idx++) {
157 fsm->link_state[dev_idx] = 0;
158 fsm->slaves_responding[dev_idx] = 0;
159 fsm->slave_states[dev_idx] = EC_SLAVE_STATE_UNKNOWN;
160 }
161
162 fsm->rescan_required = 0;
163}
164
165/****************************************************************************/
166
175 ec_fsm_master_t *fsm
176 )
177{
178 ec_datagram_state_t state = smp_load_acquire(&fsm->datagram->state);
179
180 if (state == EC_DATAGRAM_SENT || state == EC_DATAGRAM_QUEUED) {
181 // datagram was not sent or received yet.
182 return 0;
183 }
184
185 fsm->state(fsm);
186 return 1;
187}
188
189/****************************************************************************/
190
195 const ec_fsm_master_t *fsm
196 )
197{
198 return fsm->idle;
199}
200
201/****************************************************************************/
202
206 ec_fsm_master_t *fsm
207 )
208{
209 fsm->dev_idx = EC_DEVICE_MAIN;
211 fsm->state(fsm); // execute immediately
212}
213
214/*****************************************************************************
215 * Master state machine
216 ****************************************************************************/
217
223 ec_fsm_master_t *fsm
224 )
225{
226 ec_master_t *master = fsm->master;
227
228 fsm->idle = 1;
229
230 // check for emergency requests
231 if (!list_empty(&master->emerg_reg_requests)) {
232 ec_reg_request_t *request;
233
234 // get first request
235 request = list_entry(master->emerg_reg_requests.next,
236 ec_reg_request_t, list);
237 list_del_init(&request->list); // dequeue
238 request->state = EC_INT_REQUEST_BUSY;
239
240 if (request->transfer_size > fsm->datagram->mem_size) {
241 EC_MASTER_ERR(master, "Emergency request data too large!\n");
242 request->state = EC_INT_REQUEST_FAILURE;
243 wake_up_all(&master->request_queue);
244 fsm->state(fsm); // continue
245 return;
246 }
247
248 if (request->dir != EC_DIR_OUTPUT) {
249 EC_MASTER_ERR(master, "Emergency requests must be"
250 " write requests!\n");
251 request->state = EC_INT_REQUEST_FAILURE;
252 wake_up_all(&master->request_queue);
253 fsm->state(fsm); // continue
254 return;
255 }
256
257 EC_MASTER_DBG(master, 1, "Writing emergency register request...\n");
259 request->address, request->transfer_size);
260 memcpy(fsm->datagram->data, request->data, request->transfer_size);
262 request->state = EC_INT_REQUEST_SUCCESS;
263 wake_up_all(&master->request_queue);
264 return;
265 }
266
267 ec_datagram_brd(fsm->datagram, 0x0130, 2);
269 fsm->datagram->device_index = fsm->dev_idx;
270 fsm->retries = EC_FSM_RETRIES;
272}
273
274/****************************************************************************/
275
281 ec_fsm_master_t *fsm
282 )
283{
284 ec_datagram_t *datagram = fsm->datagram;
285 unsigned int i, size;
286 ec_slave_t *slave;
287 ec_master_t *master = fsm->master;
288
289 if (datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--) {
290 return;
291 }
292
293 // bus topology change?
294 if (datagram->working_counter != fsm->slaves_responding[fsm->dev_idx]) {
295 fsm->rescan_required = 1;
296 fsm->slaves_responding[fsm->dev_idx] = datagram->working_counter;
297 EC_MASTER_INFO(master, "%u slave(s) responding on %s device. "
298 "Re-scanning on next possibility.\n",
299 fsm->slaves_responding[fsm->dev_idx],
300 ec_device_names[fsm->dev_idx != 0]);
301 }
302
303 if (fsm->link_state[fsm->dev_idx] &&
304 !master->devices[fsm->dev_idx].link_state) {
305 ec_device_index_t dev_idx;
306
307 EC_MASTER_DBG(master, 1, "Master state machine detected "
308 "link down on %s device. Clearing slave list.\n",
309 ec_device_names[fsm->dev_idx != 0]);
310
311#ifdef EC_EOE
312 ec_master_eoe_stop(master);
314#endif
316
317 for (dev_idx = EC_DEVICE_MAIN;
318 dev_idx < ec_master_num_devices(master); dev_idx++) {
319 fsm->slave_states[dev_idx] = 0x00;
320 /* Reset to trigger rescan on next link up. */
321 fsm->slaves_responding[dev_idx] = 0;
322 }
323 }
324 fsm->link_state[fsm->dev_idx] = master->devices[fsm->dev_idx].link_state;
325
326 if (datagram->state == EC_DATAGRAM_RECEIVED &&
327 fsm->slaves_responding[fsm->dev_idx]) {
328 uint8_t states = EC_READ_U8(datagram->data);
329 if (states != fsm->slave_states[fsm->dev_idx]) {
330 // slave states changed
331 char state_str[EC_STATE_STRING_SIZE];
332 fsm->slave_states[fsm->dev_idx] = states;
333 ec_state_string(states, state_str, 1);
334 EC_MASTER_INFO(master, "Slave states on %s device: %s.\n",
335 ec_device_names[fsm->dev_idx != 0], state_str);
336 }
337 } else {
338 fsm->slave_states[fsm->dev_idx] = 0x00;
339 }
340
341 fsm->dev_idx++;
342 if (fsm->dev_idx < ec_master_num_devices(master)) {
343 // check number of responding slaves on next device
345 fsm->state(fsm); // execute immediately
346 return;
347 }
348
349 if (fsm->rescan_required) {
350 down(&master->scan_sem);
351 if (!master->allow_scan) {
352 up(&master->scan_sem);
353 } else {
354 unsigned int count = 0, next_dev_slave, ring_position;
355 ec_device_index_t dev_idx;
356
357 master->scan_busy = 1;
358 master->scan_index = 0;
359 up(&master->scan_sem);
360
361 EC_MASTER_INFO(master, "Re-scanning now.\n");
362
363 // clear all slaves and scan the bus
364 fsm->rescan_required = 0;
365 fsm->idle = 0;
366 fsm->scan_jiffies = jiffies;
367
368#ifdef EC_EOE
369 ec_master_eoe_stop(master);
371#endif
373
374 for (dev_idx = EC_DEVICE_MAIN;
375 dev_idx < ec_master_num_devices(master); dev_idx++) {
376 count += fsm->slaves_responding[dev_idx];
377 }
378
379 if (!count) {
380 // no slaves present -> finish state machine.
381 master->scan_busy = 0;
382 wake_up_interruptible(&master->scan_queue);
384 return;
385 }
386
387 size = sizeof(ec_slave_t) * count;
388 if (!(master->slaves =
389 (ec_slave_t *) kmalloc(size, GFP_KERNEL))) {
390 EC_MASTER_ERR(master, "Failed to allocate %u bytes"
391 " of slave memory!\n", size);
392 master->scan_busy = 0;
393 wake_up_interruptible(&master->scan_queue);
395 return;
396 }
397
398 // init slaves
399 dev_idx = EC_DEVICE_MAIN;
400 next_dev_slave = fsm->slaves_responding[dev_idx];
401 ring_position = 0;
402 for (i = 0; i < count; i++, ring_position++) {
403 slave = master->slaves + i;
404 while (i >= next_dev_slave) {
405 dev_idx++;
406 next_dev_slave += fsm->slaves_responding[dev_idx];
407 ring_position = 0;
408 }
409
410 ec_slave_init(slave, master, dev_idx, ring_position, i + 1);
411
412 // do not force reconfiguration in operation phase to avoid
413 // unnecesssary process data interruptions
414 if (master->phase != EC_OPERATION) {
415 slave->force_config = 1;
416 }
417 }
418 master->slave_count = count;
419 master->fsm_slave = master->slaves;
420
421 /* start with first device with slaves responding; at least one
422 * has responding slaves, otherwise count would be zero. */
423 fsm->dev_idx = EC_DEVICE_MAIN;
424 while (!fsm->slaves_responding[fsm->dev_idx]) {
425 fsm->dev_idx++;
426 }
427
429 return;
430 }
431 }
432
433 if (master->slave_count) {
434 // application applied configurations
435 if (master->config_changed) {
436 master->config_changed = 0;
437
438 EC_MASTER_DBG(master, 1, "Configuration changed.\n");
439
440 fsm->slave = master->slaves; // begin with first slave
442 }
443 else {
444 // fetch state from first slave
445 fsm->slave = master->slaves;
447 0x0130, 2);
448 ec_datagram_zero(datagram);
450 fsm->retries = EC_FSM_RETRIES;
452 }
453 } else {
455 }
456}
457
458/****************************************************************************/
459
465 ec_fsm_master_t *fsm
466 )
467{
468 ec_master_t *master = fsm->master;
469 ec_sii_write_request_t *request;
470 ec_slave_config_t *config;
471 ec_flag_t *flag;
472 int assign_to_pdi;
473
474 // search the first request to be processed
475 while (1) {
476 if (list_empty(&master->sii_requests))
477 break;
478
479 // get first request
480 request = list_entry(master->sii_requests.next,
482 list_del_init(&request->list); // dequeue
483 request->state = EC_INT_REQUEST_BUSY;
484
485 assign_to_pdi = 0;
486 config = request->slave->config;
487 if (config) {
488 flag = ec_slave_config_find_flag(config, "AssignToPdi");
489 if (flag) {
490 assign_to_pdi = flag->value;
491 }
492 }
493
494 if (assign_to_pdi) {
495 fsm->sii_request = request;
496 EC_SLAVE_DBG(request->slave, 1,
497 "Assigning SII back to EtherCAT.\n");
499 0x0500, 0x01);
500 EC_WRITE_U8(fsm->datagram->data, 0x00); // EtherCAT
501 fsm->retries = EC_FSM_RETRIES;
503 return 1;
504 }
505
506 // found pending SII write operation. execute it!
507 EC_SLAVE_DBG(request->slave, 1, "Writing SII data...\n");
508 fsm->sii_request = request;
509 fsm->sii_index = 0;
510 ec_fsm_sii_write(&fsm->fsm_sii, request->slave, request->offset,
513 fsm->state(fsm); // execute immediately
514 return 1;
515 }
516
517 return 0;
518}
519
520/****************************************************************************/
521
527 ec_fsm_master_t *fsm
528 )
529{
530 ec_master_t *master = fsm->master;
531 ec_slave_t *slave;
532 ec_sdo_request_t *sdo_req;
533 ec_soe_request_t *soe_req;
534
535 // search for internal requests to be processed
536 for (slave = master->slaves;
537 slave < master->slaves + master->slave_count;
538 slave++) {
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 if (ec_sdo_request_timed_out(sdo_req)) {
546 sdo_req->state = EC_INT_REQUEST_FAILURE;
547 EC_SLAVE_DBG(slave, 1, "Internal SDO request"
548 " timed out.\n");
549 continue;
550 }
551
552 if (slave->current_state == EC_SLAVE_STATE_INIT) {
553 sdo_req->state = EC_INT_REQUEST_FAILURE;
554 continue;
555 }
556
557 sdo_req->state = EC_INT_REQUEST_BUSY;
558 EC_SLAVE_DBG(slave, 1, "Processing internal"
559 " SDO request...\n");
560 fsm->idle = 0;
561 fsm->sdo_request = sdo_req;
562 fsm->slave = slave;
564 ec_fsm_coe_transfer(&fsm->fsm_coe, slave, sdo_req);
565 ec_fsm_coe_exec(&fsm->fsm_coe, fsm->datagram);
566 return 1;
567 }
568 }
569
570 list_for_each_entry(soe_req, &slave->config->soe_requests, list) {
571 if (soe_req->state == EC_INT_REQUEST_QUEUED) {
572 if (ec_soe_request_timed_out(soe_req)) {
573 soe_req->state = EC_INT_REQUEST_FAILURE;
574 EC_SLAVE_DBG(slave, 1, "Internal SoE request"
575 " timed out.\n");
576 continue;
577 }
578
579 if (slave->current_state == EC_SLAVE_STATE_INIT) {
580 soe_req->state = EC_INT_REQUEST_FAILURE;
581 continue;
582 }
583
584 soe_req->state = EC_INT_REQUEST_BUSY;
585 EC_SLAVE_DBG(slave, 1, "Processing internal"
586 " SoE request...\n");
587 fsm->idle = 0;
588 fsm->soe_request = soe_req;
589 fsm->slave = slave;
591 ec_fsm_soe_transfer(&fsm->fsm_soe, slave, soe_req);
592 ec_fsm_soe_exec(&fsm->fsm_soe, fsm->datagram);
593 return 1;
594 }
595 }
596 }
597 return 0;
598}
599
600/****************************************************************************/
601
607 ec_fsm_master_t *fsm
608 )
609{
610 ec_master_t *master = fsm->master;
611 ec_slave_t *slave;
612
613 // Check for pending internal SDO or SoE requests
615 return;
616 }
617
618 // enable processing of requests
619 for (slave = master->slaves;
620 slave < master->slaves + master->slave_count;
621 slave++) {
623 }
624
625 // check, if slaves have an SDO dictionary to read out.
626 for (slave = master->slaves;
627 slave < master->slaves + master->slave_count;
628 slave++) {
629 if (!(slave->sii.mailbox_protocols & EC_MBOX_COE)
630 || (slave->sii.has_general
632 || slave->sdo_dictionary_fetched
635 || jiffies - slave->jiffies_preop < EC_WAIT_SDO_DICT * HZ) {
636 continue;
637 }
638
639 EC_SLAVE_DBG(slave, 1, "Fetching SDO dictionary.\n");
640
641 slave->sdo_dictionary_fetched = 1;
642
643 // start fetching SDO dictionary
644 fsm->idle = 0;
645 fsm->slave = slave;
647 ec_fsm_coe_dictionary(&fsm->fsm_coe, slave);
648 ec_fsm_coe_exec(&fsm->fsm_coe, fsm->datagram); // execute immediately
650 return;
651 }
652
653 // check for pending SII write operations.
655 return; // SII write request found
656 }
657
659}
660
661/****************************************************************************/
662
666 ec_fsm_master_t *fsm
667 )
668{
669 ec_master_t *master = fsm->master;
670
671 // is there another slave to query?
672 fsm->slave++;
673 if (fsm->slave < master->slaves + master->slave_count) {
674 // fetch state from next slave
675 fsm->idle = 1;
677 fsm->slave->station_address, 0x0130, 2);
680 fsm->retries = EC_FSM_RETRIES;
682 return;
683 }
684
685 // all slaves processed
687}
688
689/****************************************************************************/
690
694 ec_fsm_master_t *fsm
695 )
696{
697 ec_master_t *master = fsm->master;
698 ec_slave_t *slave = fsm->slave;
699
700 if (master->config_changed) {
701 master->config_changed = 0;
702
703 // abort iterating through slaves,
704 // first compensate DC system time offsets,
705 // then begin configuring at slave 0
706 EC_MASTER_DBG(master, 1, "Configuration changed"
707 " (aborting state check).\n");
708
709 fsm->slave = master->slaves; // begin with first slave
711 return;
712 }
713
714 // Does the slave have to be configured?
715 if ((slave->current_state != slave->requested_state
716 || slave->force_config) && !slave->error_flag) {
717 // Start slave configuration
718 down(&master->config_sem);
719 master->config_busy = 1;
720 up(&master->config_sem);
721
722 if (master->debug_level) {
723 char old_state[EC_STATE_STRING_SIZE],
724 new_state[EC_STATE_STRING_SIZE];
725 ec_state_string(slave->current_state, old_state, 0);
726 ec_state_string(slave->requested_state, new_state, 0);
727 EC_SLAVE_DBG(slave, 1, "Changing state from %s to %s%s.\n",
728 old_state, new_state,
729 slave->force_config ? " (forced)" : "");
730 }
731
732 fsm->idle = 0;
735 fsm->state(fsm); // execute immediately
737 return;
738 }
739
740 // process next slave
742}
743
744/****************************************************************************/
745
751 ec_fsm_master_t *fsm
752 )
753{
754 ec_slave_t *slave = fsm->slave;
755 ec_datagram_t *datagram = fsm->datagram;
756
757 if (datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--) {
758 return;
759 }
760
761 if (datagram->state != EC_DATAGRAM_RECEIVED) {
762 EC_SLAVE_ERR(slave, "Failed to receive AL state datagram: ");
763 ec_datagram_print_state(datagram);
765 return;
766 }
767
768 // did the slave not respond to its station address?
769 if (datagram->working_counter != 1) {
770 if (!slave->error_flag) {
771 slave->error_flag = 1;
772 EC_SLAVE_DBG(slave, 1, "Slave did not respond to state query.\n");
773 }
775 return;
776 }
777
778 // A single slave responded
779 ec_slave_set_state(slave, EC_READ_U8(datagram->data));
780
781 if (!slave->error_flag) {
782 // Check, if new slave state has to be acknowledged
784 fsm->idle = 0;
786 ec_fsm_change_ack(&fsm->fsm_change, slave);
787 fsm->state(fsm); // execute immediately
788 return;
789 }
790
791 // No acknowlegde necessary; check for configuration
793 return;
794 }
795
796 // slave has error flag set; process next one
798}
799
800/****************************************************************************/
801
805 ec_fsm_master_t *fsm
806 )
807{
808 ec_slave_t *slave = fsm->slave;
809
810 if (ec_fsm_change_exec(&fsm->fsm_change)) {
811 return;
812 }
813
814 if (!ec_fsm_change_success(&fsm->fsm_change)) {
815 fsm->slave->error_flag = 1;
816 EC_SLAVE_ERR(slave, "Failed to acknowledge state change.\n");
817 }
818
820}
821
822/****************************************************************************/
823
827 ec_fsm_master_t *fsm
828 )
829{
830 // broadcast clear all station addresses
831 ec_datagram_bwr(fsm->datagram, 0x0010, 2);
832 EC_WRITE_U16(fsm->datagram->data, 0x0000);
833 fsm->datagram->device_index = fsm->dev_idx;
834 fsm->retries = EC_FSM_RETRIES;
836}
837
838/****************************************************************************/
839
843 ec_fsm_master_t *fsm
844 )
845{
846 ec_master_t *master = fsm->master;
847 ec_datagram_t *datagram = fsm->datagram;
848
849 if (datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--) {
850 return;
851 }
852
853 if (datagram->state != EC_DATAGRAM_RECEIVED) {
854 EC_MASTER_ERR(master, "Failed to receive address"
855 " clearing datagram on %s link: ",
856 ec_device_names[fsm->dev_idx != 0]);
857 ec_datagram_print_state(datagram);
858 master->scan_busy = 0;
859 master->scan_index = master->slave_count;
860 wake_up_interruptible(&master->scan_queue);
862 return;
863 }
864
865 if (datagram->working_counter != fsm->slaves_responding[fsm->dev_idx]) {
866 EC_MASTER_WARN(master, "Failed to clear station addresses on %s link:"
867 " Cleared %u of %u",
868 ec_device_names[fsm->dev_idx != 0], datagram->working_counter,
869 fsm->slaves_responding[fsm->dev_idx]);
870 }
871
872 EC_MASTER_DBG(master, 1, "Sending broadcast-write"
873 " to measure transmission delays on %s link.\n",
874 ec_device_names[fsm->dev_idx != 0]);
875
876 ec_datagram_bwr(datagram, 0x0900, 1);
877 ec_datagram_zero(datagram);
878 fsm->datagram->device_index = fsm->dev_idx;
879 fsm->retries = EC_FSM_RETRIES;
881}
882
883/****************************************************************************/
884
888 ec_fsm_master_t *fsm
889 )
890{
891 ec_master_t *master = fsm->master;
892 ec_datagram_t *datagram = fsm->datagram;
893
894 if (datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--) {
895 return;
896 }
897
898 if (datagram->state != EC_DATAGRAM_RECEIVED) {
899 EC_MASTER_ERR(master, "Failed to receive delay measuring datagram"
900 " on %s link: ", ec_device_names[fsm->dev_idx != 0]);
901 ec_datagram_print_state(datagram);
902 master->scan_busy = 0;
903 master->scan_index = master->slave_count;
904 wake_up_interruptible(&master->scan_queue);
906 return;
907 }
908
909 EC_MASTER_DBG(master, 1, "%u slaves responded to delay measuring"
910 " on %s link.\n",
911 datagram->working_counter, ec_device_names[fsm->dev_idx != 0]);
912
913 do {
914 fsm->dev_idx++;
915 } while (fsm->dev_idx < ec_master_num_devices(master) &&
916 !fsm->slaves_responding[fsm->dev_idx]);
917 if (fsm->dev_idx < ec_master_num_devices(master)) {
919 return;
920 }
921
922 EC_MASTER_INFO(master, "Scanning bus.\n");
923
924 // begin scanning of slaves
925 fsm->slave = master->slaves;
926 master->scan_index = 0;
927 EC_MASTER_DBG(master, 1, "Scanning slave %u on %s link.\n",
928 fsm->slave->ring_position,
932 ec_fsm_slave_scan_exec(&fsm->fsm_slave_scan); // execute immediately
934}
935
936/****************************************************************************/
937
943 ec_fsm_master_t *fsm
944 )
945{
946 ec_master_t *master = fsm->master;
947#ifdef EC_EOE
948 ec_slave_t *slave = fsm->slave;
949#endif
950
952 return;
953 }
954
955#ifdef EC_EOE
956 if (slave->sii.mailbox_protocols & EC_MBOX_EOE) {
957 // create EoE handler for this slave
958 ec_eoe_t *eoe;
959 if (!(eoe = kmalloc(sizeof(ec_eoe_t), GFP_KERNEL))) {
960 EC_SLAVE_ERR(slave, "Failed to allocate EoE handler memory!\n");
961 } else if (ec_eoe_init(eoe, slave)) {
962 EC_SLAVE_ERR(slave, "Failed to init EoE handler!\n");
963 kfree(eoe);
964 } else {
965 list_add_tail(&eoe->list, &master->eoe_handlers);
966 }
967 }
968#endif
969
970 // another slave to fetch?
971 fsm->slave++;
972 master->scan_index++;
973 if (fsm->slave < master->slaves + master->slave_count) {
974 EC_MASTER_DBG(master, 1, "Scanning slave %u on %s link.\n",
975 fsm->slave->ring_position,
978 ec_fsm_slave_scan_exec(&fsm->fsm_slave_scan); // execute immediately
980 return;
981 }
982
983 EC_MASTER_INFO(master, "Bus scanning completed in %lu ms.\n",
984 (jiffies - fsm->scan_jiffies) * 1000 / HZ);
985
986 master->scan_busy = 0;
987 master->scan_index = master->slave_count;
988 wake_up_interruptible(&master->scan_queue);
989
990 // Attach slave configurations
992
993 // Calculate DC (needs attached slaves due to reference clock selection)
994 ec_master_calc_dc(master);
995
996#ifdef EC_EOE
997 // check if EoE processing has to be started
998 ec_master_eoe_start(master);
999#endif
1000
1001 if (master->slave_count) {
1002 master->config_changed = 0;
1003
1004 fsm->slave = master->slaves; // begin with first slave
1006 } else {
1008 }
1009}
1010
1011/****************************************************************************/
1012
1018 ec_fsm_master_t *fsm
1019 )
1020{
1021 ec_master_t *master = fsm->master;
1022
1024 return;
1025 }
1026
1027 fsm->slave->force_config = 0;
1028
1029 // configuration finished
1030 master->config_busy = 0;
1031 wake_up_interruptible(&master->config_queue);
1032
1034 // TODO(fp): mark slave_config as failed.
1035 }
1036
1037 fsm->idle = 1;
1039}
1040
1041/****************************************************************************/
1042
1046 ec_fsm_master_t *fsm
1047 )
1048{
1049 ec_master_t *master = fsm->master;
1050
1051 if (master->dc_ref_time) {
1052 while (fsm->slave < master->slaves + master->slave_count) {
1053 if (!fsm->slave->base_dc_supported
1054 || !fsm->slave->has_dc_system_time) {
1055 fsm->slave++;
1056 continue;
1057 }
1058
1059 EC_SLAVE_DBG(fsm->slave, 1, "Checking system time offset.\n");
1060
1061 // read DC system time (0x0910, 64 bit)
1062 // gap (64 bit)
1063 // and time offset (0x0920, 64 bit)
1065 0x0910, 24);
1067 fsm->retries = EC_FSM_RETRIES;
1069 return;
1070 }
1071
1072 } else {
1073 if (master->active) {
1074 EC_MASTER_WARN(master, "No application time received up to now,"
1075 " but master already active.\n");
1076 } else {
1077 EC_MASTER_DBG(master, 1, "No app_time received up to now.\n");
1078 }
1079 }
1080
1081 // scanning and setting system times complete
1082 ec_master_request_op(master);
1083 EC_MASTER_DBG(master, 1, "After requesting OP, rescan_required is %u.\n",
1084 fsm->rescan_required);
1086}
1087
1088/****************************************************************************/
1089
1095 ec_fsm_master_t *fsm,
1096 u64 system_time,
1097 u64 old_offset,
1098 unsigned long jiffies_since_read
1099 )
1100{
1101 ec_slave_t *slave = fsm->slave;
1102 u32 correction, system_time32, old_offset32, new_offset;
1103 s32 time_diff;
1104
1105 system_time32 = (u32) system_time;
1106 old_offset32 = (u32) old_offset;
1107
1108 // correct read system time by elapsed time since read operation
1109 correction = jiffies_since_read * 1000 / HZ * 1000000;
1110 system_time32 += correction;
1111 time_diff = (u32) slave->master->app_time - system_time32;
1112
1113 EC_SLAVE_DBG(slave, 1, "DC 32 bit system time offset calculation:"
1114 " system_time=%u (corrected with %u),"
1115 " app_time=%llu, diff=%i\n",
1116 system_time32, correction,
1117 slave->master->app_time, time_diff);
1118
1119 if (EC_ABS(time_diff) > EC_SYSTEM_TIME_TOLERANCE_NS) {
1120 new_offset = time_diff + old_offset32;
1121 EC_SLAVE_DBG(slave, 1, "Setting time offset to %u (was %u)\n",
1122 new_offset, old_offset32);
1123 return (u64) new_offset;
1124 } else {
1125 EC_SLAVE_DBG(slave, 1, "Not touching time offset.\n");
1126 return old_offset;
1127 }
1128}
1129
1130/****************************************************************************/
1131
1137 ec_fsm_master_t *fsm,
1138 u64 system_time,
1139 u64 old_offset,
1140 unsigned long jiffies_since_read
1141 )
1142{
1143 ec_slave_t *slave = fsm->slave;
1144 u64 new_offset, correction;
1145 s64 time_diff;
1146
1147 // correct read system time by elapsed time since read operation
1148 correction = (u64) (jiffies_since_read * 1000 / HZ) * 1000000;
1149 system_time += correction;
1150 time_diff = fsm->slave->master->app_time - system_time;
1151
1152 EC_SLAVE_DBG(slave, 1, "DC 64 bit system time offset calculation:"
1153 " system_time=%llu (corrected with %llu),"
1154 " app_time=%llu, diff=%lli\n",
1155 system_time, correction,
1156 slave->master->app_time, time_diff);
1157
1158 if (EC_ABS(time_diff) > EC_SYSTEM_TIME_TOLERANCE_NS) {
1159 new_offset = time_diff + old_offset;
1160 EC_SLAVE_DBG(slave, 1, "Setting time offset to %llu (was %llu)\n",
1161 new_offset, old_offset);
1162 } else {
1163 new_offset = old_offset;
1164 EC_SLAVE_DBG(slave, 1, "Not touching time offset.\n");
1165 }
1166
1167 return new_offset;
1168}
1169
1170/****************************************************************************/
1171
1175 ec_fsm_master_t *fsm
1176 )
1177{
1178 ec_datagram_t *datagram = fsm->datagram;
1179 ec_slave_t *slave = fsm->slave;
1180 u64 system_time, old_offset, new_offset;
1181 unsigned long jiffies_since_read;
1182
1183 if (datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--)
1184 return;
1185
1186 if (datagram->state != EC_DATAGRAM_RECEIVED) {
1187 EC_SLAVE_ERR(slave, "Failed to receive DC times datagram: ");
1188 ec_datagram_print_state(datagram);
1189 fsm->slave++;
1191 return;
1192 }
1193
1194 if (datagram->working_counter != 1) {
1195 EC_SLAVE_WARN(slave, "Failed to get DC times: ");
1197 fsm->slave++;
1199 return;
1200 }
1201
1202 system_time = EC_READ_U64(datagram->data); // 0x0910
1203 old_offset = EC_READ_U64(datagram->data + 16); // 0x0920
1204 jiffies_since_read = jiffies - datagram->jiffies_sent;
1205
1206 if (slave->base_dc_range == EC_DC_32) {
1207 new_offset = ec_fsm_master_dc_offset32(fsm,
1208 system_time, old_offset, jiffies_since_read);
1209 } else {
1210 new_offset = ec_fsm_master_dc_offset64(fsm,
1211 system_time, old_offset, jiffies_since_read);
1212 }
1213
1214 // set DC system time offset and transmission delay
1215 ec_datagram_fpwr(datagram, slave->station_address, 0x0920, 12);
1216 EC_WRITE_U64(datagram->data, new_offset);
1217 EC_WRITE_U32(datagram->data + 8, slave->transmission_delay);
1218 fsm->datagram->device_index = slave->device_index;
1219 fsm->retries = EC_FSM_RETRIES;
1221}
1222
1223/****************************************************************************/
1224
1228 ec_fsm_master_t *fsm
1229 )
1230{
1231 ec_datagram_t *datagram = fsm->datagram;
1232 ec_slave_t *slave = fsm->slave;
1233
1234 if (datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--)
1235 return;
1236
1237 if (datagram->state != EC_DATAGRAM_RECEIVED) {
1238 EC_SLAVE_ERR(slave,
1239 "Failed to receive DC system time offset datagram: ");
1240 ec_datagram_print_state(datagram);
1241 fsm->slave++;
1243 return;
1244 }
1245
1246 if (datagram->working_counter != 1) {
1247 EC_SLAVE_ERR(slave, "Failed to set DC system time offset: ");
1249 fsm->slave++;
1251 return;
1252 }
1253
1254 fsm->slave++;
1256}
1257
1258/****************************************************************************/
1259
1263 ec_fsm_master_t *fsm
1264 )
1265{
1266 ec_datagram_t *datagram = fsm->datagram;
1267 ec_sii_write_request_t *request = fsm->sii_request;
1268 ec_slave_t *slave = request->slave;
1269
1270 if (datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--)
1271 return;
1272
1273 if (datagram->state != EC_DATAGRAM_RECEIVED) {
1274 EC_SLAVE_ERR(slave, "Failed to receive SII assignment datagram: ");
1275 ec_datagram_print_state(datagram);
1276 goto cont;
1277 }
1278
1279 if (datagram->working_counter != 1) {
1280 EC_SLAVE_ERR(slave, "Failed to assign SII back to EtherCAT: ");
1282 goto cont;
1283 }
1284
1285cont:
1286 // found pending SII write operation. execute it!
1287 EC_SLAVE_DBG(slave, 1, "Writing SII data (after assignment)...\n");
1288 fsm->sii_index = 0;
1289 ec_fsm_sii_write(&fsm->fsm_sii, slave, request->offset,
1292 fsm->state(fsm); // execute immediately
1293}
1294
1295/****************************************************************************/
1296
1300 ec_fsm_master_t *fsm
1301 )
1302{
1303 ec_master_t *master = fsm->master;
1304 ec_sii_write_request_t *request = fsm->sii_request;
1305 ec_slave_t *slave = request->slave;
1306
1307 if (ec_fsm_sii_exec(&fsm->fsm_sii)) return;
1308
1309 if (!ec_fsm_sii_success(&fsm->fsm_sii)) {
1310 EC_SLAVE_ERR(slave, "Failed to write SII data.\n");
1311 request->state = EC_INT_REQUEST_FAILURE;
1312 wake_up_all(&master->request_queue);
1314 return;
1315 }
1316
1317 fsm->sii_index++;
1318 if (fsm->sii_index < request->nwords) {
1319 ec_fsm_sii_write(&fsm->fsm_sii, slave,
1320 request->offset + fsm->sii_index,
1321 request->words + fsm->sii_index,
1323 ec_fsm_sii_exec(&fsm->fsm_sii); // execute immediately
1324 return;
1325 }
1326
1327 // finished writing SII
1328 EC_SLAVE_DBG(slave, 1, "Finished writing %zu words of SII data.\n",
1329 request->nwords);
1330
1331 if (request->offset <= 4 && request->offset + request->nwords > 4) {
1332 // alias was written
1333 slave->sii.alias = EC_READ_U16(request->words + 4);
1334 // TODO(fp): read alias from register 0x0012
1335 slave->effective_alias = slave->sii.alias;
1336 }
1337 // TODO(fp): Evaluate other SII contents!
1338
1339 request->state = EC_INT_REQUEST_SUCCESS;
1340 wake_up_all(&master->request_queue);
1341
1342 // check for another SII write request
1344 return; // processing another request
1345
1347}
1348
1349/****************************************************************************/
1350
1354 ec_fsm_master_t *fsm
1355 )
1356{
1357 ec_slave_t *slave = fsm->slave;
1358 ec_master_t *master = fsm->master;
1359
1360 if (ec_fsm_coe_exec(&fsm->fsm_coe, fsm->datagram)) {
1361 return;
1362 }
1363
1364 if (!ec_fsm_coe_success(&fsm->fsm_coe)) {
1366 return;
1367 }
1368
1369 // SDO dictionary fetching finished
1370
1371 if (master->debug_level) {
1372 unsigned int sdo_count, entry_count;
1373 ec_slave_sdo_dict_info(slave, &sdo_count, &entry_count);
1374 EC_SLAVE_DBG(slave, 1, "Fetched %u SDOs and %u entries.\n",
1375 sdo_count, entry_count);
1376 }
1377
1378 // attach pdo names from dictionary
1380
1382}
1383
1384/****************************************************************************/
1385
1389 ec_fsm_master_t *fsm
1390 )
1391{
1392 ec_sdo_request_t *request = fsm->sdo_request;
1393
1394 if (!request) {
1395 // configuration was cleared in the meantime
1397 return;
1398 }
1399
1400 if (ec_fsm_coe_exec(&fsm->fsm_coe, fsm->datagram)) {
1401 return;
1402 }
1403
1404 if (!ec_fsm_coe_success(&fsm->fsm_coe)) {
1405 EC_SLAVE_DBG(fsm->slave, 1,
1406 "Failed to process internal SDO request.\n");
1407 request->state = EC_INT_REQUEST_FAILURE;
1408 wake_up_all(&fsm->master->request_queue);
1410 return;
1411 }
1412
1413 // SDO request finished
1414 request->state = EC_INT_REQUEST_SUCCESS;
1415 wake_up_all(&fsm->master->request_queue);
1416
1417 EC_SLAVE_DBG(fsm->slave, 1, "Finished internal SDO request.\n");
1418
1419 // check for another SDO/SoE request
1421 return; // processing another request
1422 }
1423
1425}
1426
1427/****************************************************************************/
1428
1432 ec_fsm_master_t *fsm
1433 )
1434{
1435 ec_soe_request_t *request = fsm->soe_request;
1436
1437 if (!request) {
1438 // configuration was cleared in the meantime
1440 return;
1441 }
1442
1443 if (ec_fsm_soe_exec(&fsm->fsm_soe, fsm->datagram)) {
1444 return;
1445 }
1446
1447 if (!ec_fsm_soe_success(&fsm->fsm_soe)) {
1448 EC_SLAVE_DBG(fsm->slave, 1,
1449 "Failed to process internal SoE request.\n");
1450 request->state = EC_INT_REQUEST_FAILURE;
1451 wake_up_all(&fsm->master->request_queue);
1453 return;
1454 }
1455
1456 // SoE request finished
1457 request->state = EC_INT_REQUEST_SUCCESS;
1458 wake_up_all(&fsm->master->request_queue);
1459
1460 EC_SLAVE_DBG(fsm->slave, 1, "Finished internal SoE request.\n");
1461
1462 // check for another CoE/SoE request
1464 return; // processing another request
1465 }
1466
1468}
1469
1470/****************************************************************************/
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_state_t
EtherCAT datagram state.
Definition datagram.h:66
@ 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:174
void ec_fsm_master_state_scan_slave(ec_fsm_master_t *)
Master state: SCAN SLAVE.
Definition fsm_master.c:942
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:526
void ec_fsm_master_state_dc_measure_delays(ec_fsm_master_t *)
Master state: DC MEASURE DELAYS.
Definition fsm_master.c:887
void ec_fsm_master_state_acknowledge(ec_fsm_master_t *)
Master state: ACKNOWLEDGE.
Definition fsm_master.c:804
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:83
void ec_fsm_master_action_next_slave_state(ec_fsm_master_t *)
Master action: Get state of next slave.
Definition fsm_master.c:665
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:194
void ec_fsm_master_state_clear_addresses(ec_fsm_master_t *)
Master state: CLEAR ADDRESSES.
Definition fsm_master.c:842
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:693
void ec_fsm_master_state_read_state(ec_fsm_master_t *)
Master state: READ STATE.
Definition fsm_master.c:750
int ec_fsm_master_action_process_sii(ec_fsm_master_t *)
Check for pending SII write requests and process one.
Definition fsm_master.c:464
void ec_fsm_master_restart(ec_fsm_master_t *)
Restarts the master state machine.
Definition fsm_master.c:205
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:826
#define EC_SYSTEM_TIME_TOLERANCE_NS
Time difference [ns] to tolerate without setting a new system time offset.
Definition fsm_master.c:44
void ec_fsm_master_state_broadcast(ec_fsm_master_t *)
Master state: BROADCAST.
Definition fsm_master.c:280
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:124
void ec_fsm_master_state_start(ec_fsm_master_t *)
Master state: START.
Definition fsm_master.c:222
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:606
void ec_fsm_master_reset(ec_fsm_master_t *fsm)
Reset state machine.
Definition fsm_master.c:145
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:250
#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:309
const char * ec_device_names[2]
Device names.
Definition module.c:465
ec_device_index_t
Master devices.
Definition globals.h:197
@ EC_DEVICE_MAIN
Main device.
Definition globals.h:198
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:2221
void ec_master_eoe_start(ec_master_t *master)
Starts Ethernet over EtherCAT processing on demand.
Definition master.c:1678
void ec_master_attach_slave_configs(ec_master_t *master)
Attaches the slave configurations to the slaves.
Definition master.c:1790
void ec_master_calc_dc(ec_master_t *master)
Distributed-clocks calculations.
Definition master.c:2204
void ec_master_clear_eoe_handlers(ec_master_t *master)
Clear and free all EoE handlers.
Definition master.c:446
void ec_master_clear_slaves(ec_master_t *master)
Clear all slaves.
Definition master.c:482
void ec_master_eoe_stop(ec_master_t *master)
Stops the Ethernet over EtherCAT processing.
Definition master.c:1712
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.
Definitions of Kernel SMP macros.
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:85
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