IgH EtherCAT Master  1.6.1
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 
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
44 void 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
64 void ec_fsm_slave_scan_state_regalias(ec_fsm_slave_scan_t *);
65 #endif
69 
72 
73 /****************************************************************************/
74 
78  ec_fsm_slave_scan_t *fsm,
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
100  ec_fsm_sii_clear(&fsm->fsm_sii);
101 }
102 
103 /****************************************************************************/
104 
110  ec_fsm_slave_scan_t *fsm,
111  ec_slave_t *slave
112  )
113 {
114  fsm->slave = slave;
116 }
117 
118 /****************************************************************************/
119 
125  const ec_fsm_slave_scan_t *fsm
126  )
127 {
128  return fsm->state != ec_fsm_slave_scan_state_end
130 }
131 
132 /****************************************************************************/
133 
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 
160 {
161  return fsm->state == ec_fsm_slave_scan_state_end;
162 }
163 
164 /*****************************************************************************
165  * slave scan state machine
166  ****************************************************************************/
167 
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 
190  ec_fsm_slave_scan_t *fsm
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: ");
210  ec_datagram_print_wc_error(datagram);
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 
228  ec_fsm_slave_scan_t *fsm
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: ");
248  ec_datagram_print_wc_error(datagram);
249  return;
250  }
251 
252  slave->current_state = EC_READ_U8(datagram->data);
253  if (slave->current_state & EC_SLAVE_STATE_ACK_ERR) {
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 
272  ec_fsm_slave_scan_t *fsm
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: ");
294  ec_datagram_print_wc_error(datagram);
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);
306  slave->base_fmmu_count = EC_MAX_FMMUS;
307  }
308 
309  slave->base_sync_count = EC_READ_U8(datagram->data + 5);
310  if (slave->base_sync_count > EC_MAX_SYNC_MANAGERS) {
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 
346  ec_fsm_slave_scan_t *fsm
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: ");
373  ec_datagram_print_wc_error(datagram);
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 
391  ec_fsm_slave_scan_t *fsm
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: ");
412  ec_datagram_print_wc_error(datagram);
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 
430  ec_fsm_slave_scan_t *fsm
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 
448  ec_fsm_slave_scan_t *fsm
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 
469  ec_fsm_slave_scan_t *fsm
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 
493  ec_fsm_slave_scan_t *fsm
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: ");
515  ec_datagram_print_wc_error(datagram);
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 
545  ec_fsm_slave_scan_t *fsm
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: ");
564  ec_datagram_print_wc_error(datagram);
565  // Try to go on, probably assignment is correct
566  }
567 
568 continue_with_sii_size:
570 }
571 
572 #endif
573 
574 /****************************************************************************/
575 
581  ec_fsm_slave_scan_t *fsm
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 
626 alloc_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 
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);
704  slave->sii.boot_rx_mailbox_offset =
705  EC_READ_U16(slave->sii_words + 0x0014);
706  slave->sii.boot_rx_mailbox_size =
707  EC_READ_U16(slave->sii_words + 0x0015);
708  slave->sii.boot_tx_mailbox_offset =
709  EC_READ_U16(slave->sii_words + 0x0016);
710  slave->sii.boot_tx_mailbox_size =
711  EC_READ_U16(slave->sii_words + 0x0017);
712  slave->sii.std_rx_mailbox_offset =
713  EC_READ_U16(slave->sii_words + 0x0018);
714  slave->sii.std_rx_mailbox_size =
715  EC_READ_U16(slave->sii_words + 0x0019);
716  slave->sii.std_tx_mailbox_offset =
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 
872 end:
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 
884 void ec_fsm_slave_scan_enter_regalias(
885  ec_fsm_slave_scan_t *fsm
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 
903 void ec_fsm_slave_scan_state_regalias(
904  ec_fsm_slave_scan_t *fsm
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 
942  ec_fsm_slave_scan_t *fsm
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,
969  EC_SYNC_PAGE_SIZE * 2);
970  fsm->retries = EC_FSM_RETRIES;
972  }
973 }
974 
975 /****************************************************************************/
976 
980  ec_fsm_slave_scan_t *fsm
981  )
982 {
984  return;
985 
988  return;
989  }
990 
992 }
993 
994 /****************************************************************************/
995 
999  ec_fsm_slave_scan_t *fsm
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: ");
1021  ec_datagram_print_wc_error(datagram);
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 
1067  ec_fsm_slave_scan_t *fsm
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 
1083  ec_fsm_slave_scan_t *fsm
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 
1106  ec_fsm_slave_scan_t *fsm
1107  )
1108 {
1109 }
1110 
1111 /****************************************************************************/
1112 
1116  ec_fsm_slave_scan_t *fsm
1117  )
1118 {
1119 }
1120 
1121 /****************************************************************************/
#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:146
uint16_t ring_position
Ring position.
Definition: slave.h:175
uint32_t revision_number
Revision number.
Definition: slave.h:129
uint16_t boot_rx_mailbox_offset
Bootstrap receive mailbox address.
Definition: slave.h:131
#define EC_SYNC_PAGE_SIZE
Size of a sync manager configuration page.
Definition: globals.h:89
void ec_fsm_slave_scan_enter_assign_sii(ec_fsm_slave_scan_t *)
Enter slave scan state ASSIGN_SII.
#define EC_SLAVE_STATE_MASK
Slave state mask.
Definition: globals.h:117
ec_sii_t sii
Extracted SII data.
Definition: slave.h:215
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
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.
uint16_t configured_tx_mailbox_size
Configured send mailbox size.
Definition: slave.h:193
uint16_t base_build
Build number.
Definition: slave.h:198
#define EC_SLAVE_DBG(slave, level, fmt, args...)
Convenience macro for printing slave-specific debug messages to syslog.
Definition: slave.h:98
OP (mailbox communication and input/output update)
Definition: globals.h:132
uint16_t configured_tx_mailbox_offset
Configured send mailbox offset.
Definition: slave.h:191
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:401
ec_slave_port_t ports[EC_MAX_PORTS]
Ports.
Definition: slave.h:179
ec_slave_state_t current_state
Current application state.
Definition: slave.h:184
ec_slave_port_link_t link
Port link status.
Definition: slave.h:112
void ec_fsm_slave_scan_state_preop(ec_fsm_slave_scan_t *)
Slave scan state: PREOP.
Servo-Profile over EtherCAT.
Definition: globals.h:148
#define EC_SLAVE_WARN(slave, fmt, args...)
Convenience macro for printing slave-specific warnings to syslog.
Definition: slave.h:82
void ec_fsm_slave_scan_state_assign_sii(ec_fsm_slave_scan_t *)
Slave scan state: ASSIGN_SII.
EtherCAT datagram.
Definition: datagram.h:79
uint32_t serial_number
Serial number.
Definition: slave.h:130
#define EC_WRITE_U8(DATA, VAL)
Write an 8-bit unsigned value to EtherCAT data.
Definition: ecrt.h:3137
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:93
void ec_fsm_slave_scan_state_start(ec_fsm_slave_scan_t *)
Slave scan state: START.
Acknowledge/Error bit (no actual state)
Definition: globals.h:134
uint16_t boot_tx_mailbox_size
Bootstrap transmit mailbox size.
Definition: slave.h:134
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
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
EtherCAT slave scanning state machine.
uint16_t station_address
Configured station address.
Definition: slave.h:176
#define EC_MAX_SII_SIZE
Maximum SII size in words, to avoid infinite reading.
Definition: globals.h:57
uint16_t std_rx_mailbox_size
Standard receive mailbox size.
Definition: slave.h:136
#define EC_MAX_FMMUS
Maximum number of FMMUs per slave.
Definition: globals.h:92
uint8_t base_type
Slave type.
Definition: slave.h:196
int ec_fsm_slave_scan_exec(ec_fsm_slave_scan_t *fsm)
Executes the current state of the state machine.
Global definitions and macros.
uint16_t std_tx_mailbox_offset
Standard transmit mailbox address.
Definition: slave.h:137
EtherCAT master structure.
SAFEOP (mailbox communication and input update)
Definition: globals.h:130
uint16_t boot_tx_mailbox_offset
Bootstrap transmit mailbox address.
Definition: slave.h:133
ec_fsm_slave_config_t * fsm_slave_config
Slave configuration state machine to use.
EtherCAT slave.
Definition: slave.h:168
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:202
void ec_datagram_zero(ec_datagram_t *datagram)
Fills the datagram payload memory with zeros.
Definition: datagram.c:170
ec_datagram_state_t state
State.
Definition: datagram.h:94
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.
void ec_slave_clear_sync_managers(ec_slave_t *slave)
Clear the sync manager array.
Definition: slave.c:265
Use configured addresses.
Definition: fsm_sii.h:42
uint16_t * sii_words
Complete SII image.
Definition: slave.h:211
uint16_t mailbox_protocols
Supported mailbox protocols.
Definition: slave.h:139
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
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:275
#define EC_SLAVE_ERR(slave, fmt, args...)
Convenience macro for printing slave-specific errors to syslog.
Definition: slave.h:68
void ec_datagram_print_wc_error(const ec_datagram_t *datagram)
Evaluates the working counter of a single-cast datagram.
Definition: datagram.c:594
ec_slave_dc_range_t base_dc_range
DC range.
Definition: slave.h:203
uint16_t std_rx_mailbox_offset
Standard receive mailbox address.
Definition: slave.h:135
uint8_t base_fmmu_bit_operation
FMMU bit operation is supported.
Definition: slave.h:201
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:126
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:3154
uint8_t base_fmmu_count
Number of supported FMMUs.
Definition: slave.h:199
uint16_t configured_rx_mailbox_offset
Configured receive mailbox offset.
Definition: slave.h:187
File-Access over EtherCAT.
Definition: globals.h:147
#define EC_READ_U32(DATA)
Read a 32-bit unsigned value from EtherCAT data.
Definition: ecrt.h:3061
ec_slave_port_desc_t desc
Port descriptors.
Definition: slave.h:111
Finite state machine for scanning an EtherCAT slave.
ec_master_t * master
Master owning the slave.
Definition: slave.h:170
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
uint8_t has_dc_system_time
The slave supports the DC system time register.
Definition: slave.h:204
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:265
Values read by the master.
Definition: ecrt.h:507
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:197
32 bit.
Definition: globals.h:173
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_clear(ec_fsm_sii_t *fsm)
Destructor.
Definition: fsm_sii.c:80
int ec_fsm_pdo_success(const ec_fsm_pdo_t *fsm)
Get execution result.
Definition: fsm_pdo.c:180
uint16_t effective_alias
Effective alias address.
Definition: slave.h:177
void ec_fsm_slave_scan_state_datalink(ec_fsm_slave_scan_t *)
Slave scan state: DATALINK.
int ec_fsm_sii_exec(ec_fsm_sii_t *fsm)
Executes the SII state machine.
Definition: fsm_sii.c:129
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
#define EC_READ_U16(DATA)
Read a 16-bit unsigned value from EtherCAT data.
Definition: ecrt.h:3045
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:557
Mailbox functionality.
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
#define EC_STATE_STRING_SIZE
Minimum size of a buffer used with ec_state_string().
Definition: globals.h:54
uint16_t boot_rx_mailbox_size
Bootstrap receive mailbox size.
Definition: slave.h:132
#define EC_MAX_PORTS
Maximum number of slave ports.
Definition: ecrt.h:276
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.
uint32_t receive_time
Port receive times for delay measurement.
Definition: slave.h:114
Timed out (dequeued).
Definition: datagram.h:71
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:306
uint16_t configured_rx_mailbox_size
Configured receive mailbox size.
Definition: slave.h:189
uint8_t base_dc_supported
Distributed clocks are supported.
Definition: slave.h:202
void ec_fsm_slave_scan_start(ec_fsm_slave_scan_t *fsm, ec_slave_t *slave)
Start slave scan state machine.
size_t sii_nwords
Size of the SII contents in words.
Definition: slave.h:212
uint8_t * data
Datagram payload.
Definition: datagram.h:88
uint8_t base_sync_count
Number of supported sync managers.
Definition: slave.h:200
#define EC_READ_U8(DATA)
Read an 8-bit unsigned value from EtherCAT data.
Definition: ecrt.h:3029
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.
uint32_t product_code
Vendor-specific product code.
Definition: slave.h:128
PREOP state (mailbox communication, no IO)
Definition: globals.h:126
Values written by the master.
Definition: ecrt.h:506
void ec_fsm_slave_scan_enter_preop(ec_fsm_slave_scan_t *)
Enter slave scan state PREOP.
Received (dequeued).
Definition: datagram.h:70
unsigned int error_flag
Stop processing after an error.
Definition: slave.h:185
void ec_fsm_slave_scan_state_address(ec_fsm_slave_scan_t *)
Slave scan state: ADDRESS.
uint16_t std_tx_mailbox_size
Standard transmit mailbox size.
Definition: slave.h:138
void ec_fsm_slave_scan_state_state(ec_fsm_slave_scan_t *)
Slave scan state: STATE.
Vendor specific.
Definition: globals.h:149
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
#define EC_MAX_SYNC_MANAGERS
Maximum number of sync managers per slave.
Definition: ecrt.h:267
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
ADS over EtherCAT.
Definition: globals.h:144
uint32_t vendor_id
Vendor ID.
Definition: slave.h:127
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)
uint8_t value[4]
raw SII value (32bit)
Definition: fsm_sii.h:62