IgH EtherCAT Master  1.6.1
fsm_slave_config.c
Go to the documentation of this file.
1 /*****************************************************************************
2  *
3  * Copyright (C) 2006-2024 Florian Pose, Ingenieurgemeinschaft IgH
4  *
5  * This file is part of the IgH EtherCAT Master.
6  *
7  * The IgH EtherCAT Master is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License version 2, as
9  * published by the Free Software Foundation.
10  *
11  * The IgH EtherCAT Master is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
14  * Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License along
17  * with the IgH EtherCAT Master; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19  */
20 
26 /****************************************************************************/
27 
28 #include <asm/div64.h>
29 
30 #include "globals.h"
31 #include "master.h"
32 #include "mailbox.h"
33 #include "slave_config.h"
34 #include "fsm_slave_config.h"
35 
36 /****************************************************************************/
37 
43 #define EC_DC_MAX_SYNC_DIFF_NS 10000
44 
47 #define EC_DC_SYNC_WAIT_MS 5000
48 
51 #define EC_DC_START_OFFSET 100000000ULL
52 
53 /****************************************************************************/
54 
55 // prototypes for private methods
57 
58 /****************************************************************************/
59 
66 #ifdef EC_SII_ASSIGN
68 #endif
70 #ifdef EC_SII_ASSIGN
72 #endif
89 
94 #ifdef EC_SII_ASSIGN
96 #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  ec_fsm_eoe_t *fsm_eoe
129  )
130 {
133 
134  fsm->datagram = datagram;
135  fsm->fsm_change = fsm_change;
136  fsm->fsm_coe = fsm_coe;
137  fsm->fsm_soe = fsm_soe;
138  fsm->fsm_pdo = fsm_pdo;
139  fsm->fsm_eoe = fsm_eoe;
140 
141  fsm->wait_ms = 0;
142 }
143 
144 /****************************************************************************/
145 
150  )
151 {
154 }
155 
156 /****************************************************************************/
157 
161  ec_fsm_slave_config_t *fsm,
162  ec_slave_t *slave
163  )
164 {
165  fsm->slave = slave;
167 }
168 
169 /****************************************************************************/
170 
175  const ec_fsm_slave_config_t *fsm
176  )
177 {
178  return fsm->state != ec_fsm_slave_config_state_end
180 }
181 
182 /****************************************************************************/
183 
193  )
194 {
195  if (fsm->datagram->state == EC_DATAGRAM_SENT
196  || fsm->datagram->state == EC_DATAGRAM_QUEUED) {
197  // datagram was not sent or received yet.
198  return ec_fsm_slave_config_running(fsm);
199  }
200 
201  fsm->state(fsm);
202  return ec_fsm_slave_config_running(fsm);
203 }
204 
205 /****************************************************************************/
206 
211  const ec_fsm_slave_config_t *fsm
212  )
213 {
214  return fsm->state == ec_fsm_slave_config_state_end;
215 }
216 
217 /*****************************************************************************
218  * Slave configuration state machine
219  ****************************************************************************/
220 
225  )
226 {
227  EC_SLAVE_DBG(fsm->slave, 1, "Configuring...\n");
229 }
230 
231 /****************************************************************************/
232 
237  )
238 {
242 }
243 
244 /****************************************************************************/
245 
250  )
251 {
252  ec_slave_t *slave = fsm->slave;
253  ec_datagram_t *datagram = fsm->datagram;
254 
255  if (ec_fsm_change_exec(fsm->fsm_change)) return;
256 
257  if (!ec_fsm_change_success(fsm->fsm_change)) {
258  if (!fsm->fsm_change->spontaneous_change)
259  slave->error_flag = 1;
261  return;
262  }
263 
264  EC_SLAVE_DBG(slave, 1, "Now in INIT.\n");
265 
266  if (!slave->base_fmmu_count) { // skip FMMU configuration
268  return;
269  }
270 
271  EC_SLAVE_DBG(slave, 1, "Clearing FMMU configurations...\n");
272 
273  // clear FMMU configurations
274  ec_datagram_fpwr(datagram, slave->station_address,
275  0x0600, EC_FMMU_PAGE_SIZE * slave->base_fmmu_count);
276  ec_datagram_zero(datagram);
277  fsm->retries = EC_FSM_RETRIES;
279 }
280 
281 /****************************************************************************/
282 
287  )
288 {
289  ec_datagram_t *datagram = fsm->datagram;
290 
291  if (datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--)
292  return;
293 
294  if (datagram->state != EC_DATAGRAM_RECEIVED) {
296  EC_SLAVE_ERR(fsm->slave, "Failed receive FMMU clearing datagram.\n");
297  return;
298  }
299 
300  if (datagram->working_counter != 1) {
301  fsm->slave->error_flag = 1;
303  EC_SLAVE_ERR(fsm->slave, "Failed to clear FMMUs: ");
304  ec_datagram_print_wc_error(datagram);
305  return;
306  }
307 
309 }
310 
311 /****************************************************************************/
312 
317  )
318 {
319  ec_slave_t *slave = fsm->slave;
320  ec_datagram_t *datagram = fsm->datagram;
321  size_t sync_size;
322 
323  if (!slave->base_sync_count) {
324  // no sync managers
326  return;
327  }
328 
329  EC_SLAVE_DBG(slave, 1, "Clearing sync manager configurations...\n");
330 
331  sync_size = EC_SYNC_PAGE_SIZE * slave->base_sync_count;
332 
333  // clear sync manager configurations
334  ec_datagram_fpwr(datagram, slave->station_address, 0x0800, sync_size);
335  ec_datagram_zero(datagram);
336  fsm->retries = EC_FSM_RETRIES;
338 }
339 
340 /****************************************************************************/
341 
346  )
347 {
348  ec_datagram_t *datagram = fsm->datagram;
349 
350  if (datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--)
351  return;
352 
353  if (datagram->state != EC_DATAGRAM_RECEIVED) {
355  EC_SLAVE_ERR(fsm->slave, "Failed receive sync manager"
356  " clearing datagram.\n");
357  return;
358  }
359 
360  if (datagram->working_counter != 1) {
361  fsm->slave->error_flag = 1;
363  EC_SLAVE_ERR(fsm->slave,
364  "Failed to clear sync manager configurations: ");
365  ec_datagram_print_wc_error(datagram);
366  return;
367  }
368 
370 }
371 
372 /****************************************************************************/
373 
378  )
379 {
380  ec_slave_t *slave = fsm->slave;
381  ec_datagram_t *datagram = fsm->datagram;
382 
383  if (!slave->base_dc_supported || !slave->has_dc_system_time) {
385  return;
386  }
387 
388  EC_SLAVE_DBG(slave, 1, "Clearing DC assignment...\n");
389 
390  ec_datagram_fpwr(datagram, slave->station_address, 0x0980, 2);
391  ec_datagram_zero(datagram);
392  fsm->retries = EC_FSM_RETRIES;
394 }
395 
396 /****************************************************************************/
397 
402  )
403 {
404  ec_datagram_t *datagram = fsm->datagram;
405 
406  if (datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--)
407  return;
408 
409  if (datagram->state != EC_DATAGRAM_RECEIVED) {
411  EC_SLAVE_ERR(fsm->slave, "Failed receive DC assignment"
412  " clearing datagram.\n");
413  return;
414  }
415 
416  if (datagram->working_counter != 1) {
417  // clearing the DC assignment does not succeed on simple slaves
418  EC_SLAVE_DBG(fsm->slave, 1, "Failed to clear DC assignment: ");
419  ec_datagram_print_wc_error(datagram);
420  }
421 
423 }
424 
425 /****************************************************************************/
426 
431  )
432 {
433  ec_slave_t *slave = fsm->slave;
434  ec_datagram_t *datagram = fsm->datagram;
435  unsigned int i;
436 
437  // slave is now in INIT
438  if (slave->current_state == slave->requested_state) {
439  fsm->state = ec_fsm_slave_config_state_end; // successful
440  EC_SLAVE_DBG(slave, 1, "Finished configuration.\n");
441  return;
442  }
443 
444  if (!slave->sii.mailbox_protocols) {
445  // no mailbox protocols supported
446  EC_SLAVE_DBG(slave, 1, "Slave does not support"
447  " mailbox communication.\n");
448 #ifdef EC_SII_ASSIGN
450 #else
452 #endif
453  return;
454  }
455 
456  EC_SLAVE_DBG(slave, 1, "Configuring mailbox sync managers...\n");
457 
458  if (slave->requested_state == EC_SLAVE_STATE_BOOT) {
459  ec_sync_t sync;
460 
461  ec_datagram_fpwr(datagram, slave->station_address, 0x0800,
462  EC_SYNC_PAGE_SIZE * 2);
463  ec_datagram_zero(datagram);
464 
465  ec_sync_init(&sync, slave);
467  sync.control_register = 0x26;
468  sync.enable = 1;
469  ec_sync_page(&sync, 0, slave->sii.boot_rx_mailbox_size,
470  EC_DIR_INVALID, // use default direction
471  0, // no PDO xfer
472  datagram->data);
476  slave->sii.boot_rx_mailbox_size;
477 
478  ec_sync_init(&sync, slave);
480  sync.control_register = 0x22;
481  sync.enable = 1;
482  ec_sync_page(&sync, 1, slave->sii.boot_tx_mailbox_size,
483  EC_DIR_INVALID, // use default direction
484  0, // no PDO xfer
485  datagram->data + EC_SYNC_PAGE_SIZE);
489  slave->sii.boot_tx_mailbox_size;
490 
491  } else if (slave->sii.sync_count >= 2) { // mailbox configuration provided
492  ec_datagram_fpwr(datagram, slave->station_address, 0x0800,
493  EC_SYNC_PAGE_SIZE * slave->sii.sync_count);
494  ec_datagram_zero(datagram);
495 
496  for (i = 0; i < 2; i++) {
497  ec_sync_page(&slave->sii.syncs[i], i,
498  slave->sii.syncs[i].default_length,
499  NULL, // use default sync manager configuration
500  0, // no PDO xfer
501  datagram->data + EC_SYNC_PAGE_SIZE * i);
502  }
503 
505  slave->sii.syncs[0].physical_start_address;
507  slave->sii.syncs[0].default_length;
509  slave->sii.syncs[1].physical_start_address;
511  slave->sii.syncs[1].default_length;
512  } else { // no mailbox sync manager configurations provided
513  ec_sync_t sync;
514 
515  EC_SLAVE_DBG(slave, 1, "Slave does not provide"
516  " mailbox sync manager configurations.\n");
517 
518  ec_datagram_fpwr(datagram, slave->station_address, 0x0800,
519  EC_SYNC_PAGE_SIZE * 2);
520  ec_datagram_zero(datagram);
521 
522  ec_sync_init(&sync, slave);
524  sync.control_register = 0x26;
525  sync.enable = 1;
526  ec_sync_page(&sync, 0, slave->sii.std_rx_mailbox_size,
527  NULL, // use default sync manager configuration
528  0, // no PDO xfer
529  datagram->data);
531  slave->sii.std_rx_mailbox_offset;
533  slave->sii.std_rx_mailbox_size;
534 
535  ec_sync_init(&sync, slave);
537  sync.control_register = 0x22;
538  sync.enable = 1;
539  ec_sync_page(&sync, 1, slave->sii.std_tx_mailbox_size,
540  NULL, // use default sync manager configuration
541  0, // no PDO xfer
542  datagram->data + EC_SYNC_PAGE_SIZE);
544  slave->sii.std_tx_mailbox_offset;
546  slave->sii.std_tx_mailbox_size;
547  }
548 
549  fsm->take_time = 1;
550 
551  fsm->retries = EC_FSM_RETRIES;
553 }
554 
555 /****************************************************************************/
556 
563  )
564 {
565  ec_datagram_t *datagram = fsm->datagram;
566  ec_slave_t *slave = fsm->slave;
567 
568  if (datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--)
569  return;
570 
571  if (datagram->state != EC_DATAGRAM_RECEIVED) {
573  EC_SLAVE_ERR(slave, "Failed to receive sync manager"
574  " configuration datagram: ");
575  ec_datagram_print_state(datagram);
576  return;
577  }
578 
579  if (fsm->take_time) {
580  fsm->take_time = 0;
581  fsm->jiffies_start = datagram->jiffies_sent;
582  }
583 
584  /* Because the sync manager configurations are cleared during the last
585  * cycle, some slaves do not immediately respond to the mailbox sync
586  * manager configuration datagram. Therefore, resend the datagram for
587  * a certain time, if the slave does not respond.
588  */
589  if (datagram->working_counter == 0) {
590  unsigned long diff = datagram->jiffies_received - fsm->jiffies_start;
591 
592  if (diff >= HZ) {
593  slave->error_flag = 1;
595  EC_SLAVE_ERR(slave, "Timeout while configuring"
596  " mailbox sync managers.\n");
597  return;
598  } else {
599  EC_SLAVE_DBG(slave, 1, "Resending after %u ms...\n",
600  (unsigned int) diff * 1000 / HZ);
601  }
602 
603  // send configuration datagram again
604  fsm->retries = EC_FSM_RETRIES;
605  return;
606  }
607  else if (datagram->working_counter != 1) {
608  slave->error_flag = 1;
610  EC_SLAVE_ERR(slave, "Failed to set sync managers: ");
611  ec_datagram_print_wc_error(datagram);
612  return;
613  }
614 
615 #ifdef EC_SII_ASSIGN
617 #else
619 #endif
620 }
621 
622 /****************************************************************************/
623 
624 #ifdef EC_SII_ASSIGN
625 
630  )
631 {
632  ec_datagram_t *datagram = fsm->datagram;
633  ec_slave_t *slave = fsm->slave;
634 
636  EC_SLAVE_DBG(slave, 1, "Assigning SII access to PDI.\n");
637 
638  ec_datagram_fpwr(datagram, slave->station_address, 0x0500, 0x01);
639  EC_WRITE_U8(datagram->data, 0x01); // PDI
640  fsm->retries = EC_FSM_RETRIES;
642  }
643  else {
645  }
646 }
647 
648 /****************************************************************************/
649 
654  )
655 {
656  ec_datagram_t *datagram = fsm->datagram;
657  ec_slave_t *slave = fsm->slave;
658 
659  if (datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--) {
660  return;
661  }
662 
663  if (datagram->state != EC_DATAGRAM_RECEIVED) {
664  EC_SLAVE_WARN(slave, "Failed receive SII assignment datagram: ");
665  ec_datagram_print_state(datagram);
666  goto cont_preop;
667  }
668 
669  if (datagram->working_counter != 1) {
670  EC_SLAVE_WARN(slave, "Failed to assign SII to PDI: ");
671  ec_datagram_print_wc_error(datagram);
672  }
673 
674 cont_preop:
676 }
677 
678 #endif
679 
680 /****************************************************************************/
681 
686  )
687 {
689 
693  } else { // BOOT
695  fsm->slave, EC_SLAVE_STATE_BOOT);
696  }
697 
698  ec_fsm_change_exec(fsm->fsm_change); // execute immediately
699 }
700 
701 /****************************************************************************/
702 
707  )
708 {
709  ec_slave_t *slave = fsm->slave;
710 #ifdef EC_SII_ASSIGN
711  int assign_to_pdi;
712  ec_slave_config_t *config;
713  ec_flag_t *flag;
714 #endif
715 
716  if (ec_fsm_change_exec(fsm->fsm_change)) {
717  return;
718  }
719 
720  if (!ec_fsm_change_success(fsm->fsm_change)) {
721  if (!fsm->fsm_change->spontaneous_change)
722  slave->error_flag = 1;
724  return;
725  }
726 
727  // slave is now in BOOT or PREOP
728  slave->jiffies_preop = fsm->datagram->jiffies_received;
729 
730  EC_SLAVE_DBG(slave, 1, "Now in %s.\n",
731  slave->requested_state != EC_SLAVE_STATE_BOOT ? "PREOP" : "BOOT");
732 
733 #ifdef EC_SII_ASSIGN
734  assign_to_pdi = 0;
735  config = fsm->slave->config;
736  if (config) {
737  flag = ec_slave_config_find_flag(config, "AssignToPdi");
738  if (flag) {
739  assign_to_pdi = flag->value;
740  }
741  }
742 
743  if (assign_to_pdi) {
744  EC_SLAVE_DBG(slave, 1, "Skipping SII assignment back to EtherCAT.\n");
745  if (slave->current_state == slave->requested_state) {
746  fsm->state = ec_fsm_slave_config_state_end; // successful
747  EC_SLAVE_DBG(slave, 1, "Finished configuration.\n");
748  return;
749  }
750 
752  }
753  else {
754  EC_SLAVE_DBG(slave, 1, "Assigning SII access back to EtherCAT.\n");
755 
756  ec_datagram_fpwr(fsm->datagram, slave->station_address, 0x0500, 0x01);
757  EC_WRITE_U8(fsm->datagram->data, 0x00); // EtherCAT
758  fsm->retries = EC_FSM_RETRIES;
760  }
761 #else
762  if (slave->current_state == slave->requested_state) {
763  fsm->state = ec_fsm_slave_config_state_end; // successful
764  EC_SLAVE_DBG(slave, 1, "Finished configuration.\n");
765  return;
766  }
767 
769 #endif
770 }
771 
772 /****************************************************************************/
773 
774 #ifdef EC_SII_ASSIGN
775 
780  )
781 {
782  ec_datagram_t *datagram = fsm->datagram;
783  ec_slave_t *slave = fsm->slave;
784 
785  if (datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--) {
786  return;
787  }
788 
789  if (datagram->state != EC_DATAGRAM_RECEIVED) {
790  EC_SLAVE_WARN(slave, "Failed receive SII assignment datagram: ");
791  ec_datagram_print_state(datagram);
792  goto cont_sdo_conf;
793  }
794 
795  if (datagram->working_counter != 1) {
796  EC_SLAVE_WARN(slave, "Failed to assign SII back to EtherCAT: ");
797  ec_datagram_print_wc_error(datagram);
798  }
799 
800 cont_sdo_conf:
801  if (slave->current_state == slave->requested_state) {
802  fsm->state = ec_fsm_slave_config_state_end; // successful
803  EC_SLAVE_DBG(slave, 1, "Finished configuration.\n");
804  return;
805  }
806 
808 }
809 
810 #endif
811 
812 /****************************************************************************/
813 
818  )
819 {
820  ec_slave_t *slave = fsm->slave;
821 
822  if (!slave->config) {
824  return;
825  }
826 
827  // No CoE configuration to be applied?
828  if (list_empty(&slave->config->sdo_configs)) { // skip SDO configuration
830  return;
831  }
832 
833  // start SDO configuration
835  fsm->request = list_entry(fsm->slave->config->sdo_configs.next,
836  ec_sdo_request_t, list);
839  ec_fsm_coe_transfer(fsm->fsm_coe, fsm->slave, &fsm->request_copy);
840  ec_fsm_coe_exec(fsm->fsm_coe, fsm->datagram); // execute immediately
841 }
842 
843 /****************************************************************************/
844 
849  )
850 {
851  if (ec_fsm_coe_exec(fsm->fsm_coe, fsm->datagram)) {
852  return;
853  }
854 
855  if (!ec_fsm_coe_success(fsm->fsm_coe)) {
856  EC_SLAVE_ERR(fsm->slave, "SDO configuration failed.\n");
857  fsm->slave->error_flag = 1;
859  return;
860  }
861 
862  if (!fsm->slave->config) { // config removed in the meantime
864  return;
865  }
866 
867  // Another SDO to configure?
868  if (fsm->request->list.next != &fsm->slave->config->sdo_configs) {
869  fsm->request = list_entry(fsm->request->list.next,
870  ec_sdo_request_t, list);
873  ec_fsm_coe_transfer(fsm->fsm_coe, fsm->slave, &fsm->request_copy);
874  ec_fsm_coe_exec(fsm->fsm_coe, fsm->datagram); // execute immediately
875  return;
876  }
877 
878  // All SDOs are now configured.
880 }
881 
882 /****************************************************************************/
883 
888  )
889 {
890  ec_slave_t *slave = fsm->slave;
891  ec_soe_request_t *req;
892 
893  if (!slave->config) {
895  return;
896  }
897 
898  list_for_each_entry(req, &slave->config->soe_configs, list) {
899  if (req->al_state == EC_AL_STATE_PREOP) {
900  // start SoE configuration
902  fsm->soe_request = req;
905  ec_fsm_soe_transfer(fsm->fsm_soe, fsm->slave,
906  &fsm->soe_request_copy);
907  ec_fsm_soe_exec(fsm->fsm_soe, fsm->datagram);
908  return;
909  }
910  }
911 
912  // No SoE configuration to be applied in PREOP
914 }
915 
916 /****************************************************************************/
917 
922  )
923 {
924  ec_slave_t *slave = fsm->slave;
925 
926  if (ec_fsm_soe_exec(fsm->fsm_soe, fsm->datagram)) {
927  return;
928  }
929 
930  if (!ec_fsm_soe_success(fsm->fsm_soe)) {
931  EC_SLAVE_ERR(slave, "SoE configuration failed.\n");
932  fsm->slave->error_flag = 1;
934  return;
935  }
936 
937  if (!fsm->slave->config) { // config removed in the meantime
939  return;
940  }
941 
942  // Another IDN to configure in PREOP?
943  while (fsm->soe_request->list.next != &fsm->slave->config->soe_configs) {
944  fsm->soe_request = list_entry(fsm->soe_request->list.next,
945  ec_soe_request_t, list);
946  if (fsm->soe_request->al_state == EC_AL_STATE_PREOP) {
949  ec_fsm_soe_transfer(fsm->fsm_soe, fsm->slave,
950  &fsm->soe_request_copy);
951  ec_fsm_soe_exec(fsm->fsm_soe, fsm->datagram);
952  return;
953  }
954  }
955 
956  // All PREOP IDNs are now configured.
958 }
959 
960 /****************************************************************************/
961 
966  )
967 {
968 #ifdef EC_EOE
969  ec_slave_t *slave = fsm->slave;
970  ec_eoe_request_t *request = &slave->config->eoe_ip_param_request;
971 
972  if (ec_eoe_request_valid(request)) {
973  EC_SLAVE_DBG(slave, 1, "Setting EoE IP parameters...\n");
974 
975  // Start EoE command
977  ec_fsm_eoe_set_ip_param(fsm->fsm_eoe, slave, request);
978  ec_fsm_eoe_exec(fsm->fsm_eoe, fsm->datagram); // execute immediately
979  return;
980  }
981 #endif
982 
984 }
985 
986 /****************************************************************************/
987 
992  )
993 {
994 #ifdef EC_EOE
995  ec_slave_t *slave = fsm->slave;
996 
997  if (ec_fsm_eoe_exec(fsm->fsm_eoe, fsm->datagram)) {
998  return;
999  }
1000 
1001  if (ec_fsm_eoe_success(fsm->fsm_eoe)) {
1002  EC_SLAVE_DBG(slave, 1, "Finished setting EoE IP parameters.\n");
1003  }
1004  else {
1005  EC_SLAVE_ERR(slave, "Failed to set EoE IP parameters.\n");
1006  }
1007 #endif
1009 }
1010 
1011 /****************************************************************************/
1012 
1016  ec_fsm_slave_config_t *fsm
1017  )
1018 {
1019  // Start configuring PDOs
1022  fsm->state(fsm); // execute immediately
1023 }
1024 
1025 /****************************************************************************/
1026 
1030  ec_fsm_slave_config_t *fsm
1031  )
1032 {
1033  // TODO check for config here
1034 
1035  if (ec_fsm_pdo_exec(fsm->fsm_pdo, fsm->datagram)) {
1036  return;
1037  }
1038 
1039  if (!fsm->slave->config) { // config removed in the meantime
1041  return;
1042  }
1043 
1044  if (!ec_fsm_pdo_success(fsm->fsm_pdo)) {
1045  EC_SLAVE_WARN(fsm->slave, "PDO configuration failed.\n");
1046  }
1047 
1049 }
1050 
1051 /****************************************************************************/
1052 
1056  ec_fsm_slave_config_t *fsm
1057  )
1058 {
1059  ec_slave_t *slave = fsm->slave;
1060  ec_datagram_t *datagram = fsm->datagram;
1061  ec_slave_config_t *config = slave->config;
1062 
1063  if (config && config->watchdog_divider) {
1064  EC_SLAVE_DBG(slave, 1, "Setting watchdog divider to %u.\n",
1065  config->watchdog_divider);
1066 
1067  ec_datagram_fpwr(datagram, slave->station_address, 0x0400, 2);
1068  EC_WRITE_U16(datagram->data, config->watchdog_divider);
1069  fsm->retries = EC_FSM_RETRIES;
1071  } else {
1073  }
1074 }
1075 
1076 /****************************************************************************/
1077 
1081  ec_fsm_slave_config_t *fsm
1082  )
1083 {
1084  ec_datagram_t *datagram = fsm->datagram;
1085  ec_slave_t *slave = fsm->slave;
1086 
1087  if (datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--)
1088  return;
1089 
1090  if (datagram->state != EC_DATAGRAM_RECEIVED) {
1092  EC_SLAVE_ERR(slave, "Failed to receive watchdog divider"
1093  " configuration datagram: ");
1094  ec_datagram_print_state(datagram);
1095  return;
1096  }
1097 
1098  if (datagram->working_counter != 1) {
1099  slave->error_flag = 1;
1100  EC_SLAVE_WARN(slave, "Failed to set watchdog divider: ");
1101  ec_datagram_print_wc_error(datagram);
1102  return;
1103  }
1104 
1106 }
1107 
1108 /****************************************************************************/
1109 
1113  ec_fsm_slave_config_t *fsm
1114  )
1115 {
1116  ec_datagram_t *datagram = fsm->datagram;
1117  ec_slave_t *slave = fsm->slave;
1118  ec_slave_config_t *config = slave->config;
1119 
1120  if (config && config->watchdog_intervals) {
1121  EC_SLAVE_DBG(slave, 1, "Setting process data"
1122  " watchdog intervals to %u.\n", config->watchdog_intervals);
1123 
1124  ec_datagram_fpwr(datagram, slave->station_address, 0x0420, 2);
1125  EC_WRITE_U16(datagram->data, config->watchdog_intervals);
1126 
1127  fsm->retries = EC_FSM_RETRIES;
1129  } else {
1131  }
1132 }
1133 
1134 /****************************************************************************/
1135 
1140  ec_fsm_slave_config_t *fsm
1141  )
1142 {
1143  ec_datagram_t *datagram = fsm->datagram;
1144  ec_slave_t *slave = fsm->slave;
1145 
1146  if (datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--)
1147  return;
1148 
1149  if (datagram->state != EC_DATAGRAM_RECEIVED) {
1151  EC_SLAVE_ERR(slave, "Failed to receive sync manager"
1152  " watchdog configuration datagram: ");
1153  ec_datagram_print_state(datagram);
1154  return;
1155  }
1156 
1157  if (datagram->working_counter != 1) {
1158  EC_SLAVE_WARN(slave, "Failed to set process data"
1159  " watchdog intervals: ");
1160  ec_datagram_print_wc_error(datagram);
1161  }
1162 
1164 }
1165 
1166 /****************************************************************************/
1167 
1171  ec_fsm_slave_config_t *fsm
1172  )
1173 {
1174  ec_slave_t *slave = fsm->slave;
1175  ec_datagram_t *datagram = fsm->datagram;
1176  unsigned int i, j, offset, num_pdo_syncs;
1177  uint8_t sync_index;
1178  const ec_sync_t *sync;
1179  uint16_t size;
1180 
1181  if (slave->sii.mailbox_protocols) {
1182  offset = 2; // slave has mailboxes
1183  } else {
1184  offset = 0;
1185  }
1186 
1187  if (slave->sii.sync_count <= offset) {
1188  // no PDO sync managers to configure
1190  return;
1191  }
1192 
1193  num_pdo_syncs = slave->sii.sync_count - offset;
1194 
1195  // configure sync managers for process data
1196  ec_datagram_fpwr(datagram, slave->station_address,
1197  0x0800 + EC_SYNC_PAGE_SIZE * offset,
1198  EC_SYNC_PAGE_SIZE * num_pdo_syncs);
1199  ec_datagram_zero(datagram);
1200 
1201  for (i = 0; i < num_pdo_syncs; i++) {
1202  const ec_sync_config_t *sync_config;
1203  uint8_t pdo_xfer = 0;
1204  sync_index = i + offset;
1205  sync = &slave->sii.syncs[sync_index];
1206 
1207  if (slave->config) {
1208  const ec_slave_config_t *sc = slave->config;
1209  sync_config = &sc->sync_configs[sync_index];
1210  size = ec_pdo_list_total_size(&sync_config->pdos);
1211 
1212  // determine, if PDOs shall be transferred via this SM
1213  // inthat case, enable sync manager in every case
1214  for (j = 0; j < sc->used_fmmus; j++) {
1215  if (sc->fmmu_configs[j].sync_index == sync_index) {
1216  pdo_xfer = 1;
1217  break;
1218  }
1219  }
1220 
1221  } else {
1222  sync_config = NULL;
1223  size = sync->default_length;
1224  }
1225 
1226  ec_sync_page(sync, sync_index, size, sync_config, pdo_xfer,
1227  datagram->data + EC_SYNC_PAGE_SIZE * i);
1228  }
1229 
1230  fsm->retries = EC_FSM_RETRIES;
1232 }
1233 
1234 /****************************************************************************/
1235 
1239  ec_fsm_slave_config_t *fsm
1240  )
1241 {
1242  ec_datagram_t *datagram = fsm->datagram;
1243  ec_slave_t *slave = fsm->slave;
1244 
1245  if (datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--)
1246  return;
1247 
1248  if (datagram->state != EC_DATAGRAM_RECEIVED) {
1250  EC_SLAVE_ERR(slave, "Failed to receive process data sync"
1251  " manager configuration datagram: ");
1252  ec_datagram_print_state(datagram);
1253  return;
1254  }
1255 
1256  if (datagram->working_counter != 1) {
1257  slave->error_flag = 1;
1259  EC_SLAVE_ERR(slave, "Failed to set process data sync managers: ");
1260  ec_datagram_print_wc_error(datagram);
1261  return;
1262  }
1263 
1265 }
1266 
1267 /****************************************************************************/
1268 
1272  ec_fsm_slave_config_t *fsm
1273  )
1274 {
1275  ec_slave_t *slave = fsm->slave;
1276  ec_datagram_t *datagram = fsm->datagram;
1277  unsigned int i;
1278  const ec_fmmu_config_t *fmmu;
1279  const ec_sync_t *sync;
1280 
1281  if (!slave->config) {
1283  return;
1284  }
1285 
1286  if (slave->base_fmmu_count < slave->config->used_fmmus) {
1287  slave->error_flag = 1;
1289  EC_SLAVE_ERR(slave, "Slave has less FMMUs (%u)"
1290  " than requested (%u).\n", slave->base_fmmu_count,
1291  slave->config->used_fmmus);
1292  return;
1293  }
1294 
1295  if (!slave->base_fmmu_count) { // skip FMMU configuration
1297  return;
1298  }
1299 
1300  // configure FMMUs
1301  ec_datagram_fpwr(datagram, slave->station_address,
1302  0x0600, EC_FMMU_PAGE_SIZE * slave->base_fmmu_count);
1303  ec_datagram_zero(datagram);
1304  for (i = 0; i < slave->config->used_fmmus; i++) {
1305  fmmu = &slave->config->fmmu_configs[i];
1306  if (!(sync = ec_slave_get_sync(slave, fmmu->sync_index))) {
1307  slave->error_flag = 1;
1309  EC_SLAVE_ERR(slave, "Failed to determine PDO sync manager"
1310  " for FMMU!\n");
1311  return;
1312  }
1313  ec_fmmu_config_page(fmmu, sync,
1314  datagram->data + EC_FMMU_PAGE_SIZE * i);
1315  }
1316 
1317  fsm->retries = EC_FSM_RETRIES;
1319 }
1320 
1321 /****************************************************************************/
1322 
1326  ec_fsm_slave_config_t *fsm
1327  )
1328 {
1329  ec_datagram_t *datagram = fsm->datagram;
1330  ec_slave_t *slave = fsm->slave;
1331 
1332  if (datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--)
1333  return;
1334 
1335  if (datagram->state != EC_DATAGRAM_RECEIVED) {
1337  EC_SLAVE_ERR(slave, "Failed to receive FMMUs datagram: ");
1338  ec_datagram_print_state(datagram);
1339  return;
1340  }
1341 
1342  if (datagram->working_counter != 1) {
1343  slave->error_flag = 1;
1345  EC_SLAVE_ERR(slave, "Failed to set FMMUs: ");
1346  ec_datagram_print_wc_error(datagram);
1347  return;
1348  }
1349 
1351 }
1352 
1353 /****************************************************************************/
1354 
1358  ec_fsm_slave_config_t *fsm
1359  )
1360 {
1361  ec_datagram_t *datagram = fsm->datagram;
1362  ec_slave_t *slave = fsm->slave;
1363  ec_slave_config_t *config = slave->config;
1364 
1365  if (!config) { // config removed in the meantime
1367  return;
1368  }
1369 
1370  if (config->dc_assign_activate) {
1371  if (!slave->base_dc_supported || !slave->has_dc_system_time) {
1372  EC_SLAVE_WARN(slave, "Slave seems not to support"
1373  " distributed clocks!\n");
1374  }
1375 
1376  EC_SLAVE_DBG(slave, 1, "Setting DC cycle times to %u / %u.\n",
1377  config->dc_sync[0].cycle_time, config->dc_sync[1].cycle_time);
1378 
1379  // set DC cycle times
1380  ec_datagram_fpwr(datagram, slave->station_address, 0x09A0, 8);
1381  EC_WRITE_U32(datagram->data, config->dc_sync[0].cycle_time);
1382  EC_WRITE_U32(datagram->data + 4, config->dc_sync[1].cycle_time);
1383  fsm->retries = EC_FSM_RETRIES;
1385  } else {
1386  // DC are unused
1388  }
1389 }
1390 
1391 /****************************************************************************/
1392 
1396  ec_fsm_slave_config_t *fsm
1397  )
1398 {
1399  ec_datagram_t *datagram = fsm->datagram;
1400  ec_slave_t *slave = fsm->slave;
1401  ec_slave_config_t *config = slave->config;
1402 
1403  if (!config) { // config removed in the meantime
1405  return;
1406  }
1407 
1408  if (datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--)
1409  return;
1410 
1411  if (datagram->state != EC_DATAGRAM_RECEIVED) {
1413  EC_SLAVE_ERR(slave, "Failed to receive DC cycle times datagram: ");
1414  ec_datagram_print_state(datagram);
1415  return;
1416  }
1417 
1418  if (datagram->working_counter != 1) {
1419  slave->error_flag = 1;
1421  EC_SLAVE_ERR(slave, "Failed to set DC cycle times: ");
1422  ec_datagram_print_wc_error(datagram);
1423  return;
1424  }
1425 
1426  EC_SLAVE_DBG(slave, 1, "Checking for synchrony.\n");
1427 
1428  fsm->jiffies_start = jiffies;
1429  ec_datagram_fprd(datagram, slave->station_address, 0x092c, 4);
1430  fsm->retries = EC_FSM_RETRIES;
1432 }
1433 
1434 /****************************************************************************/
1435 
1439  ec_fsm_slave_config_t *fsm
1440  )
1441 {
1442  ec_datagram_t *datagram = fsm->datagram;
1443  ec_slave_t *slave = fsm->slave;
1444  ec_master_t *master = slave->master;
1445  ec_slave_config_t *config = slave->config;
1446  uint32_t abs_sync_diff;
1447  unsigned long diff_ms;
1448  ec_sync_signal_t *sync0 = &config->dc_sync[0];
1449  ec_sync_signal_t *sync1 = &config->dc_sync[1];
1450  u64 start_time;
1451 
1452  if (!config) { // config removed in the meantime
1454  return;
1455  }
1456 
1457  if (datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--)
1458  return;
1459 
1460  if (datagram->state != EC_DATAGRAM_RECEIVED) {
1462  EC_SLAVE_ERR(slave, "Failed to receive DC sync check datagram: ");
1463  ec_datagram_print_state(datagram);
1464  return;
1465  }
1466 
1467  if (datagram->working_counter != 1) {
1468  slave->error_flag = 1;
1470  EC_SLAVE_ERR(slave, "Failed to check DC synchrony: ");
1471  ec_datagram_print_wc_error(datagram);
1472  return;
1473  }
1474 
1475  abs_sync_diff = EC_READ_U32(datagram->data) & 0x7fffffff;
1476  diff_ms = (datagram->jiffies_received - fsm->jiffies_start) * 1000 / HZ;
1477 
1478  if (abs_sync_diff > EC_DC_MAX_SYNC_DIFF_NS) {
1479 
1480  if (diff_ms >= EC_DC_SYNC_WAIT_MS) {
1481  EC_SLAVE_WARN(slave, "Slave did not sync after %lu ms.\n",
1482  diff_ms);
1483  } else {
1484  EC_SLAVE_DBG(slave, 1, "Sync after %4lu ms: %10u ns\n",
1485  diff_ms, abs_sync_diff);
1486 
1487  // check synchrony again
1488  ec_datagram_fprd(datagram, slave->station_address, 0x092c, 4);
1489  fsm->retries = EC_FSM_RETRIES;
1490  return;
1491  }
1492  } else {
1493  EC_SLAVE_DBG(slave, 1, "%u ns difference after %lu ms.\n",
1494  abs_sync_diff, diff_ms);
1495  }
1496 
1497  // set DC start time (roughly in the future, not in-phase)
1498  start_time = master->app_time + EC_DC_START_OFFSET; // now + X ns
1499 
1500  if (sync0->cycle_time) {
1501  // find correct phase
1502  if (master->dc_ref_time) {
1503  u64 diff, start;
1504  u32 remainder, cycle;
1505 
1506  diff = start_time - master->dc_ref_time;
1507  cycle = sync0->cycle_time + sync1->cycle_time;
1508  remainder = do_div(diff, cycle);
1509 
1510  start = start_time + cycle - remainder + sync0->shift_time;
1511 
1512  EC_SLAVE_DBG(slave, 1, " ref_time=%llu\n", master->dc_ref_time);
1513  EC_SLAVE_DBG(slave, 1, " app_time=%llu\n", master->app_time);
1514  EC_SLAVE_DBG(slave, 1, " start_time=%llu\n", start_time);
1515  EC_SLAVE_DBG(slave, 1, " cycle=%u\n", cycle);
1516  EC_SLAVE_DBG(slave, 1, " shift_time=%i\n", sync0->shift_time);
1517  EC_SLAVE_DBG(slave, 1, " remainder=%u\n", remainder);
1518  EC_SLAVE_DBG(slave, 1, " start=%llu\n", start);
1519  start_time = start;
1520  } else {
1521  EC_SLAVE_WARN(slave, "No application time supplied."
1522  " Cyclic start time will not be in phase.\n");
1523  }
1524  }
1525 
1526  EC_SLAVE_DBG(slave, 1, "Setting DC cyclic operation"
1527  " start time to %llu.\n", start_time);
1528 
1529  ec_datagram_fpwr(datagram, slave->station_address, 0x0990, 8);
1530  EC_WRITE_U64(datagram->data, start_time);
1531  fsm->retries = EC_FSM_RETRIES;
1533 }
1534 
1535 /****************************************************************************/
1536 
1540  ec_fsm_slave_config_t *fsm
1541  )
1542 {
1543  ec_datagram_t *datagram = fsm->datagram;
1544  ec_slave_t *slave = fsm->slave;
1545  ec_slave_config_t *config = slave->config;
1546 
1547  if (!config) { // config removed in the meantime
1549  return;
1550  }
1551 
1552  if (datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--)
1553  return;
1554 
1555  if (datagram->state != EC_DATAGRAM_RECEIVED) {
1557  EC_SLAVE_ERR(slave, "Failed to receive DC start time datagram: ");
1558  ec_datagram_print_state(datagram);
1559  return;
1560  }
1561 
1562  if (datagram->working_counter != 1) {
1563  slave->error_flag = 1;
1565  EC_SLAVE_ERR(slave, "Failed to set DC start time: ");
1566  ec_datagram_print_wc_error(datagram);
1567  return;
1568  }
1569 
1570  EC_SLAVE_DBG(slave, 1, "Setting DC AssignActivate to 0x%04x.\n",
1571  config->dc_assign_activate);
1572 
1573  // assign sync unit to EtherCAT or PDI
1574  ec_datagram_fpwr(datagram, slave->station_address, 0x0980, 2);
1575  EC_WRITE_U16(datagram->data, config->dc_assign_activate);
1576  fsm->retries = EC_FSM_RETRIES;
1578 }
1579 
1580 /****************************************************************************/
1581 
1585  ec_fsm_slave_config_t *fsm
1586  )
1587 {
1588  ec_datagram_t *datagram = fsm->datagram;
1589  ec_slave_t *slave = fsm->slave;
1590 
1591  if (datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--)
1592  return;
1593 
1594  if (datagram->state != EC_DATAGRAM_RECEIVED) {
1596  EC_SLAVE_ERR(slave, "Failed to receive DC activation datagram: ");
1597  ec_datagram_print_state(datagram);
1598  return;
1599  }
1600 
1601  if (datagram->working_counter != 1) {
1602  slave->error_flag = 1;
1604  EC_SLAVE_ERR(slave, "Failed to activate DC: ");
1605  ec_datagram_print_wc_error(datagram);
1606  return;
1607  }
1608 
1610 }
1611 
1612 /****************************************************************************/
1613 
1621  ec_fsm_slave_config_t *fsm
1622  )
1623 {
1624  ec_slave_config_t *config = fsm->slave->config;
1625  fsm->wait_ms = 0UL;
1626  if (config) {
1627  ec_flag_t *flag = ec_slave_config_find_flag(config,
1628  "WaitBeforeSAFEOPms");
1629  if (flag && flag->value > 0) {
1630  fsm->wait_ms = (unsigned long) flag->value;
1631  }
1632  }
1633 
1634  if (fsm->wait_ms > 0) {
1636 
1637  /* dummy read */
1639  0x0600, 1);
1640 
1641  fsm->jiffies_start = jiffies;
1642  }
1643  else {
1645  }
1646 }
1647 
1648 /****************************************************************************/
1649 
1653  ec_fsm_slave_config_t *fsm
1654  )
1655 {
1656  unsigned long diff = jiffies - fsm->jiffies_start;
1657 
1658  if (diff * 1000 / HZ < fsm->wait_ms) {
1659  return;
1660  }
1661 
1663 }
1664 
1665 /****************************************************************************/
1666 
1670  ec_fsm_slave_config_t *fsm
1671  )
1672 {
1675  ec_fsm_change_exec(fsm->fsm_change); // execute immediately
1676 }
1677 
1678 /****************************************************************************/
1679 
1683  ec_fsm_slave_config_t *fsm
1684  )
1685 {
1686  ec_slave_t *slave = fsm->slave;
1687 
1688  if (ec_fsm_change_exec(fsm->fsm_change)) return;
1689 
1690  if (!ec_fsm_change_success(fsm->fsm_change)) {
1691  if (!fsm->fsm_change->spontaneous_change)
1692  fsm->slave->error_flag = 1;
1694  return;
1695  }
1696 
1697  // slave is now in SAFEOP
1698 
1699  EC_SLAVE_DBG(slave, 1, "Now in SAFEOP.\n");
1700 
1701  if (fsm->slave->current_state == fsm->slave->requested_state) {
1702  fsm->state = ec_fsm_slave_config_state_end; // successful
1703  EC_SLAVE_DBG(slave, 1, "Finished configuration.\n");
1704  return;
1705  }
1706 
1708 }
1709 
1710 /****************************************************************************/
1711 
1715  ec_fsm_slave_config_t *fsm
1716  )
1717 {
1718  ec_slave_t *slave = fsm->slave;
1719  ec_soe_request_t *req;
1720 
1721  if (!slave->config) {
1723  return;
1724  }
1725 
1726  list_for_each_entry(req, &slave->config->soe_configs, list) {
1727  if (req->al_state == EC_AL_STATE_SAFEOP) {
1728  // start SoE configuration
1730  fsm->soe_request = req;
1733  ec_fsm_soe_transfer(fsm->fsm_soe, fsm->slave,
1734  &fsm->soe_request_copy);
1735  ec_fsm_soe_exec(fsm->fsm_soe, fsm->datagram);
1736  return;
1737  }
1738  }
1739 
1740  // No SoE configuration to be applied in SAFEOP
1742 }
1743 
1744 /****************************************************************************/
1745 
1749  ec_fsm_slave_config_t *fsm
1750  )
1751 {
1752  ec_slave_t *slave = fsm->slave;
1753 
1754  if (ec_fsm_soe_exec(fsm->fsm_soe, fsm->datagram)) {
1755  return;
1756  }
1757 
1758  if (!ec_fsm_soe_success(fsm->fsm_soe)) {
1759  EC_SLAVE_ERR(slave, "SoE configuration failed.\n");
1760  fsm->slave->error_flag = 1;
1762  return;
1763  }
1764 
1765  if (!fsm->slave->config) { // config removed in the meantime
1767  return;
1768  }
1769 
1770  // Another IDN to configure in SAFEOP?
1771  while (fsm->soe_request->list.next != &fsm->slave->config->soe_configs) {
1772  fsm->soe_request = list_entry(fsm->soe_request->list.next,
1773  ec_soe_request_t, list);
1774  if (fsm->soe_request->al_state == EC_AL_STATE_SAFEOP) {
1777  ec_fsm_soe_transfer(fsm->fsm_soe, fsm->slave,
1778  &fsm->soe_request_copy);
1779  ec_fsm_soe_exec(fsm->fsm_soe, fsm->datagram);
1780  return;
1781  }
1782  }
1783 
1784  // All SAFEOP IDNs are now configured.
1786 }
1787 
1788 /****************************************************************************/
1789 
1793  ec_fsm_slave_config_t *fsm
1794  )
1795 {
1796  // set state to OP
1799  ec_fsm_change_exec(fsm->fsm_change); // execute immediately
1800 }
1801 
1802 /****************************************************************************/
1803 
1807  ec_fsm_slave_config_t *fsm
1808  )
1809 {
1810  ec_slave_t *slave = fsm->slave;
1811 
1812  if (ec_fsm_change_exec(fsm->fsm_change)) return;
1813 
1814  if (!ec_fsm_change_success(fsm->fsm_change)) {
1815  if (!fsm->fsm_change->spontaneous_change)
1816  slave->error_flag = 1;
1818  return;
1819  }
1820 
1821  // slave is now in OP
1822 
1823  EC_SLAVE_DBG(slave, 1, "Now in OP. Finished configuration.\n");
1824 
1825  fsm->state = ec_fsm_slave_config_state_end; // successful
1826 }
1827 
1828 /****************************************************************************/
1829 
1833  ec_fsm_slave_config_t *fsm
1834  )
1835 {
1836  EC_SLAVE_DBG(fsm->slave, 1, "Slave configuration detached during "
1837  "configuration. Reconfiguring.");
1838 
1839  ec_fsm_slave_config_enter_init(fsm); // reconfigure
1840 }
1841 
1842 /*****************************************************************************
1843  * Common state functions
1844  ****************************************************************************/
1845 
1849  ec_fsm_slave_config_t *fsm
1850  )
1851 {
1852 }
1853 
1854 /****************************************************************************/
1855 
1859  ec_fsm_slave_config_t *fsm
1860  )
1861 {
1862 }
1863 
1864 /****************************************************************************/
#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:43
int ec_fsm_eoe_exec(ec_fsm_eoe_t *fsm, ec_datagram_t *datagram)
Executes the current state of the state machine.
Definition: fsm_eoe.c:121
unsigned long jiffies_sent
Jiffies, when the datagram was sent.
Definition: datagram.h:98
Pre-operational.
Definition: ecrt.h:617
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:136
uint16_t boot_rx_mailbox_offset
Bootstrap receive mailbox address.
Definition: slave.h:131
#define EC_SYNC_PAGE_SIZE
Size of a sync manager configuration page.
Definition: globals.h:89
ec_sii_t sii
Extracted SII data.
Definition: slave.h:215
int ec_fsm_pdo_exec(ec_fsm_pdo_t *fsm, ec_datagram_t *datagram)
Executes the current state of the state machine.
Definition: fsm_pdo.c:164
void ec_fsm_slave_config_start(ec_fsm_slave_config_t *fsm, ec_slave_t *slave)
Start slave configuration state machine.
uint8_t spontaneous_change
spontaneous state change detected
Definition: fsm_change.h:68
void ec_fsm_slave_config_enter_watchdog(ec_fsm_slave_config_t *)
WATCHDOG entry function.
int ecrt_sdo_request_write(ec_sdo_request_t *req)
Schedule an SDO write operation.
Definition: sdo_request.c:232
uint16_t configured_tx_mailbox_size
Configured send mailbox size.
Definition: slave.h:193
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:38
ec_sdo_request_t * request
SDO request for SDO configuration.
void ec_fsm_slave_config_state_wait_safeop(ec_fsm_slave_config_t *)
Slave configuration state: WAIT SAFEOP.
void ec_fsm_slave_config_reconfigure(ec_fsm_slave_config_t *)
Reconfigure the slave starting at INIT.
#define EC_SLAVE_DBG(slave, level, fmt, args...)
Convenience macro for printing slave-specific debug messages to syslog.
Definition: slave.h:98
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:182
void ec_fsm_slave_config_enter_eoe_ip_param(ec_fsm_slave_config_t *)
EOE_IP_PARAM entry function.
OP (mailbox communication and input/output update)
Definition: globals.h:132
uint16_t configured_tx_mailbox_offset
Configured send mailbox offset.
Definition: slave.h:191
void ec_fsm_slave_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:40
ec_slave_state_t current_state
Current application state.
Definition: slave.h:184
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:132
Safe-operational.
Definition: ecrt.h:618
#define EC_SLAVE_WARN(slave, fmt, args...)
Convenience macro for printing slave-specific warnings to syslog.
Definition: slave.h:82
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:79
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:3137
u64 dc_ref_time
Common reference timestamp for DC start times.
Definition: master.h:228
Bootstrap state (mailbox communication, firmware update)
Definition: globals.h:128
void ec_fsm_slave_config_state_soe_conf_preop(ec_fsm_slave_config_t *)
Slave configuration state: SOE_CONF.
ec_eoe_request_t eoe_ip_param_request
EoE IP parameters.
Definition: slave_config.h:146
uint32_t cycle_time
Cycle time [ns].
Definition: globals.h:181
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:123
uint16_t working_counter
Working counter.
Definition: datagram.h:93
int ec_fsm_coe_success(const ec_fsm_coe_t *fsm)
Returns, if the state machine terminated with success.
Definition: fsm_coe.c:267
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:134
Sent (still in the queue).
Definition: datagram.h:69
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:68
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:176
int ec_soe_request_write(ec_soe_request_t *req)
Request a write operation.
Definition: soe_request.c:241
unsigned int sync_count
Number of sync managers.
Definition: slave.h:158
ec_fsm_eoe_t * fsm_eoe
EoE state machine.
ec_sdo_request_t request_copy
Copied SDO request.
uint16_t std_rx_mailbox_size
Standard receive mailbox size.
Definition: slave.h:136
void ec_fsm_eoe_set_ip_param(ec_fsm_eoe_t *fsm, ec_slave_t *slave, ec_eoe_request_t *request)
Starts to set the EoE IP partameters of a slave.
Definition: fsm_eoe.c:104
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:86
Global definitions and macros.
uint16_t std_tx_mailbox_offset
Standard transmit mailbox address.
Definition: slave.h:137
ec_al_state_t al_state
AL state (only valid for IDN config).
Definition: soe_request.h:44
EtherCAT master structure.
ec_fmmu_config_t fmmu_configs[EC_MAX_FMMUS]
FMMU configurations.
Definition: slave_config.h:131
SAFEOP (mailbox communication and input update)
Definition: globals.h:130
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:134
uint16_t boot_tx_mailbox_offset
Bootstrap transmit mailbox address.
Definition: slave.h:133
void ec_fsm_slave_config_state_assign_pdi(ec_fsm_slave_config_t *)
Slave configuration state: ASSIGN_PDI.
EtherCAT slave.
Definition: slave.h:168
int ec_eoe_request_valid(const ec_eoe_request_t *req)
Checks if EoE request has something to set.
Definition: eoe_request.c:67
void ec_sdo_request_clear(ec_sdo_request_t *req)
SDO request destructor.
Definition: sdo_request.c:70
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:79
void ec_datagram_zero(ec_datagram_t *datagram)
Fills the datagram payload memory with zeros.
Definition: datagram.c:170
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:130
int ec_fsm_soe_success(const ec_fsm_soe_t *fsm)
Returns, if the state machine terminated with success.
Definition: fsm_soe.c:187
ec_sync_config_t sync_configs[EC_MAX_SYNC_MANAGERS]
Sync manager configurations.
Definition: slave_config.h:129
ec_datagram_state_t state
State.
Definition: datagram.h:94
ec_slave_config_t * config
Current configuration.
Definition: slave.h:182
#define EC_WRITE_U32(DATA, VAL)
Write a 32-bit unsigned value to EtherCAT data.
Definition: ecrt.h:3171
uint8_t sync_index
Index of sync manager to use.
Definition: fmmu_config.h:42
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:139
ec_flag_t * ec_slave_config_find_flag(ec_slave_config_t *sc, const char *key)
Finds a flag.
Definition: slave_config.c:638
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 *)
#define EC_SLAVE_ERR(slave, fmt, args...)
Convenience macro for printing slave-specific errors to syslog.
Definition: slave.h:68
void ec_datagram_print_wc_error(const ec_datagram_t *datagram)
Evaluates the working counter of a single-cast datagram.
Definition: datagram.c:594
#define EC_DC_START_OFFSET
Time offset (in ns), that is added to cyclic start time.
Sync manager.
Definition: sync.h:39
uint16_t std_rx_mailbox_offset
Standard receive mailbox address.
Definition: slave.h:135
int ec_fsm_change_exec(ec_fsm_change_t *fsm)
Executes the current state of the state machine.
Definition: fsm_change.c:157
struct list_head list
List item.
Definition: soe_request.h:41
void ec_soe_request_clear(ec_soe_request_t *req)
SoE request destructor.
Definition: soe_request.c:71
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:41
uint16_t dc_assign_activate
Vendor-specific AssignActivate word.
Definition: slave_config.h:133
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:3154
uint8_t base_fmmu_count
Number of supported FMMUs.
Definition: slave.h:199
uint16_t configured_rx_mailbox_offset
Configured receive mailbox offset.
Definition: slave.h:187
int ec_fsm_eoe_success(const ec_fsm_eoe_t *fsm)
Returns, if the state machine terminated with success.
Definition: fsm_eoe.c:156
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:3061
unsigned long wait_ms
Wait time (used to wait before SAFEOP).
uint16_t watchdog_intervals
Process data watchdog intervals (see spec.
Definition: slave_config.h:123
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:170
int ec_sdo_request_copy(ec_sdo_request_t *req, const ec_sdo_request_t *other)
Copy another SDO request.
Definition: sdo_request.c:85
void ec_fsm_slave_config_enter_soe_conf_preop(ec_fsm_slave_config_t *)
Check for SoE configurations to be applied.
void(* state)(ec_fsm_slave_config_t *)
State function.
int ec_datagram_fpwr(ec_datagram_t *datagram, uint16_t configured_address, uint16_t mem_address, size_t data_size)
Initializes an EtherCAT FPWR datagram.
Definition: datagram.c:290
uint8_t has_dc_system_time
The slave supports the DC system time register.
Definition: slave.h:204
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:265
uint8_t control_register
Control register value.
Definition: sync.h:43
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:121
PDO configuration state machine.
Definition: fsm_pdo.h:46
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, ec_fsm_eoe_t *fsm_eoe)
Constructor.
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:141
void ec_fsm_slave_config_enter_pdo_conf(ec_fsm_slave_config_t *)
PDO_CONF entry function.
Ethernet-over-EtherCAT set IP parameter request.
Definition: eoe_request.h:41
unsigned int take_time
Store jiffies after datagram reception.
void ec_fsm_slave_config_state_eoe_ip_param(ec_fsm_slave_config_t *)
Slave configuration state: EOE_IP_PARAM.
INIT state (no mailbox communication, no IO)
Definition: globals.h:124
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:557
Mailbox functionality.
uint8_t enable
Enable bit.
Definition: sync.h:44
ec_slave_t * slave
Slave the FSM runs on.
Invalid direction.
Definition: ecrt.h:505
void ec_sdo_request_init(ec_sdo_request_t *req)
SDO request constructor.
Definition: sdo_request.c:48
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:3188
uint16_t boot_rx_mailbox_size
Bootstrap receive mailbox size.
Definition: slave.h:132
ec_soe_request_t soe_request_copy
Copied SDO request.
Sync manager configuration.
Definition: sync_config.h:38
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:41
EtherCAT slave sync signal configuration.
Definition: globals.h:180
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:233
void ec_fsm_slave_config_state_clear_sync(ec_fsm_slave_config_t *)
Slave configuration state: CLEAR SYNC.
Queued for sending.
Definition: datagram.h:68
Timed out (dequeued).
Definition: datagram.h:71
void ec_fsm_slave_config_enter_wait_safeop(ec_fsm_slave_config_t *)
Wait before SAFEOP transition.
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:227
uint16_t physical_start_address
Physical start address.
Definition: sync.h:41
unsigned long jiffies_preop
Time, the slave went to PREOP.
Definition: slave.h:219
uint16_t configured_rx_mailbox_size
Configured receive mailbox size.
Definition: slave.h:189
uint8_t base_dc_supported
Distributed clocks are supported.
Definition: slave.h:202
uint8_t * data
Datagram payload.
Definition: datagram.h:88
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:200
void ec_fsm_slave_config_enter_op(ec_fsm_slave_config_t *)
Bring slave to OP.
EtherCAT slave configuration.
Definition: slave_config.h:111
ec_soe_request_t * soe_request
SDO request for SDO configuration.
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:48
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:152
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:210
uint16_t default_length
Data length in bytes.
Definition: sync.h:42
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:126
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:70
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:185
ec_sync_t * syncs
SYNC MANAGER categories.
Definition: slave.h:157
uint16_t std_tx_mailbox_size
Standard transmit mailbox size.
Definition: slave.h:138
EtherCAT master.
Definition: master.h:187
ec_slave_state_t requested_state
Requested application state.
Definition: slave.h:183
#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:38
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.
Sercos-over-EtherCAT request.
Definition: soe_request.h:40
unsigned long jiffies_received
Jiffies, when the datagram was received.
Definition: datagram.h:102
EtherCAT state change FSM.
Definition: fsm_change.h:56
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:84
int ec_fsm_change_success(ec_fsm_change_t *fsm)
Returns, if the state machine terminated with success.
Definition: fsm_change.c:172
Finite state machines for the Ethernet over EtherCAT protocol.
Definition: fsm_eoe.h:43
unsigned long jiffies_start
For timeout calculations.
Finite state machines for the CANopen over EtherCAT protocol.
Definition: fsm_coe.h:44
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:600
unsigned int retries
Retries on datagram timeout.