IgH EtherCAT Master  1.5.3
fsm_master.c
Go to the documentation of this file.
1 /******************************************************************************
2  *
3  * Copyright (C) 2006-2023 Florian Pose, Ingenieurgemeinschaft IgH
4  *
5  * This file is part of the IgH EtherCAT Master.
6  *
7  * The IgH EtherCAT Master is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License version 2, as
9  * published by the Free Software Foundation.
10  *
11  * The IgH EtherCAT Master is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
14  * Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License along
17  * with the IgH EtherCAT Master; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19  *
20  * ---
21  *
22  * The license mentioned above concerns the source code only. Using the
23  * EtherCAT technology and brand is only permitted in compliance with the
24  * industrial property and similar rights of Beckhoff Automation GmbH.
25  *
26  *****************************************************************************/
27 
32 /*****************************************************************************/
33 
34 #include "globals.h"
35 #include "master.h"
36 #include "mailbox.h"
37 #include "slave_config.h"
38 #ifdef EC_EOE
39 #include "ethernet.h"
40 #endif
41 
42 #include "fsm_master.h"
43 #include "fsm_foe.h"
44 
45 /*****************************************************************************/
46 
49 #define EC_SYSTEM_TIME_TOLERANCE_NS 1000000
50 
51 /*****************************************************************************/
52 
68 
71 
72 /*****************************************************************************/
73 
77  ec_fsm_master_t *fsm,
78  ec_master_t *master,
79  ec_datagram_t *datagram
80  )
81 {
82  fsm->master = master;
83  fsm->datagram = datagram;
84 
85  // inits the member variables state, idle, dev_idx, link_state,
86  // slaves_responding, slave_states and rescan_required
88 
89  fsm->retries = 0;
90  fsm->scan_jiffies = 0;
91  fsm->slave = NULL;
92  fsm->sii_request = NULL;
93  fsm->sii_index = 0;
94  fsm->sdo_request = NULL;
95  fsm->soe_request = NULL;
96 
97  // init sub-state-machines
98  ec_fsm_coe_init(&fsm->fsm_coe);
99  ec_fsm_soe_init(&fsm->fsm_soe);
100  ec_fsm_pdo_init(&fsm->fsm_pdo, &fsm->fsm_coe);
103  &fsm->fsm_change, &fsm->fsm_coe, &fsm->fsm_soe, &fsm->fsm_pdo);
105  &fsm->fsm_slave_config, &fsm->fsm_pdo);
106  ec_fsm_sii_init(&fsm->fsm_sii, fsm->datagram);
107 }
108 
109 /*****************************************************************************/
110 
114  ec_fsm_master_t *fsm
115  )
116 {
117  // clear sub-state machines
118  ec_fsm_coe_clear(&fsm->fsm_coe);
119  ec_fsm_soe_clear(&fsm->fsm_soe);
120  ec_fsm_pdo_clear(&fsm->fsm_pdo);
124  ec_fsm_sii_clear(&fsm->fsm_sii);
125 }
126 
127 /*****************************************************************************/
128 
132  ec_fsm_master_t *fsm
133  )
134 {
135  ec_device_index_t dev_idx;
136 
138  fsm->idle = 0;
139  fsm->dev_idx = EC_DEVICE_MAIN;
140 
141  for (dev_idx = EC_DEVICE_MAIN;
142  dev_idx < ec_master_num_devices(fsm->master); dev_idx++) {
143  fsm->link_state[dev_idx] = 0;
144  fsm->slaves_responding[dev_idx] = 0;
145  fsm->slave_states[dev_idx] = EC_SLAVE_STATE_UNKNOWN;
146  }
147 
148  fsm->rescan_required = 0;
149 }
150 
151 /*****************************************************************************/
152 
161  ec_fsm_master_t *fsm
162  )
163 {
164  if (fsm->datagram->state == EC_DATAGRAM_SENT
165  || fsm->datagram->state == EC_DATAGRAM_QUEUED) {
166  // datagram was not sent or received yet.
167  return 0;
168  }
169 
170  fsm->state(fsm);
171  return 1;
172 }
173 
174 /*****************************************************************************/
175 
180  const ec_fsm_master_t *fsm
181  )
182 {
183  return fsm->idle;
184 }
185 
186 /*****************************************************************************/
187 
191  ec_fsm_master_t *fsm
192  )
193 {
194  fsm->dev_idx = EC_DEVICE_MAIN;
196  fsm->state(fsm); // execute immediately
197 }
198 
199 /******************************************************************************
200  * Master state machine
201  *****************************************************************************/
202 
208  ec_fsm_master_t *fsm
209  )
210 {
211  ec_master_t *master = fsm->master;
212 
213  fsm->idle = 1;
214 
215  // check for emergency requests
216  if (!list_empty(&master->emerg_reg_requests)) {
217  ec_reg_request_t *request;
218 
219  // get first request
220  request = list_entry(master->emerg_reg_requests.next,
221  ec_reg_request_t, list);
222  list_del_init(&request->list); // dequeue
223  request->state = EC_INT_REQUEST_BUSY;
224 
225  if (request->transfer_size > fsm->datagram->mem_size) {
226  EC_MASTER_ERR(master, "Emergency request data too large!\n");
227  request->state = EC_INT_REQUEST_FAILURE;
228  wake_up_all(&master->request_queue);
229  fsm->state(fsm); // continue
230  return;
231  }
232 
233  if (request->dir != EC_DIR_OUTPUT) {
234  EC_MASTER_ERR(master, "Emergency requests must be"
235  " write requests!\n");
236  request->state = EC_INT_REQUEST_FAILURE;
237  wake_up_all(&master->request_queue);
238  fsm->state(fsm); // continue
239  return;
240  }
241 
242  EC_MASTER_DBG(master, 1, "Writing emergency register request...\n");
243  ec_datagram_apwr(fsm->datagram, request->ring_position,
244  request->address, request->transfer_size);
245  memcpy(fsm->datagram->data, request->data, request->transfer_size);
247  request->state = EC_INT_REQUEST_SUCCESS;
248  wake_up_all(&master->request_queue);
249  return;
250  }
251 
252  ec_datagram_brd(fsm->datagram, 0x0130, 2);
254  fsm->datagram->device_index = fsm->dev_idx;
255  fsm->retries = EC_FSM_RETRIES;
257 }
258 
259 /*****************************************************************************/
260 
266  ec_fsm_master_t *fsm
267  )
268 {
269  ec_datagram_t *datagram = fsm->datagram;
270  unsigned int i, size;
271  ec_slave_t *slave;
272  ec_master_t *master = fsm->master;
273 
274  if (datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--) {
275  return;
276  }
277 
278  // bus topology change?
279  if (datagram->working_counter != fsm->slaves_responding[fsm->dev_idx]) {
280  fsm->rescan_required = 1;
281  fsm->slaves_responding[fsm->dev_idx] = datagram->working_counter;
282  EC_MASTER_INFO(master, "%u slave(s) responding on %s device.\n",
283  fsm->slaves_responding[fsm->dev_idx],
284  ec_device_names[fsm->dev_idx != 0]);
285  }
286 
287  if (fsm->link_state[fsm->dev_idx] &&
288  !master->devices[fsm->dev_idx].link_state) {
289  ec_device_index_t dev_idx;
290 
291  EC_MASTER_DBG(master, 1, "Master state machine detected "
292  "link down on %s device. Clearing slave list.\n",
293  ec_device_names[fsm->dev_idx != 0]);
294 
295 #ifdef EC_EOE
296  ec_master_eoe_stop(master);
298 #endif
299  ec_master_clear_slaves(master);
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  down(&master->scan_sem);
335  if (!master->allow_scan) {
336  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  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 
349 #ifdef EC_EOE
350  ec_master_eoe_stop(master);
352 #endif
353  ec_master_clear_slaves(master);
354 
355  for (dev_idx = EC_DEVICE_MAIN;
356  dev_idx < ec_master_num_devices(master); dev_idx++) {
357  count += fsm->slaves_responding[dev_idx];
358  }
359 
360  if (!count) {
361  // no slaves present -> finish state machine.
362  master->scan_busy = 0;
363  wake_up_interruptible(&master->scan_queue);
365  return;
366  }
367 
368  size = sizeof(ec_slave_t) * count;
369  if (!(master->slaves =
370  (ec_slave_t *) kmalloc(size, GFP_KERNEL))) {
371  EC_MASTER_ERR(master, "Failed to allocate %u bytes"
372  " of slave memory!\n", size);
373  master->scan_busy = 0;
374  wake_up_interruptible(&master->scan_queue);
376  return;
377  }
378 
379  // init slaves
380  dev_idx = EC_DEVICE_MAIN;
381  next_dev_slave = fsm->slaves_responding[dev_idx];
382  ring_position = 0;
383  for (i = 0; i < count; i++, ring_position++) {
384  slave = master->slaves + i;
385  while (i >= next_dev_slave) {
386  dev_idx++;
387  next_dev_slave += fsm->slaves_responding[dev_idx];
388  ring_position = 0;
389  }
390 
391  ec_slave_init(slave, master, dev_idx, ring_position, i + 1);
392 
393  // do not force reconfiguration in operation phase to avoid
394  // unnecesssary process data interruptions
395  if (master->phase != EC_OPERATION) {
396  slave->force_config = 1;
397  }
398  }
399  master->slave_count = count;
400  master->fsm_slave = master->slaves;
401 
402  /* start with first device with slaves responding; at least one
403  * has responding slaves, otherwise count would be zero. */
404  fsm->dev_idx = EC_DEVICE_MAIN;
405  while (!fsm->slaves_responding[fsm->dev_idx]) {
406  fsm->dev_idx++;
407  }
408 
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 
420  EC_MASTER_DBG(master, 1, "Configuration changed.\n");
421 
422  fsm->slave = master->slaves; // begin with first slave
424 
425  } else {
426  // fetch state from first slave
427  fsm->slave = master->slaves;
429  0x0130, 2);
430  ec_datagram_zero(datagram);
431  fsm->datagram->device_index = fsm->slave->device_index;
432  fsm->retries = EC_FSM_RETRIES;
434  }
435  } else {
437  }
438 }
439 
440 /*****************************************************************************/
441 
447  ec_fsm_master_t *fsm
448  )
449 {
450  ec_master_t *master = fsm->master;
451  ec_sii_write_request_t *request;
452  ec_slave_config_t *config;
453  ec_flag_t *flag;
454  int assign_to_pdi;
455 
456  // search the first request to be processed
457  while (1) {
458  if (list_empty(&master->sii_requests))
459  break;
460 
461  // get first request
462  request = list_entry(master->sii_requests.next,
463  ec_sii_write_request_t, list);
464  list_del_init(&request->list); // dequeue
465  request->state = EC_INT_REQUEST_BUSY;
466 
467  assign_to_pdi = 0;
468  config = request->slave->config;
469  if (config) {
470  flag = ec_slave_config_find_flag(config, "AssignToPdi");
471  if (flag) {
472  assign_to_pdi = flag->value;
473  }
474  }
475 
476  if (assign_to_pdi) {
477  fsm->sii_request = request;
478  EC_SLAVE_DBG(request->slave, 1,
479  "Assigning SII back to EtherCAT.\n");
481  0x0500, 0x01);
482  EC_WRITE_U8(fsm->datagram->data, 0x00); // EtherCAT
483  fsm->retries = EC_FSM_RETRIES;
485  return 1;
486  }
487 
488  // found pending SII write operation. execute it!
489  EC_SLAVE_DBG(request->slave, 1, "Writing SII data...\n");
490  fsm->sii_request = request;
491  fsm->sii_index = 0;
492  ec_fsm_sii_write(&fsm->fsm_sii, request->slave, request->offset,
495  fsm->state(fsm); // execute immediately
496  return 1;
497  }
498 
499  return 0;
500 }
501 
502 /*****************************************************************************/
503 
509  ec_fsm_master_t *fsm
510  )
511 {
512  ec_master_t *master = fsm->master;
513  ec_slave_t *slave;
514  ec_sdo_request_t *sdo_req;
515  ec_soe_request_t *soe_req;
516 
517  // search for internal requests to be processed
518  for (slave = master->slaves;
519  slave < master->slaves + master->slave_count;
520  slave++) {
521 
522  if (!slave->config) {
523  continue;
524  }
525 
526  list_for_each_entry(sdo_req, &slave->config->sdo_requests, list) {
527  if (sdo_req->state == EC_INT_REQUEST_QUEUED) {
528 
529  if (ec_sdo_request_timed_out(sdo_req)) {
530  sdo_req->state = EC_INT_REQUEST_FAILURE;
531  EC_SLAVE_DBG(slave, 1, "Internal SDO request"
532  " timed out.\n");
533  continue;
534  }
535 
536  if (slave->current_state == EC_SLAVE_STATE_INIT) {
537  sdo_req->state = EC_INT_REQUEST_FAILURE;
538  continue;
539  }
540 
541  sdo_req->state = EC_INT_REQUEST_BUSY;
542  EC_SLAVE_DBG(slave, 1, "Processing internal"
543  " SDO request...\n");
544  fsm->idle = 0;
545  fsm->sdo_request = sdo_req;
546  fsm->slave = slave;
548  ec_fsm_coe_transfer(&fsm->fsm_coe, slave, sdo_req);
549  ec_fsm_coe_exec(&fsm->fsm_coe, fsm->datagram);
550  return 1;
551  }
552  }
553 
554  list_for_each_entry(soe_req, &slave->config->soe_requests, list) {
555  if (soe_req->state == EC_INT_REQUEST_QUEUED) {
556 
557  if (ec_soe_request_timed_out(soe_req)) {
558  soe_req->state = EC_INT_REQUEST_FAILURE;
559  EC_SLAVE_DBG(slave, 1, "Internal SoE request"
560  " timed out.\n");
561  continue;
562  }
563 
564  if (slave->current_state == EC_SLAVE_STATE_INIT) {
565  soe_req->state = EC_INT_REQUEST_FAILURE;
566  continue;
567  }
568 
569  soe_req->state = EC_INT_REQUEST_BUSY;
570  EC_SLAVE_DBG(slave, 1, "Processing internal"
571  " SoE request...\n");
572  fsm->idle = 0;
573  fsm->soe_request = soe_req;
574  fsm->slave = slave;
576  ec_fsm_soe_transfer(&fsm->fsm_soe, slave, soe_req);
577  ec_fsm_soe_exec(&fsm->fsm_soe, fsm->datagram);
578  return 1;
579  }
580  }
581  }
582  return 0;
583 }
584 
585 /*****************************************************************************/
586 
592  ec_fsm_master_t *fsm
593  )
594 {
595  ec_master_t *master = fsm->master;
596  ec_slave_t *slave;
597 
598  // Check for pending internal SDO or SoE requests
600  return;
601  }
602 
603  // enable processing of requests
604  for (slave = master->slaves;
605  slave < master->slaves + master->slave_count;
606  slave++) {
607  ec_fsm_slave_set_ready(&slave->fsm);
608  }
609 
610  // check, if slaves have an SDO dictionary to read out.
611  for (slave = master->slaves;
612  slave < master->slaves + master->slave_count;
613  slave++) {
614  if (!(slave->sii.mailbox_protocols & EC_MBOX_COE)
615  || (slave->sii.has_general
616  && !slave->sii.coe_details.enable_sdo_info)
617  || slave->sdo_dictionary_fetched
620  || jiffies - slave->jiffies_preop < EC_WAIT_SDO_DICT * HZ
621  ) continue;
622 
623  EC_SLAVE_DBG(slave, 1, "Fetching SDO dictionary.\n");
624 
625  slave->sdo_dictionary_fetched = 1;
626 
627  // start fetching SDO dictionary
628  fsm->idle = 0;
629  fsm->slave = slave;
631  ec_fsm_coe_dictionary(&fsm->fsm_coe, slave);
632  ec_fsm_coe_exec(&fsm->fsm_coe, fsm->datagram); // execute immediately
633  fsm->datagram->device_index = fsm->slave->device_index;
634  return;
635  }
636 
637  // check for pending SII write operations.
639  return; // SII write request found
640  }
641 
643 }
644 
645 /*****************************************************************************/
646 
650  ec_fsm_master_t *fsm
651  )
652 {
653  ec_master_t *master = fsm->master;
654 
655  // is there another slave to query?
656  fsm->slave++;
657  if (fsm->slave < master->slaves + master->slave_count) {
658  // fetch state from next slave
659  fsm->idle = 1;
661  fsm->slave->station_address, 0x0130, 2);
663  fsm->datagram->device_index = fsm->slave->device_index;
664  fsm->retries = EC_FSM_RETRIES;
666  return;
667  }
668 
669  // all slaves processed
671 }
672 
673 /*****************************************************************************/
674 
678  ec_fsm_master_t *fsm
679  )
680 {
681  ec_master_t *master = fsm->master;
682  ec_slave_t *slave = fsm->slave;
683 
684  if (master->config_changed) {
685  master->config_changed = 0;
686 
687  // abort iterating through slaves,
688  // first compensate DC system time offsets,
689  // then begin configuring at slave 0
690  EC_MASTER_DBG(master, 1, "Configuration changed"
691  " (aborting state check).\n");
692 
693  fsm->slave = master->slaves; // begin with first slave
695  return;
696  }
697 
698  // Does the slave have to be configured?
699  if ((slave->current_state != slave->requested_state
700  || slave->force_config) && !slave->error_flag) {
701 
702  // Start slave configuration
703  down(&master->config_sem);
704  master->config_busy = 1;
705  up(&master->config_sem);
706 
707  if (master->debug_level) {
708  char old_state[EC_STATE_STRING_SIZE],
709  new_state[EC_STATE_STRING_SIZE];
710  ec_state_string(slave->current_state, old_state, 0);
711  ec_state_string(slave->requested_state, new_state, 0);
712  EC_SLAVE_DBG(slave, 1, "Changing state from %s to %s%s.\n",
713  old_state, new_state,
714  slave->force_config ? " (forced)" : "");
715  }
716 
717  fsm->idle = 0;
720  fsm->state(fsm); // execute immediately
721  fsm->datagram->device_index = fsm->slave->device_index;
722  return;
723  }
724 
725  // process next slave
727 }
728 
729 /*****************************************************************************/
730 
736  ec_fsm_master_t *fsm
737  )
738 {
739  ec_slave_t *slave = fsm->slave;
740  ec_datagram_t *datagram = fsm->datagram;
741 
742  if (datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--) {
743  return;
744  }
745 
746  if (datagram->state != EC_DATAGRAM_RECEIVED) {
747  EC_SLAVE_ERR(slave, "Failed to receive AL state datagram: ");
748  ec_datagram_print_state(datagram);
750  return;
751  }
752 
753  // did the slave not respond to its station address?
754  if (datagram->working_counter != 1) {
755  if (!slave->error_flag) {
756  slave->error_flag = 1;
757  EC_SLAVE_DBG(slave, 1, "Slave did not respond to state query.\n");
758  }
759  fsm->rescan_required = 1;
761  return;
762  }
763 
764  // A single slave responded
765  ec_slave_set_state(slave, EC_READ_U8(datagram->data));
766 
767  if (!slave->error_flag) {
768  // Check, if new slave state has to be acknowledged
769  if (slave->current_state & EC_SLAVE_STATE_ACK_ERR) {
770  fsm->idle = 0;
772  ec_fsm_change_ack(&fsm->fsm_change, slave);
773  fsm->state(fsm); // execute immediately
774  return;
775  }
776 
777  // No acknowlegde necessary; check for configuration
779  return;
780  }
781 
782  // slave has error flag set; process next one
784 }
785 
786 /*****************************************************************************/
787 
791  ec_fsm_master_t *fsm
792  )
793 {
794  ec_slave_t *slave = fsm->slave;
795 
796  if (ec_fsm_change_exec(&fsm->fsm_change)) {
797  return;
798  }
799 
800  if (!ec_fsm_change_success(&fsm->fsm_change)) {
801  fsm->slave->error_flag = 1;
802  EC_SLAVE_ERR(slave, "Failed to acknowledge state change.\n");
803  }
804 
806 }
807 
808 /*****************************************************************************/
809 
813  ec_fsm_master_t *fsm
814  )
815 {
816  // broadcast clear all station addresses
817  ec_datagram_bwr(fsm->datagram, 0x0010, 2);
818  EC_WRITE_U16(fsm->datagram->data, 0x0000);
819  fsm->datagram->device_index = fsm->dev_idx;
820  fsm->retries = EC_FSM_RETRIES;
822 }
823 
824 /*****************************************************************************/
825 
829  ec_fsm_master_t *fsm
830  )
831 {
832  ec_master_t *master = fsm->master;
833  ec_datagram_t *datagram = fsm->datagram;
834 
835  if (datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--) {
836  return;
837  }
838 
839  if (datagram->state != EC_DATAGRAM_RECEIVED) {
840  EC_MASTER_ERR(master, "Failed to receive address"
841  " clearing datagram on %s link: ",
842  ec_device_names[fsm->dev_idx != 0]);
843  ec_datagram_print_state(datagram);
844  master->scan_busy = 0;
845  wake_up_interruptible(&master->scan_queue);
847  return;
848  }
849 
850  if (datagram->working_counter != fsm->slaves_responding[fsm->dev_idx]) {
851  EC_MASTER_WARN(master, "Failed to clear station addresses on %s link:"
852  " Cleared %u of %u",
853  ec_device_names[fsm->dev_idx != 0], datagram->working_counter,
854  fsm->slaves_responding[fsm->dev_idx]);
855  }
856 
857  EC_MASTER_DBG(master, 1, "Sending broadcast-write"
858  " to measure transmission delays on %s link.\n",
859  ec_device_names[fsm->dev_idx != 0]);
860 
861  ec_datagram_bwr(datagram, 0x0900, 1);
862  ec_datagram_zero(datagram);
863  fsm->datagram->device_index = fsm->dev_idx;
864  fsm->retries = EC_FSM_RETRIES;
866 }
867 
868 /*****************************************************************************/
869 
873  ec_fsm_master_t *fsm
874  )
875 {
876  ec_master_t *master = fsm->master;
877  ec_datagram_t *datagram = fsm->datagram;
878 
879  if (datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--) {
880  return;
881  }
882 
883  if (datagram->state != EC_DATAGRAM_RECEIVED) {
884  EC_MASTER_ERR(master, "Failed to receive delay measuring datagram"
885  " on %s link: ", ec_device_names[fsm->dev_idx != 0]);
886  ec_datagram_print_state(datagram);
887  master->scan_busy = 0;
888  wake_up_interruptible(&master->scan_queue);
890  return;
891  }
892 
893  EC_MASTER_DBG(master, 1, "%u slaves responded to delay measuring"
894  " on %s link.\n",
895  datagram->working_counter, ec_device_names[fsm->dev_idx != 0]);
896 
897  do {
898  fsm->dev_idx++;
899  } while (fsm->dev_idx < ec_master_num_devices(master) &&
900  !fsm->slaves_responding[fsm->dev_idx]);
901  if (fsm->dev_idx < ec_master_num_devices(master)) {
903  return;
904  }
905 
906  EC_MASTER_INFO(master, "Scanning bus.\n");
907 
908  // begin scanning of slaves
909  fsm->slave = master->slaves;
910  EC_MASTER_DBG(master, 1, "Scanning slave %u on %s link.\n",
911  fsm->slave->ring_position,
912  ec_device_names[fsm->slave->device_index != 0]);
915  ec_fsm_slave_scan_exec(&fsm->fsm_slave_scan); // execute immediately
916  fsm->datagram->device_index = fsm->slave->device_index;
917 }
918 
919 /*****************************************************************************/
920 
926  ec_fsm_master_t *fsm
927  )
928 {
929  ec_master_t *master = fsm->master;
930 #ifdef EC_EOE
931  ec_slave_t *slave = fsm->slave;
932 #endif
933 
935  return;
936  }
937 
938 #ifdef EC_EOE
939  if (slave->sii.mailbox_protocols & EC_MBOX_EOE) {
940  // create EoE handler for this slave
941  ec_eoe_t *eoe;
942  if (!(eoe = kmalloc(sizeof(ec_eoe_t), GFP_KERNEL))) {
943  EC_SLAVE_ERR(slave, "Failed to allocate EoE handler memory!\n");
944  } else if (ec_eoe_init(eoe, slave)) {
945  EC_SLAVE_ERR(slave, "Failed to init EoE handler!\n");
946  kfree(eoe);
947  } else {
948  list_add_tail(&eoe->list, &master->eoe_handlers);
949  }
950  }
951 #endif
952 
953  // another slave to fetch?
954  fsm->slave++;
955  if (fsm->slave < master->slaves + master->slave_count) {
956  EC_MASTER_DBG(master, 1, "Scanning slave %u on %s link.\n",
957  fsm->slave->ring_position,
958  ec_device_names[fsm->slave->device_index != 0]);
960  ec_fsm_slave_scan_exec(&fsm->fsm_slave_scan); // execute immediately
961  fsm->datagram->device_index = fsm->slave->device_index;
962  return;
963  }
964 
965  EC_MASTER_INFO(master, "Bus scanning completed in %lu ms.\n",
966  (jiffies - fsm->scan_jiffies) * 1000 / HZ);
967 
968  master->scan_busy = 0;
969  wake_up_interruptible(&master->scan_queue);
970 
971  ec_master_calc_dc(master);
972 
973  // Attach slave configurations
975 
976 #ifdef EC_EOE
977  // check if EoE processing has to be started
978  ec_master_eoe_start(master);
979 #endif
980 
981  if (master->slave_count) {
982  master->config_changed = 0;
983 
984  fsm->slave = master->slaves; // begin with first slave
986  } else {
988  }
989 }
990 
991 /*****************************************************************************/
992 
998  ec_fsm_master_t *fsm
999  )
1000 {
1001  ec_master_t *master = fsm->master;
1002 
1004  return;
1005  }
1006 
1007  fsm->slave->force_config = 0;
1008 
1009  // configuration finished
1010  master->config_busy = 0;
1011  wake_up_interruptible(&master->config_queue);
1012 
1014  // TODO: mark slave_config as failed.
1015  }
1016 
1017  fsm->idle = 1;
1019 }
1020 
1021 /*****************************************************************************/
1022 
1026  ec_fsm_master_t *fsm
1027  )
1028 {
1029  ec_master_t *master = fsm->master;
1030 
1031  if (master->dc_ref_time) {
1032 
1033  while (fsm->slave < master->slaves + master->slave_count) {
1034  if (!fsm->slave->base_dc_supported
1035  || !fsm->slave->has_dc_system_time) {
1036  fsm->slave++;
1037  continue;
1038  }
1039 
1040  EC_SLAVE_DBG(fsm->slave, 1, "Checking system time offset.\n");
1041 
1042  // read DC system time (0x0910, 64 bit)
1043  // gap (64 bit)
1044  // and time offset (0x0920, 64 bit)
1046  0x0910, 24);
1047  fsm->datagram->device_index = fsm->slave->device_index;
1048  fsm->retries = EC_FSM_RETRIES;
1050  return;
1051  }
1052 
1053  } else {
1054  if (master->active) {
1055  EC_MASTER_WARN(master, "No application time received up to now,"
1056  " but master already active.\n");
1057  } else {
1058  EC_MASTER_DBG(master, 1, "No app_time received up to now.\n");
1059  }
1060  }
1061 
1062  // scanning and setting system times complete
1063  ec_master_request_op(master);
1064  ec_fsm_master_restart(fsm);
1065 }
1066 
1067 /*****************************************************************************/
1068 
1074  ec_fsm_master_t *fsm,
1075  u64 system_time,
1076  u64 old_offset,
1077  unsigned long jiffies_since_read
1078  )
1079 {
1080  ec_slave_t *slave = fsm->slave;
1081  u32 correction, system_time32, old_offset32, new_offset;
1082  s32 time_diff;
1083 
1084  system_time32 = (u32) system_time;
1085  old_offset32 = (u32) old_offset;
1086 
1087  // correct read system time by elapsed time since read operation
1088  correction = jiffies_since_read * 1000 / HZ * 1000000;
1089  system_time32 += correction;
1090  time_diff = (u32) slave->master->app_time - system_time32;
1091 
1092  EC_SLAVE_DBG(slave, 1, "DC 32 bit system time offset calculation:"
1093  " system_time=%u (corrected with %u),"
1094  " app_time=%llu, diff=%i\n",
1095  system_time32, correction,
1096  slave->master->app_time, time_diff);
1097 
1098  if (EC_ABS(time_diff) > EC_SYSTEM_TIME_TOLERANCE_NS) {
1099  new_offset = time_diff + old_offset32;
1100  EC_SLAVE_DBG(slave, 1, "Setting time offset to %u (was %u)\n",
1101  new_offset, old_offset32);
1102  return (u64) new_offset;
1103  } else {
1104  EC_SLAVE_DBG(slave, 1, "Not touching time offset.\n");
1105  return old_offset;
1106  }
1107 }
1108 
1109 /*****************************************************************************/
1110 
1116  ec_fsm_master_t *fsm,
1117  u64 system_time,
1118  u64 old_offset,
1119  unsigned long jiffies_since_read
1120  )
1121 {
1122  ec_slave_t *slave = fsm->slave;
1123  u64 new_offset, correction;
1124  s64 time_diff;
1125 
1126  // correct read system time by elapsed time since read operation
1127  correction = (u64) (jiffies_since_read * 1000 / HZ) * 1000000;
1128  system_time += correction;
1129  time_diff = fsm->slave->master->app_time - system_time;
1130 
1131  EC_SLAVE_DBG(slave, 1, "DC 64 bit system time offset calculation:"
1132  " system_time=%llu (corrected with %llu),"
1133  " app_time=%llu, diff=%lli\n",
1134  system_time, correction,
1135  slave->master->app_time, time_diff);
1136 
1137  if (EC_ABS(time_diff) > EC_SYSTEM_TIME_TOLERANCE_NS) {
1138  new_offset = time_diff + old_offset;
1139  EC_SLAVE_DBG(slave, 1, "Setting time offset to %llu (was %llu)\n",
1140  new_offset, old_offset);
1141  } else {
1142  new_offset = old_offset;
1143  EC_SLAVE_DBG(slave, 1, "Not touching time offset.\n");
1144  }
1145 
1146  return new_offset;
1147 }
1148 
1149 /*****************************************************************************/
1150 
1154  ec_fsm_master_t *fsm
1155  )
1156 {
1157  ec_datagram_t *datagram = fsm->datagram;
1158  ec_slave_t *slave = fsm->slave;
1159  u64 system_time, old_offset, new_offset;
1160  unsigned long jiffies_since_read;
1161 
1162  if (datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--)
1163  return;
1164 
1165  if (datagram->state != EC_DATAGRAM_RECEIVED) {
1166  EC_SLAVE_ERR(slave, "Failed to receive DC times datagram: ");
1167  ec_datagram_print_state(datagram);
1168  fsm->slave++;
1170  return;
1171  }
1172 
1173  if (datagram->working_counter != 1) {
1174  EC_SLAVE_WARN(slave, "Failed to get DC times: ");
1175  ec_datagram_print_wc_error(datagram);
1176  fsm->slave++;
1178  return;
1179  }
1180 
1181  system_time = EC_READ_U64(datagram->data); // 0x0910
1182  old_offset = EC_READ_U64(datagram->data + 16); // 0x0920
1183  jiffies_since_read = jiffies - datagram->jiffies_sent;
1184 
1185  if (slave->base_dc_range == EC_DC_32) {
1186  new_offset = ec_fsm_master_dc_offset32(fsm,
1187  system_time, old_offset, jiffies_since_read);
1188  } else {
1189  new_offset = ec_fsm_master_dc_offset64(fsm,
1190  system_time, old_offset, jiffies_since_read);
1191  }
1192 
1193  // set DC system time offset and transmission delay
1194  ec_datagram_fpwr(datagram, slave->station_address, 0x0920, 12);
1195  EC_WRITE_U64(datagram->data, new_offset);
1196  EC_WRITE_U32(datagram->data + 8, slave->transmission_delay);
1197  fsm->datagram->device_index = slave->device_index;
1198  fsm->retries = EC_FSM_RETRIES;
1200 }
1201 
1202 /*****************************************************************************/
1203 
1207  ec_fsm_master_t *fsm
1208  )
1209 {
1210  ec_datagram_t *datagram = fsm->datagram;
1211  ec_slave_t *slave = fsm->slave;
1212 
1213  if (datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--)
1214  return;
1215 
1216  if (datagram->state != EC_DATAGRAM_RECEIVED) {
1217  EC_SLAVE_ERR(slave,
1218  "Failed to receive DC system time offset datagram: ");
1219  ec_datagram_print_state(datagram);
1220  fsm->slave++;
1222  return;
1223  }
1224 
1225  if (datagram->working_counter != 1) {
1226  EC_SLAVE_ERR(slave, "Failed to set DC system time offset: ");
1227  ec_datagram_print_wc_error(datagram);
1228  fsm->slave++;
1230  return;
1231  }
1232 
1233  fsm->slave++;
1235 }
1236 
1237 /*****************************************************************************/
1238 
1242  ec_fsm_master_t *fsm
1243  )
1244 {
1245  ec_datagram_t *datagram = fsm->datagram;
1246  ec_sii_write_request_t *request = fsm->sii_request;
1247  ec_slave_t *slave = request->slave;
1248 
1249  if (datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--)
1250  return;
1251 
1252  if (datagram->state != EC_DATAGRAM_RECEIVED) {
1253  EC_SLAVE_ERR(slave, "Failed to receive SII assignment datagram: ");
1254  ec_datagram_print_state(datagram);
1255  goto cont;
1256  }
1257 
1258  if (datagram->working_counter != 1) {
1259  EC_SLAVE_ERR(slave, "Failed to assign SII back to EtherCAT: ");
1260  ec_datagram_print_wc_error(datagram);
1261  goto cont;
1262  }
1263 
1264 cont:
1265  // found pending SII write operation. execute it!
1266  EC_SLAVE_DBG(slave, 1, "Writing SII data (after assignment)...\n");
1267  fsm->sii_index = 0;
1268  ec_fsm_sii_write(&fsm->fsm_sii, slave, request->offset,
1271  fsm->state(fsm); // execute immediately
1272 }
1273 
1274 /*****************************************************************************/
1275 
1279  ec_fsm_master_t *fsm
1280  )
1281 {
1282  ec_master_t *master = fsm->master;
1283  ec_sii_write_request_t *request = fsm->sii_request;
1284  ec_slave_t *slave = request->slave;
1285 
1286  if (ec_fsm_sii_exec(&fsm->fsm_sii)) return;
1287 
1288  if (!ec_fsm_sii_success(&fsm->fsm_sii)) {
1289  EC_SLAVE_ERR(slave, "Failed to write SII data.\n");
1290  request->state = EC_INT_REQUEST_FAILURE;
1291  wake_up_all(&master->request_queue);
1292  ec_fsm_master_restart(fsm);
1293  return;
1294  }
1295 
1296  fsm->sii_index++;
1297  if (fsm->sii_index < request->nwords) {
1298  ec_fsm_sii_write(&fsm->fsm_sii, slave,
1299  request->offset + fsm->sii_index,
1300  request->words + fsm->sii_index,
1302  ec_fsm_sii_exec(&fsm->fsm_sii); // execute immediately
1303  return;
1304  }
1305 
1306  // finished writing SII
1307  EC_SLAVE_DBG(slave, 1, "Finished writing %zu words of SII data.\n",
1308  request->nwords);
1309 
1310  if (request->offset <= 4 && request->offset + request->nwords > 4) {
1311  // alias was written
1312  slave->sii.alias = EC_READ_U16(request->words + 4);
1313  // TODO: read alias from register 0x0012
1314  slave->effective_alias = slave->sii.alias;
1315  }
1316  // TODO: Evaluate other SII contents!
1317 
1318  request->state = EC_INT_REQUEST_SUCCESS;
1319  wake_up_all(&master->request_queue);
1320 
1321  // check for another SII write request
1323  return; // processing another request
1324 
1325  ec_fsm_master_restart(fsm);
1326 }
1327 
1328 /*****************************************************************************/
1329 
1333  ec_fsm_master_t *fsm
1334  )
1335 {
1336  ec_slave_t *slave = fsm->slave;
1337  ec_master_t *master = fsm->master;
1338 
1339  if (ec_fsm_coe_exec(&fsm->fsm_coe, fsm->datagram)) {
1340  return;
1341  }
1342 
1343  if (!ec_fsm_coe_success(&fsm->fsm_coe)) {
1344  ec_fsm_master_restart(fsm);
1345  return;
1346  }
1347 
1348  // SDO dictionary fetching finished
1349 
1350  if (master->debug_level) {
1351  unsigned int sdo_count, entry_count;
1352  ec_slave_sdo_dict_info(slave, &sdo_count, &entry_count);
1353  EC_SLAVE_DBG(slave, 1, "Fetched %u SDOs and %u entries.\n",
1354  sdo_count, entry_count);
1355  }
1356 
1357  // attach pdo names from dictionary
1359 
1360  ec_fsm_master_restart(fsm);
1361 }
1362 
1363 /*****************************************************************************/
1364 
1368  ec_fsm_master_t *fsm
1369  )
1370 {
1371  ec_sdo_request_t *request = fsm->sdo_request;
1372 
1373  if (!request) {
1374  // configuration was cleared in the meantime
1375  ec_fsm_master_restart(fsm);
1376  return;
1377  }
1378 
1379  if (ec_fsm_coe_exec(&fsm->fsm_coe, fsm->datagram)) {
1380  return;
1381  }
1382 
1383  if (!ec_fsm_coe_success(&fsm->fsm_coe)) {
1384  EC_SLAVE_DBG(fsm->slave, 1,
1385  "Failed to process internal SDO request.\n");
1386  request->state = EC_INT_REQUEST_FAILURE;
1387  wake_up_all(&fsm->master->request_queue);
1388  ec_fsm_master_restart(fsm);
1389  return;
1390  }
1391 
1392  // SDO request finished
1393  request->state = EC_INT_REQUEST_SUCCESS;
1394  wake_up_all(&fsm->master->request_queue);
1395 
1396  EC_SLAVE_DBG(fsm->slave, 1, "Finished internal SDO request.\n");
1397 
1398  // check for another SDO/SoE request
1400  return; // processing another request
1401  }
1402 
1403  ec_fsm_master_restart(fsm);
1404 }
1405 
1406 /*****************************************************************************/
1407 
1411  ec_fsm_master_t *fsm
1412  )
1413 {
1414  ec_soe_request_t *request = fsm->soe_request;
1415 
1416  if (!request) {
1417  // configuration was cleared in the meantime
1418  ec_fsm_master_restart(fsm);
1419  return;
1420  }
1421 
1422  if (ec_fsm_soe_exec(&fsm->fsm_soe, fsm->datagram)) {
1423  return;
1424  }
1425 
1426  if (!ec_fsm_soe_success(&fsm->fsm_soe)) {
1427  EC_SLAVE_DBG(fsm->slave, 1,
1428  "Failed to process internal SoE request.\n");
1429  request->state = EC_INT_REQUEST_FAILURE;
1430  wake_up_all(&fsm->master->request_queue);
1431  ec_fsm_master_restart(fsm);
1432  return;
1433  }
1434 
1435  // SoE request finished
1436  request->state = EC_INT_REQUEST_SUCCESS;
1437  wake_up_all(&fsm->master->request_queue);
1438 
1439  EC_SLAVE_DBG(fsm->slave, 1, "Finished internal SoE request.\n");
1440 
1441  // check for another CoE/SoE request
1443  return; // processing another request
1444  }
1445 
1446  ec_fsm_master_restart(fsm);
1447 }
1448 
1449 /*****************************************************************************/
#define EC_FSM_RETRIES
Number of state machine retries on datagram timeout.
Definition: globals.h:47
void ec_fsm_master_state_configure_slave(ec_fsm_master_t *)
Master state: CONFIGURE SLAVE.
Definition: fsm_master.c:997
uint16_t ring_position
Ring position for emergency requests.
Definition: reg_request.h:57
ec_internal_request_state_t state
Request state.
Definition: reg_request.h:56
uint16_t offset
SII word offset.
Definition: fsm_master.h:54
uint16_t ring_position
Ring position.
Definition: slave.h:183
unsigned long jiffies_sent
Jiffies, when the datagram was sent.
Definition: datagram.h:104
ec_datagram_t * datagram
datagram used in the state machine
Definition: fsm_master.h:68
ec_sii_write_request_t * sii_request
SII write request.
Definition: fsm_master.h:86
ec_sii_t sii
Extracted SII data.
Definition: slave.h:223
void ec_fsm_slave_config_start(ec_fsm_slave_config_t *fsm, ec_slave_t *slave)
Start slave configuration state machine.
ec_fsm_soe_t fsm_soe
SoE state machine.
Definition: fsm_master.h:92
struct semaphore config_sem
Semaphore protecting the config_busy variable and the allow_config flag.
Definition: master.h:258
void ec_master_calc_dc(ec_master_t *master)
Distributed-clocks calculations.
Definition: master.c:2223
size_t transfer_size
Size of the data to transfer.
Definition: reg_request.h:55
void ec_slave_attach_pdo_names(ec_slave_t *slave)
Attach PDO names.
Definition: slave.c:781
struct list_head sii_requests
SII write requests.
Definition: master.h:307
#define EC_SLAVE_DBG(slave, level, fmt, args...)
Convenience macro for printing slave-specific debug messages to syslog.
Definition: slave.h:106
ec_fsm_pdo_t fsm_pdo
PDO configuration state machine.
Definition: fsm_master.h:93
Finite state machine of an EtherCAT master.
Definition: fsm_master.h:66
ec_internal_request_state_t state
State of the request.
Definition: fsm_master.h:57
unsigned int slaves_responding[EC_MAX_NUM_DEVICES]
Number of responding slaves for every device.
Definition: fsm_master.h:78
void ec_fsm_slave_scan_init(ec_fsm_slave_scan_t *fsm, ec_datagram_t *datagram, ec_fsm_slave_config_t *fsm_slave_config, ec_fsm_pdo_t *fsm_pdo)
Constructor.
size_t ec_state_string(uint8_t, char *, uint8_t)
Prints slave states in clear text.
Definition: module.c:405
void ec_fsm_master_reset(ec_fsm_master_t *fsm)
Reset state machine.
Definition: fsm_master.c:131
struct ec_slave ec_slave_t
Definition: globals.h:301
void ec_master_request_op(ec_master_t *master)
Request OP state for configured slaves.
Definition: master.c:2240
CANopen SDO request.
Definition: sdo_request.h:46
ec_slave_state_t current_state
Current application state.
Definition: slave.h:192
#define ec_master_num_devices(MASTER)
Number of Ethernet devices.
Definition: master.h:328
u64 ec_fsm_master_dc_offset64(ec_fsm_master_t *fsm, u64 system_time, u64 old_offset, unsigned long jiffies_since_read)
Configure 64 bit time offset.
Definition: fsm_master.c:1115
size_t nwords
Number of words.
Definition: fsm_master.h:55
void(* state)(ec_fsm_master_t *)
master state function
Definition: fsm_master.h:71
ec_internal_request_state_t state
SDO request state.
Definition: sdo_request.h:61
uint16_t address
Register address.
Definition: reg_request.h:54
Register request.
Definition: reg_request.h:48
struct list_head eoe_handlers
Ethernet over EtherCAT handlers.
Definition: master.h:293
Operation phase.
Definition: master.h:135
unsigned int allow_scan
True, if slave scanning is allowed.
Definition: master.h:251
#define EC_SLAVE_WARN(slave, fmt, args...)
Convenience macro for printing slave-specific warnings to syslog.
Definition: slave.h:90
void ec_fsm_master_restart(ec_fsm_master_t *fsm)
Restarts the master state machine.
Definition: fsm_master.c:190
unsigned int rescan_required
A bus rescan is required.
Definition: fsm_master.h:81
EtherCAT datagram.
Definition: datagram.h:87
ec_sii_coe_details_t coe_details
CoE detail flags.
Definition: slave.h:160
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:116
#define EC_WRITE_U8(DATA, VAL)
Write an 8-bit unsigned value to EtherCAT data.
Definition: ecrt.h:2401
u64 dc_ref_time
Common reference timestamp for DC start times.
Definition: master.h:239
ec_slave_state_t slave_states[EC_MAX_NUM_DEVICES]
AL states of responding slaves for every device.
Definition: fsm_master.h:82
struct list_head emerg_reg_requests
Emergency register access requests.
Definition: master.h:308
#define EC_SYSTEM_TIME_TOLERANCE_NS
Time difference [ns] to tolerate without setting a new system time offset.
Definition: fsm_master.c:49
ec_fsm_slave_t fsm
Slave state machine.
Definition: slave.h:234
void ec_slave_set_state(ec_slave_t *slave, ec_slave_state_t new_state)
Sets the application state of a slave.
Definition: slave.c:274
uint16_t working_counter
Working counter.
Definition: datagram.h:99
int ec_sdo_request_timed_out(const ec_sdo_request_t *req)
Checks, if the timeout was exceeded.
Definition: sdo_request.c:177
int ec_fsm_master_action_process_int_request(ec_fsm_master_t *fsm)
Check for pending internal SDO/SoE requests and process one.
Definition: fsm_master.c:508
void ec_fsm_master_action_idle(ec_fsm_master_t *fsm)
Master action: IDLE.
Definition: fsm_master.c:591
int ec_eoe_init(ec_eoe_t *eoe, ec_slave_t *slave)
EoE constructor.
Definition: ethernet.c:114
Acknowledge/Error bit (no actual state)
Definition: globals.h:128
int ec_fsm_coe_success(const ec_fsm_coe_t *fsm)
Returns, if the state machine terminated with success.
Definition: fsm_coe.c:262
uint8_t link_state
device link state
Definition: device.h:88
void ec_fsm_master_state_dc_write_offset(ec_fsm_master_t *)
Master state: DC WRITE OFFSET.
Definition: fsm_master.c:1206
Sent (still in the queue).
Definition: datagram.h:77
wait_queue_head_t request_queue
Wait queue for external requests from user space.
Definition: master.h:311
void ec_fsm_sii_init(ec_fsm_sii_t *fsm, ec_datagram_t *datagram)
Constructor.
Definition: fsm_sii.c:74
EtherCAT master state machine.
uint16_t station_address
Configured station address.
Definition: slave.h:184
const char * ec_device_names[2]
Device names.
Definition: module.c:469
struct list_head list
List head.
Definition: fsm_master.h:52
SII write request.
Definition: fsm_master.h:51
void ec_fsm_master_action_next_slave_state(ec_fsm_master_t *fsm)
Master action: Get state of next slave.
Definition: fsm_master.c:649
#define EC_WAIT_SDO_DICT
Seconds to wait before fetching SDO dictionary after slave entered PREOP state.
Definition: globals.h:51
void ec_fsm_slave_config_init(ec_fsm_slave_config_t *fsm, ec_datagram_t *datagram, ec_fsm_change_t *fsm_change, ec_fsm_coe_t *fsm_coe, ec_fsm_soe_t *fsm_soe, ec_fsm_pdo_t *fsm_pdo)
Constructor.
int ec_fsm_slave_scan_exec(ec_fsm_slave_scan_t *fsm)
Executes the current state of the state machine.
Global definitions and macros.
void ec_fsm_pdo_clear(ec_fsm_pdo_t *fsm)
Destructor.
Definition: fsm_pdo.c:90
void ec_fsm_master_enter_clear_addresses(ec_fsm_master_t *)
Start clearing slave addresses.
Definition: fsm_master.c:812
EtherCAT master structure.
void ec_fsm_master_init(ec_fsm_master_t *fsm, ec_master_t *master, ec_datagram_t *datagram)
Constructor.
Definition: fsm_master.c:76
#define EC_MASTER_DBG(master, level, fmt, args...)
Convenience macro for printing master-specific debug messages to syslog.
Definition: master.h:111
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:446
ec_slave_t * fsm_slave
Slave that is queried next for FSM exec.
Definition: master.h:281
ec_slave_t * slave
EtherCAT slave.
Definition: fsm_master.h:53
u64 ec_fsm_master_dc_offset32(ec_fsm_master_t *fsm, u64 system_time, u64 old_offset, unsigned long jiffies_since_read)
Configure 32 bit time offset.
Definition: fsm_master.c:1073
void ec_slave_sdo_dict_info(const ec_slave_t *slave, unsigned int *sdo_count, unsigned int *entry_count)
Counts the total number of SDOs and entries in the dictionary.
Definition: slave.c:608
EtherCAT slave.
Definition: slave.h:176
void ec_master_attach_slave_configs(ec_master_t *master)
Attaches the slave configurations to the slaves.
Definition: master.c:1808
int ec_datagram_apwr(ec_datagram_t *datagram, uint16_t ring_position, uint16_t mem_address, size_t data_size)
Initializes an EtherCAT APWR datagram.
Definition: datagram.c:210
void ec_fsm_master_state_read_state(ec_fsm_master_t *)
Master state: READ STATE.
Definition: fsm_master.c:735
void ec_datagram_zero(ec_datagram_t *datagram)
Fills the datagram payload memory with zeros.
Definition: datagram.c:178
void ec_fsm_master_state_sdo_request(ec_fsm_master_t *)
Master state: SDO REQUEST.
Definition: fsm_master.c:1367
void ec_fsm_master_state_scan_slave(ec_fsm_master_t *)
Master state: SCAN SLAVE.
Definition: fsm_master.c:925
void ec_fsm_soe_transfer(ec_fsm_soe_t *fsm, ec_slave_t *slave, ec_soe_request_t *request)
Starts to transfer an IDN to/from a slave.
Definition: fsm_soe.c:128
int ec_fsm_soe_success(const ec_fsm_soe_t *fsm)
Returns, if the state machine terminated with success.
Definition: fsm_soe.c:185
Ethernet over EtherCAT (EoE)
ec_datagram_state_t state
State.
Definition: datagram.h:100
ec_slave_config_t * config
Current configuration.
Definition: slave.h:190
ec_master_phase_t phase
Master phase.
Definition: master.h:223
#define EC_WRITE_U32(DATA, VAL)
Write a 32-bit unsigned value to EtherCAT data.
Definition: ecrt.h:2435
ec_fsm_sii_t fsm_sii
SII state machine.
Definition: fsm_master.h:97
ec_slave_t * slaves
Array of slaves on the bus.
Definition: master.h:231
uint8_t enable_sdo_info
SDO information service available.
Definition: globals.h:147
Use configured addresses.
Definition: fsm_sii.h:50
Slave configutation feature flag.
Definition: flag.h:38
ec_fsm_slave_scan_t fsm_slave_scan
slave state machine
Definition: fsm_master.h:96
uint8_t sdo_dictionary_fetched
Dictionary has been fetched.
Definition: slave.h:226
struct list_head sdo_requests
List of SDO requests.
Definition: slave_config.h:143
void ec_fsm_master_action_configure(ec_fsm_master_t *fsm)
Master action: Configure.
Definition: fsm_master.c:677
uint16_t mailbox_protocols
Supported mailbox protocols.
Definition: slave.h:147
ec_flag_t * ec_slave_config_find_flag(ec_slave_config_t *sc, const char *key)
Finds a flag.
Definition: slave_config.c:608
ec_sdo_request_t * sdo_request
SDO request to process.
Definition: fsm_master.h:88
unsigned int debug_level
Master debug level.
Definition: master.h:285
#define EC_SLAVE_ERR(slave, fmt, args...)
Convenience macro for printing slave-specific errors to syslog.
Definition: slave.h:76
void ec_datagram_print_wc_error(const ec_datagram_t *datagram)
Evaluates the working counter of a single-cast datagram.
Definition: datagram.c:602
ec_slave_dc_range_t base_dc_range
DC range.
Definition: slave.h:211
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:146
int ec_fsm_change_exec(ec_fsm_change_t *fsm)
Executes the current state of the state machine.
Definition: fsm_change.c:124
uint32_t transmission_delay
DC system time transmission delay (offset from reference clock).
Definition: slave.h:215
unsigned int slave_count
Number of slaves on the bus.
Definition: master.h:232
unsigned int scan_busy
Current scan state.
Definition: master.h:250
ec_device_index_t
Master devices.
Definition: globals.h:189
void ec_fsm_master_state_dc_measure_delays(ec_fsm_master_t *)
Master state: DC MEASURE DELAYS.
Definition: fsm_master.c:872
void ec_fsm_master_state_broadcast(ec_fsm_master_t *)
Master state: BROADCAST.
Definition: fsm_master.c:265
void ec_fsm_pdo_init(ec_fsm_pdo_t *fsm, ec_fsm_coe_t *fsm_coe)
Constructor.
Definition: fsm_pdo.c:74
ec_soe_request_t * soe_request
SoE request to process.
Definition: fsm_master.h:89
void ec_fsm_coe_clear(ec_fsm_coe_t *fsm)
Destructor.
Definition: fsm_coe.c:182
uint16_t alias
Configured station alias.
Definition: slave.h:134
#define EC_WRITE_U16(DATA, VAL)
Write a 16-bit unsigned value to EtherCAT data.
Definition: ecrt.h:2418
unsigned long scan_jiffies
beginning of slave scanning
Definition: fsm_master.h:75
#define EC_ABS(X)
Absolute value.
Definition: globals.h:242
Main device.
Definition: globals.h:190
void ec_fsm_master_state_assign_sii(ec_fsm_master_t *)
Master state: ASSIGN SII.
Definition: fsm_master.c:1241
#define EC_MASTER_WARN(master, fmt, args...)
Convenience macro for printing master-specific warnings to syslog.
Definition: master.h:97
unsigned int active
Master has been activated.
Definition: master.h:224
ec_master_t * master
Master owning the slave.
Definition: slave.h:178
struct list_head soe_requests
List of SoE requests.
Definition: slave_config.h:144
void ec_fsm_change_clear(ec_fsm_change_t *fsm)
Destructor.
Definition: fsm_change.c:80
int ec_datagram_brd(ec_datagram_t *datagram, uint16_t mem_address, size_t data_size)
Initializes an EtherCAT BRD datagram.
Definition: datagram.c:373
int ec_datagram_fpwr(ec_datagram_t *datagram, uint16_t configured_address, uint16_t mem_address, size_t data_size)
Initializes an EtherCAT FPWR datagram.
Definition: datagram.c:298
uint8_t has_dc_system_time
The slave supports the DC system time register.
Definition: slave.h:212
wait_queue_head_t scan_queue
Queue for processes that wait for slave scanning.
Definition: master.h:254
CANopen over EtherCAT.
Definition: globals.h:137
#define EC_MASTER_ERR(master, fmt, args...)
Convenience macro for printing master-specific errors to syslog.
Definition: master.h:85
int ec_datagram_fprd(ec_datagram_t *datagram, uint16_t configured_address, uint16_t mem_address, size_t data_size)
Initializes an EtherCAT FPRD datagram.
Definition: datagram.c:273
void ec_fsm_coe_dictionary(ec_fsm_coe_t *fsm, ec_slave_t *slave)
Starts reading a slaves&#39; SDO dictionary.
Definition: fsm_coe.c:192
void ec_fsm_master_state_soe_request(ec_fsm_master_t *)
Master state: SoE REQUEST.
Definition: fsm_master.c:1410
ec_device_index_t device_index
Device via which the datagram shall be / was sent.
Definition: datagram.h:90
int ec_fsm_master_idle(const ec_fsm_master_t *fsm)
Definition: fsm_master.c:179
32 bit.
Definition: globals.h:164
void ec_master_clear_slaves(ec_master_t *master)
Clear all slaves.
Definition: master.c:478
void ec_fsm_change_init(ec_fsm_change_t *fsm, ec_datagram_t *datagram)
Constructor.
Definition: fsm_change.c:65
struct list_head list
list item
Definition: ethernet.h:78
void ec_fsm_coe_init(ec_fsm_coe_t *fsm)
Constructor.
Definition: fsm_coe.c:170
void ec_fsm_master_state_acknowledge(ec_fsm_master_t *)
Master state: ACKNOWLEDGE.
Definition: fsm_master.c:790
Ethernet over EtherCAT.
Definition: globals.h:136
void ec_fsm_sii_clear(ec_fsm_sii_t *fsm)
Destructor.
Definition: fsm_sii.c:88
INIT state (no mailbox communication, no IO)
Definition: globals.h:118
int idle
state machine is in idle phase
Definition: fsm_master.h:74
struct semaphore scan_sem
Semaphore protecting the scan_busy variable and the allow_scan flag.
Definition: master.h:252
void ec_fsm_master_state_start(ec_fsm_master_t *)
Master state: START.
Definition: fsm_master.c:207
uint16_t effective_alias
Effective alias address.
Definition: slave.h:185
void ec_master_clear_eoe_handlers(ec_master_t *master)
Clear and free all EoE handlers.
Definition: master.c:442
ec_fsm_slave_config_t fsm_slave_config
slave state machine
Definition: fsm_master.h:95
int ec_fsm_sii_exec(ec_fsm_sii_t *fsm)
Executes the SII state machine.
Definition: fsm_sii.c:137
int ec_fsm_sii_success(ec_fsm_sii_t *fsm)
Returns, if the master startup state machine terminated with success.
Definition: fsm_sii.c:152
#define EC_READ_U16(DATA)
Read a 16-bit unsigned value from EtherCAT data.
Definition: ecrt.h:2313
void ec_master_eoe_start(ec_master_t *master)
Starts Ethernet over EtherCAT processing on demand.
Definition: master.c:1694
void ec_datagram_print_state(const ec_datagram_t *datagram)
Prints the state of a datagram.
Definition: datagram.c:565
Mailbox functionality.
ec_master_t * master
master the FSM runs on
Definition: fsm_master.h:67
void ec_fsm_master_state_sdo_dictionary(ec_fsm_master_t *)
Master state: SDO DICTIONARY.
Definition: fsm_master.c:1332
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:54
#define EC_WRITE_U64(DATA, VAL)
Write a 64-bit unsigned value to EtherCAT data.
Definition: ecrt.h:2452
void ec_fsm_master_state_clear_addresses(ec_fsm_master_t *)
Master state: CLEAR ADDRESSES.
Definition: fsm_master.c:828
int ec_fsm_slave_config_exec(ec_fsm_slave_config_t *fsm)
Executes the current state of the state machine.
int ec_fsm_coe_exec(ec_fsm_coe_t *fsm, ec_datagram_t *datagram)
Executes the current state of the state machine.
Definition: fsm_coe.c:228
void ec_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
Queued for sending.
Definition: datagram.h:76
void ec_fsm_change_ack(ec_fsm_change_t *fsm, ec_slave_t *slave)
Starts the change state machine to only acknowlegde a slave&#39;s state.
Definition: fsm_change.c:107
Timed out (dequeued).
Definition: datagram.h:79
wait_queue_head_t config_queue
Queue for processes that wait for slave configuration.
Definition: master.h:260
int32_t value
Flag value (meaning depends on key).
Definition: flag.h:41
unsigned int retries
retries on datagram timeout.
Definition: fsm_master.h:69
void ec_fsm_slave_config_clear(ec_fsm_slave_config_t *fsm)
Destructor.
u64 app_time
Time of the last ecrt_master_sync() call.
Definition: master.h:238
unsigned long jiffies_preop
Time, the slave went to PREOP.
Definition: slave.h:227
void ec_fsm_soe_init(ec_fsm_soe_t *fsm)
Constructor.
Definition: fsm_soe.c:105
uint8_t base_dc_supported
Distributed clocks are supported.
Definition: slave.h:210
void ec_fsm_soe_clear(ec_fsm_soe_t *fsm)
Destructor.
Definition: fsm_soe.c:118
void ec_fsm_slave_scan_start(ec_fsm_slave_scan_t *fsm, ec_slave_t *slave)
Start slave scan state machine.
void ec_fsm_master_state_write_sii(ec_fsm_master_t *)
Master state: WRITE SII.
Definition: fsm_master.c:1278
uint8_t * data
Datagram payload.
Definition: datagram.h:94
#define EC_READ_U8(DATA)
Read an 8-bit unsigned value from EtherCAT data.
Definition: ecrt.h:2297
EtherCAT slave configuration.
Definition: slave_config.h:117
int ec_soe_request_timed_out(const ec_soe_request_t *req)
Checks, if the timeout was exceeded.
Definition: soe_request.c:262
int ec_fsm_master_exec(ec_fsm_master_t *fsm)
Executes the current state of the state machine.
Definition: fsm_master.c:160
int ec_fsm_slave_config_success(const ec_fsm_slave_config_t *fsm)
void ec_fsm_slave_scan_clear(ec_fsm_slave_scan_t *fsm)
Destructor.
EtherCAT slave configuration structure.
size_t mem_size
Datagram data memory size.
Definition: datagram.h:96
ec_device_index_t device_index
Index of device the slave responds on.
Definition: slave.h:179
int ec_fsm_soe_exec(ec_fsm_soe_t *fsm, ec_datagram_t *datagram)
Executes the current state of the state machine.
Definition: fsm_soe.c:150
void ec_fsm_coe_transfer(ec_fsm_coe_t *fsm, ec_slave_t *slave, ec_sdo_request_t *request)
Starts to transfer an SDO to/from a slave.
Definition: fsm_coe.c:205
ec_slave_t * slave
current slave
Definition: fsm_master.h:85
Values written by the master.
Definition: ecrt.h:448
ec_fsm_change_t fsm_change
State change state machine.
Definition: fsm_master.h:94
Received (dequeued).
Definition: datagram.h:78
Ethernet over EtherCAT (EoE) handler.
Definition: ethernet.h:76
off_t sii_index
index to SII write request data
Definition: fsm_master.h:87
#define EC_MASTER_INFO(master, fmt, args...)
Convenience macro for printing master-specific information to syslog.
Definition: master.h:73
unsigned int error_flag
Stop processing after an error.
Definition: slave.h:193
unsigned int config_changed
The configuration changed.
Definition: master.h:225
EtherCAT master.
Definition: master.h:194
struct list_head list
List item.
Definition: reg_request.h:49
ec_slave_state_t requested_state
Requested application state.
Definition: slave.h:191
ec_device_index_t dev_idx
Current device index (for scanning etc.).
Definition: fsm_master.h:72
#define EC_READ_U64(DATA)
Read a 64-bit unsigned value from EtherCAT data.
Definition: ecrt.h:2345
ec_device_t devices[EC_MAX_NUM_DEVICES]
EtherCAT devices.
Definition: master.h:211
ec_internal_request_state_t state
Request state.
Definition: soe_request.h:60
unsigned int config_busy
State of slave configuration.
Definition: master.h:257
const uint16_t * words
Pointer to the data words.
Definition: fsm_master.h:56
void ec_fsm_master_clear(ec_fsm_master_t *fsm)
Destructor.
Definition: fsm_master.c:113
EtherCAT FoE state machines.
Sercos-over-EtherCAT request.
Definition: soe_request.h:48
unknown state
Definition: globals.h:116
void ec_fsm_master_enter_write_system_times(ec_fsm_master_t *)
Start writing DC system times.
Definition: fsm_master.c:1025
void ec_master_eoe_stop(ec_master_t *master)
Stops the Ethernet over EtherCAT processing.
Definition: master.c:1728
uint8_t link_state[EC_MAX_NUM_DEVICES]
Last link state for every device.
Definition: fsm_master.h:76
ec_fsm_coe_t fsm_coe
CoE state machine.
Definition: fsm_master.h:91
void ec_fsm_master_state_dc_read_offset(ec_fsm_master_t *)
Master state: DC READ OFFSET.
Definition: fsm_master.c:1153
unsigned int force_config
Force (re-)configuration.
Definition: slave.h:194
int ec_fsm_change_success(ec_fsm_change_t *fsm)
Returns, if the state machine terminated with success.
Definition: fsm_change.c:139
unsigned int has_general
General category present.
Definition: slave.h:154
int ec_datagram_bwr(ec_datagram_t *datagram, uint16_t mem_address, size_t data_size)
Initializes an EtherCAT BWR datagram.
Definition: datagram.c:393