IgH EtherCAT Master  1.6.9
fsm_slave_scan.c
Go to the documentation of this file.
1/*****************************************************************************
2 *
3 * Copyright (C) 2006-2008 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
26
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
43#ifdef EC_REGALIAS
44void ec_fsm_slave_scan_enter_regalias(ec_fsm_slave_scan_t *);
45#endif
48
49/****************************************************************************/
50
58#ifdef EC_SII_ASSIGN
60#endif
63#ifdef EC_REGALIAS
64void ec_fsm_slave_scan_state_regalias(ec_fsm_slave_scan_t *);
65#endif
69
72
73/****************************************************************************/
74
79 ec_datagram_t *datagram,
80 ec_fsm_slave_config_t *fsm_slave_config,
82 ec_fsm_pdo_t *fsm_pdo
83 )
84{
85 fsm->datagram = datagram;
86 fsm->fsm_slave_config = fsm_slave_config;
87 fsm->fsm_pdo = fsm_pdo;
88
89 // init sub state machines
90 ec_fsm_sii_init(&fsm->fsm_sii, fsm->datagram);
91}
92
93/****************************************************************************/
94
98{
99 // clear sub state machines
101}
102
103/****************************************************************************/
104
108
111 ec_slave_t *slave
112 )
113{
114 fsm->slave = slave;
116}
117
118/****************************************************************************/
119
123
125 const ec_fsm_slave_scan_t *fsm
126 )
127{
130}
131
132/****************************************************************************/
133
140
142{
143 if (fsm->datagram->state == EC_DATAGRAM_SENT
144 || fsm->datagram->state == EC_DATAGRAM_QUEUED) {
145 // datagram was not sent or received yet.
146 return ec_fsm_slave_scan_running(fsm);
147 }
148
149 fsm->state(fsm);
150 return ec_fsm_slave_scan_running(fsm);
151}
152
153/****************************************************************************/
154
158
163
164/*****************************************************************************
165 * slave scan state machine
166 ****************************************************************************/
167
173
175{
176 // write station address
177 ec_datagram_apwr(fsm->datagram, fsm->slave->ring_position, 0x0010, 2);
179 fsm->retries = EC_FSM_RETRIES;
181}
182
183/****************************************************************************/
184
188
191 )
192{
193 ec_datagram_t *datagram = fsm->datagram;
194
195 if (datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--)
196 return;
197
198 if (datagram->state != EC_DATAGRAM_RECEIVED) {
200 EC_SLAVE_ERR(fsm->slave,
201 "Failed to receive station address datagram: ");
202 ec_datagram_print_state(datagram);
203 return;
204 }
205
206 if (datagram->working_counter != 1) {
207 fsm->slave->error_flag = 1;
209 EC_SLAVE_ERR(fsm->slave, "Failed to write station address: ");
211 return;
212 }
213
214 // Read AL state
215 ec_datagram_fprd(datagram, fsm->slave->station_address, 0x0130, 2);
216 ec_datagram_zero(datagram);
217 fsm->retries = EC_FSM_RETRIES;
219}
220
221/****************************************************************************/
222
226
229 )
230{
231 ec_datagram_t *datagram = fsm->datagram;
232 ec_slave_t *slave = fsm->slave;
233
234 if (datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--)
235 return;
236
237 if (datagram->state != EC_DATAGRAM_RECEIVED) {
239 EC_SLAVE_ERR(slave, "Failed to receive AL state datagram: ");
240 ec_datagram_print_state(datagram);
241 return;
242 }
243
244 if (datagram->working_counter != 1) {
245 fsm->slave->error_flag = 1;
247 EC_SLAVE_ERR(slave, "Failed to read AL state: ");
249 return;
250 }
251
252 slave->current_state = EC_READ_U8(datagram->data);
254 char state_str[EC_STATE_STRING_SIZE];
255 ec_state_string(slave->current_state, state_str, 0);
256 EC_SLAVE_WARN(slave, "Slave has state error bit set (%s)!\n",
257 state_str);
258 }
259
260 // read base data
261 ec_datagram_fprd(datagram, fsm->slave->station_address, 0x0000, 12);
262 ec_datagram_zero(datagram);
263 fsm->retries = EC_FSM_RETRIES;
265}
266
267/****************************************************************************/
268
273 )
274{
275 ec_datagram_t *datagram = fsm->datagram;
276 ec_slave_t *slave = fsm->slave;
277 u8 octet;
278 int i;
279
280 if (datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--)
281 return;
282
283 if (datagram->state != EC_DATAGRAM_RECEIVED) {
285 EC_SLAVE_ERR(slave, "Failed to receive base data datagram: ");
286 ec_datagram_print_state(datagram);
287 return;
288 }
289
290 if (datagram->working_counter != 1) {
291 fsm->slave->error_flag = 1;
293 EC_SLAVE_ERR(slave, "Failed to read base data: ");
295 return;
296 }
297
298 slave->base_type = EC_READ_U8 (datagram->data);
299 slave->base_revision = EC_READ_U8 (datagram->data + 1);
300 slave->base_build = EC_READ_U16(datagram->data + 2);
301
302 slave->base_fmmu_count = EC_READ_U8 (datagram->data + 4);
303 if (slave->base_fmmu_count > EC_MAX_FMMUS) {
304 EC_SLAVE_WARN(slave, "Slave has more FMMUs (%u) than the master can"
305 " handle (%u).\n", slave->base_fmmu_count, EC_MAX_FMMUS);
307 }
308
309 slave->base_sync_count = EC_READ_U8(datagram->data + 5);
311 EC_SLAVE_WARN(slave, "Slave provides more sync managers (%u)"
312 " than the master can handle (%u).\n",
315 }
316
317 octet = EC_READ_U8(datagram->data + 7);
318 for (i = 0; i < EC_MAX_PORTS; i++) {
319 slave->ports[i].desc = (octet >> (2 * i)) & 0x03;
320 }
321
322 octet = EC_READ_U8(datagram->data + 8);
323 slave->base_fmmu_bit_operation = octet & 0x01;
324 slave->base_dc_supported = (octet >> 2) & 0x01;
325 slave->base_dc_range = ((octet >> 3) & 0x01) ? EC_DC_64 : EC_DC_32;
326
327 if (slave->base_dc_supported) {
328 // read DC capabilities
329 ec_datagram_fprd(datagram, slave->station_address, 0x0910,
330 slave->base_dc_range == EC_DC_64 ? 8 : 4);
331 ec_datagram_zero(datagram);
332 fsm->retries = EC_FSM_RETRIES;
334 } else {
336 }
337}
338
339/****************************************************************************/
340
344
347 )
348{
349 ec_datagram_t *datagram = fsm->datagram;
350 ec_slave_t *slave = fsm->slave;
351
352 if (datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--)
353 return;
354
355 if (datagram->state != EC_DATAGRAM_RECEIVED) {
357 EC_SLAVE_ERR(slave, "Failed to receive system time datagram: ");
358 ec_datagram_print_state(datagram);
359 return;
360 }
361
362 if (datagram->working_counter == 1) {
363 slave->has_dc_system_time = 1;
364 EC_SLAVE_DBG(slave, 1, "Slave has the System Time register.\n");
365 } else if (datagram->working_counter == 0) {
366 EC_SLAVE_DBG(slave, 1, "Slave has no System Time register; delay "
367 "measurement only.\n");
368 } else {
369 fsm->slave->error_flag = 1;
371 EC_SLAVE_ERR(slave, "Failed to determine, if system time register is "
372 "supported: ");
374 return;
375 }
376
377 // read DC port receive times
378 ec_datagram_fprd(datagram, slave->station_address, 0x0900, 16);
379 ec_datagram_zero(datagram);
380 fsm->retries = EC_FSM_RETRIES;
382}
383
384/****************************************************************************/
385
389
392 )
393{
394 ec_datagram_t *datagram = fsm->datagram;
395 ec_slave_t *slave = fsm->slave;
396 int i;
397
398 if (datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--)
399 return;
400
401 if (datagram->state != EC_DATAGRAM_RECEIVED) {
403 EC_SLAVE_ERR(slave, "Failed to receive system time datagram: ");
404 ec_datagram_print_state(datagram);
405 return;
406 }
407
408 if (datagram->working_counter != 1) {
409 fsm->slave->error_flag = 1;
411 EC_SLAVE_ERR(slave, "Failed to get DC receive times: ");
413 return;
414 }
415
416 for (i = 0; i < EC_MAX_PORTS; i++) {
417 slave->ports[i].receive_time = EC_READ_U32(datagram->data + 4 * i);
418 }
419
421}
422
423/****************************************************************************/
424
428
431 )
432{
433 ec_datagram_t *datagram = fsm->datagram;
434 ec_slave_t *slave = fsm->slave;
435
436 // read data link status
437 ec_datagram_fprd(datagram, slave->station_address, 0x0110, 2);
438 ec_datagram_zero(datagram);
439 fsm->retries = EC_FSM_RETRIES;
441}
442
443/****************************************************************************/
444
449 )
450{
451 // Start fetching SII size
452
453 EC_SLAVE_DBG(fsm->slave, 1, "Determining SII size.\n");
454
455 fsm->sii_offset = EC_FIRST_SII_CATEGORY_OFFSET; // first category header
456 ec_fsm_sii_read(&fsm->fsm_sii, fsm->slave, fsm->sii_offset,
459 fsm->state(fsm); // execute state immediately
460}
461
462/****************************************************************************/
463
464#ifdef EC_SII_ASSIGN
465
470 )
471{
472 ec_datagram_t *datagram = fsm->datagram;
473 ec_slave_t *slave = fsm->slave;
474
475 EC_SLAVE_DBG(slave, 1, "Assigning SII access to EtherCAT.\n");
476
477 // assign SII to ECAT
478 ec_datagram_fpwr(datagram, slave->station_address, 0x0500, 1);
479 EC_WRITE_U8(datagram->data, 0x00); // EtherCAT
480 fsm->retries = EC_FSM_RETRIES;
482}
483
484#endif
485
486/****************************************************************************/
487
491
494 )
495{
496 ec_datagram_t *datagram = fsm->datagram;
497 ec_slave_t *slave = fsm->slave;
498 uint16_t dl_status;
499 unsigned int i;
500
501 if (datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--)
502 return;
503
504 if (datagram->state != EC_DATAGRAM_RECEIVED) {
506 EC_SLAVE_ERR(slave, "Failed to receive DL status datagram: ");
507 ec_datagram_print_state(datagram);
508 return;
509 }
510
511 if (datagram->working_counter != 1) {
512 fsm->slave->error_flag = 1;
514 EC_SLAVE_ERR(slave, "Failed to read DL status: ");
516 return;
517 }
518
519 dl_status = EC_READ_U16(datagram->data);
520 for (i = 0; i < EC_MAX_PORTS; i++) {
521 slave->ports[i].link.link_up =
522 dl_status & (1 << (4 + i)) ? 1 : 0;
523 slave->ports[i].link.loop_closed =
524 dl_status & (1 << (8 + i * 2)) ? 1 : 0;
525 slave->ports[i].link.signal_detected =
526 dl_status & (1 << (9 + i * 2)) ? 1 : 0;
527 }
528
529#ifdef EC_SII_ASSIGN
531#else
533#endif
534}
535
536/****************************************************************************/
537
538#ifdef EC_SII_ASSIGN
539
543
546 )
547{
548 ec_datagram_t *datagram = fsm->datagram;
549 ec_slave_t *slave = fsm->slave;
550
551 if (datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--) {
552 return;
553 }
554
555 if (datagram->state != EC_DATAGRAM_RECEIVED) {
556 EC_SLAVE_WARN(slave, "Failed to receive SII assignment datagram: ");
557 ec_datagram_print_state(datagram);
558 // Try to go on, probably assignment is correct
559 goto continue_with_sii_size;
560 }
561
562 if (datagram->working_counter != 1) {
563 EC_SLAVE_WARN(slave, "Failed to assign SII to EtherCAT: ");
565 // Try to go on, probably assignment is correct
566 }
567
568continue_with_sii_size:
570}
571
572#endif
573
574/****************************************************************************/
575
579
582 )
583{
584 ec_slave_t *slave = fsm->slave;
585 uint16_t cat_type, cat_size;
586
587 if (ec_fsm_sii_exec(&fsm->fsm_sii))
588 return;
589
590 if (!ec_fsm_sii_success(&fsm->fsm_sii)) {
591 fsm->slave->error_flag = 1;
593 EC_SLAVE_ERR(slave, "Failed to determine SII content size:"
594 " Reading word offset 0x%04x failed. Assuming %u words.\n",
597 goto alloc_sii;
598 }
599
600 cat_type = EC_READ_U16(fsm->fsm_sii.value);
601 cat_size = EC_READ_U16(fsm->fsm_sii.value + 2);
602
603 if (cat_type != 0xFFFF) { // not the last category
604 off_t next_offset = 2UL + fsm->sii_offset + cat_size;
605
606 EC_SLAVE_DBG(slave, 1, "Found category type %u with size %u."
607 " Proceeding to offset %zd.\n",
608 cat_type, cat_size, (ssize_t)next_offset);
609
610 if (next_offset >= EC_MAX_SII_SIZE) {
611 EC_SLAVE_WARN(slave, "SII size exceeds %u words"
612 " (0xffff limiter missing?).\n", EC_MAX_SII_SIZE);
613 // cut off category data...
615 goto alloc_sii;
616 }
617 fsm->sii_offset = next_offset;
618 ec_fsm_sii_read(&fsm->fsm_sii, slave, fsm->sii_offset,
620 ec_fsm_sii_exec(&fsm->fsm_sii); // execute state immediately
621 return;
622 }
623
624 slave->sii_nwords = fsm->sii_offset + 1;
625
626alloc_sii:
627 if (slave->sii_words) {
628 EC_SLAVE_WARN(slave, "Freeing old SII data...\n");
629 kfree(slave->sii_words);
630 }
631
632 if (!(slave->sii_words =
633 (uint16_t *) kmalloc(slave->sii_nwords * 2, GFP_KERNEL))) {
634 EC_SLAVE_ERR(slave, "Failed to allocate %zu words of SII data.\n",
635 slave->sii_nwords);
636 slave->sii_nwords = 0;
637 slave->error_flag = 1;
639 return;
640 }
641
642 // Start fetching SII contents
643
645 fsm->sii_offset = 0x0000;
646 ec_fsm_sii_read(&fsm->fsm_sii, slave, fsm->sii_offset,
648 ec_fsm_sii_exec(&fsm->fsm_sii); // execute state immediately
649}
650
651/****************************************************************************/
652
656
659{
660 ec_slave_t *slave = fsm->slave;
661 uint16_t *cat_word, cat_type, cat_size;
662
663 if (ec_fsm_sii_exec(&fsm->fsm_sii)) return;
664
665 if (!ec_fsm_sii_success(&fsm->fsm_sii)) {
666 fsm->slave->error_flag = 1;
668 EC_SLAVE_ERR(slave, "Failed to fetch SII contents.\n");
669 return;
670 }
671
672 // 2 words fetched
673
674 if (fsm->sii_offset + 2 <= slave->sii_nwords) { // 2 words fit
675 memcpy(slave->sii_words + fsm->sii_offset, fsm->fsm_sii.value, 4);
676 } else { // copy the last word
677 memcpy(slave->sii_words + fsm->sii_offset, fsm->fsm_sii.value, 2);
678 }
679
680 if (fsm->sii_offset + 2 < slave->sii_nwords) {
681 // fetch the next 2 words
682 fsm->sii_offset += 2;
683 ec_fsm_sii_read(&fsm->fsm_sii, slave, fsm->sii_offset,
685 ec_fsm_sii_exec(&fsm->fsm_sii); // execute state immediately
686 return;
687 }
688
689 // Evaluate SII contents
690
692
693 slave->sii.alias =
694 EC_READ_U16(slave->sii_words + 0x0004);
695 slave->effective_alias = slave->sii.alias;
696 slave->sii.vendor_id =
697 EC_READ_U32(slave->sii_words + 0x0008);
698 slave->sii.product_code =
699 EC_READ_U32(slave->sii_words + 0x000A);
700 slave->sii.revision_number =
701 EC_READ_U32(slave->sii_words + 0x000C);
702 slave->sii.serial_number =
703 EC_READ_U32(slave->sii_words + 0x000E);
705 EC_READ_U16(slave->sii_words + 0x0014);
707 EC_READ_U16(slave->sii_words + 0x0015);
709 EC_READ_U16(slave->sii_words + 0x0016);
711 EC_READ_U16(slave->sii_words + 0x0017);
713 EC_READ_U16(slave->sii_words + 0x0018);
714 slave->sii.std_rx_mailbox_size =
715 EC_READ_U16(slave->sii_words + 0x0019);
717 EC_READ_U16(slave->sii_words + 0x001A);
718 slave->sii.std_tx_mailbox_size =
719 EC_READ_U16(slave->sii_words + 0x001B);
720 slave->sii.mailbox_protocols =
721 EC_READ_U16(slave->sii_words + 0x001C);
722 if (slave->sii.mailbox_protocols) {
723 int need_delim = 0;
724 uint16_t all = EC_MBOX_AOE | EC_MBOX_COE | EC_MBOX_FOE |
726 if ((slave->sii.mailbox_protocols & all) &&
727 slave->master->debug_level >= 1) {
728 EC_SLAVE_DBG(slave, 1, "Slave announces to support ");
729 if (slave->sii.mailbox_protocols & EC_MBOX_AOE) {
730 printk(KERN_CONT "AoE");
731 need_delim = 1;
732 }
733 if (slave->sii.mailbox_protocols & EC_MBOX_COE) {
734 if (need_delim) {
735 printk(KERN_CONT ", ");
736 }
737 printk(KERN_CONT "CoE");
738 need_delim = 1;
739 }
740 if (slave->sii.mailbox_protocols & EC_MBOX_FOE) {
741 if (need_delim) {
742 printk(KERN_CONT ", ");
743 }
744 printk(KERN_CONT "FoE");
745 need_delim = 1;
746 }
747 if (slave->sii.mailbox_protocols & EC_MBOX_SOE) {
748 if (need_delim) {
749 printk(KERN_CONT ", ");
750 }
751 printk(KERN_CONT "SoE");
752 need_delim = 1;
753 }
754 if (slave->sii.mailbox_protocols & EC_MBOX_VOE) {
755 if (need_delim) {
756 printk(KERN_CONT ", ");
757 }
758 printk(KERN_CONT "VoE");
759 need_delim = 1;
760 }
761 printk(KERN_CONT ".\n");
762 }
763 if (slave->sii.mailbox_protocols & ~all) {
764 EC_SLAVE_DBG(slave, 1, "Slave announces to support unknown"
765 " mailbox protocols 0x%04X.",
766 slave->sii.mailbox_protocols & ~all);
767 }
768 }
769 else {
770 EC_SLAVE_DBG(slave, 1, "Slave announces to support no mailbox"
771 " protocols.");
772 }
773
774 if (slave->sii.boot_rx_mailbox_offset == 0xffff ||
775 slave->sii.boot_rx_mailbox_size == 0xffff ||
776 slave->sii.boot_tx_mailbox_offset == 0xffff ||
777 slave->sii.boot_tx_mailbox_size == 0xffff ||
778 slave->sii.std_rx_mailbox_offset == 0xffff ||
779 slave->sii.std_rx_mailbox_size == 0xffff ||
780 slave->sii.std_tx_mailbox_offset == 0xffff ||
781 slave->sii.std_tx_mailbox_size == 0xffff) {
782 slave->sii.mailbox_protocols = 0x0000;
783 EC_SLAVE_ERR(slave, "Invalid mailbox settings in SII."
784 " Disabling mailbox communication.");
785 }
786
788 // sii does not contain category data
790 return;
791 }
792
793 if (slave->sii_nwords < EC_FIRST_SII_CATEGORY_OFFSET + 1) {
794 EC_SLAVE_ERR(slave, "Unexpected end of SII data:"
795 " First category header missing.\n");
796 goto end;
797 }
798
799 // evaluate category data
800 cat_word = slave->sii_words + EC_FIRST_SII_CATEGORY_OFFSET;
801 while (EC_READ_U16(cat_word) != 0xFFFF) {
802
803 // type and size words must fit
804 if (cat_word + 2 - slave->sii_words > slave->sii_nwords) {
805 EC_SLAVE_ERR(slave, "Unexpected end of SII data:"
806 " Category header incomplete.\n");
807 goto end;
808 }
809
810 cat_type = EC_READ_U16(cat_word) & 0x7FFF;
811 cat_size = EC_READ_U16(cat_word + 1);
812 cat_word += 2;
813
814 if (cat_word + cat_size - slave->sii_words > slave->sii_nwords) {
815 EC_SLAVE_WARN(slave, "Unexpected end of SII data:"
816 " Category data incomplete.\n");
817 goto end;
818 }
819
820 switch (cat_type) {
821 case 0x000A:
822 if (ec_slave_fetch_sii_strings(slave, (uint8_t *) cat_word,
823 cat_size * 2))
824 goto end;
825 break;
826 case 0x001E:
827 if (ec_slave_fetch_sii_general(slave, (uint8_t *) cat_word,
828 cat_size * 2))
829 goto end;
830 break;
831 case 0x0028:
832 break;
833 case 0x0029:
834 if (ec_slave_fetch_sii_syncs(slave, (uint8_t *) cat_word,
835 cat_size * 2))
836 goto end;
837 break;
838 case 0x0032:
839 if (ec_slave_fetch_sii_pdos( slave, (uint8_t *) cat_word,
840 cat_size * 2, EC_DIR_INPUT)) // TxPDO
841 goto end;
842 break;
843 case 0x0033:
844 if (ec_slave_fetch_sii_pdos( slave, (uint8_t *) cat_word,
845 cat_size * 2, EC_DIR_OUTPUT)) // RxPDO
846 goto end;
847 break;
848 default:
849 EC_SLAVE_DBG(slave, 1, "Unknown category type 0x%04X.\n",
850 cat_type);
851 }
852
853 cat_word += cat_size;
854 if (cat_word - slave->sii_words >= slave->sii_nwords) {
855 EC_SLAVE_WARN(slave, "Unexpected end of SII data:"
856 " Next category header missing.\n");
857 goto end;
858 }
859 }
860
861#ifdef EC_REGALIAS
862 ec_fsm_slave_scan_enter_regalias(fsm);
863#else
864 if (slave->sii.mailbox_protocols & EC_MBOX_COE) {
866 } else {
868 }
869#endif
870 return;
871
872end:
873 EC_SLAVE_ERR(slave, "Failed to analyze category data.\n");
874 fsm->slave->error_flag = 1;
876}
877
878/****************************************************************************/
879
880#ifdef EC_REGALIAS
881
884void ec_fsm_slave_scan_enter_regalias(
886 )
887{
888 ec_datagram_t *datagram = fsm->datagram;
889 ec_slave_t *slave = fsm->slave;
890
891 // read alias from register
892 EC_SLAVE_DBG(slave, 1, "Reading alias from register.\n");
893 ec_datagram_fprd(datagram, slave->station_address, 0x0012, 2);
894 ec_datagram_zero(datagram);
895 fsm->retries = EC_FSM_RETRIES;
896 fsm->state = ec_fsm_slave_scan_state_regalias;
897}
898
899/****************************************************************************/
900
903void ec_fsm_slave_scan_state_regalias(
905 )
906{
907 ec_datagram_t *datagram = fsm->datagram;
908 ec_slave_t *slave = fsm->slave;
909
910 if (datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--)
911 return;
912
913 if (datagram->state != EC_DATAGRAM_RECEIVED) {
915 EC_SLAVE_ERR(slave, "Failed to receive register alias datagram: ");
916 ec_datagram_print_state(datagram);
917 return;
918 }
919
920 if (datagram->working_counter != 1) {
921 EC_SLAVE_DBG(slave, 1, "Failed to read register alias.\n");
922 } else {
923 slave->effective_alias = EC_READ_U16(datagram->data);
924 EC_SLAVE_DBG(slave, 1, "Read alias %u from register.\n",
925 slave->effective_alias);
926 }
927
928 if (slave->sii.mailbox_protocols & EC_MBOX_COE) {
930 } else {
932 }
933}
934
935#endif // defined EC_REGALIAS
936
937/****************************************************************************/
938
943 )
944{
945 ec_slave_t *slave = fsm->slave;
946 uint8_t current_state = slave->current_state & EC_SLAVE_STATE_MASK;
947
948 if (current_state != EC_SLAVE_STATE_PREOP
949 && current_state != EC_SLAVE_STATE_SAFEOP
950 && current_state != EC_SLAVE_STATE_OP) {
951 if (slave->master->debug_level) {
952 char str[EC_STATE_STRING_SIZE];
953 ec_state_string(current_state, str, 0);
954 EC_SLAVE_DBG(slave, 0, "Slave is not in the state"
955 " to do mailbox com (%s), setting to PREOP.\n", str);
956 }
957
962 } else {
963 EC_SLAVE_DBG(slave, 1, "Reading mailbox"
964 " sync manager configuration.\n");
965
966 /* Scan current sync manager configuration to get configured mailbox
967 * sizes. */
968 ec_datagram_fprd(fsm->datagram, slave->station_address, 0x0800,
970 fsm->retries = EC_FSM_RETRIES;
972 }
973}
974
975/****************************************************************************/
976
981 )
982{
984 return;
985
988 return;
989 }
990
992}
993
994/****************************************************************************/
995
1000 )
1001{
1002 ec_datagram_t *datagram = fsm->datagram;
1003 ec_slave_t *slave = fsm->slave;
1004 uint16_t tx_offset, tx_size, rx_offset, rx_size;
1005
1006 if (datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--)
1007 return;
1008
1009 if (datagram->state != EC_DATAGRAM_RECEIVED) {
1011 EC_SLAVE_ERR(slave, "Failed to receive sync manager"
1012 " configuration datagram: ");
1013 ec_datagram_print_state(datagram);
1014 return;
1015 }
1016
1017 if (datagram->working_counter != 1) {
1018 fsm->slave->error_flag = 1;
1020 EC_SLAVE_ERR(slave, "Failed to read DL status: ");
1022 return;
1023 }
1024
1025 rx_offset = EC_READ_U16(datagram->data);
1026 rx_size = EC_READ_U16(datagram->data + 2);
1027 tx_offset = EC_READ_U16(datagram->data + 8);
1028 tx_size = EC_READ_U16(datagram->data + 10);
1029
1030 if (rx_size == 0xffff) {
1032 slave->sii.mailbox_protocols = 0x0000;
1033 EC_SLAVE_ERR(slave, "Invalid RX mailbox size (%u) configured."
1034 " Disabling mailbox communication.", rx_size);
1035 return;
1036 }
1037
1038 if (tx_size == 0xffff) {
1040 slave->sii.mailbox_protocols = 0x0000;
1041 EC_SLAVE_ERR(slave, "Invalid TX mailbox size (%u) configured."
1042 " Disabling mailbox communication.", tx_size);
1043 return;
1044 }
1045
1046 slave->configured_rx_mailbox_offset = rx_offset;
1047 slave->configured_rx_mailbox_size = rx_size;
1048 slave->configured_tx_mailbox_offset = tx_offset;
1049 slave->configured_tx_mailbox_size = tx_size;
1050
1051 EC_SLAVE_DBG(slave, 1, "Mailbox configuration:\n");
1052 EC_SLAVE_DBG(slave, 1, " RX offset=0x%04x size=%u\n",
1055 EC_SLAVE_DBG(slave, 1, " TX offset=0x%04x size=%u\n",
1058
1060}
1061
1062/****************************************************************************/
1063
1068 )
1069{
1070 ec_slave_t *slave = fsm->slave;
1071
1072 EC_SLAVE_DBG(slave, 1, "Scanning PDO assignment and mapping.\n");
1074 ec_fsm_pdo_start_reading(fsm->fsm_pdo, slave);
1075 ec_fsm_pdo_exec(fsm->fsm_pdo, fsm->datagram); // execute immediately
1076}
1077
1078/****************************************************************************/
1079
1084 )
1085{
1086 if (ec_fsm_pdo_exec(fsm->fsm_pdo, fsm->datagram)) {
1087 return;
1088 }
1089
1090 if (!ec_fsm_pdo_success(fsm->fsm_pdo)) {
1092 return;
1093 }
1094
1095 // reading PDO configuration finished
1097}
1098
1099/*****************************************************************************
1100 * Common state functions
1101 ****************************************************************************/
1102
1107 )
1108{
1109}
1110
1111/****************************************************************************/
1112
1117 )
1118{
1119}
1120
1121/****************************************************************************/
void ec_datagram_print_wc_error(const ec_datagram_t *datagram)
Evaluates the working counter of a single-cast datagram.
Definition datagram.c:594
void ec_datagram_zero(ec_datagram_t *datagram)
Fills the datagram payload memory with zeros.
Definition datagram.c:170
int ec_datagram_apwr(ec_datagram_t *datagram, uint16_t ring_position, uint16_t mem_address, size_t data_size)
Initializes an EtherCAT APWR datagram.
Definition datagram.c:202
void ec_datagram_print_state(const ec_datagram_t *datagram)
Prints the state of a datagram.
Definition datagram.c:557
int ec_datagram_fpwr(ec_datagram_t *datagram, uint16_t configured_address, uint16_t mem_address, size_t data_size)
Initializes an EtherCAT FPWR datagram.
Definition datagram.c:290
int ec_datagram_fprd(ec_datagram_t *datagram, uint16_t configured_address, uint16_t mem_address, size_t data_size)
Initializes an EtherCAT FPRD datagram.
Definition datagram.c:265
@ EC_DATAGRAM_RECEIVED
Received (dequeued).
Definition datagram.h:70
@ EC_DATAGRAM_TIMED_OUT
Timed out (dequeued).
Definition datagram.h:71
@ EC_DATAGRAM_SENT
Sent (still in the queue).
Definition datagram.h:69
@ EC_DATAGRAM_QUEUED
Queued for sending.
Definition datagram.h:68
void ec_fsm_pdo_start_reading(ec_fsm_pdo_t *fsm, ec_slave_t *slave)
Start reading the PDO configuration.
Definition fsm_pdo.c:119
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:164
int ec_fsm_pdo_success(const ec_fsm_pdo_t *fsm)
Get execution result.
Definition fsm_pdo.c:180
struct ec_fsm_pdo ec_fsm_pdo_t
Definition fsm_pdo.h:42
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_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:90
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
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.
int ec_fsm_slave_config_exec(ec_fsm_slave_config_t *fsm)
Executes the current state of the state machine.
struct ec_fsm_slave_config ec_fsm_slave_config_t
void ec_fsm_slave_scan_state_start(ec_fsm_slave_scan_t *)
Slave scan state: START.
void ec_fsm_slave_scan_enter_datalink(ec_fsm_slave_scan_t *)
Slave scan entry function: DATALINK.
void ec_fsm_slave_scan_state_end(ec_fsm_slave_scan_t *)
State: END.
void ec_fsm_slave_scan_state_preop(ec_fsm_slave_scan_t *)
Slave scan state: PREOP.
void ec_fsm_slave_scan_state_sii_size(ec_fsm_slave_scan_t *)
Slave scan state: SII SIZE.
void ec_fsm_slave_scan_state_base(ec_fsm_slave_scan_t *)
Slave scan state: BASE.
void ec_fsm_slave_scan_state_assign_sii(ec_fsm_slave_scan_t *)
Slave scan state: ASSIGN_SII.
void ec_fsm_slave_scan_enter_assign_sii(ec_fsm_slave_scan_t *)
Enter slave scan state ASSIGN_SII.
int ec_fsm_slave_scan_running(const ec_fsm_slave_scan_t *)
void ec_fsm_slave_scan_state_state(ec_fsm_slave_scan_t *)
Slave scan state: STATE.
void ec_fsm_slave_scan_enter_pdos(ec_fsm_slave_scan_t *)
Enter slave scan state PDOS.
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_state_datalink(ec_fsm_slave_scan_t *)
Slave scan state: DATALINK.
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_enter_sii_size(ec_fsm_slave_scan_t *)
Enter slave scan state SII_SIZE.
void ec_fsm_slave_scan_state_dc_times(ec_fsm_slave_scan_t *)
Slave scan state: DC TIMES.
void ec_fsm_slave_scan_state_sync(ec_fsm_slave_scan_t *)
Slave scan state: SYNC.
void ec_fsm_slave_scan_state_pdos(ec_fsm_slave_scan_t *)
Slave scan state: PDOS.
void ec_fsm_slave_scan_state_dc_cap(ec_fsm_slave_scan_t *)
Slave scan state: DC CAPABILITIES.
void ec_fsm_slave_scan_clear(ec_fsm_slave_scan_t *fsm)
Destructor.
void ec_fsm_slave_scan_state_address(ec_fsm_slave_scan_t *)
Slave scan state: ADDRESS.
void ec_fsm_slave_scan_state_sii_data(ec_fsm_slave_scan_t *)
Slave scan state: SII DATA.
int ec_fsm_slave_scan_exec(ec_fsm_slave_scan_t *fsm)
Executes the current state of the state machine.
void ec_fsm_slave_scan_state_error(ec_fsm_slave_scan_t *)
State: ERROR.
int ec_fsm_slave_scan_success(const ec_fsm_slave_scan_t *fsm)
void ec_fsm_slave_scan_enter_preop(ec_fsm_slave_scan_t *)
Enter slave scan state PREOP.
EtherCAT slave scanning state machine.
struct ec_fsm_slave_scan ec_fsm_slave_scan_t
Global definitions and macros.
#define EC_MAX_SII_SIZE
Maximum SII size in words, to avoid infinite reading.
Definition globals.h:57
#define EC_SYNC_PAGE_SIZE
Size of a sync manager configuration page.
Definition globals.h:89
@ EC_SLAVE_STATE_PREOP
PREOP state (mailbox communication, no IO).
Definition globals.h:126
@ EC_SLAVE_STATE_OP
OP (mailbox communication and input/output update).
Definition globals.h:132
@ EC_SLAVE_STATE_SAFEOP
SAFEOP (mailbox communication and input update).
Definition globals.h:130
@ EC_SLAVE_STATE_ACK_ERR
Acknowledge/Error bit (no actual state).
Definition globals.h:134
#define EC_STATE_STRING_SIZE
Minimum size of a buffer used with ec_state_string().
Definition globals.h:54
#define EC_FSM_RETRIES
Number of state machine retries on datagram timeout.
Definition globals.h:47
#define EC_SLAVE_STATE_MASK
Slave state mask.
Definition globals.h:117
@ EC_MBOX_FOE
File-Access over EtherCAT.
Definition globals.h:147
@ EC_MBOX_COE
CANopen over EtherCAT.
Definition globals.h:146
@ EC_MBOX_VOE
Vendor specific.
Definition globals.h:149
@ EC_MBOX_SOE
Servo-Profile over EtherCAT.
Definition globals.h:148
@ EC_MBOX_AOE
ADS over EtherCAT.
Definition globals.h:144
#define EC_FIRST_SII_CATEGORY_OFFSET
Word offset of first SII category.
Definition globals.h:86
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
#define EC_MAX_FMMUS
Maximum number of FMMUs per slave.
Definition globals.h:92
struct ec_slave ec_slave_t
Definition globals.h:310
#define EC_MAX_PORTS
Maximum number of slave ports.
Definition ecrt.h:276
#define EC_WRITE_U8(DATA, VAL)
Write an 8-bit unsigned value to EtherCAT data.
Definition ecrt.h:3040
#define EC_READ_U16(DATA)
Read a 16-bit unsigned value from EtherCAT data.
Definition ecrt.h:2948
#define EC_MAX_SYNC_MANAGERS
Maximum number of sync managers per slave.
Definition ecrt.h:267
#define EC_READ_U8(DATA)
Read an 8-bit unsigned value from EtherCAT data.
Definition ecrt.h:2932
#define EC_READ_U32(DATA)
Read a 32-bit unsigned value from EtherCAT data.
Definition ecrt.h:2964
#define EC_WRITE_U16(DATA, VAL)
Write a 16-bit unsigned value to EtherCAT data.
Definition ecrt.h:3057
@ EC_DIR_INPUT
Values read by the master.
Definition ecrt.h:507
@ EC_DIR_OUTPUT
Values written by the master.
Definition ecrt.h:506
Mailbox functionality.
EtherCAT master structure.
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:306
void ec_slave_clear_sync_managers(ec_slave_t *slave)
Clear the sync manager array.
Definition slave.c:265
int ec_slave_fetch_sii_pdos(ec_slave_t *slave, const uint8_t *data, size_t data_size, ec_direction_t dir)
Fetches data from a [RT]xPDO category.
Definition slave.c:495
int ec_slave_fetch_sii_strings(ec_slave_t *slave, const uint8_t *data, size_t data_size)
Fetches data from a STRING category.
Definition slave.c:322
int ec_slave_fetch_sii_syncs(ec_slave_t *slave, const uint8_t *data, size_t data_size)
Fetches data from a SYNC MANAGER category.
Definition slave.c:429
int ec_slave_fetch_sii_general(ec_slave_t *slave, const uint8_t *data, size_t data_size)
Fetches data from a GENERAL category.
Definition slave.c:378
#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
EtherCAT slave configuration structure.
EtherCAT datagram.
Definition datagram.h:79
uint16_t working_counter
Working counter.
Definition datagram.h:93
ec_datagram_state_t state
State.
Definition datagram.h:94
uint8_t * data
Datagram payload.
Definition datagram.h:88
uint8_t value[4]
raw SII value (32bit)
Definition fsm_sii.h:62
unsigned int retries
Retries on datagram timeout.
ec_fsm_slave_config_t * fsm_slave_config
Slave configuration state machine to use.
ec_slave_t * slave
Slave the FSM runs on.
void(* state)(ec_fsm_slave_scan_t *)
State function.
ec_fsm_sii_t fsm_sii
SII state machine.
uint16_t sii_offset
SII offset in words.
ec_datagram_t * datagram
Datagram used in the state machine.
ec_fsm_pdo_t * fsm_pdo
PDO configuration state machine to use.
unsigned int debug_level
Master debug level.
Definition master.h:275
uint16_t std_rx_mailbox_offset
Standard receive mailbox address.
Definition slave.h:135
uint16_t alias
Configured station alias.
Definition slave.h:126
uint32_t serial_number
Serial number.
Definition slave.h:130
uint16_t std_tx_mailbox_size
Standard transmit mailbox size.
Definition slave.h:138
uint16_t boot_tx_mailbox_size
Bootstrap transmit mailbox size.
Definition slave.h:134
uint32_t product_code
Vendor-specific product code.
Definition slave.h:128
uint16_t mailbox_protocols
Supported mailbox protocols.
Definition slave.h:139
uint16_t boot_tx_mailbox_offset
Bootstrap transmit mailbox address.
Definition slave.h:133
uint16_t std_tx_mailbox_offset
Standard transmit mailbox address.
Definition slave.h:137
uint16_t boot_rx_mailbox_size
Bootstrap receive mailbox size.
Definition slave.h:132
uint32_t revision_number
Revision number.
Definition slave.h:129
uint16_t std_rx_mailbox_size
Standard receive mailbox size.
Definition slave.h:136
uint16_t boot_rx_mailbox_offset
Bootstrap receive mailbox address.
Definition slave.h:131
uint32_t vendor_id
Vendor ID.
Definition slave.h:127
uint32_t receive_time
Port receive times for delay measurement.
Definition slave.h:114
ec_slave_port_link_t link
Port link status.
Definition slave.h:112
ec_slave_port_desc_t desc
Port descriptors.
Definition slave.h:111
uint16_t configured_rx_mailbox_size
Configured receive mailbox size.
Definition slave.h:189
ec_sii_t sii
Extracted SII data.
Definition slave.h:215
ec_slave_port_t ports[EC_MAX_PORTS]
Ports.
Definition slave.h:179
uint8_t base_dc_supported
Distributed clocks are supported.
Definition slave.h:202
uint16_t ring_position
Ring position.
Definition slave.h:175
uint16_t configured_tx_mailbox_offset
Configured send mailbox offset.
Definition slave.h:191
uint16_t * sii_words
Complete SII image.
Definition slave.h:211
uint8_t base_fmmu_bit_operation
FMMU bit operation is supported.
Definition slave.h:201
uint8_t base_fmmu_count
Number of supported FMMUs.
Definition slave.h:199
uint8_t base_revision
Revision.
Definition slave.h:197
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
uint16_t configured_tx_mailbox_size
Configured send mailbox size.
Definition slave.h:193
uint16_t configured_rx_mailbox_offset
Configured receive mailbox offset.
Definition slave.h:187
ec_slave_dc_range_t base_dc_range
DC range.
Definition slave.h:203
uint8_t base_type
Slave type.
Definition slave.h:196
uint16_t effective_alias
Effective alias address.
Definition slave.h:177
size_t sii_nwords
Size of the SII contents in words.
Definition slave.h:212
uint8_t base_sync_count
Number of supported sync managers.
Definition slave.h:200
ec_master_t * master
Master owning the slave.
Definition slave.h:170
uint16_t station_address
Configured station address.
Definition slave.h:176
unsigned int error_flag
Stop processing after an error.
Definition slave.h:185
uint16_t base_build
Build number.
Definition slave.h:198