IgH EtherCAT Master  1.5.2
fsm_slave_config.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 <asm/div64.h>
38 
39 #include "globals.h"
40 #include "master.h"
41 #include "mailbox.h"
42 #include "slave_config.h"
43 #include "fsm_slave_config.h"
44 
45 /*****************************************************************************/
46 
52 #define EC_DC_MAX_SYNC_DIFF_NS 10000
53 
56 #define EC_DC_SYNC_WAIT_MS 5000
57 
60 #define EC_DC_START_OFFSET 100000000ULL
61 
62 /*****************************************************************************/
63 
70 #ifdef EC_SII_ASSIGN
72 #endif
74 #ifdef EC_SII_ASSIGN
76 #endif
91 
96 #ifdef EC_SII_ASSIGN
98 #endif
111 
114 
116 
117 /*****************************************************************************/
118 
122  ec_fsm_slave_config_t *fsm,
123  ec_datagram_t *datagram,
124  ec_fsm_change_t *fsm_change,
125  ec_fsm_coe_t *fsm_coe,
126  ec_fsm_soe_t *fsm_soe,
127  ec_fsm_pdo_t *fsm_pdo
128  )
129 {
132 
133  fsm->datagram = datagram;
134  fsm->fsm_change = fsm_change;
135  fsm->fsm_coe = fsm_coe;
136  fsm->fsm_soe = fsm_soe;
137  fsm->fsm_pdo = fsm_pdo;
138 }
139 
140 /*****************************************************************************/
141 
146  )
147 {
150 }
151 
152 /*****************************************************************************/
153 
157  ec_fsm_slave_config_t *fsm,
158  ec_slave_t *slave
159  )
160 {
161  fsm->slave = slave;
163 }
164 
165 /*****************************************************************************/
166 
171  const ec_fsm_slave_config_t *fsm
172  )
173 {
174  return fsm->state != ec_fsm_slave_config_state_end
176 }
177 
178 /*****************************************************************************/
179 
189  )
190 {
191  if (fsm->datagram->state == EC_DATAGRAM_SENT
192  || fsm->datagram->state == EC_DATAGRAM_QUEUED) {
193  // datagram was not sent or received yet.
194  return ec_fsm_slave_config_running(fsm);
195  }
196 
197  fsm->state(fsm);
198  return ec_fsm_slave_config_running(fsm);
199 }
200 
201 /*****************************************************************************/
202 
207  const ec_fsm_slave_config_t *fsm
208  )
209 {
210  return fsm->state == ec_fsm_slave_config_state_end;
211 }
212 
213 /******************************************************************************
214  * Slave configuration state machine
215  *****************************************************************************/
216 
221  )
222 {
223  EC_SLAVE_DBG(fsm->slave, 1, "Configuring...\n");
225 }
226 
227 /*****************************************************************************/
228 
233  )
234 {
238 }
239 
240 /*****************************************************************************/
241 
246  )
247 {
248  ec_slave_t *slave = fsm->slave;
249  ec_datagram_t *datagram = fsm->datagram;
250 
251  if (ec_fsm_change_exec(fsm->fsm_change)) return;
252 
253  if (!ec_fsm_change_success(fsm->fsm_change)) {
254  if (!fsm->fsm_change->spontaneous_change)
255  slave->error_flag = 1;
257  return;
258  }
259 
260  EC_SLAVE_DBG(slave, 1, "Now in INIT.\n");
261 
262  if (!slave->base_fmmu_count) { // skip FMMU configuration
264  return;
265  }
266 
267  EC_SLAVE_DBG(slave, 1, "Clearing FMMU configurations...\n");
268 
269  // clear FMMU configurations
270  ec_datagram_fpwr(datagram, slave->station_address,
271  0x0600, EC_FMMU_PAGE_SIZE * slave->base_fmmu_count);
272  ec_datagram_zero(datagram);
273  fsm->retries = EC_FSM_RETRIES;
275 }
276 
277 /*****************************************************************************/
278 
283  )
284 {
285  ec_datagram_t *datagram = fsm->datagram;
286 
287  if (datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--)
288  return;
289 
290  if (datagram->state != EC_DATAGRAM_RECEIVED) {
292  EC_SLAVE_ERR(fsm->slave, "Failed receive FMMU clearing datagram.\n");
293  return;
294  }
295 
296  if (datagram->working_counter != 1) {
297  fsm->slave->error_flag = 1;
299  EC_SLAVE_ERR(fsm->slave, "Failed to clear FMMUs: ");
300  ec_datagram_print_wc_error(datagram);
301  return;
302  }
303 
305 }
306 
307 /*****************************************************************************/
308 
313  )
314 {
315  ec_slave_t *slave = fsm->slave;
316  ec_datagram_t *datagram = fsm->datagram;
317  size_t sync_size;
318 
319  if (!slave->base_sync_count) {
320  // no sync managers
322  return;
323  }
324 
325  EC_SLAVE_DBG(slave, 1, "Clearing sync manager configurations...\n");
326 
327  sync_size = EC_SYNC_PAGE_SIZE * slave->base_sync_count;
328 
329  // clear sync manager configurations
330  ec_datagram_fpwr(datagram, slave->station_address, 0x0800, sync_size);
331  ec_datagram_zero(datagram);
332  fsm->retries = EC_FSM_RETRIES;
334 }
335 
336 /*****************************************************************************/
337 
342  )
343 {
344  ec_datagram_t *datagram = fsm->datagram;
345 
346  if (datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--)
347  return;
348 
349  if (datagram->state != EC_DATAGRAM_RECEIVED) {
351  EC_SLAVE_ERR(fsm->slave, "Failed receive sync manager"
352  " clearing datagram.\n");
353  return;
354  }
355 
356  if (datagram->working_counter != 1) {
357  fsm->slave->error_flag = 1;
359  EC_SLAVE_ERR(fsm->slave,
360  "Failed to clear sync manager configurations: ");
361  ec_datagram_print_wc_error(datagram);
362  return;
363  }
364 
366 }
367 
368 /*****************************************************************************/
369 
374  )
375 {
376  ec_slave_t *slave = fsm->slave;
377  ec_datagram_t *datagram = fsm->datagram;
378 
379  if (!slave->base_dc_supported || !slave->has_dc_system_time) {
381  return;
382  }
383 
384  EC_SLAVE_DBG(slave, 1, "Clearing DC assignment...\n");
385 
386  ec_datagram_fpwr(datagram, slave->station_address, 0x0980, 2);
387  ec_datagram_zero(datagram);
388  fsm->retries = EC_FSM_RETRIES;
390 }
391 
392 /*****************************************************************************/
393 
398  )
399 {
400  ec_datagram_t *datagram = fsm->datagram;
401 
402  if (datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--)
403  return;
404 
405  if (datagram->state != EC_DATAGRAM_RECEIVED) {
407  EC_SLAVE_ERR(fsm->slave, "Failed receive DC assignment"
408  " clearing datagram.\n");
409  return;
410  }
411 
412  if (datagram->working_counter != 1) {
413  // clearing the DC assignment does not succeed on simple slaves
414  EC_SLAVE_DBG(fsm->slave, 1, "Failed to clear DC assignment: ");
415  ec_datagram_print_wc_error(datagram);
416  }
417 
419 }
420 
421 /*****************************************************************************/
422 
427  )
428 {
429  ec_slave_t *slave = fsm->slave;
430  ec_datagram_t *datagram = fsm->datagram;
431  unsigned int i;
432 
433  // slave is now in INIT
434  if (slave->current_state == slave->requested_state) {
435  fsm->state = ec_fsm_slave_config_state_end; // successful
436  EC_SLAVE_DBG(slave, 1, "Finished configuration.\n");
437  return;
438  }
439 
440  if (!slave->sii.mailbox_protocols) {
441  // no mailbox protocols supported
442  EC_SLAVE_DBG(slave, 1, "Slave does not support"
443  " mailbox communication.\n");
444 #ifdef EC_SII_ASSIGN
446 #else
448 #endif
449  return;
450  }
451 
452  EC_SLAVE_DBG(slave, 1, "Configuring mailbox sync managers...\n");
453 
454  if (slave->requested_state == EC_SLAVE_STATE_BOOT) {
455  ec_sync_t sync;
456 
457  ec_datagram_fpwr(datagram, slave->station_address, 0x0800,
458  EC_SYNC_PAGE_SIZE * 2);
459  ec_datagram_zero(datagram);
460 
461  ec_sync_init(&sync, slave);
463  sync.control_register = 0x26;
464  sync.enable = 1;
465  ec_sync_page(&sync, 0, slave->sii.boot_rx_mailbox_size,
466  EC_DIR_INVALID, // use default direction
467  0, // no PDO xfer
468  datagram->data);
472  slave->sii.boot_rx_mailbox_size;
473 
474  ec_sync_init(&sync, slave);
476  sync.control_register = 0x22;
477  sync.enable = 1;
478  ec_sync_page(&sync, 1, slave->sii.boot_tx_mailbox_size,
479  EC_DIR_INVALID, // use default direction
480  0, // no PDO xfer
481  datagram->data + EC_SYNC_PAGE_SIZE);
485  slave->sii.boot_tx_mailbox_size;
486 
487  } else if (slave->sii.sync_count >= 2) { // mailbox configuration provided
488  ec_datagram_fpwr(datagram, slave->station_address, 0x0800,
489  EC_SYNC_PAGE_SIZE * slave->sii.sync_count);
490  ec_datagram_zero(datagram);
491 
492  for (i = 0; i < 2; i++) {
493  ec_sync_page(&slave->sii.syncs[i], i,
494  slave->sii.syncs[i].default_length,
495  NULL, // use default sync manager configuration
496  0, // no PDO xfer
497  datagram->data + EC_SYNC_PAGE_SIZE * i);
498  }
499 
501  slave->sii.syncs[0].physical_start_address;
503  slave->sii.syncs[0].default_length;
505  slave->sii.syncs[1].physical_start_address;
507  slave->sii.syncs[1].default_length;
508  } else { // no mailbox sync manager configurations provided
509  ec_sync_t sync;
510 
511  EC_SLAVE_DBG(slave, 1, "Slave does not provide"
512  " mailbox sync manager configurations.\n");
513 
514  ec_datagram_fpwr(datagram, slave->station_address, 0x0800,
515  EC_SYNC_PAGE_SIZE * 2);
516  ec_datagram_zero(datagram);
517 
518  ec_sync_init(&sync, slave);
520  sync.control_register = 0x26;
521  sync.enable = 1;
522  ec_sync_page(&sync, 0, slave->sii.std_rx_mailbox_size,
523  NULL, // use default sync manager configuration
524  0, // no PDO xfer
525  datagram->data);
527  slave->sii.std_rx_mailbox_offset;
529  slave->sii.std_rx_mailbox_size;
530 
531  ec_sync_init(&sync, slave);
533  sync.control_register = 0x22;
534  sync.enable = 1;
535  ec_sync_page(&sync, 1, slave->sii.std_tx_mailbox_size,
536  NULL, // use default sync manager configuration
537  0, // no PDO xfer
538  datagram->data + EC_SYNC_PAGE_SIZE);
540  slave->sii.std_tx_mailbox_offset;
542  slave->sii.std_tx_mailbox_size;
543  }
544 
545  fsm->take_time = 1;
546 
547  fsm->retries = EC_FSM_RETRIES;
549 }
550 
551 /*****************************************************************************/
552 
559  )
560 {
561  ec_datagram_t *datagram = fsm->datagram;
562  ec_slave_t *slave = fsm->slave;
563 
564  if (datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--)
565  return;
566 
567  if (datagram->state != EC_DATAGRAM_RECEIVED) {
569  EC_SLAVE_ERR(slave, "Failed to receive sync manager"
570  " configuration datagram: ");
571  ec_datagram_print_state(datagram);
572  return;
573  }
574 
575  if (fsm->take_time) {
576  fsm->take_time = 0;
577  fsm->jiffies_start = datagram->jiffies_sent;
578  }
579 
580  /* Because the sync manager configurations are cleared during the last
581  * cycle, some slaves do not immediately respond to the mailbox sync
582  * manager configuration datagram. Therefore, resend the datagram for
583  * a certain time, if the slave does not respond.
584  */
585  if (datagram->working_counter == 0) {
586  unsigned long diff = datagram->jiffies_received - fsm->jiffies_start;
587 
588  if (diff >= HZ) {
589  slave->error_flag = 1;
591  EC_SLAVE_ERR(slave, "Timeout while configuring"
592  " mailbox sync managers.\n");
593  return;
594  } else {
595  EC_SLAVE_DBG(slave, 1, "Resending after %u ms...\n",
596  (unsigned int) diff * 1000 / HZ);
597  }
598 
599  // send configuration datagram again
600  fsm->retries = EC_FSM_RETRIES;
601  return;
602  }
603  else if (datagram->working_counter != 1) {
604  slave->error_flag = 1;
606  EC_SLAVE_ERR(slave, "Failed to set sync managers: ");
607  ec_datagram_print_wc_error(datagram);
608  return;
609  }
610 
611 #ifdef EC_SII_ASSIGN
613 #else
615 #endif
616 }
617 
618 /*****************************************************************************/
619 
620 #ifdef EC_SII_ASSIGN
621 
626  )
627 {
628  ec_datagram_t *datagram = fsm->datagram;
629  ec_slave_t *slave = fsm->slave;
630 
632  EC_SLAVE_DBG(slave, 1, "Assigning SII access to PDI.\n");
633 
634  ec_datagram_fpwr(datagram, slave->station_address, 0x0500, 0x01);
635  EC_WRITE_U8(datagram->data, 0x01); // PDI
636  fsm->retries = EC_FSM_RETRIES;
638  }
639  else {
641  }
642 }
643 
644 /*****************************************************************************/
645 
650  )
651 {
652  ec_datagram_t *datagram = fsm->datagram;
653  ec_slave_t *slave = fsm->slave;
654 
655  if (datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--) {
656  return;
657  }
658 
659  if (datagram->state != EC_DATAGRAM_RECEIVED) {
660  EC_SLAVE_WARN(slave, "Failed receive SII assignment datagram: ");
661  ec_datagram_print_state(datagram);
662  goto cont_preop;
663  }
664 
665  if (datagram->working_counter != 1) {
666  EC_SLAVE_WARN(slave, "Failed to assign SII to PDI: ");
667  ec_datagram_print_wc_error(datagram);
668  }
669 
670 cont_preop:
672 }
673 
674 #endif
675 
676 /*****************************************************************************/
677 
682  )
683 {
685 
689  } else { // BOOT
691  fsm->slave, EC_SLAVE_STATE_BOOT);
692  }
693 
694  ec_fsm_change_exec(fsm->fsm_change); // execute immediately
695 }
696 
697 /*****************************************************************************/
698 
703  )
704 {
705  ec_slave_t *slave = fsm->slave;
706 #ifdef EC_SII_ASSIGN
707  int assign_to_pdi;
708  ec_slave_config_t *config;
709  ec_flag_t *flag;
710 #endif
711 
712  if (ec_fsm_change_exec(fsm->fsm_change)) {
713  return;
714  }
715 
716  if (!ec_fsm_change_success(fsm->fsm_change)) {
717  if (!fsm->fsm_change->spontaneous_change)
718  slave->error_flag = 1;
720  return;
721  }
722 
723  // slave is now in BOOT or PREOP
724  slave->jiffies_preop = fsm->datagram->jiffies_received;
725 
726  EC_SLAVE_DBG(slave, 1, "Now in %s.\n",
727  slave->requested_state != EC_SLAVE_STATE_BOOT ? "PREOP" : "BOOT");
728 
729 #ifdef EC_SII_ASSIGN
730  assign_to_pdi = 0;
731  config = fsm->slave->config;
732  if (config) {
733  flag = ec_slave_config_find_flag(config, "AssignToPdi");
734  if (flag) {
735  assign_to_pdi = flag->value;
736  }
737  }
738 
739  if (assign_to_pdi) {
740  EC_SLAVE_DBG(slave, 1, "Skipping SII assignment back to EtherCAT.\n");
741  if (slave->current_state == slave->requested_state) {
742  fsm->state = ec_fsm_slave_config_state_end; // successful
743  EC_SLAVE_DBG(slave, 1, "Finished configuration.\n");
744  return;
745  }
746 
748  }
749  else {
750  EC_SLAVE_DBG(slave, 1, "Assigning SII access back to EtherCAT.\n");
751 
752  ec_datagram_fpwr(fsm->datagram, slave->station_address, 0x0500, 0x01);
753  EC_WRITE_U8(fsm->datagram->data, 0x00); // EtherCAT
754  fsm->retries = EC_FSM_RETRIES;
756  }
757 #else
758  if (slave->current_state == slave->requested_state) {
759  fsm->state = ec_fsm_slave_config_state_end; // successful
760  EC_SLAVE_DBG(slave, 1, "Finished configuration.\n");
761  return;
762  }
763 
765 #endif
766 }
767 
768 /*****************************************************************************/
769 
770 #ifdef EC_SII_ASSIGN
771 
776  )
777 {
778  ec_datagram_t *datagram = fsm->datagram;
779  ec_slave_t *slave = fsm->slave;
780 
781  if (datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--) {
782  return;
783  }
784 
785  if (datagram->state != EC_DATAGRAM_RECEIVED) {
786  EC_SLAVE_WARN(slave, "Failed receive SII assignment datagram: ");
787  ec_datagram_print_state(datagram);
788  goto cont_sdo_conf;
789  }
790 
791  if (datagram->working_counter != 1) {
792  EC_SLAVE_WARN(slave, "Failed to assign SII back to EtherCAT: ");
793  ec_datagram_print_wc_error(datagram);
794  }
795 
796 cont_sdo_conf:
797  if (slave->current_state == slave->requested_state) {
798  fsm->state = ec_fsm_slave_config_state_end; // successful
799  EC_SLAVE_DBG(slave, 1, "Finished configuration.\n");
800  return;
801  }
802 
804 }
805 
806 #endif
807 
808 /*****************************************************************************/
809 
814  )
815 {
816  ec_slave_t *slave = fsm->slave;
817 
818  if (!slave->config) {
820  return;
821  }
822 
823  // No CoE configuration to be applied?
824  if (list_empty(&slave->config->sdo_configs)) { // skip SDO configuration
826  return;
827  }
828 
829  // start SDO configuration
831  fsm->request = list_entry(fsm->slave->config->sdo_configs.next,
832  ec_sdo_request_t, list);
835  ec_fsm_coe_transfer(fsm->fsm_coe, fsm->slave, &fsm->request_copy);
836  ec_fsm_coe_exec(fsm->fsm_coe, fsm->datagram); // execute immediately
837 }
838 
839 /*****************************************************************************/
840 
845  )
846 {
847  if (ec_fsm_coe_exec(fsm->fsm_coe, fsm->datagram)) {
848  return;
849  }
850 
851  if (!ec_fsm_coe_success(fsm->fsm_coe)) {
852  EC_SLAVE_ERR(fsm->slave, "SDO configuration failed.\n");
853  fsm->slave->error_flag = 1;
855  return;
856  }
857 
858  if (!fsm->slave->config) { // config removed in the meantime
860  return;
861  }
862 
863  // Another SDO to configure?
864  if (fsm->request->list.next != &fsm->slave->config->sdo_configs) {
865  fsm->request = list_entry(fsm->request->list.next,
866  ec_sdo_request_t, list);
869  ec_fsm_coe_transfer(fsm->fsm_coe, fsm->slave, &fsm->request_copy);
870  ec_fsm_coe_exec(fsm->fsm_coe, fsm->datagram); // execute immediately
871  return;
872  }
873 
874  // All SDOs are now configured.
876 }
877 
878 /*****************************************************************************/
879 
884  )
885 {
886  ec_slave_t *slave = fsm->slave;
887  ec_soe_request_t *req;
888 
889  if (!slave->config) {
891  return;
892  }
893 
894  list_for_each_entry(req, &slave->config->soe_configs, list) {
895  if (req->al_state == EC_AL_STATE_PREOP) {
896  // start SoE configuration
898  fsm->soe_request = req;
901  ec_fsm_soe_transfer(fsm->fsm_soe, fsm->slave,
902  &fsm->soe_request_copy);
903  ec_fsm_soe_exec(fsm->fsm_soe, fsm->datagram);
904  return;
905  }
906  }
907 
908  // No SoE configuration to be applied in PREOP
910 }
911 
912 /*****************************************************************************/
913 
918  )
919 {
920  ec_slave_t *slave = fsm->slave;
921 
922  if (ec_fsm_soe_exec(fsm->fsm_soe, fsm->datagram)) {
923  return;
924  }
925 
926  if (!ec_fsm_soe_success(fsm->fsm_soe)) {
927  EC_SLAVE_ERR(slave, "SoE configuration failed.\n");
928  fsm->slave->error_flag = 1;
930  return;
931  }
932 
933  if (!fsm->slave->config) { // config removed in the meantime
935  return;
936  }
937 
938  // Another IDN to configure in PREOP?
939  while (fsm->soe_request->list.next != &fsm->slave->config->soe_configs) {
940  fsm->soe_request = list_entry(fsm->soe_request->list.next,
941  ec_soe_request_t, list);
942  if (fsm->soe_request->al_state == EC_AL_STATE_PREOP) {
945  ec_fsm_soe_transfer(fsm->fsm_soe, fsm->slave,
946  &fsm->soe_request_copy);
947  ec_fsm_soe_exec(fsm->fsm_soe, fsm->datagram);
948  return;
949  }
950  }
951 
952  // All PREOP IDNs are now configured.
954 }
955 
956 /*****************************************************************************/
957 
962  )
963 {
964  // Start configuring PDOs
967  fsm->state(fsm); // execute immediately
968 }
969 
970 /*****************************************************************************/
971 
976  )
977 {
978  // TODO check for config here
979 
980  if (ec_fsm_pdo_exec(fsm->fsm_pdo, fsm->datagram)) {
981  return;
982  }
983 
984  if (!fsm->slave->config) { // config removed in the meantime
986  return;
987  }
988 
989  if (!ec_fsm_pdo_success(fsm->fsm_pdo)) {
990  EC_SLAVE_WARN(fsm->slave, "PDO configuration failed.\n");
991  }
992 
994 }
995 
996 /*****************************************************************************/
997 
1001  ec_fsm_slave_config_t *fsm
1002  )
1003 {
1004  ec_slave_t *slave = fsm->slave;
1005  ec_datagram_t *datagram = fsm->datagram;
1006  ec_slave_config_t *config = slave->config;
1007 
1008  if (config && config->watchdog_divider) {
1009  EC_SLAVE_DBG(slave, 1, "Setting watchdog divider to %u.\n",
1010  config->watchdog_divider);
1011 
1012  ec_datagram_fpwr(datagram, slave->station_address, 0x0400, 2);
1013  EC_WRITE_U16(datagram->data, config->watchdog_divider);
1014  fsm->retries = EC_FSM_RETRIES;
1016  } else {
1018  }
1019 }
1020 
1021 /*****************************************************************************/
1022 
1026  ec_fsm_slave_config_t *fsm
1027  )
1028 {
1029  ec_datagram_t *datagram = fsm->datagram;
1030  ec_slave_t *slave = fsm->slave;
1031 
1032  if (datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--)
1033  return;
1034 
1035  if (datagram->state != EC_DATAGRAM_RECEIVED) {
1037  EC_SLAVE_ERR(slave, "Failed to receive watchdog divider"
1038  " configuration datagram: ");
1039  ec_datagram_print_state(datagram);
1040  return;
1041  }
1042 
1043  if (datagram->working_counter != 1) {
1044  slave->error_flag = 1;
1045  EC_SLAVE_WARN(slave, "Failed to set watchdog divider: ");
1046  ec_datagram_print_wc_error(datagram);
1047  return;
1048  }
1049 
1051 }
1052 
1053 /*****************************************************************************/
1054 
1058  ec_fsm_slave_config_t *fsm
1059  )
1060 {
1061  ec_datagram_t *datagram = fsm->datagram;
1062  ec_slave_t *slave = fsm->slave;
1063  ec_slave_config_t *config = slave->config;
1064 
1065  if (config && config->watchdog_intervals) {
1066  EC_SLAVE_DBG(slave, 1, "Setting process data"
1067  " watchdog intervals to %u.\n", config->watchdog_intervals);
1068 
1069  ec_datagram_fpwr(datagram, slave->station_address, 0x0420, 2);
1070  EC_WRITE_U16(datagram->data, config->watchdog_intervals);
1071 
1072  fsm->retries = EC_FSM_RETRIES;
1074  } else {
1076  }
1077 }
1078 
1079 /*****************************************************************************/
1080 
1085  ec_fsm_slave_config_t *fsm
1086  )
1087 {
1088  ec_datagram_t *datagram = fsm->datagram;
1089  ec_slave_t *slave = fsm->slave;
1090 
1091  if (datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--)
1092  return;
1093 
1094  if (datagram->state != EC_DATAGRAM_RECEIVED) {
1096  EC_SLAVE_ERR(slave, "Failed to receive sync manager"
1097  " watchdog configuration datagram: ");
1098  ec_datagram_print_state(datagram);
1099  return;
1100  }
1101 
1102  if (datagram->working_counter != 1) {
1103  EC_SLAVE_WARN(slave, "Failed to set process data"
1104  " watchdog intervals: ");
1105  ec_datagram_print_wc_error(datagram);
1106  }
1107 
1109 }
1110 
1111 /*****************************************************************************/
1112 
1116  ec_fsm_slave_config_t *fsm
1117  )
1118 {
1119  ec_slave_t *slave = fsm->slave;
1120  ec_datagram_t *datagram = fsm->datagram;
1121  unsigned int i, j, offset, num_pdo_syncs;
1122  uint8_t sync_index;
1123  const ec_sync_t *sync;
1124  uint16_t size;
1125 
1126  if (slave->sii.mailbox_protocols) {
1127  offset = 2; // slave has mailboxes
1128  } else {
1129  offset = 0;
1130  }
1131 
1132  if (slave->sii.sync_count <= offset) {
1133  // no PDO sync managers to configure
1135  return;
1136  }
1137 
1138  num_pdo_syncs = slave->sii.sync_count - offset;
1139 
1140  // configure sync managers for process data
1141  ec_datagram_fpwr(datagram, slave->station_address,
1142  0x0800 + EC_SYNC_PAGE_SIZE * offset,
1143  EC_SYNC_PAGE_SIZE * num_pdo_syncs);
1144  ec_datagram_zero(datagram);
1145 
1146  for (i = 0; i < num_pdo_syncs; i++) {
1147  const ec_sync_config_t *sync_config;
1148  uint8_t pdo_xfer = 0;
1149  sync_index = i + offset;
1150  sync = &slave->sii.syncs[sync_index];
1151 
1152  if (slave->config) {
1153  const ec_slave_config_t *sc = slave->config;
1154  sync_config = &sc->sync_configs[sync_index];
1155  size = ec_pdo_list_total_size(&sync_config->pdos);
1156 
1157  // determine, if PDOs shall be transferred via this SM
1158  // inthat case, enable sync manager in every case
1159  for (j = 0; j < sc->used_fmmus; j++) {
1160  if (sc->fmmu_configs[j].sync_index == sync_index) {
1161  pdo_xfer = 1;
1162  break;
1163  }
1164  }
1165 
1166  } else {
1167  sync_config = NULL;
1168  size = sync->default_length;
1169  }
1170 
1171  ec_sync_page(sync, sync_index, size, sync_config, pdo_xfer,
1172  datagram->data + EC_SYNC_PAGE_SIZE * i);
1173  }
1174 
1175  fsm->retries = EC_FSM_RETRIES;
1177 }
1178 
1179 /*****************************************************************************/
1180 
1184  ec_fsm_slave_config_t *fsm
1185  )
1186 {
1187  ec_datagram_t *datagram = fsm->datagram;
1188  ec_slave_t *slave = fsm->slave;
1189 
1190  if (datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--)
1191  return;
1192 
1193  if (datagram->state != EC_DATAGRAM_RECEIVED) {
1195  EC_SLAVE_ERR(slave, "Failed to receive process data sync"
1196  " manager configuration datagram: ");
1197  ec_datagram_print_state(datagram);
1198  return;
1199  }
1200 
1201  if (datagram->working_counter != 1) {
1202  slave->error_flag = 1;
1204  EC_SLAVE_ERR(slave, "Failed to set process data sync managers: ");
1205  ec_datagram_print_wc_error(datagram);
1206  return;
1207  }
1208 
1210 }
1211 
1212 /*****************************************************************************/
1213 
1217  ec_fsm_slave_config_t *fsm
1218  )
1219 {
1220  ec_slave_t *slave = fsm->slave;
1221  ec_datagram_t *datagram = fsm->datagram;
1222  unsigned int i;
1223  const ec_fmmu_config_t *fmmu;
1224  const ec_sync_t *sync;
1225 
1226  if (!slave->config) {
1228  return;
1229  }
1230 
1231  if (slave->base_fmmu_count < slave->config->used_fmmus) {
1232  slave->error_flag = 1;
1234  EC_SLAVE_ERR(slave, "Slave has less FMMUs (%u)"
1235  " than requested (%u).\n", slave->base_fmmu_count,
1236  slave->config->used_fmmus);
1237  return;
1238  }
1239 
1240  if (!slave->base_fmmu_count) { // skip FMMU configuration
1242  return;
1243  }
1244 
1245  // configure FMMUs
1246  ec_datagram_fpwr(datagram, slave->station_address,
1247  0x0600, EC_FMMU_PAGE_SIZE * slave->base_fmmu_count);
1248  ec_datagram_zero(datagram);
1249  for (i = 0; i < slave->config->used_fmmus; i++) {
1250  fmmu = &slave->config->fmmu_configs[i];
1251  if (!(sync = ec_slave_get_sync(slave, fmmu->sync_index))) {
1252  slave->error_flag = 1;
1254  EC_SLAVE_ERR(slave, "Failed to determine PDO sync manager"
1255  " for FMMU!\n");
1256  return;
1257  }
1258  ec_fmmu_config_page(fmmu, sync,
1259  datagram->data + EC_FMMU_PAGE_SIZE * i);
1260  }
1261 
1262  fsm->retries = EC_FSM_RETRIES;
1264 }
1265 
1266 /*****************************************************************************/
1267 
1271  ec_fsm_slave_config_t *fsm
1272  )
1273 {
1274  ec_datagram_t *datagram = fsm->datagram;
1275  ec_slave_t *slave = fsm->slave;
1276 
1277  if (datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--)
1278  return;
1279 
1280  if (datagram->state != EC_DATAGRAM_RECEIVED) {
1282  EC_SLAVE_ERR(slave, "Failed to receive FMMUs datagram: ");
1283  ec_datagram_print_state(datagram);
1284  return;
1285  }
1286 
1287  if (datagram->working_counter != 1) {
1288  slave->error_flag = 1;
1290  EC_SLAVE_ERR(slave, "Failed to set FMMUs: ");
1291  ec_datagram_print_wc_error(datagram);
1292  return;
1293  }
1294 
1296 }
1297 
1298 /*****************************************************************************/
1299 
1303  ec_fsm_slave_config_t *fsm
1304  )
1305 {
1306  ec_datagram_t *datagram = fsm->datagram;
1307  ec_slave_t *slave = fsm->slave;
1308  ec_slave_config_t *config = slave->config;
1309 
1310  if (!config) { // config removed in the meantime
1312  return;
1313  }
1314 
1315  if (config->dc_assign_activate) {
1316  if (!slave->base_dc_supported || !slave->has_dc_system_time) {
1317  EC_SLAVE_WARN(slave, "Slave seems not to support"
1318  " distributed clocks!\n");
1319  }
1320 
1321  EC_SLAVE_DBG(slave, 1, "Setting DC cycle times to %u / %u.\n",
1322  config->dc_sync[0].cycle_time, config->dc_sync[1].cycle_time);
1323 
1324  // set DC cycle times
1325  ec_datagram_fpwr(datagram, slave->station_address, 0x09A0, 8);
1326  EC_WRITE_U32(datagram->data, config->dc_sync[0].cycle_time);
1327  EC_WRITE_U32(datagram->data + 4, config->dc_sync[1].cycle_time);
1328  fsm->retries = EC_FSM_RETRIES;
1330  } else {
1331  // DC are unused
1333  }
1334 }
1335 
1336 /*****************************************************************************/
1337 
1341  ec_fsm_slave_config_t *fsm
1342  )
1343 {
1344  ec_datagram_t *datagram = fsm->datagram;
1345  ec_slave_t *slave = fsm->slave;
1346  ec_slave_config_t *config = slave->config;
1347 
1348  if (!config) { // config removed in the meantime
1350  return;
1351  }
1352 
1353  if (datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--)
1354  return;
1355 
1356  if (datagram->state != EC_DATAGRAM_RECEIVED) {
1358  EC_SLAVE_ERR(slave, "Failed to receive DC cycle times datagram: ");
1359  ec_datagram_print_state(datagram);
1360  return;
1361  }
1362 
1363  if (datagram->working_counter != 1) {
1364  slave->error_flag = 1;
1366  EC_SLAVE_ERR(slave, "Failed to set DC cycle times: ");
1367  ec_datagram_print_wc_error(datagram);
1368  return;
1369  }
1370 
1371  EC_SLAVE_DBG(slave, 1, "Checking for synchrony.\n");
1372 
1373  fsm->jiffies_start = jiffies;
1374  ec_datagram_fprd(datagram, slave->station_address, 0x092c, 4);
1375  fsm->retries = EC_FSM_RETRIES;
1377 }
1378 
1379 /*****************************************************************************/
1380 
1384  ec_fsm_slave_config_t *fsm
1385  )
1386 {
1387  ec_datagram_t *datagram = fsm->datagram;
1388  ec_slave_t *slave = fsm->slave;
1389  ec_master_t *master = slave->master;
1390  ec_slave_config_t *config = slave->config;
1391  uint32_t abs_sync_diff;
1392  unsigned long diff_ms;
1393  ec_sync_signal_t *sync0 = &config->dc_sync[0];
1394  ec_sync_signal_t *sync1 = &config->dc_sync[1];
1395  u64 start_time;
1396 
1397  if (!config) { // config removed in the meantime
1399  return;
1400  }
1401 
1402  if (datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--)
1403  return;
1404 
1405  if (datagram->state != EC_DATAGRAM_RECEIVED) {
1407  EC_SLAVE_ERR(slave, "Failed to receive DC sync check datagram: ");
1408  ec_datagram_print_state(datagram);
1409  return;
1410  }
1411 
1412  if (datagram->working_counter != 1) {
1413  slave->error_flag = 1;
1415  EC_SLAVE_ERR(slave, "Failed to check DC synchrony: ");
1416  ec_datagram_print_wc_error(datagram);
1417  return;
1418  }
1419 
1420  abs_sync_diff = EC_READ_U32(datagram->data) & 0x7fffffff;
1421  diff_ms = (datagram->jiffies_received - fsm->jiffies_start) * 1000 / HZ;
1422 
1423  if (abs_sync_diff > EC_DC_MAX_SYNC_DIFF_NS) {
1424 
1425  if (diff_ms >= EC_DC_SYNC_WAIT_MS) {
1426  EC_SLAVE_WARN(slave, "Slave did not sync after %lu ms.\n",
1427  diff_ms);
1428  } else {
1429  EC_SLAVE_DBG(slave, 1, "Sync after %4lu ms: %10u ns\n",
1430  diff_ms, abs_sync_diff);
1431 
1432  // check synchrony again
1433  ec_datagram_fprd(datagram, slave->station_address, 0x092c, 4);
1434  fsm->retries = EC_FSM_RETRIES;
1435  return;
1436  }
1437  } else {
1438  EC_SLAVE_DBG(slave, 1, "%u ns difference after %lu ms.\n",
1439  abs_sync_diff, diff_ms);
1440  }
1441 
1442  // set DC start time (roughly in the future, not in-phase)
1443  start_time = master->app_time + EC_DC_START_OFFSET; // now + X ns
1444 
1445  if (sync0->cycle_time) {
1446  // find correct phase
1447  if (master->dc_ref_time) {
1448  u64 diff, start;
1449  u32 remainder, cycle;
1450 
1451  diff = start_time - master->dc_ref_time;
1452  cycle = sync0->cycle_time + sync1->cycle_time;
1453  remainder = do_div(diff, cycle);
1454 
1455  start = start_time + cycle - remainder + sync0->shift_time;
1456 
1457  EC_SLAVE_DBG(slave, 1, " ref_time=%llu\n", master->dc_ref_time);
1458  EC_SLAVE_DBG(slave, 1, " app_time=%llu\n", master->app_time);
1459  EC_SLAVE_DBG(slave, 1, " start_time=%llu\n", start_time);
1460  EC_SLAVE_DBG(slave, 1, " cycle=%u\n", cycle);
1461  EC_SLAVE_DBG(slave, 1, " shift_time=%i\n", sync0->shift_time);
1462  EC_SLAVE_DBG(slave, 1, " remainder=%u\n", remainder);
1463  EC_SLAVE_DBG(slave, 1, " start=%llu\n", start);
1464  start_time = start;
1465  } else {
1466  EC_SLAVE_WARN(slave, "No application time supplied."
1467  " Cyclic start time will not be in phase.\n");
1468  }
1469  }
1470 
1471  EC_SLAVE_DBG(slave, 1, "Setting DC cyclic operation"
1472  " start time to %llu.\n", start_time);
1473 
1474  ec_datagram_fpwr(datagram, slave->station_address, 0x0990, 8);
1475  EC_WRITE_U64(datagram->data, start_time);
1476  fsm->retries = EC_FSM_RETRIES;
1478 }
1479 
1480 /*****************************************************************************/
1481 
1485  ec_fsm_slave_config_t *fsm
1486  )
1487 {
1488  ec_datagram_t *datagram = fsm->datagram;
1489  ec_slave_t *slave = fsm->slave;
1490  ec_slave_config_t *config = slave->config;
1491 
1492  if (!config) { // config removed in the meantime
1494  return;
1495  }
1496 
1497  if (datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--)
1498  return;
1499 
1500  if (datagram->state != EC_DATAGRAM_RECEIVED) {
1502  EC_SLAVE_ERR(slave, "Failed to receive DC start time datagram: ");
1503  ec_datagram_print_state(datagram);
1504  return;
1505  }
1506 
1507  if (datagram->working_counter != 1) {
1508  slave->error_flag = 1;
1510  EC_SLAVE_ERR(slave, "Failed to set DC start time: ");
1511  ec_datagram_print_wc_error(datagram);
1512  return;
1513  }
1514 
1515  EC_SLAVE_DBG(slave, 1, "Setting DC AssignActivate to 0x%04x.\n",
1516  config->dc_assign_activate);
1517 
1518  // assign sync unit to EtherCAT or PDI
1519  ec_datagram_fpwr(datagram, slave->station_address, 0x0980, 2);
1520  EC_WRITE_U16(datagram->data, config->dc_assign_activate);
1521  fsm->retries = EC_FSM_RETRIES;
1523 }
1524 
1525 /*****************************************************************************/
1526 
1530  ec_fsm_slave_config_t *fsm
1531  )
1532 {
1533  ec_datagram_t *datagram = fsm->datagram;
1534  ec_slave_t *slave = fsm->slave;
1535 
1536  if (datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--)
1537  return;
1538 
1539  if (datagram->state != EC_DATAGRAM_RECEIVED) {
1541  EC_SLAVE_ERR(slave, "Failed to receive DC activation datagram: ");
1542  ec_datagram_print_state(datagram);
1543  return;
1544  }
1545 
1546  if (datagram->working_counter != 1) {
1547  slave->error_flag = 1;
1549  EC_SLAVE_ERR(slave, "Failed to activate DC: ");
1550  ec_datagram_print_wc_error(datagram);
1551  return;
1552  }
1553 
1555 }
1556 
1557 /*****************************************************************************/
1558 
1562  ec_fsm_slave_config_t *fsm
1563  )
1564 {
1567  ec_fsm_change_exec(fsm->fsm_change); // execute immediately
1568 }
1569 
1570 /*****************************************************************************/
1571 
1575  ec_fsm_slave_config_t *fsm
1576  )
1577 {
1578  ec_slave_t *slave = fsm->slave;
1579 
1580  if (ec_fsm_change_exec(fsm->fsm_change)) return;
1581 
1582  if (!ec_fsm_change_success(fsm->fsm_change)) {
1583  if (!fsm->fsm_change->spontaneous_change)
1584  fsm->slave->error_flag = 1;
1586  return;
1587  }
1588 
1589  // slave is now in SAFEOP
1590 
1591  EC_SLAVE_DBG(slave, 1, "Now in SAFEOP.\n");
1592 
1593  if (fsm->slave->current_state == fsm->slave->requested_state) {
1594  fsm->state = ec_fsm_slave_config_state_end; // successful
1595  EC_SLAVE_DBG(slave, 1, "Finished configuration.\n");
1596  return;
1597  }
1598 
1600 }
1601 
1602 /*****************************************************************************/
1603 
1607  ec_fsm_slave_config_t *fsm
1608  )
1609 {
1610  ec_slave_t *slave = fsm->slave;
1611  ec_soe_request_t *req;
1612 
1613  if (!slave->config) {
1615  return;
1616  }
1617 
1618  list_for_each_entry(req, &slave->config->soe_configs, list) {
1619  if (req->al_state == EC_AL_STATE_SAFEOP) {
1620  // start SoE configuration
1622  fsm->soe_request = req;
1625  ec_fsm_soe_transfer(fsm->fsm_soe, fsm->slave,
1626  &fsm->soe_request_copy);
1627  ec_fsm_soe_exec(fsm->fsm_soe, fsm->datagram);
1628  return;
1629  }
1630  }
1631 
1632  // No SoE configuration to be applied in SAFEOP
1634 }
1635 
1636 /*****************************************************************************/
1637 
1641  ec_fsm_slave_config_t *fsm
1642  )
1643 {
1644  ec_slave_t *slave = fsm->slave;
1645 
1646  if (ec_fsm_soe_exec(fsm->fsm_soe, fsm->datagram)) {
1647  return;
1648  }
1649 
1650  if (!ec_fsm_soe_success(fsm->fsm_soe)) {
1651  EC_SLAVE_ERR(slave, "SoE configuration failed.\n");
1652  fsm->slave->error_flag = 1;
1654  return;
1655  }
1656 
1657  if (!fsm->slave->config) { // config removed in the meantime
1659  return;
1660  }
1661 
1662  // Another IDN to configure in SAFEOP?
1663  while (fsm->soe_request->list.next != &fsm->slave->config->soe_configs) {
1664  fsm->soe_request = list_entry(fsm->soe_request->list.next,
1665  ec_soe_request_t, list);
1666  if (fsm->soe_request->al_state == EC_AL_STATE_SAFEOP) {
1669  ec_fsm_soe_transfer(fsm->fsm_soe, fsm->slave,
1670  &fsm->soe_request_copy);
1671  ec_fsm_soe_exec(fsm->fsm_soe, fsm->datagram);
1672  return;
1673  }
1674  }
1675 
1676  // All SAFEOP IDNs are now configured.
1678 }
1679 
1680 /*****************************************************************************/
1681 
1685  ec_fsm_slave_config_t *fsm
1686  )
1687 {
1688  // set state to OP
1691  ec_fsm_change_exec(fsm->fsm_change); // execute immediately
1692 }
1693 
1694 /*****************************************************************************/
1695 
1699  ec_fsm_slave_config_t *fsm
1700  )
1701 {
1702  ec_slave_t *slave = fsm->slave;
1703 
1704  if (ec_fsm_change_exec(fsm->fsm_change)) return;
1705 
1706  if (!ec_fsm_change_success(fsm->fsm_change)) {
1707  if (!fsm->fsm_change->spontaneous_change)
1708  slave->error_flag = 1;
1710  return;
1711  }
1712 
1713  // slave is now in OP
1714 
1715  EC_SLAVE_DBG(slave, 1, "Now in OP. Finished configuration.\n");
1716 
1717  fsm->state = ec_fsm_slave_config_state_end; // successful
1718 }
1719 
1720 /*****************************************************************************/
1721 
1725  ec_fsm_slave_config_t *fsm
1726  )
1727 {
1728  EC_SLAVE_DBG(fsm->slave, 1, "Slave configuration detached during "
1729  "configuration. Reconfiguring.");
1730 
1731  ec_fsm_slave_config_enter_init(fsm); // reconfigure
1732 }
1733 
1734 /******************************************************************************
1735  * Common state functions
1736  *****************************************************************************/
1737 
1741  ec_fsm_slave_config_t *fsm
1742  )
1743 {
1744 }
1745 
1746 /*****************************************************************************/
1747 
1751  ec_fsm_slave_config_t *fsm
1752  )
1753 {
1754 }
1755 
1756 /*****************************************************************************/
#define EC_FSM_RETRIES
Number of state machine retries on datagram timeout.
Definition: globals.h:47
Finite state machines for the Sercos over EtherCAT protocol.
Definition: fsm_soe.h:51
unsigned long jiffies_sent
Jiffies, when the datagram was sent.
Definition: datagram.h:104
Pre-operational.
Definition: ecrt.h:543
void ec_fsm_slave_config_state_boot_preop(ec_fsm_slave_config_t *)
Slave configuration state: BOOT/PREOP.
struct list_head sdo_configs
List of SDO configurations.
Definition: slave_config.h:144
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:89
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.
uint8_t spontaneous_change
spontaneous state change detected
Definition: fsm_change.h:76
void ec_fsm_slave_config_enter_watchdog(ec_fsm_slave_config_t *)
WATCHDOG entry function.
uint16_t configured_tx_mailbox_size
Configured send mailbox size.
Definition: slave.h:201
void ec_fsm_slave_config_state_init(ec_fsm_slave_config_t *)
Slave configuration state: INIT.
void ec_fsm_slave_config_state_safeop(ec_fsm_slave_config_t *)
Slave configuration state: SAFEOP.
void ec_fsm_slave_config_enter_assign_pdi(ec_fsm_slave_config_t *)
Assign SII to PDI.
FMMU configuration.
Definition: fmmu_config.h:46
ec_sdo_request_t * request
SDO request for SDO configuration.
void ec_fsm_slave_config_reconfigure(ec_fsm_slave_config_t *)
Reconfigure the slave starting at INIT.
struct list_head list
List item.
Definition: soe_request.h:49
#define EC_SLAVE_DBG(slave, level, fmt, args...)
Convenience macro for printing slave-specific debug messages to syslog.
Definition: slave.h:106
void ec_fsm_pdo_start_configuration(ec_fsm_pdo_t *fsm, ec_slave_t *slave)
Start writing the PDO configuration.
Definition: fsm_pdo.c:132
int32_t shift_time
Shift time [ns].
Definition: globals.h:173
OP (mailbox communication and input/output update)
Definition: globals.h:126
uint16_t configured_tx_mailbox_offset
Configured send mailbox offset.
Definition: slave.h:199
void ec_fsm_slave_config_state_dc_cycle(ec_fsm_slave_config_t *)
Slave configuration state: DC CYCLE.
ec_fsm_change_t * fsm_change
State change state machine.
CANopen SDO request.
Definition: sdo_request.h:48
ec_slave_state_t current_state
Current application state.
Definition: slave.h:192
void ec_fsm_slave_config_state_dc_clear_assign(ec_fsm_slave_config_t *)
Slave configuration state: CLEAR DC ASSIGN.
void ec_fsm_slave_config_state_dc_start(ec_fsm_slave_config_t *)
Slave configuration state: DC START.
uint8_t used_fmmus
Number of FMMUs used.
Definition: slave_config.h:140
Safe-operational.
Definition: ecrt.h:544
#define EC_SLAVE_WARN(slave, fmt, args...)
Convenience macro for printing slave-specific warnings to syslog.
Definition: slave.h:90
void ec_fsm_slave_config_enter_soe_conf_safeop(ec_fsm_slave_config_t *)
Check for SoE configurations to be applied in SAFEOP.
EtherCAT datagram.
Definition: datagram.h:87
void ec_fsm_slave_config_state_fmmu(ec_fsm_slave_config_t *)
Slave configuration state: FMMU.
#define EC_WRITE_U8(DATA, VAL)
Write an 8-bit unsigned value to EtherCAT data.
Definition: ecrt.h:2266
u64 dc_ref_time
Common reference timestamp for DC start times.
Definition: master.h:239
Bootstrap state (mailbox communication, firmware update)
Definition: globals.h:122
void ec_fsm_slave_config_state_soe_conf_preop(ec_fsm_slave_config_t *)
Slave configuration state: SOE_CONF.
uint32_t cycle_time
Cycle time [ns].
Definition: globals.h:172
void ec_fsm_change_start(ec_fsm_change_t *fsm, ec_slave_t *slave, ec_slave_state_t state)
Starts the change state machine.
Definition: fsm_change.c:90
uint16_t working_counter
Working counter.
Definition: datagram.h:99
int ec_fsm_coe_success(const ec_fsm_coe_t *fsm)
Returns, if the state machine terminated with success.
Definition: fsm_coe.c:262
void ec_fsm_slave_config_state_start(ec_fsm_slave_config_t *)
Slave configuration state: START.
uint16_t boot_tx_mailbox_size
Bootstrap transmit mailbox size.
Definition: slave.h:142
Sent (still in the queue).
Definition: datagram.h:77
void ec_fmmu_config_page(const ec_fmmu_config_t *fmmu, const ec_sync_t *sync, uint8_t *data)
Initializes an FMMU configuration page.
Definition: fmmu_config.c:76
void ec_fsm_slave_config_state_mbox_sync(ec_fsm_slave_config_t *)
Slave configuration state: SYNC.
void ec_fsm_slave_config_enter_dc_clear_assign(ec_fsm_slave_config_t *)
Clear the DC assignment.
uint16_t station_address
Configured station address.
Definition: slave.h:184
void(* state)(ec_fsm_slave_config_t *)
State function.
unsigned int sync_count
Number of sync managers.
Definition: slave.h:166
ec_sdo_request_t request_copy
Copied SDO request.
uint16_t std_rx_mailbox_size
Standard receive mailbox size.
Definition: slave.h:144
void ec_fsm_slave_config_init(ec_fsm_slave_config_t *fsm, ec_datagram_t *datagram, ec_fsm_change_t *fsm_change, ec_fsm_coe_t *fsm_coe, ec_fsm_soe_t *fsm_soe, ec_fsm_pdo_t *fsm_pdo)
Constructor.
void ec_sync_page(const ec_sync_t *sync, uint8_t sync_index, uint16_t data_size, const ec_sync_config_t *sync_config, uint8_t pdo_xfer, uint8_t *data)
Initializes a sync manager configuration page.
Definition: sync.c:94
Global definitions and macros.
uint16_t std_tx_mailbox_offset
Standard transmit mailbox address.
Definition: slave.h:145
EtherCAT master structure.
ec_fmmu_config_t fmmu_configs[EC_MAX_FMMUS]
FMMU configurations.
Definition: slave_config.h:139
SAFEOP (mailbox communication and input update)
Definition: globals.h:124
void ec_fsm_slave_config_enter_watchdog_divider(ec_fsm_slave_config_t *)
WATCHDOG_DIVIDER entry function.
ec_sync_signal_t dc_sync[EC_SYNC_SIGNAL_COUNT]
DC sync signals.
Definition: slave_config.h:142
uint16_t boot_tx_mailbox_offset
Bootstrap transmit mailbox address.
Definition: slave.h:141
void ec_fsm_slave_config_state_assign_pdi(ec_fsm_slave_config_t *)
Slave configuration state: ASSIGN_PDI.
EtherCAT slave.
Definition: slave.h:176
void ec_sdo_request_clear(ec_sdo_request_t *req)
SDO request destructor.
Definition: sdo_request.c:76
EtherCAT slave configuration state machine.
void ec_fsm_slave_config_state_soe_conf_safeop(ec_fsm_slave_config_t *)
Slave configuration state: SOE_CONF.
uint16_t ec_pdo_list_total_size(const ec_pdo_list_t *pl)
Calculates the total size of the mapped PDO entries.
Definition: pdo_list.c:87
void ec_datagram_zero(ec_datagram_t *datagram)
Fills the datagram payload memory with zeros.
Definition: datagram.c:178
ec_fsm_pdo_t * fsm_pdo
PDO configuration state machine.
void ec_fsm_soe_transfer(ec_fsm_soe_t *fsm, ec_slave_t *slave, ec_soe_request_t *request)
Starts to transfer an IDN to/from a slave.
Definition: fsm_soe.c:128
int ec_fsm_soe_success(const ec_fsm_soe_t *fsm)
Returns, if the state machine terminated with success.
Definition: fsm_soe.c:185
ec_sync_config_t sync_configs[EC_MAX_SYNC_MANAGERS]
Sync manager configurations.
Definition: slave_config.h:137
ec_datagram_state_t state
State.
Definition: datagram.h:100
ec_slave_config_t * config
Current configuration.
Definition: slave.h:190
#define EC_WRITE_U32(DATA, VAL)
Write a 32-bit unsigned value to EtherCAT data.
Definition: ecrt.h:2300
uint8_t sync_index
Index of sync manager to use.
Definition: fmmu_config.h:50
Slave configutation feature flag.
Definition: flag.h:38
void ec_fsm_slave_config_state_watchdog_divider(ec_fsm_slave_config_t *)
Slave configuration state: WATCHDOG_DIVIDER.
uint16_t mailbox_protocols
Supported mailbox protocols.
Definition: slave.h:147
ec_flag_t * ec_slave_config_find_flag(ec_slave_config_t *sc, const char *key)
Finds a flag.
Definition: slave_config.c:580
void ec_fsm_slave_config_state_end(ec_fsm_slave_config_t *)
State: END.
void ec_fsm_slave_config_enter_clear_sync(ec_fsm_slave_config_t *)
Clear the sync manager configurations.
int ec_fsm_slave_config_running(const ec_fsm_slave_config_t *fsm)
#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
#define EC_DC_START_OFFSET
Time offset (in ns), that is added to cyclic start time.
Sync manager.
Definition: sync.h:47
uint16_t std_rx_mailbox_offset
Standard receive mailbox address.
Definition: slave.h:143
int ec_fsm_change_exec(ec_fsm_change_t *fsm)
Executes the current state of the state machine.
Definition: fsm_change.c:124
void ec_soe_request_clear(ec_soe_request_t *req)
SoE request destructor.
Definition: soe_request.c:77
void ec_fsm_slave_config_state_clear_fmmus(ec_fsm_slave_config_t *)
Slave configuration state: CLEAR FMMU.
ec_pdo_list_t pdos
Current PDO assignment.
Definition: sync_config.h:49
uint16_t dc_assign_activate
Vendor-specific AssignActivate word.
Definition: slave_config.h:141
void ec_fsm_slave_config_enter_mbox_sync(ec_fsm_slave_config_t *)
Check for mailbox sync managers to be configured.
ec_datagram_t * datagram
Datagram used in the state machine.
#define EC_WRITE_U16(DATA, VAL)
Write a 16-bit unsigned value to EtherCAT data.
Definition: ecrt.h:2283
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
void ec_fsm_slave_config_enter_fmmu(ec_fsm_slave_config_t *)
Check for FMMUs to be configured.
#define EC_READ_U32(DATA)
Read a 32-bit unsigned value from EtherCAT data.
Definition: ecrt.h:2194
uint16_t watchdog_intervals
Process data watchdog intervals (see spec.
Definition: slave_config.h:131
void ec_fsm_slave_config_enter_sdo_conf(ec_fsm_slave_config_t *)
Check for SDO configurations to be applied.
ec_master_t * master
Master owning the slave.
Definition: slave.h:178
int ec_sdo_request_copy(ec_sdo_request_t *req, const ec_sdo_request_t *other)
Copy another SDO request.
Definition: sdo_request.c:91
void ec_fsm_slave_config_enter_soe_conf_preop(ec_fsm_slave_config_t *)
Check for SoE configurations to be applied.
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
void ec_fsm_slave_config_enter_init(ec_fsm_slave_config_t *)
Start state change to INIT.
void ec_fsm_slave_config_state_pdo_conf(ec_fsm_slave_config_t *)
Slave configuration state: PDO_CONF.
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
uint8_t control_register
Control register value.
Definition: sync.h:51
ec_fsm_coe_t * fsm_coe
CoE state machine.
uint16_t watchdog_divider
Watchdog divider as a number of 40ns intervals (see spec.
Definition: slave_config.h:129
PDO configuration state machine.
Definition: fsm_pdo.h:54
ec_al_state_t al_state
AL state (only valid for IDN config).
Definition: soe_request.h:52
void ec_fsm_slave_config_state_pdo_sync(ec_fsm_slave_config_t *)
Configure PDO sync managers.
#define EC_DC_MAX_SYNC_DIFF_NS
Maximum clock difference (in ns) before going to SAFEOP.
void ec_fsm_slave_config_enter_safeop(ec_fsm_slave_config_t *)
Request SAFEOP state.
ec_fsm_soe_t * fsm_soe
SoE state machine.
struct list_head soe_configs
List of SoE configurations.
Definition: slave_config.h:148
void ec_fsm_slave_config_enter_pdo_conf(ec_fsm_slave_config_t *)
PDO_CONF entry function.
unsigned int take_time
Store jiffies after datagram reception.
INIT state (no mailbox communication, no IO)
Definition: globals.h:118
int ec_fsm_pdo_success(const ec_fsm_pdo_t *fsm)
Get execution result.
Definition: fsm_pdo.c:180
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.
uint8_t enable
Enable bit.
Definition: sync.h:52
ec_slave_t * slave
Slave the FSM runs on.
Invalid direction.
Definition: ecrt.h:431
void ec_sdo_request_init(ec_sdo_request_t *req)
SDO request constructor.
Definition: sdo_request.c:56
void ec_fsm_slave_config_state_op(ec_fsm_slave_config_t *)
Slave configuration state: OP.
#define EC_WRITE_U64(DATA, VAL)
Write a 64-bit unsigned value to EtherCAT data.
Definition: ecrt.h:2317
uint16_t boot_rx_mailbox_size
Bootstrap receive mailbox size.
Definition: slave.h:140
ec_soe_request_t soe_request_copy
Copied SDO request.
Sync manager configuration.
Definition: sync_config.h:46
int ec_fsm_slave_config_exec(ec_fsm_slave_config_t *fsm)
Executes the current state of the state machine.
struct list_head list
List item.
Definition: sdo_request.h:49
EtherCAT slave sync signal configuration.
Definition: globals.h:171
int ec_fsm_coe_exec(ec_fsm_coe_t *fsm, ec_datagram_t *datagram)
Executes the current state of the state machine.
Definition: fsm_coe.c:228
void ec_fsm_slave_config_state_clear_sync(ec_fsm_slave_config_t *)
Slave configuration state: CLEAR SYNC.
Queued for sending.
Definition: datagram.h:76
Timed out (dequeued).
Definition: datagram.h:79
void ec_fsm_slave_config_state_error(ec_fsm_slave_config_t *)
State: ERROR.
int32_t value
Flag value (meaning depends on key).
Definition: flag.h:41
void ec_fsm_slave_config_clear(ec_fsm_slave_config_t *fsm)
Destructor.
u64 app_time
Time of the last ecrt_master_sync() call.
Definition: master.h:238
uint16_t physical_start_address
Physical start address.
Definition: sync.h:49
unsigned long jiffies_preop
Time, the slave went to PREOP.
Definition: slave.h:227
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
uint8_t * data
Datagram payload.
Definition: datagram.h:94
void ec_fsm_slave_config_state_dc_assign(ec_fsm_slave_config_t *)
Slave configuration state: DC ASSIGN.
uint8_t base_sync_count
Number of supported sync managers.
Definition: slave.h:208
void ec_fsm_slave_config_enter_op(ec_fsm_slave_config_t *)
Bring slave to OP.
EtherCAT slave configuration.
Definition: slave_config.h:119
ec_soe_request_t * soe_request
SDO request for SDO configuration.
void ec_soe_request_write(ec_soe_request_t *req)
Request a write operation.
Definition: soe_request.c:245
int ec_fsm_slave_config_success(const ec_fsm_slave_config_t *fsm)
void ec_fsm_slave_config_enter_pdo_sync(ec_fsm_slave_config_t *)
Check for PDO sync managers to be configured.
void ec_soe_request_init(ec_soe_request_t *req)
SoE request constructor.
Definition: soe_request.c:56
EtherCAT slave configuration structure.
int ec_fsm_soe_exec(ec_fsm_soe_t *fsm, ec_datagram_t *datagram)
Executes the current state of the state machine.
Definition: fsm_soe.c:150
void ec_fsm_coe_transfer(ec_fsm_coe_t *fsm, ec_slave_t *slave, ec_sdo_request_t *request)
Starts to transfer an SDO to/from a slave.
Definition: fsm_coe.c:205
uint16_t default_length
Data length in bytes.
Definition: sync.h:50
void ec_fsm_slave_config_state_assign_ethercat(ec_fsm_slave_config_t *)
Slave configuration state: ASSIGN_ETHERCAT.
PREOP state (mailbox communication, no IO)
Definition: globals.h:120
void ec_fsm_slave_config_state_sdo_conf(ec_fsm_slave_config_t *)
Slave configuration state: SDO_CONF.
void ec_fsm_slave_config_state_watchdog(ec_fsm_slave_config_t *)
Slave configuration state: WATCHDOG.
Received (dequeued).
Definition: datagram.h:78
void ec_fsm_slave_config_enter_boot_preop(ec_fsm_slave_config_t *)
Request PREOP state.
unsigned int error_flag
Stop processing after an error.
Definition: slave.h:193
ec_sync_t * syncs
SYNC MANAGER categories.
Definition: slave.h:165
uint16_t std_tx_mailbox_size
Standard transmit mailbox size.
Definition: slave.h:146
EtherCAT master.
Definition: master.h:194
ec_slave_state_t requested_state
Requested application state.
Definition: slave.h:191
#define EC_FMMU_PAGE_SIZE
Size of an FMMU configuration page.
Definition: globals.h:95
void ec_sync_init(ec_sync_t *sync, ec_slave_t *slave)
Constructor.
Definition: sync.c:46
void ecrt_sdo_request_write(ec_sdo_request_t *req)
Schedule an SDO write operation.
Definition: sdo_request.c:235
void ec_fsm_slave_config_state_dc_sync_check(ec_fsm_slave_config_t *)
Slave configuration state: DC SYNC CHECK.
#define EC_DC_SYNC_WAIT_MS
Maximum time (in ms) to wait for clock discipline.
unsigned long jiffies_received
Jiffies, when the datagram was received.
Definition: datagram.h:108
EtherCAT state change FSM.
Definition: fsm_change.h:64
void ec_fsm_slave_config_enter_dc_cycle(ec_fsm_slave_config_t *)
Check for DC to be configured.
int ec_soe_request_copy(ec_soe_request_t *req, const ec_soe_request_t *other)
Copy another SoE request.
Definition: soe_request.c:90
int ec_fsm_change_success(ec_fsm_change_t *fsm)
Returns, if the state machine terminated with success.
Definition: fsm_change.c:139
unsigned long jiffies_start
For timeout calculations.
Sercos-over-EtherCAT request.
Definition: soe_request.h:48
Finite state machines for the CANopen over EtherCAT protocol.
Definition: fsm_coe.h:52
ec_sync_t * ec_slave_get_sync(ec_slave_t *slave, uint8_t sync_index)
Get the sync manager given an index.
Definition: slave.c:590
unsigned int retries
Retries on datagram timeout.