IgH EtherCAT Master  1.7.0
fsm_slave_scan.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 
27 /****************************************************************************/
28 
29 #include "globals.h"
30 #include "master.h"
31 #include "mailbox.h"
32 #include "slave_config.h"
33 
34 #include "fsm_slave_scan.h"
35 
36 /****************************************************************************/
37 
38 // prototypes for private methods
44 #ifdef EC_REGALIAS
45 void ec_fsm_slave_scan_enter_regalias(ec_fsm_slave_scan_t *);
46 #endif
50 
51 /****************************************************************************/
52 
60 #ifdef EC_SII_ASSIGN
62 #endif
67 #ifdef EC_REGALIAS
68 void ec_fsm_slave_scan_state_regalias(ec_fsm_slave_scan_t *);
69 #endif
73 
76 
77 /****************************************************************************/
78 
82  ec_fsm_slave_scan_t *fsm,
83  ec_datagram_t *datagram,
84  ec_fsm_slave_config_t *fsm_slave_config,
86  ec_fsm_pdo_t *fsm_pdo
87  )
88 {
89  fsm->slave = NULL;
90  fsm->datagram = datagram;
91  fsm->fsm_slave_config = fsm_slave_config;
92  fsm->fsm_pdo = fsm_pdo;
93 
94  fsm->retries = 0;
95  fsm->state = NULL;
96  fsm->sii_offset = 0;
97 
98  // init sub state machines
99  ec_fsm_sii_init(&fsm->fsm_sii, fsm->datagram);
100 }
101 
102 /****************************************************************************/
103 
107  ec_fsm_slave_scan_t *fsm
108  )
109 {
110  // clear sub state machines
111  ec_fsm_sii_clear(&fsm->fsm_sii);
112 }
113 
114 /****************************************************************************/
115 
121  ec_fsm_slave_scan_t *fsm,
122  ec_slave_t *slave
123  )
124 {
125  fsm->slave = slave;
127 }
128 
129 /****************************************************************************/
130 
136  const ec_fsm_slave_scan_t *fsm
137  )
138 {
139  return fsm->state != ec_fsm_slave_scan_state_end
141 }
142 
143 /****************************************************************************/
144 
153  ec_fsm_slave_scan_t *fsm
154  )
155 {
156  if (fsm->datagram->state == EC_DATAGRAM_SENT
157  || fsm->datagram->state == EC_DATAGRAM_QUEUED) {
158  // datagram was not sent or received yet.
159  return ec_fsm_slave_scan_running(fsm);
160  }
161 
162  fsm->state(fsm);
163  return ec_fsm_slave_scan_running(fsm);
164 }
165 
166 /****************************************************************************/
167 
173  const ec_fsm_slave_scan_t *fsm
174  )
175 {
176  return fsm->state == ec_fsm_slave_scan_state_end;
177 }
178 
179 /*****************************************************************************
180  * slave scan state machine
181  ****************************************************************************/
182 
190  ec_fsm_slave_scan_t *fsm
191  )
192 {
193  // write station address
194  ec_datagram_apwr(fsm->datagram, fsm->slave->ring_position, 0x0010, 2);
196  fsm->retries = EC_FSM_RETRIES;
198 }
199 
200 /****************************************************************************/
201 
207  ec_fsm_slave_scan_t *fsm
208  )
209 {
210  ec_datagram_t *datagram = fsm->datagram;
211 
212  if (datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--)
213  return;
214 
215  if (datagram->state != EC_DATAGRAM_RECEIVED) {
217  EC_SLAVE_ERR(fsm->slave,
218  "Failed to receive station address datagram: ");
219  ec_datagram_print_state(datagram);
220  return;
221  }
222 
223  if (datagram->working_counter != 1) {
224  fsm->slave->error_flag = 1;
226  EC_SLAVE_ERR(fsm->slave, "Failed to write station address: ");
227  ec_datagram_print_wc_error(datagram);
228  return;
229  }
230 
231  // Read AL state
232  ec_datagram_fprd(datagram, fsm->slave->station_address, 0x0130, 2);
233  ec_datagram_zero(datagram);
234  fsm->retries = EC_FSM_RETRIES;
236 }
237 
238 /****************************************************************************/
239 
245  ec_fsm_slave_scan_t *fsm
246  )
247 {
248  ec_datagram_t *datagram = fsm->datagram;
249  ec_slave_t *slave = fsm->slave;
250 
251  if (datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--)
252  return;
253 
254  if (datagram->state != EC_DATAGRAM_RECEIVED) {
256  EC_SLAVE_ERR(slave, "Failed to receive AL state datagram: ");
257  ec_datagram_print_state(datagram);
258  return;
259  }
260 
261  if (datagram->working_counter != 1) {
262  fsm->slave->error_flag = 1;
264  EC_SLAVE_ERR(slave, "Failed to read AL state: ");
265  ec_datagram_print_wc_error(datagram);
266  return;
267  }
268 
269  slave->current_state = EC_READ_U8(datagram->data);
270  if (slave->current_state & EC_SLAVE_STATE_ACK_ERR) {
271  char state_str[EC_STATE_STRING_SIZE];
272  ec_state_string(slave->current_state, state_str, 0);
273  EC_SLAVE_WARN(slave, "Slave has state error bit set (%s)!\n",
274  state_str);
275  }
276 
277  // read base data
278  ec_datagram_fprd(datagram, fsm->slave->station_address, 0x0000, 12);
279  ec_datagram_zero(datagram);
280  fsm->retries = EC_FSM_RETRIES;
282 }
283 
284 /****************************************************************************/
285 
289  ec_fsm_slave_scan_t *fsm
290  )
291 {
292  ec_datagram_t *datagram = fsm->datagram;
293  ec_slave_t *slave = fsm->slave;
294  u8 octet;
295  int i;
296 
297  if (datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--)
298  return;
299 
300  if (datagram->state != EC_DATAGRAM_RECEIVED) {
302  EC_SLAVE_ERR(slave, "Failed to receive base data datagram: ");
303  ec_datagram_print_state(datagram);
304  return;
305  }
306 
307  if (datagram->working_counter != 1) {
308  fsm->slave->error_flag = 1;
310  EC_SLAVE_ERR(slave, "Failed to read base data: ");
311  ec_datagram_print_wc_error(datagram);
312  return;
313  }
314 
315  slave->base_type = EC_READ_U8 (datagram->data);
316  slave->base_revision = EC_READ_U8 (datagram->data + 1);
317  slave->base_build = EC_READ_U16(datagram->data + 2);
318 
319  slave->base_fmmu_count = EC_READ_U8 (datagram->data + 4);
320  if (slave->base_fmmu_count > EC_MAX_FMMUS) {
321  EC_SLAVE_WARN(slave, "Slave has more FMMUs (%u) than the master can"
322  " handle (%u).\n", slave->base_fmmu_count, EC_MAX_FMMUS);
323  slave->base_fmmu_count = EC_MAX_FMMUS;
324  }
325 
326  slave->base_sync_count = EC_READ_U8(datagram->data + 5);
327  if (slave->base_sync_count > EC_MAX_SYNC_MANAGERS) {
328  EC_SLAVE_WARN(slave, "Slave provides more sync managers (%u)"
329  " than the master can handle (%u).\n",
332  }
333 
334  octet = EC_READ_U8(datagram->data + 7);
335  for (i = 0; i < EC_MAX_PORTS; i++) {
336  slave->ports[i].desc = (octet >> (2 * i)) & 0x03;
337  }
338 
339  octet = EC_READ_U8(datagram->data + 8);
340  slave->base_fmmu_bit_operation = octet & 0x01;
341  slave->base_dc_supported = (octet >> 2) & 0x01;
342  slave->base_dc_range = ((octet >> 3) & 0x01) ? EC_DC_64 : EC_DC_32;
343 
344  if (slave->base_dc_supported) {
345  // read DC capabilities
346  ec_datagram_fprd(datagram, slave->station_address, 0x0910,
347  slave->base_dc_range == EC_DC_64 ? 8 : 4);
348  ec_datagram_zero(datagram);
349  fsm->retries = EC_FSM_RETRIES;
351  } else {
353  }
354 }
355 
356 /****************************************************************************/
357 
363  ec_fsm_slave_scan_t *fsm
364  )
365 {
366  ec_datagram_t *datagram = fsm->datagram;
367  ec_slave_t *slave = fsm->slave;
368 
369  if (datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--)
370  return;
371 
372  if (datagram->state != EC_DATAGRAM_RECEIVED) {
374  EC_SLAVE_ERR(slave, "Failed to receive system time datagram: ");
375  ec_datagram_print_state(datagram);
376  return;
377  }
378 
379  if (datagram->working_counter == 1) {
380  slave->has_dc_system_time = 1;
381  EC_SLAVE_DBG(slave, 1, "Slave has the System Time register.\n");
382  } else if (datagram->working_counter == 0) {
383  EC_SLAVE_DBG(slave, 1, "Slave has no System Time register; delay "
384  "measurement only.\n");
385  } else {
386  fsm->slave->error_flag = 1;
388  EC_SLAVE_ERR(slave, "Failed to determine, if system time register is "
389  "supported: ");
390  ec_datagram_print_wc_error(datagram);
391  return;
392  }
393 
394  // read DC port receive times
395  ec_datagram_fprd(datagram, slave->station_address, 0x0900, 16);
396  ec_datagram_zero(datagram);
397  fsm->retries = EC_FSM_RETRIES;
399 }
400 
401 /****************************************************************************/
402 
408  ec_fsm_slave_scan_t *fsm
409  )
410 {
411  ec_datagram_t *datagram = fsm->datagram;
412  ec_slave_t *slave = fsm->slave;
413  int i;
414 
415  if (datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--)
416  return;
417 
418  if (datagram->state != EC_DATAGRAM_RECEIVED) {
420  EC_SLAVE_ERR(slave, "Failed to receive system time datagram: ");
421  ec_datagram_print_state(datagram);
422  return;
423  }
424 
425  if (datagram->working_counter != 1) {
426  fsm->slave->error_flag = 1;
428  EC_SLAVE_ERR(slave, "Failed to get DC receive times: ");
429  ec_datagram_print_wc_error(datagram);
430  return;
431  }
432 
433  for (i = 0; i < EC_MAX_PORTS; i++) {
434  slave->ports[i].receive_time = EC_READ_U32(datagram->data + 4 * i);
435  }
436 
438 }
439 
440 /****************************************************************************/
441 
447  ec_fsm_slave_scan_t *fsm
448  )
449 {
450  ec_datagram_t *datagram = fsm->datagram;
451  ec_slave_t *slave = fsm->slave;
452 
453  // read data link status
454  ec_datagram_fprd(datagram, slave->station_address, 0x0110, 2);
455  ec_datagram_zero(datagram);
456  fsm->retries = EC_FSM_RETRIES;
458 }
459 
460 /****************************************************************************/
461 
465  ec_fsm_slave_scan_t *fsm
466  )
467 {
468  // Start fetching SII size
469 
470  EC_SLAVE_DBG(fsm->slave, 1, "Determining SII size.\n");
471 
472  fsm->sii_offset = EC_FIRST_SII_CATEGORY_OFFSET; // first category header
473  ec_fsm_sii_read(&fsm->fsm_sii, fsm->slave, fsm->sii_offset,
476  fsm->state(fsm); // execute state immediately
477 }
478 
479 /****************************************************************************/
480 
481 #ifdef EC_SII_ASSIGN
482 
486  ec_fsm_slave_scan_t *fsm
487  )
488 {
489  ec_datagram_t *datagram = fsm->datagram;
490  ec_slave_t *slave = fsm->slave;
491 
492  EC_SLAVE_DBG(slave, 1, "Assigning SII access to EtherCAT.\n");
493 
494  // assign SII to ECAT
495  ec_datagram_fpwr(datagram, slave->station_address, 0x0500, 1);
496  EC_WRITE_U8(datagram->data, 0x00); // EtherCAT
497  fsm->retries = EC_FSM_RETRIES;
499 }
500 
501 #endif
502 
503 /****************************************************************************/
504 
508  ec_fsm_slave_scan_t *fsm
509  )
510 {
511  // Start fetching identification (alias/vendor/product/revision/serial)
512  // to check for possible SII cache hits
513 
514  EC_SLAVE_DBG(fsm->slave, 1, "Loading SII identification words.\n");
515 
517  ec_fsm_sii_read(&fsm->fsm_sii, fsm->slave, fsm->sii_offset,
520  fsm->state(fsm); // execute state immediately
521 }
522 
523 /****************************************************************************/
524 
530  ec_fsm_slave_scan_t *fsm
531  )
532 {
533  ec_datagram_t *datagram = fsm->datagram;
534  ec_slave_t *slave = fsm->slave;
535  uint16_t dl_status;
536  unsigned int i;
537 
538  if (datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--)
539  return;
540 
541  if (datagram->state != EC_DATAGRAM_RECEIVED) {
543  EC_SLAVE_ERR(slave, "Failed to receive DL status datagram: ");
544  ec_datagram_print_state(datagram);
545  return;
546  }
547 
548  if (datagram->working_counter != 1) {
549  fsm->slave->error_flag = 1;
551  EC_SLAVE_ERR(slave, "Failed to read DL status: ");
552  ec_datagram_print_wc_error(datagram);
553  return;
554  }
555 
556  dl_status = EC_READ_U16(datagram->data);
557  for (i = 0; i < EC_MAX_PORTS; i++) {
558  slave->ports[i].link.link_up =
559  dl_status & (1 << (4 + i)) ? 1 : 0;
560  slave->ports[i].link.loop_closed =
561  dl_status & (1 << (8 + i * 2)) ? 1 : 0;
562  slave->ports[i].link.signal_detected =
563  dl_status & (1 << (9 + i * 2)) ? 1 : 0;
564  }
565 
566 #ifdef EC_SII_ASSIGN
568 #else
569  if (fsm->slave->master->sii_caching != EC_SII_DISABLE_CACHING) {
571  }
572  else {
574  }
575 #endif
576 }
577 
578 /****************************************************************************/
579 
580 #ifdef EC_SII_ASSIGN
581 
587  ec_fsm_slave_scan_t *fsm
588  )
589 {
590  ec_datagram_t *datagram = fsm->datagram;
591  ec_slave_t *slave = fsm->slave;
592 
593  if (datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--) {
594  return;
595  }
596 
597  if (datagram->state != EC_DATAGRAM_RECEIVED) {
598  EC_SLAVE_WARN(slave, "Failed to receive SII assignment datagram: ");
599  ec_datagram_print_state(datagram);
600  // Try to go on, probably assignment is correct
601  goto continue_with_sii_size;
602  }
603 
604  if (datagram->working_counter != 1) {
605  EC_SLAVE_WARN(slave, "Failed to assign SII to EtherCAT: ");
606  ec_datagram_print_wc_error(datagram);
607  // Try to go on, probably assignment is correct
608  }
609 
610 continue_with_sii_size:
611  if (fsm->slave->master->sii_caching != EC_SII_DISABLE_CACHING) {
613  }
614  else {
616  }
617 }
618 
619 #endif
620 
621 /****************************************************************************/
622 
628  ec_fsm_slave_scan_t *fsm
629  )
630 {
631  ec_slave_t *slave = fsm->slave;
632  unsigned int words_fitting;
633  int words_to_copy;
634  uint32_t vendor, product, revision, serial;
635  ec_sii_page_t *cached;
636 
637  if (ec_fsm_sii_exec(&fsm->fsm_sii)) {
638  return;
639  }
640 
641  if (!ec_fsm_sii_success(&fsm->fsm_sii)) {
642  fsm->slave->error_flag = 1;
644  EC_SLAVE_ERR(slave, "Failed to fetch SII identification.\n");
645  return;
646  }
647 
648  if (fsm->sii_offset == EC_SII_WORD_OFFSET_ALIAS) {
649  // First step: Fetch alias from 0x0004, then go to 0x0008
650  // unfortunately it makes no sense to read through, if only 2 words
651  // are read in parallel (depends on the slave)
652  slave->sii.alias = EC_READ_U16(fsm->fsm_sii.value);
653  slave->effective_alias = slave->sii.alias;
654 
655  EC_SLAVE_DBG(slave, 1, "Alias %u\n", slave->sii.alias);
656 
657  // Continue with vendor ID
659  ec_fsm_sii_read(&fsm->fsm_sii, slave, fsm->sii_offset,
661  ec_fsm_sii_exec(&fsm->fsm_sii); // execute state immediately
662  return;
663  }
664 
665  // Vendor ID and following
666  words_fitting = EC_NUM_SII_IDENT_WORDS + EC_SII_WORD_OFFSET_VENDOR
667  - fsm->sii_offset;
668  words_to_copy = min(words_fitting, fsm->fsm_sii.read_word_count);
669  memcpy(fsm->sii_ident + (fsm->sii_offset - EC_SII_WORD_OFFSET_VENDOR) * 2,
670  fsm->fsm_sii.value, words_to_copy * 2);
671 
673  + fsm->fsm_sii.read_word_count < EC_NUM_SII_IDENT_WORDS) {
674  // fetch the remaining words
675  fsm->sii_offset += fsm->fsm_sii.read_word_count;
676  ec_fsm_sii_read(&fsm->fsm_sii, slave, fsm->sii_offset,
678  ec_fsm_sii_exec(&fsm->fsm_sii); // execute state immediately
679  return;
680  }
681 
682  // All identification words read
683 
684  vendor = EC_READ_U32(fsm->sii_ident);
685  product = EC_READ_U32(fsm->sii_ident + 4);
686  revision = EC_READ_U32(fsm->sii_ident + 8);
687  serial = EC_READ_U32(fsm->sii_ident + 12);
688 
689  EC_SLAVE_DBG(slave, 1,
690  "Identification 0x%08X / 0x%08X / 0x%08X / 0x%08X\n",
691  vendor, product, revision, serial);
692 
693  cached = ec_master_find_cached_sii_page(slave->master, vendor,
694  product, revision, serial, slave->sii.alias);
695  if (cached) {
696  int ret;
697 
698  EC_SLAVE_DBG(slave, 1, "Found matching SII page in cache.\n");
699 
700  ret = ec_sii_page_copy(&slave->sii_page, cached);
701  if (ret) {
702  EC_SLAVE_ERR(slave, "Failed to copy cached SII page.\n");
703  fsm->slave->error_flag = 1;
705  return;
706  }
707 
709 
710  // Evaluate the (cached) SII contents...
711  if (ec_slave_analyze_sii_data(slave)) {
712  EC_SLAVE_ERR(slave, "Failed to analyze category data.\n");
713  fsm->slave->error_flag = 1;
715  return;
716  }
717 
718 #ifdef EC_REGALIAS
719  ec_fsm_slave_scan_enter_regalias(fsm);
720 #else
721  if (slave->sii.mailbox_protocols & EC_MBOX_COE) {
723  } else {
725  }
726 #endif
727  return;
728  }
729 
730  EC_SLAVE_DBG(slave, 1, "No matching SII page found in cache.\n");
731  // We will have to read it out by ourselves. Sigh...
733 }
734 
735 /****************************************************************************/
736 
742  ec_fsm_slave_scan_t *fsm
743  )
744 {
745  ec_slave_t *slave = fsm->slave;
746  uint16_t cat_type, cat_size;
747  size_t word_count = 0;
748 
749  if (ec_fsm_sii_exec(&fsm->fsm_sii))
750  return;
751 
752  if (!ec_fsm_sii_success(&fsm->fsm_sii)) {
753  fsm->slave->error_flag = 1;
755  EC_SLAVE_ERR(slave, "Failed to determine SII content size:"
756  " Reading word offset 0x%04x failed. Assuming %u words.\n",
758  word_count = EC_FIRST_SII_CATEGORY_OFFSET;
759  goto alloc_sii;
760  }
761 
762  cat_type = EC_READ_U16(fsm->fsm_sii.value);
763  cat_size = EC_READ_U16(fsm->fsm_sii.value + 2);
764 
765  if (cat_type != 0xFFFF) { // not the last category
766  off_t next_offset = 2UL + fsm->sii_offset + cat_size;
767 
768  EC_SLAVE_DBG(slave, 1, "Found category type %u with size %u."
769  " Proceeding to offset %zd.\n",
770  cat_type, cat_size, (ssize_t)next_offset);
771 
772  if (next_offset >= EC_MAX_SII_SIZE) {
773  EC_SLAVE_WARN(slave, "SII size exceeds %u words"
774  " (0xffff limiter missing?).\n", EC_MAX_SII_SIZE);
775  // cut off category data...
776  word_count = EC_FIRST_SII_CATEGORY_OFFSET;
777  goto alloc_sii;
778  }
779  fsm->sii_offset = next_offset;
780  ec_fsm_sii_read(&fsm->fsm_sii, slave, fsm->sii_offset,
782  ec_fsm_sii_exec(&fsm->fsm_sii); // execute state immediately
783  return;
784  }
785 
786  word_count = fsm->sii_offset + 1;
787 
788 alloc_sii:
789  if (ec_sii_page_alloc(&slave->sii_page, word_count)) {
790  EC_SLAVE_ERR(slave, "Failed to allocate %zu words of SII data.\n",
791  word_count);
792  slave->error_flag = 1;
794  return;
795  }
796 
797  // Start fetching SII contents
798 
800  fsm->sii_offset = 0x0000;
801  ec_fsm_sii_read(&fsm->fsm_sii, slave, fsm->sii_offset,
803  ec_fsm_sii_exec(&fsm->fsm_sii); // execute state immediately
804 }
805 
806 /****************************************************************************/
807 
813  ec_fsm_slave_scan_t *fsm
814  )
815 {
816  ec_slave_t *slave = fsm->slave;
817  unsigned int words_fitting;
818  int words_to_copy;
819 
820  if (ec_fsm_sii_exec(&fsm->fsm_sii)) return;
821 
822  if (!ec_fsm_sii_success(&fsm->fsm_sii)) {
823  fsm->slave->error_flag = 1;
825  EC_SLAVE_ERR(slave, "Failed to fetch SII contents.\n");
826  return;
827  }
828 
829  // Did we get 2 or 4 words?
830  words_fitting = slave->sii_page.word_count - fsm->sii_offset;
831  words_to_copy = min(words_fitting, fsm->fsm_sii.read_word_count);
832  memcpy(slave->sii_page.words + fsm->sii_offset, fsm->fsm_sii.value,
833  words_to_copy * 2);
834 
835  if (fsm->sii_offset + fsm->fsm_sii.read_word_count
836  < slave->sii_page.word_count) {
837  // fetch the next words
838  fsm->sii_offset += fsm->fsm_sii.read_word_count;
839  ec_fsm_sii_read(&fsm->fsm_sii, slave, fsm->sii_offset,
841  ec_fsm_sii_exec(&fsm->fsm_sii); // execute state immediately
842  return;
843  }
844 
846 
847  // All words read. Evaluate the SII contents...
848  if (ec_slave_analyze_sii_data(slave)) {
849  EC_SLAVE_ERR(slave, "Failed to analyze category data.\n");
850  fsm->slave->error_flag = 1;
852  }
853 
854  // Add the page that we just read to the cache
855  ec_master_cache_sii_page(slave->master, &slave->sii_page);
856 
857 #ifdef EC_REGALIAS
858  ec_fsm_slave_scan_enter_regalias(fsm);
859 #else
860  if (slave->sii.mailbox_protocols & EC_MBOX_COE) {
862  } else {
864  }
865 #endif
866 }
867 
868 /****************************************************************************/
869 
870 #ifdef EC_REGALIAS
871 
874 void ec_fsm_slave_scan_enter_regalias(
875  ec_fsm_slave_scan_t *fsm
876  )
877 {
878  ec_datagram_t *datagram = fsm->datagram;
879  ec_slave_t *slave = fsm->slave;
880 
881  // read alias from register
882  EC_SLAVE_DBG(slave, 1, "Reading alias from register.\n");
883  ec_datagram_fprd(datagram, slave->station_address, 0x0012, 2);
884  ec_datagram_zero(datagram);
885  fsm->retries = EC_FSM_RETRIES;
886  fsm->state = ec_fsm_slave_scan_state_regalias;
887 }
888 
889 /****************************************************************************/
890 
893 void ec_fsm_slave_scan_state_regalias(
894  ec_fsm_slave_scan_t *fsm
895  )
896 {
897  ec_datagram_t *datagram = fsm->datagram;
898  ec_slave_t *slave = fsm->slave;
899 
900  if (datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--)
901  return;
902 
903  if (datagram->state != EC_DATAGRAM_RECEIVED) {
905  EC_SLAVE_ERR(slave, "Failed to receive register alias datagram: ");
906  ec_datagram_print_state(datagram);
907  return;
908  }
909 
910  if (datagram->working_counter != 1) {
911  EC_SLAVE_DBG(slave, 1, "Failed to read register alias.\n");
912  } else {
913  slave->effective_alias = EC_READ_U16(datagram->data);
914  EC_SLAVE_DBG(slave, 1, "Read alias %u from register.\n",
915  slave->effective_alias);
916  }
917 
918  if (slave->sii.mailbox_protocols & EC_MBOX_COE) {
920  } else {
922  }
923 }
924 
925 #endif // defined EC_REGALIAS
926 
927 /****************************************************************************/
928 
932  ec_fsm_slave_scan_t *fsm
933  )
934 {
935  ec_slave_t *slave = fsm->slave;
936  uint8_t current_state = slave->current_state & EC_SLAVE_STATE_MASK;
937 
938  if (current_state != EC_SLAVE_STATE_PREOP
939  && current_state != EC_SLAVE_STATE_SAFEOP
940  && current_state != EC_SLAVE_STATE_OP) {
941  if (slave->master->debug_level) {
942  char str[EC_STATE_STRING_SIZE];
943  ec_state_string(current_state, str, 0);
944  EC_SLAVE_DBG(slave, 0, "Slave is not in the state"
945  " to do mailbox com (%s), setting to PREOP.\n", str);
946  }
947 
952  } else {
953  EC_SLAVE_DBG(slave, 1, "Reading mailbox"
954  " sync manager configuration.\n");
955 
956  /* Scan current sync manager configuration to get configured mailbox
957  * sizes. */
958  ec_datagram_fprd(fsm->datagram, slave->station_address, 0x0800,
959  EC_SYNC_PAGE_SIZE * 2);
960  fsm->retries = EC_FSM_RETRIES;
962  }
963 }
964 
965 /****************************************************************************/
966 
970  ec_fsm_slave_scan_t *fsm
971  )
972 {
974  return;
975 
978  return;
979  }
980 
982 }
983 
984 /****************************************************************************/
985 
989  ec_fsm_slave_scan_t *fsm
990  )
991 {
992  ec_datagram_t *datagram = fsm->datagram;
993  ec_slave_t *slave = fsm->slave;
994  uint16_t tx_offset, tx_size, rx_offset, rx_size;
995 
996  if (datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--)
997  return;
998 
999  if (datagram->state != EC_DATAGRAM_RECEIVED) {
1001  EC_SLAVE_ERR(slave, "Failed to receive sync manager"
1002  " configuration datagram: ");
1003  ec_datagram_print_state(datagram);
1004  return;
1005  }
1006 
1007  if (datagram->working_counter != 1) {
1008  fsm->slave->error_flag = 1;
1010  EC_SLAVE_ERR(slave, "Failed to read DL status: ");
1011  ec_datagram_print_wc_error(datagram);
1012  return;
1013  }
1014 
1015  rx_offset = EC_READ_U16(datagram->data);
1016  rx_size = EC_READ_U16(datagram->data + 2);
1017  tx_offset = EC_READ_U16(datagram->data + 8);
1018  tx_size = EC_READ_U16(datagram->data + 10);
1019 
1020  if (rx_size == 0xffff) {
1022  slave->sii.mailbox_protocols = 0x0000;
1023  EC_SLAVE_ERR(slave, "Invalid RX mailbox size (%u) configured."
1024  " Disabling mailbox communication.", rx_size);
1025  return;
1026  }
1027 
1028  if (tx_size == 0xffff) {
1030  slave->sii.mailbox_protocols = 0x0000;
1031  EC_SLAVE_ERR(slave, "Invalid TX mailbox size (%u) configured."
1032  " Disabling mailbox communication.", tx_size);
1033  return;
1034  }
1035 
1036  slave->configured_rx_mailbox_offset = rx_offset;
1037  slave->configured_rx_mailbox_size = rx_size;
1038  slave->configured_tx_mailbox_offset = tx_offset;
1039  slave->configured_tx_mailbox_size = tx_size;
1040 
1041  EC_SLAVE_DBG(slave, 1, "Mailbox configuration:\n");
1042  EC_SLAVE_DBG(slave, 1, " RX offset=0x%04x size=%u\n",
1045  EC_SLAVE_DBG(slave, 1, " TX offset=0x%04x size=%u\n",
1048 
1049  // allocate memory for mailbox response data
1050  ec_slave_mbox_prealloc(slave);
1051 
1053 }
1054 
1055 /****************************************************************************/
1056 
1060  ec_fsm_slave_scan_t *fsm
1061  )
1062 {
1063  ec_slave_t *slave = fsm->slave;
1064 
1065  // If there is some old data in the slave's mailbox, read it out and
1066  // discard it. We don't need to check the mailbox first, we just ignore
1067  // an error or empty mailbox response.
1068  ec_datagram_t *datagram = fsm->datagram;
1069  ec_slave_mbox_prepare_fetch(fsm->slave, datagram);
1070  fsm->retries = EC_FSM_RETRIES;
1072 
1073  slave->valid_mbox_data = 0;
1074 }
1075 
1076 /****************************************************************************/
1077 
1081  ec_fsm_slave_scan_t *fsm
1082  )
1083 {
1084  ec_slave_t *slave = fsm->slave;
1085  ec_datagram_t *datagram = fsm->datagram;
1086 
1087  if (fsm->datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--) {
1088  ec_slave_mbox_prepare_fetch(fsm->slave, datagram);
1089  return;
1090  }
1091 
1092  if (unlikely(slave->master->debug_level > 0)
1093  && datagram->state == EC_DATAGRAM_RECEIVED
1094  && datagram->working_counter == 1)
1095  EC_SLAVE_INFO(slave, "Cleared old data from the mailbox\n");
1096 
1097  slave->valid_mbox_data = 1;
1098 
1100 }
1101 
1102 /****************************************************************************/
1103 
1107  ec_fsm_slave_scan_t *fsm
1108  )
1109 {
1110  ec_slave_t *slave = fsm->slave;
1111  ec_pdo_mode_t assign_mode = EC_PDO_MODE_DEFAULT;
1112  ec_pdo_mode_t config_mode = EC_PDO_MODE_DEFAULT;
1113  const ec_slave_config_t *sc;
1114 
1115  // Look up a not-yet-attached configuration for this slave (attaching
1116  // only happens after the whole bus has been scanned) to find out if
1117  // the application requested non-default PDO scanning behavior.
1118  if ((sc = ec_master_find_config_for_slave(slave->master, slave))) {
1119  assign_mode = sc->pdo_assign_mode;
1120  config_mode = sc->pdo_config_mode;
1121  }
1122 
1123  if (assign_mode == EC_PDO_MODE_FIXED
1124  || assign_mode == EC_PDO_MODE_WRITE) {
1125  if (config_mode == EC_PDO_MODE_FIXED
1126  || config_mode == EC_PDO_MODE_WRITE) {
1127  EC_SLAVE_DBG(slave, 1, "Skipping PDO scanning"
1128  " (fixed PDO assignment/configuration).\n");
1130  return;
1131  }
1132  }
1133 
1134  EC_SLAVE_DBG(slave, 1, "Scanning PDO assignment and mapping.\n");
1136  ec_fsm_pdo_start_reading(fsm->fsm_pdo, slave, assign_mode, config_mode);
1137  ec_fsm_pdo_exec(fsm->fsm_pdo, fsm->datagram); // execute immediately
1138 }
1139 
1140 /****************************************************************************/
1141 
1145  ec_fsm_slave_scan_t *fsm
1146  )
1147 {
1148  if (ec_fsm_pdo_exec(fsm->fsm_pdo, fsm->datagram)) {
1149  return;
1150  }
1151 
1152  if (!ec_fsm_pdo_success(fsm->fsm_pdo)) {
1154  return;
1155  }
1156 
1157  // reading PDO configuration finished
1159 }
1160 
1161 /*****************************************************************************
1162  * Common state functions
1163  ****************************************************************************/
1164 
1168  ec_fsm_slave_scan_t *fsm
1169  )
1170 {
1171 }
1172 
1173 /****************************************************************************/
1174 
1178  ec_fsm_slave_scan_t *fsm
1179  )
1180 {
1181 }
1182 
1183 /****************************************************************************/
#define EC_FSM_RETRIES
Number of state machine retries on datagram timeout.
Definition: globals.h:47
ec_slave_t * slave
Slave the FSM runs on.
CANopen over EtherCAT.
Definition: globals.h:152
uint16_t ring_position
Ring position.
Definition: slave.h:177
#define EC_SYNC_PAGE_SIZE
Size of a sync manager configuration page.
Definition: globals.h:95
void ec_fsm_slave_scan_enter_assign_sii(ec_fsm_slave_scan_t *)
Enter slave scan state ASSIGN_SII.
int ec_slave_analyze_sii_data(ec_slave_t *slave)
Analyzes SII data.
Definition: slave.c:372
#define EC_SLAVE_STATE_MASK
Slave state mask.
Definition: globals.h:123
int ec_sii_page_copy(ec_sii_page_t *page, const ec_sii_page_t *from)
Copy contents from other page.
Definition: sii_page.c:100
ec_sii_t sii
Extracted SII data.
Definition: slave.h:218
int ec_fsm_pdo_exec(ec_fsm_pdo_t *fsm, ec_datagram_t *datagram)
Executes the current state of the state machine.
Definition: fsm_pdo.c:171
Neither read nor write via CoE.
Definition: ecrt.h:552
size_t word_count
Size of the SII contents in words.
Definition: sii_page.h:61
void ec_fsm_slave_config_start(ec_fsm_slave_config_t *fsm, ec_slave_t *slave)
Start slave configuration state machine.
ec_datagram_t * datagram
Datagram used in the state machine.
ec_sii_page_origin_t origin
Page origin.
Definition: sii_page.h:58
uint16_t configured_tx_mailbox_size
Configured send mailbox size.
Definition: slave.h:195
uint16_t base_build
Build number.
Definition: slave.h:200
ec_pdo_mode_t
PDO handling mode.
Definition: ecrt.h:551
#define EC_SLAVE_DBG(slave, level, fmt, args...)
Convenience macro for printing slave-specific debug messages to syslog.
Definition: slave.h:100
OP (mailbox communication and input/output update)
Definition: globals.h:138
uint16_t configured_tx_mailbox_offset
Configured send mailbox offset.
Definition: slave.h:193
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.
size_t ec_state_string(uint8_t, char *, uint8_t)
Prints slave states in clear text.
Definition: module.c:405
ec_slave_port_t ports[EC_MAX_PORTS]
Ports.
Definition: slave.h:181
#define EC_SII_WORD_OFFSET_ALIAS
Word offset of alias address.
Definition: globals.h:89
ec_slave_state_t current_state
Current application state.
Definition: slave.h:186
uint8_t sii_ident[EC_NUM_SII_IDENT_WORDS *2]
Temporary storage for slave identification objects.
int ec_slave_mbox_prepare_fetch(const ec_slave_t *slave, ec_datagram_t *datagram)
Prepares a datagram to fetch mailbox data.
Definition: mailbox.c:219
ec_slave_port_link_t link
Port link status.
Definition: slave.h:114
void ec_fsm_slave_scan_state_preop(ec_fsm_slave_scan_t *)
Slave scan state: PREOP.
#define EC_SLAVE_WARN(slave, fmt, args...)
Convenience macro for printing slave-specific warnings to syslog.
Definition: slave.h:84
void ec_fsm_slave_scan_state_assign_sii(ec_fsm_slave_scan_t *)
Slave scan state: ASSIGN_SII.
EtherCAT datagram.
Definition: datagram.h:81
void ec_slave_mbox_prealloc(ec_slave_t *slave)
Allocates the mailbox response buffers of a slave.
Definition: mailbox.c:100
#define EC_WRITE_U8(DATA, VAL)
Write an 8-bit unsigned value to EtherCAT data.
Definition: ecrt.h:3353
void ec_fsm_slave_scan_state_dc_times(ec_fsm_slave_scan_t *)
Slave scan state: DC TIMES.
uint16_t working_counter
Working counter.
Definition: datagram.h:96
void ec_fsm_slave_scan_enter_sii_ident(ec_fsm_slave_scan_t *)
Enter slave scan state SII ident.
void ec_fsm_slave_scan_state_start(ec_fsm_slave_scan_t *)
Slave scan state: START.
ec_slave_config_t * ec_master_find_config_for_slave(ec_master_t *master, const ec_slave_t *slave)
Finds the slave configuration that will be attached to the given slave.
Definition: master.c:2045
Acknowledge/Error bit (no actual state)
Definition: globals.h:140
Sent (still in the queue).
Definition: datagram.h:69
void ec_fsm_sii_init(ec_fsm_sii_t *fsm, ec_datagram_t *datagram)
Constructor.
Definition: fsm_sii.c:66
ec_pdo_mode_t pdo_config_mode
Whether/how to read resp.
Definition: slave_config.h:129
EtherCAT slave scanning state machine.
uint16_t station_address
Configured station address.
Definition: slave.h:178
#define EC_MAX_SII_SIZE
Maximum SII size in words, to avoid infinite reading.
Definition: globals.h:57
#define EC_MAX_FMMUS
Maximum number of FMMUs per slave.
Definition: globals.h:98
uint8_t base_type
Slave type.
Definition: slave.h:198
int ec_fsm_slave_scan_exec(ec_fsm_slave_scan_t *fsm)
Executes the current state of the state machine.
Global definitions and macros.
void ec_fsm_slave_scan_state_sii_ident(ec_fsm_slave_scan_t *)
Slave scan state: SII ident.
Completely read via SII.
Definition: sii_page.h:39
EtherCAT master structure.
SAFEOP (mailbox communication and input update)
Definition: globals.h:136
ec_fsm_slave_config_t * fsm_slave_config
Slave configuration state machine to use.
EtherCAT slave.
Definition: slave.h:170
ec_sii_page_t * ec_master_find_cached_sii_page(const ec_master_t *master, uint32_t vendor_id, uint32_t product_code, uint32_t revision, uint32_t serial, uint16_t alias)
Find a matching cached SII page.
Definition: master.c:2549
Taken from cache.
Definition: sii_page.h:40
void ec_fsm_slave_scan_state_pdos(ec_fsm_slave_scan_t *)
Slave scan state: PDOS.
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
void ec_datagram_zero(ec_datagram_t *datagram)
Fills the datagram payload memory with zeros.
Definition: datagram.c:178
unsigned int read_word_count
Number of words that have been read.
Definition: fsm_sii.h:63
ec_datagram_state_t state
State.
Definition: datagram.h:97
ec_pdo_mode_t pdo_assign_mode
Whether/how to read resp.
Definition: slave_config.h:126
Slave information interface memory page.
Definition: sii_page.h:47
ec_fsm_pdo_t * fsm_pdo
PDO configuration state machine to use.
void ec_fsm_slave_scan_state_base(ec_fsm_slave_scan_t *)
Slave scan state: BASE.
int ec_master_cache_sii_page(ec_master_t *master, const ec_sii_page_t *page)
Add an SII page to the cache.
Definition: master.c:2577
Use configured addresses.
Definition: fsm_sii.h:42
uint16_t mailbox_protocols
Supported mailbox protocols.
Definition: slave.h:141
void ec_fsm_slave_scan_state_sii_data(ec_fsm_slave_scan_t *)
Slave scan state: SII DATA.
ec_fsm_sii_t fsm_sii
SII state machine.
unsigned int debug_level
Master debug level.
Definition: master.h:284
#define EC_SLAVE_ERR(slave, fmt, args...)
Convenience macro for printing slave-specific errors to syslog.
Definition: slave.h:70
void ec_datagram_print_wc_error(const ec_datagram_t *datagram)
Evaluates the working counter of a single-cast datagram.
Definition: datagram.c:605
ec_slave_dc_range_t base_dc_range
DC range.
Definition: slave.h:205
uint8_t base_fmmu_bit_operation
FMMU bit operation is supported.
Definition: slave.h:203
int ec_sii_page_alloc(ec_sii_page_t *page, size_t word_count)
Free page memory.
Definition: sii_page.c:76
void ec_fsm_pdo_start_reading(ec_fsm_pdo_t *fsm, ec_slave_t *slave, ec_pdo_mode_t assign_mode, ec_pdo_mode_t config_mode)
Start reading the PDO configuration.
Definition: fsm_pdo.c:120
void ec_fsm_slave_scan_enter_pdos(ec_fsm_slave_scan_t *)
Enter slave scan state PDOS.
int ec_fsm_slave_scan_running(const ec_fsm_slave_scan_t *)
uint16_t alias
Configured station alias.
Definition: slave.h:128
void ec_fsm_slave_scan_state_sync(ec_fsm_slave_scan_t *)
Slave scan state: SYNC.
#define EC_WRITE_U16(DATA, VAL)
Write a 16-bit unsigned value to EtherCAT data.
Definition: ecrt.h:3370
uint8_t base_fmmu_count
Number of supported FMMUs.
Definition: slave.h:201
uint16_t configured_rx_mailbox_offset
Configured receive mailbox offset.
Definition: slave.h:189
#define EC_READ_U32(DATA)
Read a 32-bit unsigned value from EtherCAT data.
Definition: ecrt.h:3277
ec_slave_port_desc_t desc
Port descriptors.
Definition: slave.h:113
Finite state machine for scanning an EtherCAT slave.
ec_master_t * master
Master owning the slave.
Definition: slave.h:172
#define EC_SII_WORD_OFFSET_VENDOR
Word offset of vendor ID.
Definition: globals.h:92
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
uint8_t has_dc_system_time
The slave supports the DC system time register.
Definition: slave.h:206
unsigned int retries
Retries on datagram timeout.
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
PDO configuration state machine.
Definition: fsm_pdo.h:46
#define EC_FIRST_SII_CATEGORY_OFFSET
Word offset of first SII category.
Definition: globals.h:86
uint8_t base_revision
Revision.
Definition: slave.h:199
32 bit.
Definition: globals.h:179
void ec_fsm_sii_read(ec_fsm_sii_t *fsm, ec_slave_t *slave, uint16_t word_offset, ec_fsm_sii_addressing_t mode)
Initializes the SII read state machine.
Definition: fsm_sii.c:91
#define EC_SLAVE_INFO(slave, fmt, args...)
Convenience macro for printing slave-specific information to syslog.
Definition: slave.h:56
uint8_t valid_mbox_data
Received mailbox data is valid.
Definition: slave.h:243
void ec_fsm_sii_clear(ec_fsm_sii_t *fsm)
Destructor.
Definition: fsm_sii.c:81
int ec_fsm_pdo_success(const ec_fsm_pdo_t *fsm)
Get execution result.
Definition: fsm_pdo.c:187
Write the configured state via CoE every time the slave is configured, without reading the current st...
Definition: ecrt.h:555
uint16_t effective_alias
Effective alias address.
Definition: slave.h:179
uint8_t value[8]
raw SII value (32 bit / 64 bit)
Definition: fsm_sii.h:62
void ec_fsm_slave_scan_state_datalink(ec_fsm_slave_scan_t *)
Slave scan state: DATALINK.
unsigned int sii_caching
SII caching mode.
Definition: master.h:286
int ec_fsm_sii_exec(ec_fsm_sii_t *fsm)
Executes the SII state machine.
Definition: fsm_sii.c:131
int ec_fsm_sii_success(ec_fsm_sii_t *fsm)
Returns, if the master startup state machine terminated with success.
Definition: fsm_sii.c:146
#define EC_READ_U16(DATA)
Read a 16-bit unsigned value from EtherCAT data.
Definition: ecrt.h:3261
Finite state machine to configure an EtherCAT slave.
void ec_datagram_print_state(const ec_datagram_t *datagram)
Prints the state of a datagram.
Definition: datagram.c:565
Mailbox functionality.
#define EC_STATE_STRING_SIZE
Minimum size of a buffer used with ec_state_string().
Definition: globals.h:54
#define EC_MAX_PORTS
Maximum number of slave ports.
Definition: ecrt.h:294
uint16_t * words
Complete SII image.
Definition: sii_page.h:60
#define EC_PDO_MODE_DEFAULT
Default PDO handling mode: read via CoE while scanning, and unconditionally (re-)write via CoE every ...
Definition: ecrt.h:575
int ec_fsm_slave_config_exec(ec_fsm_slave_config_t *fsm)
Executes the current state of the state machine.
void(* state)(ec_fsm_slave_scan_t *)
State function.
Queued for sending.
Definition: datagram.h:68
void ec_fsm_slave_scan_state_error(ec_fsm_slave_scan_t *)
State: ERROR.
ec_sii_page_t sii_page
The SII contents, either fetched or taken from the cache.
Definition: slave.h:213
uint32_t receive_time
Port receive times for delay measurement.
Definition: slave.h:116
Timed out (dequeued).
Definition: datagram.h:71
void ec_fsm_slave_scan_state_mailbox_cleared(ec_fsm_slave_scan_t *)
Slave scan state: Mailbox cleared.
uint16_t sii_offset
SII offset in words.
void ec_slave_request_state(ec_slave_t *slave, ec_slave_state_t state)
Request a slave state and resets the error flag.
Definition: slave.c:357
uint16_t configured_rx_mailbox_size
Configured receive mailbox size.
Definition: slave.h:191
uint8_t base_dc_supported
Distributed clocks are supported.
Definition: slave.h:204
void ec_fsm_slave_scan_start(ec_fsm_slave_scan_t *fsm, ec_slave_t *slave)
Start slave scan state machine.
uint8_t * data
Datagram payload.
Definition: datagram.h:91
uint8_t base_sync_count
Number of supported sync managers.
Definition: slave.h:202
#define EC_READ_U8(DATA)
Read an 8-bit unsigned value from EtherCAT data.
Definition: ecrt.h:3245
EtherCAT slave configuration.
Definition: slave_config.h:111
int ec_fsm_slave_config_success(const ec_fsm_slave_config_t *fsm)
void ec_fsm_slave_scan_clear(ec_fsm_slave_scan_t *fsm)
Destructor.
EtherCAT slave configuration structure.
void ec_fsm_slave_scan_state_end(ec_fsm_slave_scan_t *)
State: END.
void ec_fsm_slave_scan_state_dc_cap(ec_fsm_slave_scan_t *)
Slave scan state: DC CAPABILITIES.
void ec_fsm_slave_scan_enter_sii_size(ec_fsm_slave_scan_t *)
Enter slave scan state SII_SIZE.
PREOP state (mailbox communication, no IO)
Definition: globals.h:132
void ec_fsm_slave_scan_enter_preop(ec_fsm_slave_scan_t *)
Enter slave scan state PREOP.
void ec_fsm_slave_scan_enter_clear_mailbox(ec_fsm_slave_scan_t *)
Enter slave scan state: Clear Mailbox.
Received (dequeued).
Definition: datagram.h:70
unsigned int error_flag
Stop processing after an error.
Definition: slave.h:187
void ec_fsm_slave_scan_state_address(ec_fsm_slave_scan_t *)
Slave scan state: ADDRESS.
void ec_fsm_slave_scan_state_state(ec_fsm_slave_scan_t *)
Slave scan state: STATE.
#define EC_MAX_SYNC_MANAGERS
Maximum number of sync managers per slave.
Definition: ecrt.h:285
void ec_fsm_slave_scan_enter_datalink(ec_fsm_slave_scan_t *)
Slave scan entry function: DATALINK.
void ec_fsm_slave_scan_state_sii_size(ec_fsm_slave_scan_t *)
Slave scan state: SII SIZE.
int ec_fsm_slave_scan_success(const ec_fsm_slave_scan_t *fsm)