IgH EtherCAT Master  1.5.2
fsm_master.c
Go to the documentation of this file.
1 /******************************************************************************
2  *
3  * $Id$
4  *
5  * Copyright (C) 2006-2012 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 
34 /*****************************************************************************/
35 
36 #include "globals.h"
37 #include "master.h"
38 #include "mailbox.h"
39 #include "slave_config.h"
40 #ifdef EC_EOE
41 #include "ethernet.h"
42 #endif
43 
44 #include "fsm_master.h"
45 #include "fsm_foe.h"
46 
47 /*****************************************************************************/
48 
51 #define EC_SYSTEM_TIME_TOLERANCE_NS 1000
52 
53 /*****************************************************************************/
54 
58 #ifdef EC_LOOP_CONTROL
59 void ec_fsm_master_state_read_dl_status(ec_fsm_master_t *);
60 void ec_fsm_master_state_open_port(ec_fsm_master_t *);
61 #endif
64 #ifdef EC_LOOP_CONTROL
65 void ec_fsm_master_state_loop_control(ec_fsm_master_t *);
66 #endif
74 
78 
79 /*****************************************************************************/
80 
84  ec_fsm_master_t *fsm,
85  ec_master_t *master,
86  ec_datagram_t *datagram
87  )
88 {
89  fsm->master = master;
90  fsm->datagram = datagram;
91 
93 
94  // init sub-state-machines
96  ec_fsm_sii_init(&fsm->fsm_sii);
97 }
98 
99 /*****************************************************************************/
100 
104  ec_fsm_master_t *fsm
105  )
106 {
107  // clear sub-state machines
109  ec_fsm_sii_clear(&fsm->fsm_sii);
110 }
111 
112 /*****************************************************************************/
113 
117  ec_fsm_master_t *fsm
118  )
119 {
120  ec_device_index_t dev_idx;
121 
123  fsm->idle = 0;
124  fsm->dev_idx = EC_DEVICE_MAIN;
125 
126  for (dev_idx = EC_DEVICE_MAIN;
127  dev_idx < ec_master_num_devices(fsm->master); dev_idx++) {
128  fsm->link_state[dev_idx] = 0;
129  fsm->slaves_responding[dev_idx] = 0;
130  fsm->slave_states[dev_idx] = EC_SLAVE_STATE_UNKNOWN;
131  }
132 
133  fsm->rescan_required = 0;
134 }
135 
136 /*****************************************************************************/
137 
146  ec_fsm_master_t *fsm
147  )
148 {
149  if (fsm->datagram->state == EC_DATAGRAM_SENT
150  || fsm->datagram->state == EC_DATAGRAM_QUEUED) {
151  // datagram was not sent or received yet.
152  return 0;
153  }
154 
155  fsm->state(fsm);
156  return 1;
157 }
158 
159 /*****************************************************************************/
160 
165  const ec_fsm_master_t *fsm
166  )
167 {
168  return fsm->idle;
169 }
170 
171 /*****************************************************************************/
172 
176  ec_fsm_master_t *fsm
177  )
178 {
179  fsm->dev_idx = EC_DEVICE_MAIN;
181  fsm->state(fsm); // execute immediately
182 }
183 
184 /******************************************************************************
185  * Master state machine
186  *****************************************************************************/
187 
193  ec_fsm_master_t *fsm
194  )
195 {
196  ec_master_t *master = fsm->master;
197 
198  fsm->idle = 1;
199 
200  // check for emergency requests
201  if (!list_empty(&master->emerg_reg_requests)) {
202  ec_reg_request_t *request;
203 
204  // get first request
205  request = list_entry(master->emerg_reg_requests.next,
206  ec_reg_request_t, list);
207  list_del_init(&request->list); // dequeue
208  request->state = EC_INT_REQUEST_BUSY;
209 
210  if (request->transfer_size > fsm->datagram->mem_size) {
211  EC_MASTER_ERR(master, "Emergency request data too large!\n");
212  request->state = EC_INT_REQUEST_FAILURE;
213  wake_up_all(&master->request_queue);
214  fsm->state(fsm); // continue
215  return;
216  }
217 
218  if (request->dir != EC_DIR_OUTPUT) {
219  EC_MASTER_ERR(master, "Emergency requests must be"
220  " write requests!\n");
221  request->state = EC_INT_REQUEST_FAILURE;
222  wake_up_all(&master->request_queue);
223  fsm->state(fsm); // continue
224  return;
225  }
226 
227  EC_MASTER_DBG(master, 1, "Writing emergency register request...\n");
228  ec_datagram_apwr(fsm->datagram, request->ring_position,
229  request->address, request->transfer_size);
230  memcpy(fsm->datagram->data, request->data, request->transfer_size);
232  request->state = EC_INT_REQUEST_SUCCESS;
233  wake_up_all(&master->request_queue);
234  return;
235  }
236 
237  // check for detached config requests
239 
240  if (master->reboot) {
241  // A reboot of all slaves was requested
242  master->reboot = 0;
243  fsm->idle = 0;
245  fsm->slave = NULL;
246  ec_fsm_reboot_all(&fsm->fsm_reboot, master);
247  fsm->state(fsm); // execute immediately
248  return;
249  }
250 
251  ec_datagram_brd(fsm->datagram, 0x0130, 2);
253  fsm->datagram->device_index = fsm->dev_idx;
255 }
256 
257 /*****************************************************************************/
258 
264  ec_fsm_master_t *fsm
265  )
266 {
267  ec_datagram_t *datagram = fsm->datagram;
268  unsigned int i, size;
269  ec_slave_t *slave;
270  ec_master_t *master = fsm->master;
271 
272  // bus topology change?
273  if (datagram->working_counter != fsm->slaves_responding[fsm->dev_idx]) {
274  fsm->rescan_required = 1;
275  fsm->slaves_responding[fsm->dev_idx] = datagram->working_counter;
276  EC_MASTER_INFO(master, "%u slave(s) responding on %s device.\n",
277  fsm->slaves_responding[fsm->dev_idx],
278  ec_device_names[fsm->dev_idx != 0]);
279  }
280 
281  if (fsm->link_state[fsm->dev_idx] &&
282  !master->devices[fsm->dev_idx].link_state) {
283  ec_device_index_t dev_idx;
284 
285  EC_MASTER_DBG(master, 1, "Master state machine detected "
286  "link down on %s device. Clearing slave list.\n",
287  ec_device_names[fsm->dev_idx != 0]);
288 
290 #ifdef EC_EOE
291  ec_master_eoe_stop(master);
292  ec_master_clear_eoe_handlers(master, 0);
293 #endif
294  ec_master_clear_slaves(master);
296 
297  ec_lock_down(&master->config_sem);
298  master->config_busy = 0;
299  ec_lock_up(&master->config_sem);
300 
301  for (dev_idx = EC_DEVICE_MAIN;
302  dev_idx < ec_master_num_devices(master); dev_idx++) {
303  fsm->slave_states[dev_idx] = 0x00;
304  fsm->slaves_responding[dev_idx] = 0; /* Reset to trigger rescan on
305  next link up. */
306  }
307  }
308  fsm->link_state[fsm->dev_idx] = master->devices[fsm->dev_idx].link_state;
309 
310  if (datagram->state == EC_DATAGRAM_RECEIVED &&
311  fsm->slaves_responding[fsm->dev_idx]) {
312  uint8_t states = EC_READ_U8(datagram->data);
313  if (states != fsm->slave_states[fsm->dev_idx]) {
314  // slave states changed
315  char state_str[EC_STATE_STRING_SIZE];
316  fsm->slave_states[fsm->dev_idx] = states;
317  ec_state_string(states, state_str, 1);
318  EC_MASTER_INFO(master, "Slave states on %s device: %s.\n",
319  ec_device_names[fsm->dev_idx != 0], state_str);
320  }
321  } else {
322  fsm->slave_states[fsm->dev_idx] = 0x00;
323  }
324 
325  fsm->dev_idx++;
326  if (fsm->dev_idx < ec_master_num_devices(master)) {
327  // check number of responding slaves on next device
329  fsm->state(fsm); // execute immediately
330  return;
331  }
332 
333  if (fsm->rescan_required) {
334  ec_lock_down(&master->scan_sem);
335  if (!master->allow_scan) {
336  ec_lock_up(&master->scan_sem);
337  } else {
338  unsigned int count = 0, next_dev_slave, ring_position;
339  ec_device_index_t dev_idx;
340 
341  master->scan_busy = 1;
342  ec_lock_up(&master->scan_sem);
343 
344  // clear all slaves and scan the bus
345  fsm->rescan_required = 0;
346  fsm->idle = 0;
347  fsm->scan_jiffies = jiffies;
348 
350 #ifdef EC_EOE
351  ec_master_eoe_stop(master);
352  ec_master_clear_eoe_handlers(master, 0);
353 #endif
354  ec_master_clear_slaves(master);
356 
357  ec_lock_down(&master->config_sem);
358  master->config_busy = 0;
359  ec_lock_up(&master->config_sem);
360 
361  for (dev_idx = EC_DEVICE_MAIN;
362  dev_idx < ec_master_num_devices(master); dev_idx++) {
363  count += fsm->slaves_responding[dev_idx];
364  }
365 
366  if (!count) {
367  // no slaves present -> finish state machine.
368  master->scan_busy = 0;
369  wake_up_interruptible(&master->scan_queue);
371  return;
372  }
373 
374  size = sizeof(ec_slave_t) * count;
375  if (!(master->slaves =
376  (ec_slave_t *) kmalloc(size, GFP_KERNEL))) {
377  EC_MASTER_ERR(master, "Failed to allocate %u bytes"
378  " of slave memory!\n", size);
379  master->scan_busy = 0;
380  wake_up_interruptible(&master->scan_queue);
382  return;
383  }
384 
385  // init slaves
386  dev_idx = EC_DEVICE_MAIN;
387  next_dev_slave = fsm->slaves_responding[dev_idx];
388  ring_position = 0;
389  for (i = 0; i < count; i++, ring_position++) {
390  slave = master->slaves + i;
391  while (i >= next_dev_slave) {
392  dev_idx++;
393  next_dev_slave += fsm->slaves_responding[dev_idx];
394  ring_position = 0;
395  }
396 
397  ec_slave_init(slave, master, dev_idx, ring_position, i + 1);
398 
399  // do not force reconfiguration in operation phase to avoid
400  // unnecesssary process data interruptions
401  if (master->phase != EC_OPERATION) {
402  slave->force_config = 1;
403  }
404  }
405  master->slave_count = count;
406  master->fsm_slave = master->slaves;
407 
410  return;
411  }
412  }
413 
414  if (master->slave_count) {
415 
416  // application applied configurations
417  if (master->config_changed) {
418  master->config_changed = 0;
419  master->dc_offset_valid = 0;
420 
421  EC_MASTER_DBG(master, 1, "Configuration changed.\n");
422 
423  fsm->slave = master->slaves; // begin with first slave
425 
426  } else {
427  // fetch state from first slave
428  fsm->slave = master->slaves;
430  0x0130, 2);
431  ec_datagram_zero(datagram);
432  fsm->datagram->device_index = fsm->slave->device_index;
433  fsm->retries = EC_FSM_RETRIES;
435  }
436  } else {
438  }
439 }
440 
441 /*****************************************************************************/
442 
448  ec_fsm_master_t *fsm
449  )
450 {
451  ec_master_t *master = fsm->master;
452  ec_sii_write_request_t *request;
453 
454  // search the first request to be processed
455  while (1) {
456  if (list_empty(&master->sii_requests))
457  break;
458 
459  // get first request
460  request = list_entry(master->sii_requests.next,
461  ec_sii_write_request_t, list);
462  list_del_init(&request->list); // dequeue
463  request->state = EC_INT_REQUEST_BUSY;
464 
465  // found pending SII write operation. execute it!
466  EC_SLAVE_DBG(request->slave, 1, "Writing SII data...\n");
467  fsm->sii_request = request;
468  fsm->sii_index = 0;
469  ec_fsm_sii_write(&fsm->fsm_sii, request->slave, request->offset,
472  fsm->state(fsm); // execute immediately
473  return 1;
474  }
475 
476  return 0;
477 }
478 
479 /*****************************************************************************/
480 
486  ec_fsm_master_t *fsm
487  )
488 {
489  // check for pending SII write operations.
491  return; // SII write request found
492  }
493 
495 }
496 
497 /*****************************************************************************/
498 
502  ec_fsm_master_t *fsm
503  )
504 {
505  ec_master_t *master = fsm->master;
506 
507  // is there another slave to query?
508  fsm->slave++;
509  if (fsm->slave < master->slaves + master->slave_count) {
510  // fetch state from next slave
511  fsm->idle = 1;
513  fsm->slave->station_address, 0x0130, 2);
515  fsm->datagram->device_index = fsm->slave->device_index;
516  fsm->retries = EC_FSM_RETRIES;
518  return;
519  }
520 
521  // all slaves processed
523 }
524 
525 /*****************************************************************************/
526 
527 #ifdef EC_LOOP_CONTROL
528 
531 void ec_fsm_master_action_read_dl_status(
532  ec_fsm_master_t *fsm
533  )
534 {
535  ec_datagram_fprd(fsm->datagram, fsm->slave->station_address, 0x0110, 2);
537  fsm->datagram->device_index = fsm->slave->device_index;
538  fsm->retries = EC_FSM_RETRIES;
539  fsm->state = ec_fsm_master_state_read_dl_status;
540 }
541 
542 /*****************************************************************************/
543 
546 void ec_fsm_master_action_open_port(
547  ec_fsm_master_t *fsm
548  )
549 {
550  EC_SLAVE_INFO(fsm->slave, "Opening ports.\n");
551 
552  ec_datagram_fpwr(fsm->datagram, fsm->slave->station_address, 0x0101, 1);
553  EC_WRITE_U8(fsm->datagram->data, 0x54); // port 0 auto, 1-3 auto-close
554  fsm->datagram->device_index = fsm->slave->device_index;
555  fsm->retries = EC_FSM_RETRIES;
556  fsm->state = ec_fsm_master_state_open_port;
557 }
558 
559 /*****************************************************************************/
560 
565 void ec_fsm_master_state_read_dl_status(
566  ec_fsm_master_t *fsm
567  )
568 {
569  ec_slave_t *slave = fsm->slave;
570  ec_datagram_t *datagram = fsm->datagram;
571  unsigned int i;
572 
573  if (datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--) {
574  return;
575  }
576 
577  if (datagram->state != EC_DATAGRAM_RECEIVED) {
578  EC_SLAVE_ERR(slave, "Failed to receive AL state datagram: ");
579  ec_datagram_print_state(datagram);
581  return;
582  }
583 
584  // did the slave not respond to its station address?
585  if (datagram->working_counter != 1) {
586  // try again next time
588  return;
589  }
590 
591  ec_slave_set_dl_status(slave, EC_READ_U16(datagram->data));
592 
593  // process port state machines
594  for (i = 0; i < EC_MAX_PORTS; i++) {
595  ec_slave_port_t *port = &slave->ports[i];
596 
597  switch (port->state) {
598  case EC_SLAVE_PORT_DOWN:
599  if (port->link.loop_closed) {
600  if (port->link.link_up) {
601  port->link_detection_jiffies = jiffies;
602  port->state = EC_SLAVE_PORT_WAIT;
603  }
604  }
605  else { // loop open
606  port->state = EC_SLAVE_PORT_UP;
607  }
608  break;
609  case EC_SLAVE_PORT_WAIT:
610  if (port->link.link_up) {
611  if (jiffies - port->link_detection_jiffies >
612  HZ * EC_PORT_WAIT_MS / 1000) {
613  port->state = EC_SLAVE_PORT_UP;
614  ec_fsm_master_action_open_port(fsm);
615  return;
616  }
617  }
618  else { // link down
619  port->state = EC_SLAVE_PORT_DOWN;
620  }
621  break;
622  default: // EC_SLAVE_PORT_UP
623  if (!port->link.link_up) {
624  port->state = EC_SLAVE_PORT_DOWN;
625  }
626  break;
627  }
628  }
629 
630  // process next slave
632 }
633 
634 /*****************************************************************************/
635 
640 void ec_fsm_master_state_open_port(
641  ec_fsm_master_t *fsm
642  )
643 {
644  ec_slave_t *slave = fsm->slave;
645  ec_datagram_t *datagram = fsm->datagram;
646 
647  if (datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--) {
648  return;
649  }
650 
651  if (datagram->state != EC_DATAGRAM_RECEIVED) {
652  EC_SLAVE_ERR(slave, "Failed to receive port open datagram: ");
653  ec_datagram_print_state(datagram);
655  return;
656  }
657 
658  // did the slave not respond to its station address?
659  if (datagram->working_counter != 1) {
660  EC_SLAVE_ERR(slave, "Did not respond to port open command!\n");
661  return;
662  }
663 
664  // process next slave
666 }
667 
668 #endif
669 
670 /*****************************************************************************/
671 
675  ec_fsm_master_t *fsm
676  )
677 {
678  ec_master_t *master = fsm->master;
679 
680  if (master->config_changed) {
681  master->config_changed = 0;
682  master->dc_offset_valid = 0;
683 
684  // abort iterating through slaves,
685  // first compensate DC system time offsets,
686  // then begin configuring at slave 0
687  EC_MASTER_DBG(master, 1, "Configuration changed"
688  " (aborting state check).\n");
689 
690  fsm->slave = master->slaves; // begin with first slave
692  return;
693  }
694 
695  // allow slave to start config (if not already done).
697 
698 #ifdef EC_LOOP_CONTROL
699  // read DL status
700  ec_fsm_master_action_read_dl_status(fsm);
701 #else
702  // process next slave
704 #endif
705 }
706 
707 /*****************************************************************************/
708 
714  ec_fsm_master_t *fsm
715  )
716 {
717  ec_slave_t *slave = fsm->slave;
718  ec_datagram_t *datagram = fsm->datagram;
719 
720  if (datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--) {
721  return;
722  }
723 
724  if (datagram->state != EC_DATAGRAM_RECEIVED) {
725  EC_SLAVE_ERR(slave, "Failed to receive AL state datagram: ");
726  ec_datagram_print_state(datagram);
728  return;
729  }
730 
731  // did the slave not respond to its station address?
732  if (datagram->working_counter != 1) {
733  if (!slave->error_flag) {
734  slave->error_flag = 1;
735  EC_SLAVE_DBG(slave, 1, "Slave did not respond to state query.\n");
736  }
737  fsm->rescan_required = 1;
739  return;
740  }
741 
742  // A single slave responded
743  ec_slave_set_al_status(slave, EC_READ_U8(datagram->data));
744 
745  if (slave->reboot) {
746  // A reboot of this slave was requested
747  slave->reboot = 0;
748  fsm->idle = 0;
750  ec_fsm_reboot_single(&fsm->fsm_reboot, slave);
751  fsm->state(fsm); // execute immediately
752  return;
753  }
754 
755  if (!slave->error_flag) {
756  // Check for configuration
758  return;
759  }
760 
761 #ifdef EC_LOOP_CONTROL
762  // read DL status
763  ec_fsm_master_action_read_dl_status(fsm);
764 #else
765  // process next slave
767 #endif
768 }
769 
770 /*****************************************************************************/
771 
775  ec_fsm_master_t *fsm
776  )
777 {
778  ec_slave_t *slave = fsm->slave;
779 
780  if (ec_fsm_reboot_exec(&fsm->fsm_reboot)) {
781  return;
782  }
783 
784  if (!ec_fsm_reboot_success(&fsm->fsm_reboot)) {
785  if (slave) {
786  EC_SLAVE_ERR(slave, "Failed to reboot.\n");
787  } else {
788  EC_MASTER_ERR(fsm->master, "Failed to reboot.\n");
789  }
790  }
791 
793 }
794 
795 /*****************************************************************************/
796 
800  ec_fsm_master_t *fsm
801  )
802 {
803  EC_MASTER_DBG(fsm->master, 1, "Reading old port receive times...\n");
804 
805  // read DC port receive times
806  // (station addresses not assigned yet, so must APRD.)
807  fsm->slave = fsm->master->slaves;
808  ec_datagram_aprd(fsm->datagram, fsm->slave->ring_position, 0x0900, 16);
810  fsm->datagram->device_index = fsm->slave->device_index;
811  fsm->retries = EC_FSM_RETRIES;
813 }
814 
815 /*****************************************************************************/
816 
820  ec_fsm_master_t *fsm
821  )
822 {
823  ec_master_t *master = fsm->master;
824  ec_slave_t *slave = fsm->slave;
825  ec_datagram_t *datagram = fsm->datagram;
826  int i;
827 
828  if (datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--)
829  return;
830 
831  if (datagram->state != EC_DATAGRAM_RECEIVED) {
832  EC_SLAVE_ERR(slave, "Failed to receive DC receive times datagram: ");
833  ec_datagram_print_state(datagram);
834  // continue even on error
835  } else if (datagram->working_counter != 1) {
836  EC_SLAVE_WARN(slave, "Failed to get DC receive times: ");
837  ec_datagram_print_wc_error(datagram);
838  // continue; this is just a warning because at this point we
839  // don't know if the slave supports these registers or not
840  }
841 
842  for (i = 0; i < EC_MAX_PORTS; i++) {
843  slave->ports[i].receive_time = EC_READ_U32(datagram->data + 4 * i);
844  }
845 
846  ++fsm->slave;
847  if (fsm->slave < master->slaves + master->slave_count) {
848  // read DC port receive times
849  ec_datagram_aprd(datagram, fsm->slave->ring_position, 0x0900, 16);
850  ec_datagram_zero(datagram);
851  datagram->device_index = fsm->slave->device_index;
852  fsm->retries = EC_FSM_RETRIES;
853  } else {
854  /* start with first device with slaves responding; at least one
855  * has responding slaves, otherwise count would be zero. */
856  fsm->dev_idx = EC_DEVICE_MAIN;
857  while (!fsm->slaves_responding[fsm->dev_idx]) {
858  fsm->dev_idx++;
859  }
860 
861  fsm->slave = master->slaves;
863  }
864 }
865 
866 /*****************************************************************************/
867 
871  ec_fsm_master_t *fsm
872  )
873 {
874  // broadcast clear all station addresses
875  ec_datagram_bwr(fsm->datagram, 0x0010, 2);
876  EC_WRITE_U16(fsm->datagram->data, 0x0000);
877  fsm->datagram->device_index = fsm->dev_idx;
878  fsm->retries = EC_FSM_RETRIES;
880 }
881 
882 /*****************************************************************************/
883 
887  ec_fsm_master_t *fsm
888  )
889 {
890  EC_MASTER_DBG(fsm->master, 1, "Sending broadcast-write"
891  " to measure transmission delays on %s link.\n",
892  ec_device_names[fsm->dev_idx != 0]);
893 
894  ec_datagram_bwr(fsm->datagram, 0x0900, 1);
896  fsm->datagram->device_index = fsm->dev_idx;
897  fsm->retries = EC_FSM_RETRIES;
899 }
900 
901 /*****************************************************************************/
902 
903 #ifdef EC_LOOP_CONTROL
904 
907 void ec_fsm_master_enter_loop_control(
908  ec_fsm_master_t *fsm
909  )
910 {
911  EC_MASTER_DBG(fsm->master, 1, "Broadcast-writing"
912  " loop control registers on %s link.\n",
913  ec_device_names[fsm->dev_idx != 0]);
914 
915  ec_datagram_bwr(fsm->datagram, 0x0101, 1);
916  EC_WRITE_U8(fsm->datagram->data, 0x54); // port 0 auto, 1-3 auto-close
917  fsm->datagram->device_index = fsm->dev_idx;
918  fsm->retries = EC_FSM_RETRIES;
919  fsm->state = ec_fsm_master_state_loop_control;
920 }
921 
922 /*****************************************************************************/
923 
926 void ec_fsm_master_state_loop_control(
927  ec_fsm_master_t *fsm
928  )
929 {
930  ec_master_t *master = fsm->master;
931  ec_datagram_t *datagram = fsm->datagram;
932 
933  if (datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--) {
934  return;
935  }
936 
937  if (datagram->state != EC_DATAGRAM_RECEIVED) {
938  EC_MASTER_ERR(master, "Failed to receive loop control"
939  " datagram on %s link: ",
940  ec_device_names[fsm->dev_idx != 0]);
941  ec_datagram_print_state(datagram);
942  }
943 
945 }
946 
947 #endif
948 
949 /*****************************************************************************/
950 
954  ec_fsm_master_t *fsm
955  )
956 {
957  ec_master_t *master = fsm->master;
958  ec_datagram_t *datagram = fsm->datagram;
959 
960  if (datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--) {
961  return;
962  }
963 
964  if (datagram->state != EC_DATAGRAM_RECEIVED) {
965  EC_MASTER_ERR(master, "Failed to receive address"
966  " clearing datagram on %s link: ",
967  ec_device_names[fsm->dev_idx != 0]);
968  ec_datagram_print_state(datagram);
969  master->scan_busy = 0;
970  wake_up_interruptible(&master->scan_queue);
972  return;
973  }
974 
975  if (datagram->working_counter != fsm->slaves_responding[fsm->dev_idx]) {
976  EC_MASTER_WARN(master, "Failed to clear station addresses on %s link:"
977  " Cleared %u of %u",
978  ec_device_names[fsm->dev_idx != 0], datagram->working_counter,
979  fsm->slaves_responding[fsm->dev_idx]);
980  }
981 
982 #ifdef EC_LOOP_CONTROL
983  ec_fsm_master_enter_loop_control(fsm);
984 #else
986 #endif
987 }
988 
989 /*****************************************************************************/
990 
994  ec_fsm_master_t *fsm
995  )
996 {
997  ec_master_t *master = fsm->master;
998  ec_datagram_t *datagram = fsm->datagram;
999  ec_slave_t *slave;
1000 
1001  if (datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--) {
1002  return;
1003  }
1004 
1005  if (datagram->state != EC_DATAGRAM_RECEIVED) {
1006  EC_MASTER_ERR(master, "Failed to receive delay measuring datagram"
1007  " on %s link: ", ec_device_names[fsm->dev_idx != 0]);
1008  ec_datagram_print_state(datagram);
1009  master->scan_busy = 0;
1010  wake_up_interruptible(&master->scan_queue);
1011  ec_fsm_master_restart(fsm);
1012  return;
1013  }
1014 
1015  EC_MASTER_DBG(master, 1, "%u slaves responded to delay measuring"
1016  " on %s link.\n",
1017  datagram->working_counter, ec_device_names[fsm->dev_idx != 0]);
1018 
1019  do {
1020  fsm->dev_idx++;
1021  } while (fsm->dev_idx < ec_master_num_devices(master) &&
1022  !fsm->slaves_responding[fsm->dev_idx]);
1023  if (fsm->dev_idx < ec_master_num_devices(master)) {
1025  return;
1026  }
1027 
1028  EC_MASTER_INFO(master, "Scanning bus.\n");
1029 
1030  // set slaves ready for requests (begins scan).
1031  for (slave = master->slaves;
1032  slave < master->slaves + master->slave_count;
1033  slave++) {
1034  ec_fsm_slave_set_ready(&slave->fsm);
1035  }
1036 
1038  fsm->datagram->state = EC_DATAGRAM_INVALID; // nothing to send
1039  fsm->state(fsm); // execute immediately
1040 }
1041 
1042 /*****************************************************************************/
1043 
1049  ec_fsm_master_t *fsm
1050  )
1051 {
1052  ec_master_t *master = fsm->master;
1053  ec_slave_t *slave;
1054 
1055  for (slave = master->slaves;
1056  slave < master->slaves + master->slave_count;
1057  slave++) {
1058  if (slave->scan_required && !slave->error_flag) {
1059  // still in progress
1060  return;
1061  }
1062  }
1063 
1064  EC_MASTER_INFO(master, "Bus scanning completed in %lu ms.\n",
1065  (jiffies - fsm->scan_jiffies) * 1000 / HZ);
1066 
1067  master->scan_busy = 0;
1068  wake_up_interruptible(&master->scan_queue);
1069 
1070  // Attach slave configurations
1072 
1073  // Set DC ref slave and calc topology and transmission delays
1074  // Note: must come after attach_slave_configs for application
1075  // selected dc_ref_config to return its slave
1076  ec_master_calc_dc(master);
1077 
1078 #ifdef EC_EOE
1079  // check if EoE processing has to be started
1080  ec_master_eoe_start(master);
1081 #endif
1082 
1083  if (master->slave_count) {
1084  master->config_changed = 0;
1085  master->dc_offset_valid = 0;
1086 
1087  fsm->slave = master->slaves; // begin with first slave
1089  } else {
1090  ec_fsm_master_restart(fsm);
1091  }
1092 }
1093 
1094 /*****************************************************************************/
1095 
1099  ec_fsm_master_t *fsm
1100  )
1101 {
1102  ec_master_t *master = fsm->master;
1103 
1104  if (master->active) {
1105 
1106  while (fsm->slave < master->slaves + master->slave_count) {
1107  if (!fsm->slave->base_dc_supported
1108  || !fsm->slave->has_dc_system_time) {
1109  fsm->slave++;
1110  continue;
1111  }
1112 
1113  EC_SLAVE_DBG(fsm->slave, 1, "Checking system time offset.\n");
1114 
1115  // read DC system time (0x0910, 64 bit)
1116  // gap (64 bit)
1117  // and time offset (0x0920, 64 bit)
1118  // and receive delay (0x0928, 32 bit)
1120  0x0910, 28);
1121  ec_datagram_zero(fsm->datagram);
1122  fsm->datagram->device_index = fsm->slave->device_index;
1123  fsm->retries = EC_FSM_RETRIES;
1125  return;
1126  }
1127  master->dc_offset_valid = 1;
1128 
1129  } else {
1130  EC_MASTER_DBG(master, 1, "No app_time received up to now.\n");
1131  }
1132 
1133  // scanning and setting system times complete
1134  ec_master_request_op(master);
1135  ec_fsm_master_restart(fsm);
1136 }
1137 
1138 /*****************************************************************************/
1139 
1145  ec_fsm_master_t *fsm,
1146  u64 system_time,
1147  u64 old_offset,
1148  u64 app_time_sent
1149  )
1150 {
1151  ec_slave_t *slave = fsm->slave;
1152  u32 system_time32, old_offset32, new_offset;
1153  s32 time_diff;
1154 
1155  system_time32 = (u32) system_time;
1156  old_offset32 = (u32) old_offset;
1157 
1158  time_diff = (u32) app_time_sent - system_time32;
1159 
1160  EC_SLAVE_DBG(slave, 1, "DC 32 bit system time offset calculation:"
1161  " system_time=%u, app_time=%llu, diff=%i\n",
1162  system_time32, app_time_sent, time_diff);
1163 
1164  if (EC_ABS(time_diff) > EC_SYSTEM_TIME_TOLERANCE_NS) {
1165  new_offset = time_diff + old_offset32;
1166  EC_SLAVE_DBG(slave, 1, "Setting time offset to %u (was %u)\n",
1167  new_offset, old_offset32);
1168  return (u64) new_offset;
1169  } else {
1170  EC_SLAVE_DBG(slave, 1, "Not touching time offset.\n");
1171  return old_offset;
1172  }
1173 }
1174 
1175 /*****************************************************************************/
1176 
1182  ec_fsm_master_t *fsm,
1183  u64 system_time,
1184  u64 old_offset,
1185  u64 app_time_sent
1186  )
1187 {
1188  ec_slave_t *slave = fsm->slave;
1189  u64 new_offset;
1190  s64 time_diff;
1191 
1192  time_diff = app_time_sent - system_time;
1193 
1194  EC_SLAVE_DBG(slave, 1, "DC 64 bit system time offset calculation:"
1195  " system_time=%llu, app_time=%llu, diff=%lli\n",
1196  system_time, app_time_sent, time_diff);
1197 
1198  if (EC_ABS(time_diff) > EC_SYSTEM_TIME_TOLERANCE_NS) {
1199  new_offset = time_diff + old_offset;
1200  EC_SLAVE_DBG(slave, 1, "Setting time offset to %llu (was %llu)\n",
1201  new_offset, old_offset);
1202  } else {
1203  new_offset = old_offset;
1204  EC_SLAVE_DBG(slave, 1, "Not touching time offset.\n");
1205  }
1206 
1207  return new_offset;
1208 }
1209 
1210 /*****************************************************************************/
1211 
1215  ec_fsm_master_t *fsm
1216  )
1217 {
1218  ec_datagram_t *datagram = fsm->datagram;
1219  ec_slave_t *slave = fsm->slave;
1220  ec_master_t *master = fsm->master;
1221  u64 system_time, old_offset, new_offset;
1222  u32 old_delay;
1223 
1224  if (datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--)
1225  return;
1226 
1227  if (datagram->state != EC_DATAGRAM_RECEIVED) {
1228  EC_SLAVE_ERR(slave, "Failed to receive DC times datagram: ");
1229  ec_datagram_print_state(datagram);
1230  fsm->slave++;
1232  return;
1233  }
1234 
1235  if (datagram->working_counter != 1) {
1236  EC_SLAVE_WARN(slave, "Failed to get DC times: ");
1237  ec_datagram_print_wc_error(datagram);
1238  fsm->slave++;
1240  return;
1241  }
1242 
1243  if (unlikely(!master->dc_ref_time)) {
1244  EC_MASTER_WARN(master, "No app_time received up to now,"
1245  " abort DC time offset calculation.\n");
1246  // scanning and setting system times complete
1247  ec_master_request_op(master);
1248  ec_fsm_master_restart(fsm);
1249  return;
1250  }
1251 
1252  system_time = EC_READ_U64(datagram->data); // 0x0910
1253  old_offset = EC_READ_U64(datagram->data + 16); // 0x0920
1254  old_delay = EC_READ_U32(datagram->data + 24); // 0x0928
1255 
1256  if (slave->base_dc_range == EC_DC_32) {
1257  new_offset = ec_fsm_master_dc_offset32(fsm,
1258  system_time, old_offset, datagram->app_time_sent);
1259  } else {
1260  new_offset = ec_fsm_master_dc_offset64(fsm,
1261  system_time, old_offset, datagram->app_time_sent);
1262  }
1263 
1264  if (new_offset != old_offset
1265  && slave->current_state >= EC_SLAVE_STATE_SAFEOP) {
1266  // Slave is already active; changing the system time offset could
1267  // cause problems. Leave the offset alone in this case and just
1268  // let the normal cyclic sync process gradually adjust it to the
1269  // correct time.
1270  EC_SLAVE_DBG(slave, 1, "Slave is running; ignoring DC offset change.\n");
1271  new_offset = old_offset;
1272  }
1273 
1274  if (new_offset == old_offset && slave->transmission_delay == old_delay) {
1275  // offsets have not changed; skip write to avoid possible trouble
1276  fsm->slave++;
1278  return;
1279  }
1280 
1281  // set DC system time offset and transmission delay
1282  ec_datagram_fpwr(datagram, slave->station_address, 0x0920, 12);
1283  EC_WRITE_U64(datagram->data, new_offset);
1284  EC_WRITE_U32(datagram->data + 8, slave->transmission_delay);
1285  fsm->datagram->device_index = slave->device_index;
1286  fsm->retries = EC_FSM_RETRIES;
1288 }
1289 
1290 /*****************************************************************************/
1291 
1295  ec_fsm_master_t *fsm
1296  )
1297 {
1298  ec_datagram_t *datagram = fsm->datagram;
1299  ec_slave_t *slave = fsm->slave;
1300 
1301  if (datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--)
1302  return;
1303 
1304  if (datagram->state != EC_DATAGRAM_RECEIVED) {
1305  EC_SLAVE_ERR(slave,
1306  "Failed to receive DC system time offset datagram: ");
1307  ec_datagram_print_state(datagram);
1308  fsm->slave++;
1310  return;
1311  }
1312 
1313  if (datagram->working_counter != 1) {
1314  EC_SLAVE_ERR(slave, "Failed to set DC system time offset: ");
1315  ec_datagram_print_wc_error(datagram);
1316  fsm->slave++;
1318  return;
1319  }
1320 
1321  // reset DC filter after changing offsets
1322  if (slave->current_state >= EC_SLAVE_STATE_SAFEOP) {
1323  EC_SLAVE_DBG(slave, 1, "Slave is running; not resetting DC filter.\n");
1324  fsm->slave++;
1326  } else {
1327  ec_datagram_fpwr(datagram, slave->station_address, 0x0930, 2);
1328  EC_WRITE_U16(datagram->data, 0x1000);
1329  fsm->datagram->device_index = slave->device_index;
1330  fsm->retries = EC_FSM_RETRIES;
1332  }
1333 }
1334 
1335 /*****************************************************************************/
1336 
1340  ec_fsm_master_t *fsm
1341  )
1342 {
1343  ec_datagram_t *datagram = fsm->datagram;
1344  ec_slave_t *slave = fsm->slave;
1345 
1346  if (datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--)
1347  return;
1348 
1349  if (datagram->state != EC_DATAGRAM_RECEIVED) {
1350  EC_SLAVE_ERR(slave,
1351  "Failed to receive DC reset filter datagram: ");
1352  ec_datagram_print_state(datagram);
1353  fsm->slave++;
1355  return;
1356  }
1357 
1358  if (datagram->working_counter != 1) {
1359  EC_SLAVE_ERR(slave, "Failed to reset DC filter: ");
1360  ec_datagram_print_wc_error(datagram);
1361  fsm->slave++;
1363  return;
1364  }
1365 
1366  fsm->slave++;
1368 }
1369 
1370 /*****************************************************************************/
1371 
1375  ec_fsm_master_t *fsm
1376  )
1377 {
1378  ec_master_t *master = fsm->master;
1379  ec_sii_write_request_t *request = fsm->sii_request;
1380  ec_slave_t *slave = request->slave;
1381 
1382  if (ec_fsm_sii_exec(&fsm->fsm_sii, fsm->datagram)) return;
1383 
1384  if (!ec_fsm_sii_success(&fsm->fsm_sii)) {
1385  EC_SLAVE_ERR(slave, "Failed to write SII data.\n");
1386  request->state = EC_INT_REQUEST_FAILURE;
1387  wake_up_all(&master->request_queue);
1388  ec_fsm_master_restart(fsm);
1389  return;
1390  }
1391 
1392  fsm->sii_index++;
1393  if (fsm->sii_index < request->nwords) {
1394  ec_fsm_sii_write(&fsm->fsm_sii, slave,
1395  request->offset + fsm->sii_index,
1396  request->words + fsm->sii_index,
1398  ec_fsm_sii_exec(&fsm->fsm_sii, fsm->datagram); // execute immediately
1399  return;
1400  }
1401 
1402  // finished writing SII
1403  EC_SLAVE_DBG(slave, 1, "Finished writing %zu words of SII data.\n",
1404  request->nwords);
1405 
1406  if (request->offset <= 4 && request->offset + request->nwords > 4) {
1407  // alias was written
1408  if (slave->sii_image) {
1409  slave->sii_image->sii.alias = EC_READ_U16(request->words + 4);
1410  // TODO: read alias from register 0x0012
1411  slave->effective_alias = slave->sii_image->sii.alias;
1412  }
1413  else {
1414  EC_SLAVE_WARN(slave, "Slave could not update effective alias."
1415  " SII data not available.\n");
1416  }
1417  }
1418  // TODO: Evaluate other SII contents!
1419 
1420  request->state = EC_INT_REQUEST_SUCCESS;
1421  wake_up_all(&master->request_queue);
1422 
1423  // check for another SII write request
1425  return; // processing another request
1426 
1427  ec_fsm_master_restart(fsm);
1428 }
1429 
1430 /*****************************************************************************/
#define EC_FSM_RETRIES
Number of state machine retries on datagram timeout.
Definition: globals.h:59
uint16_t ring_position
Ring position for emergency requests.
Definition: reg_request.h:57
void ec_master_clear_eoe_handlers(ec_master_t *master, unsigned int free_all)
Clear and free auto created EoE handlers.
Definition: master.c:480
void ec_fsm_reboot_all(ec_fsm_reboot_t *fsm, ec_master_t *master)
Starts the reboot state machine for all slaves on a master.
Definition: fsm_reboot.c:107
ec_internal_request_state_t state
Request state.
Definition: reg_request.h:56
uint16_t offset
SII word offset.
Definition: fsm_master.h:55
uint16_t ring_position
Ring position.
Definition: slave.h:221
ec_datagram_t * datagram
datagram used in the state machine
Definition: fsm_master.h:69
ec_sii_write_request_t * sii_request
SII write request.
Definition: fsm_master.h:87
void ec_master_calc_dc(ec_master_t *master)
Distributed-clocks calculations.
Definition: master.c:2652
size_t transfer_size
Size of the data to transfer.
Definition: reg_request.h:55
struct list_head sii_requests
SII write requests.
Definition: master.h:334
#define EC_SLAVE_DBG(slave, level, fmt, args...)
Convenience macro for printing slave-specific debug messages to syslog.
Definition: slave.h:108
unsigned int reboot
Request reboot.
Definition: slave.h:241
Finite state machine of an EtherCAT master.
Definition: fsm_master.h:67
unsigned int reboot
Reboot requested.
Definition: master.h:264
uint64_t app_time_sent
App time, when the datagram was sent.
Definition: datagram.h:106
ec_internal_request_state_t state
State of the request.
Definition: fsm_master.h:58
unsigned int slaves_responding[EC_MAX_NUM_DEVICES]
Number of responding slaves for every device.
Definition: fsm_master.h:79
size_t ec_state_string(uint8_t, char *, uint8_t)
Prints slave states in clear text.
Definition: module.c:408
ec_slave_port_t ports[EC_MAX_PORTS]
Ports.
Definition: slave.h:231
void ec_fsm_master_enter_dc_read_old_times(ec_fsm_master_t *)
Start reading old timestamps from slaves.
Definition: fsm_master.c:799
void ec_fsm_master_reset(ec_fsm_master_t *fsm)
Reset state machine.
Definition: fsm_master.c:116
struct ec_slave ec_slave_t
Definition: globals.h:348
void ec_master_request_op(ec_master_t *master)
Request OP state for configured slaves.
Definition: master.c:2669
ec_slave_state_t current_state
Current application state.
Definition: slave.h:237
#define ec_master_num_devices(MASTER)
Number of Ethernet devices.
Definition: master.h:359
size_t nwords
Number of words.
Definition: fsm_master.h:56
void(* state)(ec_fsm_master_t *)
master state function
Definition: fsm_master.h:72
uint16_t address
Register address.
Definition: reg_request.h:54
Register request.
Definition: reg_request.h:48
Operation phase.
Definition: master.h:143
ec_slave_port_link_t link
Port link status.
Definition: slave.h:141
u64 ec_fsm_master_dc_offset32(ec_fsm_master_t *fsm, u64 system_time, u64 old_offset, u64 app_time_sent)
Configure 32 bit time offset.
Definition: fsm_master.c:1144
unsigned int allow_scan
True, if slave scanning is allowed.
Definition: master.h:266
#define EC_SLAVE_WARN(slave, fmt, args...)
Convenience macro for printing slave-specific warnings to syslog.
Definition: slave.h:91
void ec_fsm_master_restart(ec_fsm_master_t *fsm)
Restarts the master state machine.
Definition: fsm_master.c:175
unsigned int rescan_required
A bus rescan is required.
Definition: fsm_master.h:82
int ec_fsm_reboot_success(ec_fsm_reboot_t *fsm)
Returns, if the state machine terminated with success.
Definition: fsm_reboot.c:138
EtherCAT datagram.
Definition: datagram.h:88
void ec_fsm_master_state_read_al_status(ec_fsm_master_t *)
Master state: READ AL STATUS.
Definition: fsm_master.c:713
void ec_fsm_sii_write(ec_fsm_sii_t *fsm, ec_slave_t *slave, uint16_t word_offset, const uint16_t *value, ec_fsm_sii_addressing_t mode)
Initializes the SII write state machine.
Definition: fsm_sii.c:124
void ec_master_expire_slave_config_requests(ec_master_t *master)
Abort active requests for slave configs without attached slaves.
Definition: master.c:2222
#define EC_WRITE_U8(DATA, VAL)
Write an 8-bit unsigned value to EtherCAT data.
Definition: ecrt.h:2642
u64 ec_fsm_master_dc_offset64(ec_fsm_master_t *fsm, u64 system_time, u64 old_offset, u64 app_time_sent)
Configure 64 bit time offset.
Definition: fsm_master.c:1181
u64 dc_ref_time
Common reference timestamp for DC start times.
Definition: master.h:250
ec_slave_state_t slave_states[EC_MAX_NUM_DEVICES]
AL states of responding slaves for every device.
Definition: fsm_master.h:83
struct list_head emerg_reg_requests
Emergency register access requests.
Definition: master.h:335
#define EC_SYSTEM_TIME_TOLERANCE_NS
Time difference [ns] to tolerate without setting a new system time offset.
Definition: fsm_master.c:51
ec_fsm_slave_t fsm
Slave state machine.
Definition: slave.h:282
uint16_t working_counter
Working counter.
Definition: datagram.h:100
void ec_fsm_master_action_idle(ec_fsm_master_t *fsm)
Master action: IDLE.
Definition: fsm_master.c:485
int ec_fsm_sii_exec(ec_fsm_sii_t *fsm, ec_datagram_t *datagram)
Executes the SII state machine.
Definition: fsm_sii.c:145
uint8_t link_state
device link state
Definition: device.h:97
void ec_fsm_master_state_dc_write_offset(ec_fsm_master_t *)
Master state: DC WRITE OFFSET.
Definition: fsm_master.c:1294
Sent (still in the queue).
Definition: datagram.h:77
void ec_slave_set_dl_status(ec_slave_t *slave, uint16_t new_state)
Sets the data-link state of a slave.
Definition: slave.c:374
wait_queue_head_t request_queue
Wait queue for external requests from user space.
Definition: master.h:338
EtherCAT master state machine.
uint16_t station_address
Configured station address.
Definition: slave.h:222
const char * ec_device_names[2]
Device names.
Definition: module.c:472
struct list_head list
List head.
Definition: fsm_master.h:53
SII write request.
Definition: fsm_master.h:52
void ec_fsm_master_action_next_slave_state(ec_fsm_master_t *fsm)
Master action: Get state of next slave.
Definition: fsm_master.c:501
int ec_datagram_aprd(ec_datagram_t *datagram, uint16_t ring_position, uint16_t mem_address, size_t data_size)
Initializes an EtherCAT APRD datagram.
Definition: datagram.c:211
Global definitions and macros.
void ec_fsm_master_enter_clear_addresses(ec_fsm_master_t *)
Start clearing slave addresses.
Definition: fsm_master.c:870
EtherCAT master structure.
SAFEOP (mailbox communication and input update)
Definition: globals.h:168
ec_lock_t config_sem
Semaphore protecting the config_busy variable and the allow_config flag.
Definition: master.h:273
void ec_fsm_master_init(ec_fsm_master_t *fsm, ec_master_t *master, ec_datagram_t *datagram)
Constructor.
Definition: fsm_master.c:83
#define EC_MASTER_DBG(master, level, fmt, args...)
Convenience macro for printing master-specific debug messages to syslog.
Definition: master.h:106
int ec_fsm_master_action_process_sii(ec_fsm_master_t *fsm)
Check for pending SII write requests and process one.
Definition: fsm_master.c:447
ec_slave_t * fsm_slave
Slave that is queried next for FSM exec.
Definition: master.h:306
ec_slave_t * slave
EtherCAT slave.
Definition: fsm_master.h:54
EtherCAT slave.
Definition: slave.h:214
void ec_master_clear_sii_images(ec_master_t *master)
Clear the SII data applied during bus scanning.
Definition: master.c:559
void ec_master_attach_slave_configs(ec_master_t *master)
Attaches the slave configurations to the slaves.
Definition: master.c:2207
int ec_datagram_apwr(ec_datagram_t *datagram, uint16_t ring_position, uint16_t mem_address, size_t data_size)
Initializes an EtherCAT APWR datagram.
Definition: datagram.c:232
void ec_datagram_zero(ec_datagram_t *datagram)
Fills the datagram payload memory with zeros.
Definition: datagram.c:179
u8 dc_offset_valid
DC slaves have valid system time offsets.
Definition: master.h:251
void ec_fsm_master_state_scan_slave(ec_fsm_master_t *)
Master state: SCAN SLAVE.
Definition: fsm_master.c:1048
ec_sii_image_t * sii_image
Current complete SII image.
Definition: slave.h:267
Ethernet over EtherCAT (EoE)
ec_datagram_state_t state
State.
Definition: datagram.h:101
ec_master_phase_t phase
Master phase.
Definition: master.h:231
#define EC_WRITE_U32(DATA, VAL)
Write a 32-bit unsigned value to EtherCAT data.
Definition: ecrt.h:2676
ec_fsm_sii_t fsm_sii
SII state machine.
Definition: fsm_master.h:91
ec_slave_t * slaves
Array of slaves on the bus.
Definition: master.h:239
Use configured addresses.
Definition: fsm_sii.h:50
void ec_fsm_master_action_configure(ec_fsm_master_t *fsm)
Master action: Configure.
Definition: fsm_master.c:674
#define EC_SLAVE_ERR(slave, fmt, args...)
Convenience macro for printing slave-specific errors to syslog.
Definition: slave.h:77
void ec_datagram_print_wc_error(const ec_datagram_t *datagram)
Evaluates the working counter of a single-cast datagram.
Definition: datagram.c:627
ec_slave_dc_range_t base_dc_range
DC range.
Definition: slave.h:258
void ec_fsm_slave_set_ready(ec_fsm_slave_t *fsm)
Sets the current state of the state machine to READY.
Definition: fsm_slave.c:209
void ec_fsm_master_state_dc_reset_filter(ec_fsm_master_t *)
Master state: DC RESET FILTER.
Definition: fsm_master.c:1339
uint32_t transmission_delay
DC system time transmission delay (offset from reference clock).
Definition: slave.h:262
unsigned int slave_count
Number of slaves on the bus.
Definition: master.h:240
unsigned int scan_busy
Current scan state.
Definition: master.h:265
ec_device_index_t
Master devices.
Definition: globals.h:236
void ec_fsm_master_state_dc_measure_delays(ec_fsm_master_t *)
Master state: DC MEASURE DELAYS.
Definition: fsm_master.c:993
void ec_fsm_master_state_broadcast(ec_fsm_master_t *)
Master state: BROADCAST.
Definition: fsm_master.c:263
uint16_t alias
Configured station alias.
Definition: slave.h:159
#define EC_WRITE_U16(DATA, VAL)
Write a 16-bit unsigned value to EtherCAT data.
Definition: ecrt.h:2659
unsigned long scan_jiffies
beginning of slave scanning
Definition: fsm_master.h:76
ec_fsm_reboot_t fsm_reboot
Slave reboot state machine.
Definition: fsm_master.h:90
#define EC_ABS(X)
Absolute value.
Definition: globals.h:289
Main device.
Definition: globals.h:237
#define EC_READ_U32(DATA)
Read a 32-bit unsigned value from EtherCAT data.
Definition: ecrt.h:2570
#define EC_MASTER_WARN(master, fmt, args...)
Convenience macro for printing master-specific warnings to syslog.
Definition: master.h:92
int ec_fsm_reboot_exec(ec_fsm_reboot_t *fsm)
Executes the current state of the state machine.
Definition: fsm_reboot.c:123
unsigned int active
Master has been activated.
Definition: master.h:232
int ec_datagram_brd(ec_datagram_t *datagram, uint16_t mem_address, size_t data_size)
Initializes an EtherCAT BRD datagram.
Definition: datagram.c:395
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:320
uint8_t has_dc_system_time
The slave supports the DC system time register.
Definition: slave.h:259
void ec_fsm_reboot_init(ec_fsm_reboot_t *fsm, ec_datagram_t *datagram)
Constructor.
Definition: fsm_reboot.c:68
void ec_fsm_reboot_single(ec_fsm_reboot_t *fsm, ec_slave_t *slave)
Starts the reboot state machine for a single slave.
Definition: fsm_reboot.c:92
wait_queue_head_t scan_queue
Queue for processes that wait for slave scanning.
Definition: master.h:269
#define EC_MASTER_ERR(master, fmt, args...)
Convenience macro for printing master-specific errors to syslog.
Definition: master.h:80
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:295
ec_device_index_t device_index
Device via which the datagram shall be / was sent.
Definition: datagram.h:91
int ec_fsm_master_idle(const ec_fsm_master_t *fsm)
Definition: fsm_master.c:164
32 bit.
Definition: globals.h:211
void ec_master_clear_slaves(ec_master_t *master)
Clear all slaves.
Definition: master.c:606
#define EC_SLAVE_INFO(slave, fmt, args...)
Convenience macro for printing slave-specific information to syslog.
Definition: slave.h:63
void ec_fsm_sii_clear(ec_fsm_sii_t *fsm)
Destructor.
Definition: fsm_sii.c:96
int idle
state machine is in idle phase
Definition: fsm_master.h:75
void ec_fsm_master_state_start(ec_fsm_master_t *)
Master state: START.
Definition: fsm_master.c:192
uint16_t effective_alias
Effective alias address.
Definition: slave.h:223
int ec_fsm_sii_success(ec_fsm_sii_t *fsm)
Returns, if the master startup state machine terminated with success.
Definition: fsm_sii.c:179
#define EC_READ_U16(DATA)
Read a 16-bit unsigned value from EtherCAT data.
Definition: ecrt.h:2554
void ec_master_eoe_start(ec_master_t *master)
Starts Ethernet over EtherCAT processing on demand.
Definition: master.c:1997
void ec_datagram_print_state(const ec_datagram_t *datagram)
Prints the state of a datagram.
Definition: datagram.c:587
Mailbox functionality.
ec_master_t * master
master the FSM runs on
Definition: fsm_master.h:68
uint8_t * data
Pointer to data memory.
Definition: reg_request.h:51
#define EC_STATE_STRING_SIZE
Minimum size of a buffer used with ec_state_string().
Definition: globals.h:65
#define EC_WRITE_U64(DATA, VAL)
Write a 64-bit unsigned value to EtherCAT data.
Definition: ecrt.h:2693
#define EC_MAX_PORTS
Maximum number of slave ports.
Definition: ecrt.h:217
void ec_fsm_master_state_clear_addresses(ec_fsm_master_t *)
Master state: CLEAR ADDRESSES.
Definition: fsm_master.c:953
void ec_slave_init(ec_slave_t *slave, ec_master_t *master, ec_device_index_t dev_idx, uint16_t ring_position, uint16_t station_address)
Slave constructor.
Definition: slave.c:62
ec_direction_t dir
Direction.
Definition: reg_request.h:52
void ec_fsm_sii_init(ec_fsm_sii_t *fsm)
Constructor.
Definition: fsm_sii.c:83
Queued for sending.
Definition: datagram.h:76
uint32_t receive_time
Port receive times for delay measurement.
Definition: slave.h:143
Timed out (dequeued).
Definition: datagram.h:79
Slave port.
Definition: slave.h:139
void ec_fsm_master_state_reboot_slave(ec_fsm_master_t *)
Master state: REBOOT SLAVE.
Definition: fsm_master.c:774
unsigned int retries
retries on datagram timeout.
Definition: fsm_master.h:70
uint8_t base_dc_supported
Distributed clocks are supported.
Definition: slave.h:257
void ec_fsm_master_state_write_sii(ec_fsm_master_t *)
Master state: WRITE SII.
Definition: fsm_master.c:1374
uint8_t * data
Datagram payload.
Definition: datagram.h:95
#define EC_READ_U8(DATA)
Read an 8-bit unsigned value from EtherCAT data.
Definition: ecrt.h:2538
void ec_master_slaves_not_available(ec_master_t *master)
Set flag to say that the slaves are not available for slave request processing.
Definition: master.c:585
int ec_fsm_master_exec(ec_fsm_master_t *fsm)
Executes the current state of the state machine.
Definition: fsm_master.c:145
EtherCAT slave configuration structure.
ec_sii_t sii
Extracted SII data.
Definition: slave.h:207
size_t mem_size
Datagram data memory size.
Definition: datagram.h:97
void ec_fsm_master_enter_dc_measure_delays(ec_fsm_master_t *fsm)
Start measuring DC delays.
Definition: fsm_master.c:886
ec_device_index_t device_index
Index of device the slave responds on.
Definition: slave.h:217
Unused and should not be queued (dequeued).
Definition: datagram.h:81
ec_slave_t * slave
current slave
Definition: fsm_master.h:86
Values written by the master.
Definition: ecrt.h:438
Received (dequeued).
Definition: datagram.h:78
uint8_t scan_required
Scan required.
Definition: slave.h:270
off_t sii_index
index to SII write request data
Definition: fsm_master.h:88
#define EC_MASTER_INFO(master, fmt, args...)
Convenience macro for printing master-specific information to syslog.
Definition: master.h:68
unsigned int error_flag
Stop processing after an error.
Definition: slave.h:239
void ec_fsm_master_state_dc_read_old_times(ec_fsm_master_t *)
Master state: DC READ OLD TIMES.
Definition: fsm_master.c:819
unsigned int config_changed
The configuration changed.
Definition: master.h:233
EtherCAT master.
Definition: master.h:202
struct list_head list
List item.
Definition: reg_request.h:49
ec_device_index_t dev_idx
Current device index (for scanning etc.).
Definition: fsm_master.h:73
#define EC_READ_U64(DATA)
Read a 64-bit unsigned value from EtherCAT data.
Definition: ecrt.h:2586
ec_device_t devices[EC_MAX_NUM_DEVICES]
EtherCAT devices.
Definition: master.h:219
ec_lock_t scan_sem
Semaphore protecting the scan_busy variable and the allow_scan flag.
Definition: master.h:267
unsigned int config_busy
State of slave configuration.
Definition: master.h:272
const uint16_t * words
Pointer to the data words.
Definition: fsm_master.h:57
void ec_fsm_master_clear(ec_fsm_master_t *fsm)
Destructor.
Definition: fsm_master.c:103
EtherCAT FoE state machines.
void ec_slave_set_al_status(ec_slave_t *slave, ec_slave_state_t new_state)
Sets the application state of a slave.
Definition: slave.c:414
unknown state
Definition: globals.h:160
void ec_fsm_master_enter_write_system_times(ec_fsm_master_t *)
Start writing DC system times.
Definition: fsm_master.c:1098
void ec_master_eoe_stop(ec_master_t *master)
Stops the Ethernet over EtherCAT processing.
Definition: master.c:2036
uint8_t link_state[EC_MAX_NUM_DEVICES]
Last link state for every device.
Definition: fsm_master.h:77
void ec_fsm_master_state_dc_read_offset(ec_fsm_master_t *)
Master state: DC READ OFFSET.
Definition: fsm_master.c:1214
void ec_fsm_reboot_clear(ec_fsm_reboot_t *fsm)
Destructor.
Definition: fsm_reboot.c:82
unsigned int force_config
Force (re-)configuration.
Definition: slave.h:240
int ec_datagram_bwr(ec_datagram_t *datagram, uint16_t mem_address, size_t data_size)
Initializes an EtherCAT BWR datagram.
Definition: datagram.c:415
void ec_master_slaves_available(ec_master_t *master)
Set flag to say that the slaves are now available for slave request processing.
Definition: master.c:597