IgH EtherCAT Master  1.5.2
fsm_slave_scan.c
Go to the documentation of this file.
1 /******************************************************************************
2  *
3  * $Id$
4  *
5  * Copyright (C) 2006-2008 Florian Pose, Ingenieurgemeinschaft IgH
6  *
7  * This file is part of the IgH EtherCAT Master.
8  *
9  * The IgH EtherCAT Master is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU General Public License version 2, as
11  * published by the Free Software Foundation.
12  *
13  * The IgH EtherCAT Master is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
16  * Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License along
19  * with the IgH EtherCAT Master; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
21  *
22  * ---
23  *
24  * The license mentioned above concerns the source code only. Using the
25  * EtherCAT technology and brand is only permitted in compliance with the
26  * industrial property and similar rights of Beckhoff Automation GmbH.
27  *
28  *****************************************************************************/
29 
35 /*****************************************************************************/
36 
37 #include "globals.h"
38 #include "master.h"
39 #include "mailbox.h"
40 #include "slave_config.h"
41 
42 #include "fsm_slave_scan.h"
43 
44 /*****************************************************************************/
45 
53 #ifdef EC_SII_ASSIGN
54 void ec_fsm_slave_scan_state_assign_sii(ec_fsm_slave_scan_t *);
55 #endif
58 #ifdef EC_REGALIAS
59 void ec_fsm_slave_scan_state_regalias(ec_fsm_slave_scan_t *);
60 #endif
64 
67 
69 #ifdef EC_REGALIAS
70 void ec_fsm_slave_scan_enter_regalias(ec_fsm_slave_scan_t *);
71 #endif
74 
75 /*****************************************************************************/
76 
80  ec_fsm_slave_scan_t *fsm,
81  ec_datagram_t *datagram,
82  ec_fsm_slave_config_t *fsm_slave_config,
84  ec_fsm_pdo_t *fsm_pdo
85  )
86 {
87  fsm->datagram = datagram;
88  fsm->fsm_slave_config = fsm_slave_config;
89  fsm->fsm_pdo = fsm_pdo;
90 
91  // init sub state machines
92  ec_fsm_sii_init(&fsm->fsm_sii, fsm->datagram);
93 }
94 
95 /*****************************************************************************/
96 
100 {
101  // clear sub state machines
102  ec_fsm_sii_clear(&fsm->fsm_sii);
103 }
104 
105 /*****************************************************************************/
106 
112  ec_fsm_slave_scan_t *fsm,
113  ec_slave_t *slave
114  )
115 {
116  fsm->slave = slave;
118 }
119 
120 /*****************************************************************************/
121 
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  fsm->sii_offset = EC_FIRST_SII_CATEGORY_OFFSET; // first category header
454  ec_fsm_sii_read(&fsm->fsm_sii, fsm->slave, fsm->sii_offset,
457  fsm->state(fsm); // execute state immediately
458 }
459 
460 /*****************************************************************************/
461 
462 #ifdef EC_SII_ASSIGN
463 
466 void ec_fsm_slave_scan_enter_assign_sii(
467  ec_fsm_slave_scan_t *fsm
468  )
469 {
470  ec_datagram_t *datagram = fsm->datagram;
471  ec_slave_t *slave = fsm->slave;
472 
473  EC_SLAVE_DBG(slave, 1, "Assigning SII access to EtherCAT.\n");
474 
475  // assign SII to ECAT
476  ec_datagram_fpwr(datagram, slave->station_address, 0x0500, 1);
477  EC_WRITE_U8(datagram->data, 0x00); // EtherCAT
478  fsm->retries = EC_FSM_RETRIES;
479  fsm->state = ec_fsm_slave_scan_state_assign_sii;
480 }
481 
482 #endif
483 
484 /*****************************************************************************/
485 
491  ec_fsm_slave_scan_t *fsm
492  )
493 {
494  ec_datagram_t *datagram = fsm->datagram;
495  ec_slave_t *slave = fsm->slave;
496  uint16_t dl_status;
497  unsigned int i;
498 
499  if (datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--)
500  return;
501 
502  if (datagram->state != EC_DATAGRAM_RECEIVED) {
504  EC_SLAVE_ERR(slave, "Failed to receive DL status datagram: ");
505  ec_datagram_print_state(datagram);
506  return;
507  }
508 
509  if (datagram->working_counter != 1) {
510  fsm->slave->error_flag = 1;
512  EC_SLAVE_ERR(slave, "Failed to read DL status: ");
513  ec_datagram_print_wc_error(datagram);
514  return;
515  }
516 
517  dl_status = EC_READ_U16(datagram->data);
518  for (i = 0; i < EC_MAX_PORTS; i++) {
519  slave->ports[i].link.link_up =
520  dl_status & (1 << (4 + i)) ? 1 : 0;
521  slave->ports[i].link.loop_closed =
522  dl_status & (1 << (8 + i * 2)) ? 1 : 0;
523  slave->ports[i].link.signal_detected =
524  dl_status & (1 << (9 + i * 2)) ? 1 : 0;
525  }
526 
527 #ifdef EC_SII_ASSIGN
528  ec_fsm_slave_scan_enter_assign_sii(fsm);
529 #else
531 #endif
532 }
533 
534 /*****************************************************************************/
535 
536 #ifdef EC_SII_ASSIGN
537 
542 void ec_fsm_slave_scan_state_assign_sii(
543  ec_fsm_slave_scan_t *fsm
544  )
545 {
546  ec_datagram_t *datagram = fsm->datagram;
547  ec_slave_t *slave = fsm->slave;
548 
549  if (datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--) {
550  return;
551  }
552 
553  if (datagram->state != EC_DATAGRAM_RECEIVED) {
554  EC_SLAVE_WARN(slave, "Failed to receive SII assignment datagram: ");
555  ec_datagram_print_state(datagram);
556  // Try to go on, probably assignment is correct
557  goto continue_with_sii_size;
558  }
559 
560  if (datagram->working_counter != 1) {
561  EC_SLAVE_WARN(slave, "Failed to assign SII to EtherCAT: ");
562  ec_datagram_print_wc_error(datagram);
563  // Try to go on, probably assignment is correct
564  }
565 
566 continue_with_sii_size:
568 }
569 
570 #endif
571 
572 /*****************************************************************************/
573 
579  ec_fsm_slave_scan_t *fsm
580  )
581 {
582  ec_slave_t *slave = fsm->slave;
583  uint16_t cat_type, cat_size;
584 
585  if (ec_fsm_sii_exec(&fsm->fsm_sii))
586  return;
587 
588  if (!ec_fsm_sii_success(&fsm->fsm_sii)) {
589  fsm->slave->error_flag = 1;
591  EC_SLAVE_ERR(slave, "Failed to determine SII content size:"
592  " Reading word offset 0x%04x failed. Assuming %u words.\n",
595  goto alloc_sii;
596  }
597 
598  cat_type = EC_READ_U16(fsm->fsm_sii.value);
599  cat_size = EC_READ_U16(fsm->fsm_sii.value + 2);
600 
601  if (cat_type != 0xFFFF) { // not the last category
602  off_t next_offset = 2UL + fsm->sii_offset + cat_size;
603  if (next_offset >= EC_MAX_SII_SIZE) {
604  EC_SLAVE_WARN(slave, "SII size exceeds %u words"
605  " (0xffff limiter missing?).\n", EC_MAX_SII_SIZE);
606  // cut off category data...
608  goto alloc_sii;
609  }
610  fsm->sii_offset = next_offset;
611  ec_fsm_sii_read(&fsm->fsm_sii, slave, fsm->sii_offset,
613  ec_fsm_sii_exec(&fsm->fsm_sii); // execute state immediately
614  return;
615  }
616 
617  slave->sii_nwords = fsm->sii_offset + 1;
618 
619 alloc_sii:
620  if (slave->sii_words) {
621  EC_SLAVE_WARN(slave, "Freeing old SII data...\n");
622  kfree(slave->sii_words);
623  }
624 
625  if (!(slave->sii_words =
626  (uint16_t *) kmalloc(slave->sii_nwords * 2, GFP_KERNEL))) {
627  EC_SLAVE_ERR(slave, "Failed to allocate %zu words of SII data.\n",
628  slave->sii_nwords);
629  slave->sii_nwords = 0;
630  slave->error_flag = 1;
632  return;
633  }
634 
635  // Start fetching SII contents
636 
638  fsm->sii_offset = 0x0000;
639  ec_fsm_sii_read(&fsm->fsm_sii, slave, fsm->sii_offset,
641  ec_fsm_sii_exec(&fsm->fsm_sii); // execute state immediately
642 }
643 
644 /*****************************************************************************/
645 
651 {
652  ec_slave_t *slave = fsm->slave;
653  uint16_t *cat_word, cat_type, cat_size;
654 
655  if (ec_fsm_sii_exec(&fsm->fsm_sii)) return;
656 
657  if (!ec_fsm_sii_success(&fsm->fsm_sii)) {
658  fsm->slave->error_flag = 1;
660  EC_SLAVE_ERR(slave, "Failed to fetch SII contents.\n");
661  return;
662  }
663 
664  // 2 words fetched
665 
666  if (fsm->sii_offset + 2 <= slave->sii_nwords) { // 2 words fit
667  memcpy(slave->sii_words + fsm->sii_offset, fsm->fsm_sii.value, 4);
668  } else { // copy the last word
669  memcpy(slave->sii_words + fsm->sii_offset, fsm->fsm_sii.value, 2);
670  }
671 
672  if (fsm->sii_offset + 2 < slave->sii_nwords) {
673  // fetch the next 2 words
674  fsm->sii_offset += 2;
675  ec_fsm_sii_read(&fsm->fsm_sii, slave, fsm->sii_offset,
677  ec_fsm_sii_exec(&fsm->fsm_sii); // execute state immediately
678  return;
679  }
680 
681  // Evaluate SII contents
682 
684 
685  slave->sii.alias =
686  EC_READ_U16(slave->sii_words + 0x0004);
687  slave->effective_alias = slave->sii.alias;
688  slave->sii.vendor_id =
689  EC_READ_U32(slave->sii_words + 0x0008);
690  slave->sii.product_code =
691  EC_READ_U32(slave->sii_words + 0x000A);
692  slave->sii.revision_number =
693  EC_READ_U32(slave->sii_words + 0x000C);
694  slave->sii.serial_number =
695  EC_READ_U32(slave->sii_words + 0x000E);
696  slave->sii.boot_rx_mailbox_offset =
697  EC_READ_U16(slave->sii_words + 0x0014);
698  slave->sii.boot_rx_mailbox_size =
699  EC_READ_U16(slave->sii_words + 0x0015);
700  slave->sii.boot_tx_mailbox_offset =
701  EC_READ_U16(slave->sii_words + 0x0016);
702  slave->sii.boot_tx_mailbox_size =
703  EC_READ_U16(slave->sii_words + 0x0017);
704  slave->sii.std_rx_mailbox_offset =
705  EC_READ_U16(slave->sii_words + 0x0018);
706  slave->sii.std_rx_mailbox_size =
707  EC_READ_U16(slave->sii_words + 0x0019);
708  slave->sii.std_tx_mailbox_offset =
709  EC_READ_U16(slave->sii_words + 0x001A);
710  slave->sii.std_tx_mailbox_size =
711  EC_READ_U16(slave->sii_words + 0x001B);
712  slave->sii.mailbox_protocols =
713  EC_READ_U16(slave->sii_words + 0x001C);
714 
716  // sii does not contain category data
718  return;
719  }
720 
721  if (slave->sii_nwords < EC_FIRST_SII_CATEGORY_OFFSET + 1) {
722  EC_SLAVE_ERR(slave, "Unexpected end of SII data:"
723  " First category header missing.\n");
724  goto end;
725  }
726 
727  // evaluate category data
728  cat_word = slave->sii_words + EC_FIRST_SII_CATEGORY_OFFSET;
729  while (EC_READ_U16(cat_word) != 0xFFFF) {
730 
731  // type and size words must fit
732  if (cat_word + 2 - slave->sii_words > slave->sii_nwords) {
733  EC_SLAVE_ERR(slave, "Unexpected end of SII data:"
734  " Category header incomplete.\n");
735  goto end;
736  }
737 
738  cat_type = EC_READ_U16(cat_word) & 0x7FFF;
739  cat_size = EC_READ_U16(cat_word + 1);
740  cat_word += 2;
741 
742  if (cat_word + cat_size - slave->sii_words > slave->sii_nwords) {
743  EC_SLAVE_WARN(slave, "Unexpected end of SII data:"
744  " Category data incomplete.\n");
745  goto end;
746  }
747 
748  switch (cat_type) {
749  case 0x000A:
750  if (ec_slave_fetch_sii_strings(slave, (uint8_t *) cat_word,
751  cat_size * 2))
752  goto end;
753  break;
754  case 0x001E:
755  if (ec_slave_fetch_sii_general(slave, (uint8_t *) cat_word,
756  cat_size * 2))
757  goto end;
758  break;
759  case 0x0028:
760  break;
761  case 0x0029:
762  if (ec_slave_fetch_sii_syncs(slave, (uint8_t *) cat_word,
763  cat_size * 2))
764  goto end;
765  break;
766  case 0x0032:
767  if (ec_slave_fetch_sii_pdos( slave, (uint8_t *) cat_word,
768  cat_size * 2, EC_DIR_INPUT)) // TxPDO
769  goto end;
770  break;
771  case 0x0033:
772  if (ec_slave_fetch_sii_pdos( slave, (uint8_t *) cat_word,
773  cat_size * 2, EC_DIR_OUTPUT)) // RxPDO
774  goto end;
775  break;
776  default:
777  EC_SLAVE_DBG(slave, 1, "Unknown category type 0x%04X.\n",
778  cat_type);
779  }
780 
781  cat_word += cat_size;
782  if (cat_word - slave->sii_words >= slave->sii_nwords) {
783  EC_SLAVE_WARN(slave, "Unexpected end of SII data:"
784  " Next category header missing.\n");
785  goto end;
786  }
787  }
788 
789 #ifdef EC_REGALIAS
790  ec_fsm_slave_scan_enter_regalias(fsm);
791 #else
792  if (slave->sii.mailbox_protocols & EC_MBOX_COE) {
794  } else {
796  }
797 #endif
798  return;
799 
800 end:
801  EC_SLAVE_ERR(slave, "Failed to analyze category data.\n");
802  fsm->slave->error_flag = 1;
804 }
805 
806 /*****************************************************************************/
807 
808 #ifdef EC_REGALIAS
809 
812 void ec_fsm_slave_scan_enter_regalias(
813  ec_fsm_slave_scan_t *fsm
814  )
815 {
816  ec_datagram_t *datagram = fsm->datagram;
817  ec_slave_t *slave = fsm->slave;
818 
819  // read alias from register
820  EC_SLAVE_DBG(slave, 1, "Reading alias from register.\n");
821  ec_datagram_fprd(datagram, slave->station_address, 0x0012, 2);
822  ec_datagram_zero(datagram);
823  fsm->retries = EC_FSM_RETRIES;
824  fsm->state = ec_fsm_slave_scan_state_regalias;
825 }
826 
827 /*****************************************************************************/
828 
831 void ec_fsm_slave_scan_state_regalias(
832  ec_fsm_slave_scan_t *fsm
833  )
834 {
835  ec_datagram_t *datagram = fsm->datagram;
836  ec_slave_t *slave = fsm->slave;
837 
838  if (datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--)
839  return;
840 
841  if (datagram->state != EC_DATAGRAM_RECEIVED) {
843  EC_SLAVE_ERR(slave, "Failed to receive register alias datagram: ");
844  ec_datagram_print_state(datagram);
845  return;
846  }
847 
848  if (datagram->working_counter != 1) {
849  EC_SLAVE_DBG(slave, 1, "Failed to read register alias.\n");
850  } else {
851  slave->effective_alias = EC_READ_U16(datagram->data);
852  EC_SLAVE_DBG(slave, 1, "Read alias %u from register.\n",
853  slave->effective_alias);
854  }
855 
856  if (slave->sii.mailbox_protocols & EC_MBOX_COE) {
858  } else {
860  }
861 }
862 
863 #endif // defined EC_REGALIAS
864 
865 /*****************************************************************************/
866 
870  ec_fsm_slave_scan_t *fsm
871  )
872 {
873  ec_slave_t *slave = fsm->slave;
874  uint8_t current_state = slave->current_state & EC_SLAVE_STATE_MASK;
875 
876  if (current_state != EC_SLAVE_STATE_PREOP
877  && current_state != EC_SLAVE_STATE_SAFEOP
878  && current_state != EC_SLAVE_STATE_OP) {
879  if (slave->master->debug_level) {
880  char str[EC_STATE_STRING_SIZE];
881  ec_state_string(current_state, str, 0);
882  EC_SLAVE_DBG(slave, 0, "Slave is not in the state"
883  " to do mailbox com (%s), setting to PREOP.\n", str);
884  }
885 
890  } else {
891  EC_SLAVE_DBG(slave, 1, "Reading mailbox"
892  " sync manager configuration.\n");
893 
894  /* Scan current sync manager configuration to get configured mailbox
895  * sizes. */
896  ec_datagram_fprd(fsm->datagram, slave->station_address, 0x0800,
897  EC_SYNC_PAGE_SIZE * 2);
898  fsm->retries = EC_FSM_RETRIES;
900  }
901 }
902 
903 /*****************************************************************************/
904 
908  ec_fsm_slave_scan_t *fsm
909  )
910 {
912  return;
913 
916  return;
917  }
918 
920 }
921 
922 /*****************************************************************************/
923 
927  ec_fsm_slave_scan_t *fsm
928  )
929 {
930  ec_datagram_t *datagram = fsm->datagram;
931  ec_slave_t *slave = fsm->slave;
932 
933  if (datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--)
934  return;
935 
936  if (datagram->state != EC_DATAGRAM_RECEIVED) {
938  EC_SLAVE_ERR(slave, "Failed to receive sync manager"
939  " configuration datagram: ");
940  ec_datagram_print_state(datagram);
941  return;
942  }
943 
944  if (datagram->working_counter != 1) {
945  fsm->slave->error_flag = 1;
947  EC_SLAVE_ERR(slave, "Failed to read DL status: ");
948  ec_datagram_print_wc_error(datagram);
949  return;
950  }
951 
952  slave->configured_rx_mailbox_offset = EC_READ_U16(datagram->data);
953  slave->configured_rx_mailbox_size = EC_READ_U16(datagram->data + 2);
954  slave->configured_tx_mailbox_offset = EC_READ_U16(datagram->data + 8);
955  slave->configured_tx_mailbox_size = EC_READ_U16(datagram->data + 10);
956 
957  EC_SLAVE_DBG(slave, 1, "Mailbox configuration:\n");
958  EC_SLAVE_DBG(slave, 1, " RX offset=0x%04x size=%u\n",
961  EC_SLAVE_DBG(slave, 1, " TX offset=0x%04x size=%u\n",
964 
966 }
967 
968 /*****************************************************************************/
969 
973  ec_fsm_slave_scan_t *fsm
974  )
975 {
976  ec_slave_t *slave = fsm->slave;
977 
978  EC_SLAVE_DBG(slave, 1, "Scanning PDO assignment and mapping.\n");
980  ec_fsm_pdo_start_reading(fsm->fsm_pdo, slave);
981  ec_fsm_pdo_exec(fsm->fsm_pdo, fsm->datagram); // execute immediately
982 }
983 
984 /*****************************************************************************/
985 
989  ec_fsm_slave_scan_t *fsm
990  )
991 {
992  if (ec_fsm_pdo_exec(fsm->fsm_pdo, fsm->datagram)) {
993  return;
994  }
995 
996  if (!ec_fsm_pdo_success(fsm->fsm_pdo)) {
998  return;
999  }
1000 
1001  // reading PDO configuration finished
1003 }
1004 
1005 /******************************************************************************
1006  * Common state functions
1007  *****************************************************************************/
1008 
1012  ec_fsm_slave_scan_t *fsm
1013  )
1014 {
1015 }
1016 
1017 /*****************************************************************************/
1018 
1022  ec_fsm_slave_scan_t *fsm
1023  )
1024 {
1025 }
1026 
1027 /*****************************************************************************/
#define EC_FSM_RETRIES
Number of state machine retries on datagram timeout.
Definition: globals.h:59
ec_slave_t * slave
Slave the FSM runs on.
uint16_t ring_position
Ring position.
Definition: slave.h:183
uint32_t revision_number
Revision number.
Definition: slave.h:137
uint16_t boot_rx_mailbox_offset
Bootstrap receive mailbox address.
Definition: slave.h:139
#define EC_SYNC_PAGE_SIZE
Size of a sync manager configuration page.
Definition: globals.h:101
#define EC_SLAVE_STATE_MASK
Slave state mask.
Definition: globals.h:123
ec_sii_t sii
Extracted SII data.
Definition: slave.h:223
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.
CANopen over EtherCAT.
Definition: globals.h:149
uint16_t configured_tx_mailbox_size
Configured send mailbox size.
Definition: slave.h:201
uint16_t base_build
Build number.
Definition: slave.h:206
#define EC_SLAVE_DBG(slave, level, fmt, args...)
Convenience macro for printing slave-specific debug messages to syslog.
Definition: slave.h:106
OP (mailbox communication and input/output update)
Definition: globals.h:138
uint16_t configured_tx_mailbox_offset
Configured send mailbox offset.
Definition: slave.h:199
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:394
ec_slave_port_t ports[EC_MAX_PORTS]
Ports.
Definition: slave.h:187
ec_slave_state_t current_state
Current application state.
Definition: slave.h:192
ec_slave_port_link_t link
Port link status.
Definition: slave.h:120
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:90
EtherCAT datagram.
Definition: datagram.h:87
uint32_t serial_number
Serial number.
Definition: slave.h:138
#define EC_WRITE_U8(DATA, VAL)
Write an 8-bit unsigned value to EtherCAT data.
Definition: ecrt.h:2187
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:99
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:140
uint16_t boot_tx_mailbox_size
Bootstrap transmit mailbox size.
Definition: slave.h:142
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:312
Sent (still in the queue).
Definition: datagram.h:77
void ec_fsm_sii_init(ec_fsm_sii_t *fsm, ec_datagram_t *datagram)
Constructor.
Definition: fsm_sii.c:74
EtherCAT slave scanning state machine.
uint16_t station_address
Configured station address.
Definition: slave.h:184
#define EC_MAX_SII_SIZE
Maximum SII size in words, to avoid infinite reading.
Definition: globals.h:69
uint16_t std_rx_mailbox_size
Standard receive mailbox size.
Definition: slave.h:144
#define EC_MAX_FMMUS
Maximum number of FMMUs per slave.
Definition: globals.h:104
uint8_t base_type
Slave type.
Definition: slave.h:204
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:145
EtherCAT master structure.
SAFEOP (mailbox communication and input update)
Definition: globals.h:136
uint16_t boot_tx_mailbox_offset
Bootstrap transmit mailbox address.
Definition: slave.h:141
ec_fsm_slave_config_t * fsm_slave_config
Slave configuration state machine to use.
EtherCAT slave.
Definition: slave.h:176
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
ec_datagram_state_t state
State.
Definition: datagram.h:100
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:255
Use configured addresses.
Definition: fsm_sii.h:50
uint16_t * sii_words
Complete SII image.
Definition: slave.h:219
uint16_t mailbox_protocols
Supported mailbox protocols.
Definition: slave.h:147
void(* state)(ec_fsm_slave_scan_t *)
State function.
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:286
#define EC_SLAVE_ERR(slave, fmt, args...)
Convenience macro for printing slave-specific errors to syslog.
Definition: slave.h:76
void ec_datagram_print_wc_error(const ec_datagram_t *datagram)
Evaluates the working counter of a single-cast datagram.
Definition: datagram.c:602
ec_slave_dc_range_t base_dc_range
DC range.
Definition: slave.h:211
uint16_t std_rx_mailbox_offset
Standard receive mailbox address.
Definition: slave.h:143
uint8_t base_fmmu_bit_operation
FMMU bit operation is supported.
Definition: slave.h:209
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 *fsm)
uint16_t alias
Configured station alias.
Definition: slave.h:134
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:2204
uint8_t base_fmmu_count
Number of supported FMMUs.
Definition: slave.h:207
uint16_t configured_rx_mailbox_offset
Configured receive mailbox offset.
Definition: slave.h:195
#define EC_READ_U32(DATA)
Read a 32-bit unsigned value from EtherCAT data.
Definition: ecrt.h:2151
ec_slave_port_desc_t desc
Port descriptors.
Definition: slave.h:119
Finite state machine for scanning an EtherCAT slave.
ec_master_t * master
Master owning the slave.
Definition: slave.h:178
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:212
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
Values read by the master.
Definition: ecrt.h:420
PDO configuration state machine.
Definition: fsm_pdo.h:54
#define EC_FIRST_SII_CATEGORY_OFFSET
Word offset of first SII category.
Definition: globals.h:98
uint8_t base_revision
Revision.
Definition: slave.h:205
32 bit.
Definition: globals.h:176
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:98
void ec_fsm_sii_clear(ec_fsm_sii_t *fsm)
Destructor.
Definition: fsm_sii.c:88
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:185
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:137
int ec_fsm_sii_success(ec_fsm_sii_t *fsm)
Returns, if the master startup state machine terminated with success.
Definition: fsm_sii.c:152
#define EC_READ_U16(DATA)
Read a 16-bit unsigned value from EtherCAT data.
Definition: ecrt.h:2135
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.
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:419
#define EC_STATE_STRING_SIZE
Minimum size of a buffer used with ec_state_string().
Definition: globals.h:66
uint16_t boot_rx_mailbox_size
Bootstrap receive mailbox size.
Definition: slave.h:140
#define EC_MAX_PORTS
Maximum number of slave ports.
Definition: ecrt.h:209
int ec_fsm_slave_config_exec(ec_fsm_slave_config_t *fsm)
Executes the current state of the state machine.
Queued for sending.
Definition: datagram.h:76
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:122
Timed out (dequeued).
Definition: datagram.h:79
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:296
uint16_t configured_rx_mailbox_size
Configured receive mailbox size.
Definition: slave.h:197
uint8_t base_dc_supported
Distributed clocks are supported.
Definition: slave.h:210
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:220
uint8_t * data
Datagram payload.
Definition: datagram.h:94
uint8_t base_sync_count
Number of supported sync managers.
Definition: slave.h:208
#define EC_READ_U8(DATA)
Read an 8-bit unsigned value from EtherCAT data.
Definition: ecrt.h:2119
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 *fsm)
Enter slave scan state SII_SIZE.
uint32_t product_code
Vendor-specific product code.
Definition: slave.h:136
PREOP state (mailbox communication, no IO)
Definition: globals.h:132
Values written by the master.
Definition: ecrt.h:419
void ec_fsm_slave_scan_enter_preop(ec_fsm_slave_scan_t *)
Enter slave scan state PREOP.
Received (dequeued).
Definition: datagram.h:78
unsigned int error_flag
Stop processing after an error.
Definition: slave.h:193
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:146
void ec_fsm_slave_scan_state_state(ec_fsm_slave_scan_t *)
Slave scan state: STATE.
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:485
#define EC_MAX_SYNC_MANAGERS
Maximum number of sync managers per slave.
Definition: ecrt.h:200
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:368
uint32_t vendor_id
Vendor ID.
Definition: slave.h:135
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:70