IgH EtherCAT Master  1.6.0
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 
26 /****************************************************************************/
27 
28 #include "globals.h"
29 #include "master.h"
30 #include "mailbox.h"
31 #include "slave_config.h"
32 #ifdef EC_EOE
33 #include "ethernet.h"
34 #endif
35 
36 #include "fsm_master.h"
37 #include "fsm_foe.h"
38 
39 /****************************************************************************/
40 
43 #define EC_SYSTEM_TIME_TOLERANCE_NS 1000000
44 
45 /****************************************************************************/
46 
62 
65 
66 /****************************************************************************/
67 
71  ec_fsm_master_t *fsm,
72  ec_master_t *master,
73  ec_datagram_t *datagram
74  )
75 {
76  fsm->master = master;
77  fsm->datagram = datagram;
78 
79  // inits the member variables state, idle, dev_idx, link_state,
80  // slaves_responding, slave_states and rescan_required
82 
83  fsm->retries = 0;
84  fsm->scan_jiffies = 0;
85  fsm->slave = NULL;
86  fsm->sii_request = NULL;
87  fsm->sii_index = 0;
88  fsm->sdo_request = NULL;
89  fsm->soe_request = NULL;
90 
91  // init sub-state-machines
92  ec_fsm_coe_init(&fsm->fsm_coe);
93  ec_fsm_soe_init(&fsm->fsm_soe);
94  ec_fsm_pdo_init(&fsm->fsm_pdo, &fsm->fsm_coe);
97  &fsm->fsm_change, &fsm->fsm_coe, &fsm->fsm_soe, &fsm->fsm_pdo);
99  &fsm->fsm_slave_config, &fsm->fsm_pdo);
100  ec_fsm_sii_init(&fsm->fsm_sii, fsm->datagram);
101 }
102 
103 /****************************************************************************/
104 
108  ec_fsm_master_t *fsm
109  )
110 {
111  // clear sub-state machines
112  ec_fsm_coe_clear(&fsm->fsm_coe);
113  ec_fsm_soe_clear(&fsm->fsm_soe);
114  ec_fsm_pdo_clear(&fsm->fsm_pdo);
118  ec_fsm_sii_clear(&fsm->fsm_sii);
119 }
120 
121 /****************************************************************************/
122 
126  ec_fsm_master_t *fsm
127  )
128 {
129  ec_device_index_t dev_idx;
130 
132  fsm->idle = 0;
133  fsm->dev_idx = EC_DEVICE_MAIN;
134 
135  for (dev_idx = EC_DEVICE_MAIN;
136  dev_idx < ec_master_num_devices(fsm->master); dev_idx++) {
137  fsm->link_state[dev_idx] = 0;
138  fsm->slaves_responding[dev_idx] = 0;
139  fsm->slave_states[dev_idx] = EC_SLAVE_STATE_UNKNOWN;
140  }
141 
142  fsm->rescan_required = 0;
143 }
144 
145 /****************************************************************************/
146 
155  ec_fsm_master_t *fsm
156  )
157 {
158  if (fsm->datagram->state == EC_DATAGRAM_SENT
159  || fsm->datagram->state == EC_DATAGRAM_QUEUED) {
160  // datagram was not sent or received yet.
161  return 0;
162  }
163 
164  fsm->state(fsm);
165  return 1;
166 }
167 
168 /****************************************************************************/
169 
174  const ec_fsm_master_t *fsm
175  )
176 {
177  return fsm->idle;
178 }
179 
180 /****************************************************************************/
181 
185  ec_fsm_master_t *fsm
186  )
187 {
188  fsm->dev_idx = EC_DEVICE_MAIN;
190  fsm->state(fsm); // execute immediately
191 }
192 
193 /*****************************************************************************
194  * Master state machine
195  ****************************************************************************/
196 
202  ec_fsm_master_t *fsm
203  )
204 {
205  ec_master_t *master = fsm->master;
206 
207  fsm->idle = 1;
208 
209  // check for emergency requests
210  if (!list_empty(&master->emerg_reg_requests)) {
211  ec_reg_request_t *request;
212 
213  // get first request
214  request = list_entry(master->emerg_reg_requests.next,
215  ec_reg_request_t, list);
216  list_del_init(&request->list); // dequeue
217  request->state = EC_INT_REQUEST_BUSY;
218 
219  if (request->transfer_size > fsm->datagram->mem_size) {
220  EC_MASTER_ERR(master, "Emergency request data too large!\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  if (request->dir != EC_DIR_OUTPUT) {
228  EC_MASTER_ERR(master, "Emergency requests must be"
229  " write requests!\n");
230  request->state = EC_INT_REQUEST_FAILURE;
231  wake_up_all(&master->request_queue);
232  fsm->state(fsm); // continue
233  return;
234  }
235 
236  EC_MASTER_DBG(master, 1, "Writing emergency register request...\n");
237  ec_datagram_apwr(fsm->datagram, request->ring_position,
238  request->address, request->transfer_size);
239  memcpy(fsm->datagram->data, request->data, request->transfer_size);
241  request->state = EC_INT_REQUEST_SUCCESS;
242  wake_up_all(&master->request_queue);
243  return;
244  }
245 
246  ec_datagram_brd(fsm->datagram, 0x0130, 2);
248  fsm->datagram->device_index = fsm->dev_idx;
249  fsm->retries = EC_FSM_RETRIES;
251 }
252 
253 /****************************************************************************/
254 
260  ec_fsm_master_t *fsm
261  )
262 {
263  ec_datagram_t *datagram = fsm->datagram;
264  unsigned int i, size;
265  ec_slave_t *slave;
266  ec_master_t *master = fsm->master;
267 
268  if (datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--) {
269  return;
270  }
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 
289 #ifdef EC_EOE
290  ec_master_eoe_stop(master);
292 #endif
293  ec_master_clear_slaves(master);
294 
295  for (dev_idx = EC_DEVICE_MAIN;
296  dev_idx < ec_master_num_devices(master); dev_idx++) {
297  fsm->slave_states[dev_idx] = 0x00;
298  fsm->slaves_responding[dev_idx] = 0; /* Reset to trigger rescan on
299  next link up. */
300  }
301  }
302  fsm->link_state[fsm->dev_idx] = master->devices[fsm->dev_idx].link_state;
303 
304  if (datagram->state == EC_DATAGRAM_RECEIVED &&
305  fsm->slaves_responding[fsm->dev_idx]) {
306  uint8_t states = EC_READ_U8(datagram->data);
307  if (states != fsm->slave_states[fsm->dev_idx]) {
308  // slave states changed
309  char state_str[EC_STATE_STRING_SIZE];
310  fsm->slave_states[fsm->dev_idx] = states;
311  ec_state_string(states, state_str, 1);
312  EC_MASTER_INFO(master, "Slave states on %s device: %s.\n",
313  ec_device_names[fsm->dev_idx != 0], state_str);
314  }
315  } else {
316  fsm->slave_states[fsm->dev_idx] = 0x00;
317  }
318 
319  fsm->dev_idx++;
320  if (fsm->dev_idx < ec_master_num_devices(master)) {
321  // check number of responding slaves on next device
323  fsm->state(fsm); // execute immediately
324  return;
325  }
326 
327  if (fsm->rescan_required) {
328  down(&master->scan_sem);
329  if (!master->allow_scan) {
330  up(&master->scan_sem);
331  } else {
332  unsigned int count = 0, next_dev_slave, ring_position;
333  ec_device_index_t dev_idx;
334 
335  master->scan_busy = 1;
336  master->scan_index = 0;
337  up(&master->scan_sem);
338 
339  // clear all slaves and scan the bus
340  fsm->rescan_required = 0;
341  fsm->idle = 0;
342  fsm->scan_jiffies = jiffies;
343 
344 #ifdef EC_EOE
345  ec_master_eoe_stop(master);
347 #endif
348  ec_master_clear_slaves(master);
349 
350  for (dev_idx = EC_DEVICE_MAIN;
351  dev_idx < ec_master_num_devices(master); dev_idx++) {
352  count += fsm->slaves_responding[dev_idx];
353  }
354 
355  if (!count) {
356  // no slaves present -> finish state machine.
357  master->scan_busy = 0;
358  wake_up_interruptible(&master->scan_queue);
360  return;
361  }
362 
363  size = sizeof(ec_slave_t) * count;
364  if (!(master->slaves =
365  (ec_slave_t *) kmalloc(size, GFP_KERNEL))) {
366  EC_MASTER_ERR(master, "Failed to allocate %u bytes"
367  " of slave memory!\n", size);
368  master->scan_busy = 0;
369  wake_up_interruptible(&master->scan_queue);
371  return;
372  }
373 
374  // init slaves
375  dev_idx = EC_DEVICE_MAIN;
376  next_dev_slave = fsm->slaves_responding[dev_idx];
377  ring_position = 0;
378  for (i = 0; i < count; i++, ring_position++) {
379  slave = master->slaves + i;
380  while (i >= next_dev_slave) {
381  dev_idx++;
382  next_dev_slave += fsm->slaves_responding[dev_idx];
383  ring_position = 0;
384  }
385 
386  ec_slave_init(slave, master, dev_idx, ring_position, i + 1);
387 
388  // do not force reconfiguration in operation phase to avoid
389  // unnecesssary process data interruptions
390  if (master->phase != EC_OPERATION) {
391  slave->force_config = 1;
392  }
393  }
394  master->slave_count = count;
395  master->fsm_slave = master->slaves;
396 
397  /* start with first device with slaves responding; at least one
398  * has responding slaves, otherwise count would be zero. */
399  fsm->dev_idx = EC_DEVICE_MAIN;
400  while (!fsm->slaves_responding[fsm->dev_idx]) {
401  fsm->dev_idx++;
402  }
403 
405  return;
406  }
407  }
408 
409  if (master->slave_count) {
410 
411  // application applied configurations
412  if (master->config_changed) {
413  master->config_changed = 0;
414 
415  EC_MASTER_DBG(master, 1, "Configuration changed.\n");
416 
417  fsm->slave = master->slaves; // begin with first slave
419 
420  } else {
421  // fetch state from first slave
422  fsm->slave = master->slaves;
424  0x0130, 2);
425  ec_datagram_zero(datagram);
426  fsm->datagram->device_index = fsm->slave->device_index;
427  fsm->retries = EC_FSM_RETRIES;
429  }
430  } else {
432  }
433 }
434 
435 /****************************************************************************/
436 
442  ec_fsm_master_t *fsm
443  )
444 {
445  ec_master_t *master = fsm->master;
446  ec_sii_write_request_t *request;
447  ec_slave_config_t *config;
448  ec_flag_t *flag;
449  int assign_to_pdi;
450 
451  // search the first request to be processed
452  while (1) {
453  if (list_empty(&master->sii_requests))
454  break;
455 
456  // get first request
457  request = list_entry(master->sii_requests.next,
458  ec_sii_write_request_t, list);
459  list_del_init(&request->list); // dequeue
460  request->state = EC_INT_REQUEST_BUSY;
461 
462  assign_to_pdi = 0;
463  config = request->slave->config;
464  if (config) {
465  flag = ec_slave_config_find_flag(config, "AssignToPdi");
466  if (flag) {
467  assign_to_pdi = flag->value;
468  }
469  }
470 
471  if (assign_to_pdi) {
472  fsm->sii_request = request;
473  EC_SLAVE_DBG(request->slave, 1,
474  "Assigning SII back to EtherCAT.\n");
476  0x0500, 0x01);
477  EC_WRITE_U8(fsm->datagram->data, 0x00); // EtherCAT
478  fsm->retries = EC_FSM_RETRIES;
480  return 1;
481  }
482 
483  // found pending SII write operation. execute it!
484  EC_SLAVE_DBG(request->slave, 1, "Writing SII data...\n");
485  fsm->sii_request = request;
486  fsm->sii_index = 0;
487  ec_fsm_sii_write(&fsm->fsm_sii, request->slave, request->offset,
490  fsm->state(fsm); // execute immediately
491  return 1;
492  }
493 
494  return 0;
495 }
496 
497 /****************************************************************************/
498 
504  ec_fsm_master_t *fsm
505  )
506 {
507  ec_master_t *master = fsm->master;
508  ec_slave_t *slave;
509  ec_sdo_request_t *sdo_req;
510  ec_soe_request_t *soe_req;
511 
512  // search for internal requests to be processed
513  for (slave = master->slaves;
514  slave < master->slaves + master->slave_count;
515  slave++) {
516 
517  if (!slave->config) {
518  continue;
519  }
520 
521  list_for_each_entry(sdo_req, &slave->config->sdo_requests, list) {
522  if (sdo_req->state == EC_INT_REQUEST_QUEUED) {
523 
524  if (ec_sdo_request_timed_out(sdo_req)) {
525  sdo_req->state = EC_INT_REQUEST_FAILURE;
526  EC_SLAVE_DBG(slave, 1, "Internal SDO request"
527  " timed out.\n");
528  continue;
529  }
530 
531  if (slave->current_state == EC_SLAVE_STATE_INIT) {
532  sdo_req->state = EC_INT_REQUEST_FAILURE;
533  continue;
534  }
535 
536  sdo_req->state = EC_INT_REQUEST_BUSY;
537  EC_SLAVE_DBG(slave, 1, "Processing internal"
538  " SDO request...\n");
539  fsm->idle = 0;
540  fsm->sdo_request = sdo_req;
541  fsm->slave = slave;
543  ec_fsm_coe_transfer(&fsm->fsm_coe, slave, sdo_req);
544  ec_fsm_coe_exec(&fsm->fsm_coe, fsm->datagram);
545  return 1;
546  }
547  }
548 
549  list_for_each_entry(soe_req, &slave->config->soe_requests, list) {
550  if (soe_req->state == EC_INT_REQUEST_QUEUED) {
551 
552  if (ec_soe_request_timed_out(soe_req)) {
553  soe_req->state = EC_INT_REQUEST_FAILURE;
554  EC_SLAVE_DBG(slave, 1, "Internal SoE request"
555  " timed out.\n");
556  continue;
557  }
558 
559  if (slave->current_state == EC_SLAVE_STATE_INIT) {
560  soe_req->state = EC_INT_REQUEST_FAILURE;
561  continue;
562  }
563 
564  soe_req->state = EC_INT_REQUEST_BUSY;
565  EC_SLAVE_DBG(slave, 1, "Processing internal"
566  " SoE request...\n");
567  fsm->idle = 0;
568  fsm->soe_request = soe_req;
569  fsm->slave = slave;
571  ec_fsm_soe_transfer(&fsm->fsm_soe, slave, soe_req);
572  ec_fsm_soe_exec(&fsm->fsm_soe, fsm->datagram);
573  return 1;
574  }
575  }
576  }
577  return 0;
578 }
579 
580 /****************************************************************************/
581 
587  ec_fsm_master_t *fsm
588  )
589 {
590  ec_master_t *master = fsm->master;
591  ec_slave_t *slave;
592 
593  // Check for pending internal SDO or SoE requests
595  return;
596  }
597 
598  // enable processing of requests
599  for (slave = master->slaves;
600  slave < master->slaves + master->slave_count;
601  slave++) {
602  ec_fsm_slave_set_ready(&slave->fsm);
603  }
604 
605  // check, if slaves have an SDO dictionary to read out.
606  for (slave = master->slaves;
607  slave < master->slaves + master->slave_count;
608  slave++) {
609  if (!(slave->sii.mailbox_protocols & EC_MBOX_COE)
610  || (slave->sii.has_general
611  && !slave->sii.coe_details.enable_sdo_info)
612  || slave->sdo_dictionary_fetched
615  || jiffies - slave->jiffies_preop < EC_WAIT_SDO_DICT * HZ
616  ) continue;
617 
618  EC_SLAVE_DBG(slave, 1, "Fetching SDO dictionary.\n");
619 
620  slave->sdo_dictionary_fetched = 1;
621 
622  // start fetching SDO dictionary
623  fsm->idle = 0;
624  fsm->slave = slave;
626  ec_fsm_coe_dictionary(&fsm->fsm_coe, slave);
627  ec_fsm_coe_exec(&fsm->fsm_coe, fsm->datagram); // execute immediately
628  fsm->datagram->device_index = fsm->slave->device_index;
629  return;
630  }
631 
632  // check for pending SII write operations.
634  return; // SII write request found
635  }
636 
638 }
639 
640 /****************************************************************************/
641 
645  ec_fsm_master_t *fsm
646  )
647 {
648  ec_master_t *master = fsm->master;
649 
650  // is there another slave to query?
651  fsm->slave++;
652  if (fsm->slave < master->slaves + master->slave_count) {
653  // fetch state from next slave
654  fsm->idle = 1;
656  fsm->slave->station_address, 0x0130, 2);
658  fsm->datagram->device_index = fsm->slave->device_index;
659  fsm->retries = EC_FSM_RETRIES;
661  return;
662  }
663 
664  // all slaves processed
666 }
667 
668 /****************************************************************************/
669 
673  ec_fsm_master_t *fsm
674  )
675 {
676  ec_master_t *master = fsm->master;
677  ec_slave_t *slave = fsm->slave;
678 
679  if (master->config_changed) {
680  master->config_changed = 0;
681 
682  // abort iterating through slaves,
683  // first compensate DC system time offsets,
684  // then begin configuring at slave 0
685  EC_MASTER_DBG(master, 1, "Configuration changed"
686  " (aborting state check).\n");
687 
688  fsm->slave = master->slaves; // begin with first slave
690  return;
691  }
692 
693  // Does the slave have to be configured?
694  if ((slave->current_state != slave->requested_state
695  || slave->force_config) && !slave->error_flag) {
696 
697  // Start slave configuration
698  down(&master->config_sem);
699  master->config_busy = 1;
700  up(&master->config_sem);
701 
702  if (master->debug_level) {
703  char old_state[EC_STATE_STRING_SIZE],
704  new_state[EC_STATE_STRING_SIZE];
705  ec_state_string(slave->current_state, old_state, 0);
706  ec_state_string(slave->requested_state, new_state, 0);
707  EC_SLAVE_DBG(slave, 1, "Changing state from %s to %s%s.\n",
708  old_state, new_state,
709  slave->force_config ? " (forced)" : "");
710  }
711 
712  fsm->idle = 0;
715  fsm->state(fsm); // execute immediately
716  fsm->datagram->device_index = fsm->slave->device_index;
717  return;
718  }
719 
720  // process next slave
722 }
723 
724 /****************************************************************************/
725 
731  ec_fsm_master_t *fsm
732  )
733 {
734  ec_slave_t *slave = fsm->slave;
735  ec_datagram_t *datagram = fsm->datagram;
736 
737  if (datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--) {
738  return;
739  }
740 
741  if (datagram->state != EC_DATAGRAM_RECEIVED) {
742  EC_SLAVE_ERR(slave, "Failed to receive AL state datagram: ");
743  ec_datagram_print_state(datagram);
745  return;
746  }
747 
748  // did the slave not respond to its station address?
749  if (datagram->working_counter != 1) {
750  if (!slave->error_flag) {
751  slave->error_flag = 1;
752  EC_SLAVE_DBG(slave, 1, "Slave did not respond to state query.\n");
753  }
754  fsm->rescan_required = 1;
756  return;
757  }
758 
759  // A single slave responded
760  ec_slave_set_state(slave, EC_READ_U8(datagram->data));
761 
762  if (!slave->error_flag) {
763  // Check, if new slave state has to be acknowledged
764  if (slave->current_state & EC_SLAVE_STATE_ACK_ERR) {
765  fsm->idle = 0;
767  ec_fsm_change_ack(&fsm->fsm_change, slave);
768  fsm->state(fsm); // execute immediately
769  return;
770  }
771 
772  // No acknowlegde necessary; check for configuration
774  return;
775  }
776 
777  // slave has error flag set; process next one
779 }
780 
781 /****************************************************************************/
782 
786  ec_fsm_master_t *fsm
787  )
788 {
789  ec_slave_t *slave = fsm->slave;
790 
791  if (ec_fsm_change_exec(&fsm->fsm_change)) {
792  return;
793  }
794 
795  if (!ec_fsm_change_success(&fsm->fsm_change)) {
796  fsm->slave->error_flag = 1;
797  EC_SLAVE_ERR(slave, "Failed to acknowledge state change.\n");
798  }
799 
801 }
802 
803 /****************************************************************************/
804 
808  ec_fsm_master_t *fsm
809  )
810 {
811  // broadcast clear all station addresses
812  ec_datagram_bwr(fsm->datagram, 0x0010, 2);
813  EC_WRITE_U16(fsm->datagram->data, 0x0000);
814  fsm->datagram->device_index = fsm->dev_idx;
815  fsm->retries = EC_FSM_RETRIES;
817 }
818 
819 /****************************************************************************/
820 
824  ec_fsm_master_t *fsm
825  )
826 {
827  ec_master_t *master = fsm->master;
828  ec_datagram_t *datagram = fsm->datagram;
829 
830  if (datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--) {
831  return;
832  }
833 
834  if (datagram->state != EC_DATAGRAM_RECEIVED) {
835  EC_MASTER_ERR(master, "Failed to receive address"
836  " clearing datagram on %s link: ",
837  ec_device_names[fsm->dev_idx != 0]);
838  ec_datagram_print_state(datagram);
839  master->scan_busy = 0;
840  master->scan_index = master->slave_count;
841  wake_up_interruptible(&master->scan_queue);
843  return;
844  }
845 
846  if (datagram->working_counter != fsm->slaves_responding[fsm->dev_idx]) {
847  EC_MASTER_WARN(master, "Failed to clear station addresses on %s link:"
848  " Cleared %u of %u",
849  ec_device_names[fsm->dev_idx != 0], datagram->working_counter,
850  fsm->slaves_responding[fsm->dev_idx]);
851  }
852 
853  EC_MASTER_DBG(master, 1, "Sending broadcast-write"
854  " to measure transmission delays on %s link.\n",
855  ec_device_names[fsm->dev_idx != 0]);
856 
857  ec_datagram_bwr(datagram, 0x0900, 1);
858  ec_datagram_zero(datagram);
859  fsm->datagram->device_index = fsm->dev_idx;
860  fsm->retries = EC_FSM_RETRIES;
862 }
863 
864 /****************************************************************************/
865 
869  ec_fsm_master_t *fsm
870  )
871 {
872  ec_master_t *master = fsm->master;
873  ec_datagram_t *datagram = fsm->datagram;
874 
875  if (datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--) {
876  return;
877  }
878 
879  if (datagram->state != EC_DATAGRAM_RECEIVED) {
880  EC_MASTER_ERR(master, "Failed to receive delay measuring datagram"
881  " on %s link: ", ec_device_names[fsm->dev_idx != 0]);
882  ec_datagram_print_state(datagram);
883  master->scan_busy = 0;
884  master->scan_index = master->slave_count;
885  wake_up_interruptible(&master->scan_queue);
887  return;
888  }
889 
890  EC_MASTER_DBG(master, 1, "%u slaves responded to delay measuring"
891  " on %s link.\n",
892  datagram->working_counter, ec_device_names[fsm->dev_idx != 0]);
893 
894  do {
895  fsm->dev_idx++;
896  } while (fsm->dev_idx < ec_master_num_devices(master) &&
897  !fsm->slaves_responding[fsm->dev_idx]);
898  if (fsm->dev_idx < ec_master_num_devices(master)) {
900  return;
901  }
902 
903  EC_MASTER_INFO(master, "Scanning bus.\n");
904 
905  // begin scanning of slaves
906  fsm->slave = master->slaves;
907  master->scan_index = 0;
908  EC_MASTER_DBG(master, 1, "Scanning slave %u on %s link.\n",
909  fsm->slave->ring_position,
910  ec_device_names[fsm->slave->device_index != 0]);
913  ec_fsm_slave_scan_exec(&fsm->fsm_slave_scan); // execute immediately
914  fsm->datagram->device_index = fsm->slave->device_index;
915 }
916 
917 /****************************************************************************/
918 
924  ec_fsm_master_t *fsm
925  )
926 {
927  ec_master_t *master = fsm->master;
928 #ifdef EC_EOE
929  ec_slave_t *slave = fsm->slave;
930 #endif
931 
933  return;
934  }
935 
936 #ifdef EC_EOE
937  if (slave->sii.mailbox_protocols & EC_MBOX_EOE) {
938  // create EoE handler for this slave
939  ec_eoe_t *eoe;
940  if (!(eoe = kmalloc(sizeof(ec_eoe_t), GFP_KERNEL))) {
941  EC_SLAVE_ERR(slave, "Failed to allocate EoE handler memory!\n");
942  } else if (ec_eoe_init(eoe, slave)) {
943  EC_SLAVE_ERR(slave, "Failed to init EoE handler!\n");
944  kfree(eoe);
945  } else {
946  list_add_tail(&eoe->list, &master->eoe_handlers);
947  }
948  }
949 #endif
950 
951  // another slave to fetch?
952  fsm->slave++;
953  master->scan_index++;
954  if (fsm->slave < master->slaves + master->slave_count) {
955  EC_MASTER_DBG(master, 1, "Scanning slave %u on %s link.\n",
956  fsm->slave->ring_position,
957  ec_device_names[fsm->slave->device_index != 0]);
959  ec_fsm_slave_scan_exec(&fsm->fsm_slave_scan); // execute immediately
960  fsm->datagram->device_index = fsm->slave->device_index;
961  return;
962  }
963 
964  EC_MASTER_INFO(master, "Bus scanning completed in %lu ms.\n",
965  (jiffies - fsm->scan_jiffies) * 1000 / HZ);
966 
967  master->scan_busy = 0;
968  master->scan_index = master->slave_count;
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:49
ec_internal_request_state_t state
Request state.
Definition: reg_request.h:48
uint16_t offset
SII word offset.
Definition: fsm_master.h:48
CANopen over EtherCAT.
Definition: globals.h:146
uint16_t ring_position
Ring position.
Definition: slave.h:175
unsigned long jiffies_sent
Jiffies, when the datagram was sent.
Definition: datagram.h:96
ec_datagram_t * datagram
datagram used in the state machine
Definition: fsm_master.h:62
ec_sii_write_request_t * sii_request
SII write request.
Definition: fsm_master.h:80
ec_sii_t sii
Extracted SII data.
Definition: slave.h:215
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:86
struct semaphore config_sem
Semaphore protecting the config_busy variable and the allow_config flag.
Definition: master.h:244
void ec_master_calc_dc(ec_master_t *master)
Distributed-clocks calculations.
Definition: master.c:2181
size_t transfer_size
Size of the data to transfer.
Definition: reg_request.h:47
void ec_slave_attach_pdo_names(ec_slave_t *slave)
Attach PDO names.
Definition: slave.c:785
struct list_head sii_requests
SII write requests.
Definition: master.h:293
#define EC_SLAVE_DBG(slave, level, fmt, args...)
Convenience macro for printing slave-specific debug messages to syslog.
Definition: slave.h:98
ec_fsm_pdo_t fsm_pdo
PDO configuration state machine.
Definition: fsm_master.h:87
Finite state machine of an EtherCAT master.
Definition: fsm_master.h:60
ec_internal_request_state_t state
State of the request.
Definition: fsm_master.h:51
unsigned int slaves_responding[EC_MAX_NUM_DEVICES]
Number of responding slaves for every device.
Definition: fsm_master.h:72
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:399
void ec_fsm_master_reset(ec_fsm_master_t *fsm)
Reset state machine.
Definition: fsm_master.c:125
struct ec_slave ec_slave_t
Definition: globals.h:310
void ec_master_request_op(ec_master_t *master)
Request OP state for configured slaves.
Definition: master.c:2198
CANopen SDO request.
Definition: sdo_request.h:40
ec_slave_state_t current_state
Current application state.
Definition: slave.h:184
#define ec_master_num_devices(MASTER)
Number of Ethernet devices.
Definition: master.h:319
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:49
void(* state)(ec_fsm_master_t *)
master state function
Definition: fsm_master.h:65
ec_internal_request_state_t state
SDO request state.
Definition: sdo_request.h:55
uint16_t address
Register address.
Definition: reg_request.h:46
Register request.
Definition: reg_request.h:40
struct list_head eoe_handlers
Ethernet over EtherCAT handlers.
Definition: master.h:279
Operation phase.
Definition: master.h:124
unsigned int allow_scan
True, if slave scanning is allowed.
Definition: master.h:237
#define EC_SLAVE_WARN(slave, fmt, args...)
Convenience macro for printing slave-specific warnings to syslog.
Definition: slave.h:82
void ec_fsm_master_restart(ec_fsm_master_t *fsm)
Restarts the master state machine.
Definition: fsm_master.c:184
unsigned int rescan_required
A bus rescan is required.
Definition: fsm_master.h:75
EtherCAT datagram.
Definition: datagram.h:79
ec_sii_coe_details_t coe_details
CoE detail flags.
Definition: slave.h:152
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:108
#define EC_WRITE_U8(DATA, VAL)
Write an 8-bit unsigned value to EtherCAT data.
Definition: ecrt.h:2699
unsigned int scan_index
Index of slave currently scanned.
Definition: master.h:236
u64 dc_ref_time
Common reference timestamp for DC start times.
Definition: master.h:224
ec_slave_state_t slave_states[EC_MAX_NUM_DEVICES]
AL states of responding slaves for every device.
Definition: fsm_master.h:76
struct list_head emerg_reg_requests
Emergency register access requests.
Definition: master.h:294
#define EC_SYSTEM_TIME_TOLERANCE_NS
Time difference [ns] to tolerate without setting a new system time offset.
Definition: fsm_master.c:43
ec_fsm_slave_t fsm
Slave state machine.
Definition: slave.h:227
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:278
uint16_t working_counter
Working counter.
Definition: datagram.h:91
int ec_sdo_request_timed_out(const ec_sdo_request_t *req)
Checks, if the timeout was exceeded.
Definition: sdo_request.c:171
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:503
void ec_fsm_master_action_idle(ec_fsm_master_t *fsm)
Master action: IDLE.
Definition: fsm_master.c:586
int ec_eoe_init(ec_eoe_t *eoe, ec_slave_t *slave)
EoE constructor.
Definition: ethernet.c:106
Acknowledge/Error bit (no actual state)
Definition: globals.h:134
int ec_fsm_coe_success(const ec_fsm_coe_t *fsm)
Returns, if the state machine terminated with success.
Definition: fsm_coe.c:254
uint8_t link_state
device link state
Definition: device.h:80
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:69
wait_queue_head_t request_queue
Wait queue for external requests from user space.
Definition: master.h:297
void ec_fsm_sii_init(ec_fsm_sii_t *fsm, ec_datagram_t *datagram)
Constructor.
Definition: fsm_sii.c:66
EtherCAT master state machine.
uint16_t station_address
Configured station address.
Definition: slave.h:176
const char * ec_device_names[2]
Device names.
Definition: module.c:463
struct list_head list
List head.
Definition: fsm_master.h:46
SII write request.
Definition: fsm_master.h:45
void ec_fsm_master_action_next_slave_state(ec_fsm_master_t *fsm)
Master action: Get state of next slave.
Definition: fsm_master.c:644
#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:82
void ec_fsm_master_enter_clear_addresses(ec_fsm_master_t *)
Start clearing slave addresses.
Definition: fsm_master.c:807
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:70
#define EC_MASTER_DBG(master, level, fmt, args...)
Convenience macro for printing master-specific debug messages to syslog.
Definition: master.h:100
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:441
ec_slave_t * fsm_slave
Slave that is queried next for FSM exec.
Definition: master.h:267
ec_slave_t * slave
EtherCAT slave.
Definition: fsm_master.h:47
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:612
EtherCAT slave.
Definition: slave.h:168
void ec_master_attach_slave_configs(ec_master_t *master)
Attaches the slave configurations to the slaves.
Definition: master.c:1766
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:202
void ec_fsm_master_state_read_state(ec_fsm_master_t *)
Master state: READ STATE.
Definition: fsm_master.c:730
void ec_datagram_zero(ec_datagram_t *datagram)
Fills the datagram payload memory with zeros.
Definition: datagram.c:170
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:923
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:122
int ec_fsm_soe_success(const ec_fsm_soe_t *fsm)
Returns, if the state machine terminated with success.
Definition: fsm_soe.c:179
Ethernet over EtherCAT (EoE)
ec_datagram_state_t state
State.
Definition: datagram.h:92
ec_slave_config_t * config
Current configuration.
Definition: slave.h:182
ec_master_phase_t phase
Master phase.
Definition: master.h:208
#define EC_WRITE_U32(DATA, VAL)
Write a 32-bit unsigned value to EtherCAT data.
Definition: ecrt.h:2733
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:216
uint8_t enable_sdo_info
SDO information service available.
Definition: globals.h:156
Use configured addresses.
Definition: fsm_sii.h:42
Slave configutation feature flag.
Definition: flag.h:38
ec_fsm_slave_scan_t fsm_slave_scan
slave state machine
Definition: fsm_master.h:90
Ethernet over EtherCAT.
Definition: globals.h:145
uint8_t sdo_dictionary_fetched
Dictionary has been fetched.
Definition: slave.h:218
struct list_head sdo_requests
List of SDO requests.
Definition: slave_config.h:137
void ec_fsm_master_action_configure(ec_fsm_master_t *fsm)
Master action: Configure.
Definition: fsm_master.c:672
uint16_t mailbox_protocols
Supported mailbox protocols.
Definition: slave.h:139
ec_flag_t * ec_slave_config_find_flag(ec_slave_config_t *sc, const char *key)
Finds a flag.
Definition: slave_config.c:602
ec_sdo_request_t * sdo_request
SDO request to process.
Definition: fsm_master.h:82
unsigned int debug_level
Master debug level.
Definition: master.h:271
#define EC_SLAVE_ERR(slave, fmt, args...)
Convenience macro for printing slave-specific errors to syslog.
Definition: slave.h:68
void ec_datagram_print_wc_error(const ec_datagram_t *datagram)
Evaluates the working counter of a single-cast datagram.
Definition: datagram.c:594
ec_slave_dc_range_t base_dc_range
DC range.
Definition: slave.h:203
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:160
int ec_fsm_change_exec(ec_fsm_change_t *fsm)
Executes the current state of the state machine.
Definition: fsm_change.c:119
uint32_t transmission_delay
DC system time transmission delay (offset from reference clock).
Definition: slave.h:207
unsigned int slave_count
Number of slaves on the bus.
Definition: master.h:217
unsigned int scan_busy
Current scan state.
Definition: master.h:235
ec_device_index_t
Master devices.
Definition: globals.h:198
void ec_fsm_master_state_dc_measure_delays(ec_fsm_master_t *)
Master state: DC MEASURE DELAYS.
Definition: fsm_master.c:868
void ec_fsm_master_state_broadcast(ec_fsm_master_t *)
Master state: BROADCAST.
Definition: fsm_master.c:259
void ec_fsm_pdo_init(ec_fsm_pdo_t *fsm, ec_fsm_coe_t *fsm_coe)
Constructor.
Definition: fsm_pdo.c:66
ec_soe_request_t * soe_request
SoE request to process.
Definition: fsm_master.h:83
void ec_fsm_coe_clear(ec_fsm_coe_t *fsm)
Destructor.
Definition: fsm_coe.c:174
uint16_t alias
Configured station alias.
Definition: slave.h:126
#define EC_WRITE_U16(DATA, VAL)
Write a 16-bit unsigned value to EtherCAT data.
Definition: ecrt.h:2716
unsigned long scan_jiffies
beginning of slave scanning
Definition: fsm_master.h:69
#define EC_ABS(X)
Absolute value.
Definition: globals.h:251
Main device.
Definition: globals.h:199
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:86
unsigned int active
Master has been activated.
Definition: master.h:209
ec_master_t * master
Master owning the slave.
Definition: slave.h:170
struct list_head soe_requests
List of SoE requests.
Definition: slave_config.h:138
void ec_fsm_change_clear(ec_fsm_change_t *fsm)
Destructor.
Definition: fsm_change.c:75
int ec_datagram_brd(ec_datagram_t *datagram, uint16_t mem_address, size_t data_size)
Initializes an EtherCAT BRD datagram.
Definition: datagram.c:365
int ec_datagram_fpwr(ec_datagram_t *datagram, uint16_t configured_address, uint16_t mem_address, size_t data_size)
Initializes an EtherCAT FPWR datagram.
Definition: datagram.c:290
uint8_t has_dc_system_time
The slave supports the DC system time register.
Definition: slave.h:204
wait_queue_head_t scan_queue
Queue for processes that wait for slave scanning.
Definition: master.h:240
#define EC_MASTER_ERR(master, fmt, args...)
Convenience macro for printing master-specific errors to syslog.
Definition: master.h:74
int ec_datagram_fprd(ec_datagram_t *datagram, uint16_t configured_address, uint16_t mem_address, size_t data_size)
Initializes an EtherCAT FPRD datagram.
Definition: datagram.c:265
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:184
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:82
int ec_fsm_master_idle(const ec_fsm_master_t *fsm)
Definition: fsm_master.c:173
32 bit.
Definition: globals.h:173
void ec_master_clear_slaves(ec_master_t *master)
Clear all slaves.
Definition: master.c:459
void ec_fsm_change_init(ec_fsm_change_t *fsm, ec_datagram_t *datagram)
Constructor.
Definition: fsm_change.c:60
struct list_head list
list item
Definition: ethernet.h:76
void ec_fsm_coe_init(ec_fsm_coe_t *fsm)
Constructor.
Definition: fsm_coe.c:162
void ec_fsm_master_state_acknowledge(ec_fsm_master_t *)
Master state: ACKNOWLEDGE.
Definition: fsm_master.c:785
void ec_fsm_sii_clear(ec_fsm_sii_t *fsm)
Destructor.
Definition: fsm_sii.c:80
INIT state (no mailbox communication, no IO)
Definition: globals.h:124
int idle
state machine is in idle phase
Definition: fsm_master.h:68
struct semaphore scan_sem
Semaphore protecting the scan_busy variable and the allow_scan flag.
Definition: master.h:238
void ec_fsm_master_state_start(ec_fsm_master_t *)
Master state: START.
Definition: fsm_master.c:201
uint16_t effective_alias
Effective alias address.
Definition: slave.h:177
void ec_master_clear_eoe_handlers(ec_master_t *master)
Clear and free all EoE handlers.
Definition: master.c:423
ec_fsm_slave_config_t fsm_slave_config
slave state machine
Definition: fsm_master.h:89
int ec_fsm_sii_exec(ec_fsm_sii_t *fsm)
Executes the SII state machine.
Definition: fsm_sii.c:129
int ec_fsm_sii_success(ec_fsm_sii_t *fsm)
Returns, if the master startup state machine terminated with success.
Definition: fsm_sii.c:144
#define EC_READ_U16(DATA)
Read a 16-bit unsigned value from EtherCAT data.
Definition: ecrt.h:2611
void ec_master_eoe_start(ec_master_t *master)
Starts Ethernet over EtherCAT processing on demand.
Definition: master.c:1654
void ec_datagram_print_state(const ec_datagram_t *datagram)
Prints the state of a datagram.
Definition: datagram.c:557
Mailbox functionality.
ec_master_t * master
master the FSM runs on
Definition: fsm_master.h:61
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:43
#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:2750
void ec_fsm_master_state_clear_addresses(ec_fsm_master_t *)
Master state: CLEAR ADDRESSES.
Definition: fsm_master.c:823
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:220
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:54
ec_direction_t dir
Direction.
Definition: reg_request.h:44
Queued for sending.
Definition: datagram.h:68
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:102
Timed out (dequeued).
Definition: datagram.h:71
wait_queue_head_t config_queue
Queue for processes that wait for slave configuration.
Definition: master.h:246
int32_t value
Flag value (meaning depends on key).
Definition: flag.h:41
unsigned int retries
retries on datagram timeout.
Definition: fsm_master.h:63
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:223
unsigned long jiffies_preop
Time, the slave went to PREOP.
Definition: slave.h:219
void ec_fsm_soe_init(ec_fsm_soe_t *fsm)
Constructor.
Definition: fsm_soe.c:99
uint8_t base_dc_supported
Distributed clocks are supported.
Definition: slave.h:202
void ec_fsm_soe_clear(ec_fsm_soe_t *fsm)
Destructor.
Definition: fsm_soe.c:112
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:86
#define EC_READ_U8(DATA)
Read an 8-bit unsigned value from EtherCAT data.
Definition: ecrt.h:2595
EtherCAT slave configuration.
Definition: slave_config.h:111
int ec_soe_request_timed_out(const ec_soe_request_t *req)
Checks, if the timeout was exceeded.
Definition: soe_request.c:258
int ec_fsm_master_exec(ec_fsm_master_t *fsm)
Executes the current state of the state machine.
Definition: fsm_master.c:154
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:88
ec_device_index_t device_index
Index of device the slave responds on.
Definition: slave.h:171
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:144
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:197
ec_slave_t * slave
current slave
Definition: fsm_master.h:79
Values written by the master.
Definition: ecrt.h:503
ec_fsm_change_t fsm_change
State change state machine.
Definition: fsm_master.h:88
Received (dequeued).
Definition: datagram.h:70
Ethernet over EtherCAT (EoE) handler.
Definition: ethernet.h:74
off_t sii_index
index to SII write request data
Definition: fsm_master.h:81
#define EC_MASTER_INFO(master, fmt, args...)
Convenience macro for printing master-specific information to syslog.
Definition: master.h:62
unsigned int error_flag
Stop processing after an error.
Definition: slave.h:185
unsigned int config_changed
The configuration changed.
Definition: master.h:210
EtherCAT master.
Definition: master.h:183
struct list_head list
List item.
Definition: reg_request.h:41
ec_slave_state_t requested_state
Requested application state.
Definition: slave.h:183
ec_device_index_t dev_idx
Current device index (for scanning etc.).
Definition: fsm_master.h:66
#define EC_READ_U64(DATA)
Read a 64-bit unsigned value from EtherCAT data.
Definition: ecrt.h:2643
ec_device_t devices[EC_MAX_NUM_DEVICES]
EtherCAT devices.
Definition: master.h:196
ec_internal_request_state_t state
Request state.
Definition: soe_request.h:52
unsigned int config_busy
State of slave configuration.
Definition: master.h:243
const uint16_t * words
Pointer to the data words.
Definition: fsm_master.h:50
void ec_fsm_master_clear(ec_fsm_master_t *fsm)
Destructor.
Definition: fsm_master.c:107
EtherCAT FoE state machines.
Sercos-over-EtherCAT request.
Definition: soe_request.h:40
unknown state
Definition: globals.h:122
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:1688
uint8_t link_state[EC_MAX_NUM_DEVICES]
Last link state for every device.
Definition: fsm_master.h:70
ec_fsm_coe_t fsm_coe
CoE state machine.
Definition: fsm_master.h:85
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:186
int ec_fsm_change_success(ec_fsm_change_t *fsm)
Returns, if the state machine terminated with success.
Definition: fsm_change.c:134
unsigned int has_general
General category present.
Definition: slave.h:146
int ec_datagram_bwr(ec_datagram_t *datagram, uint16_t mem_address, size_t data_size)
Initializes an EtherCAT BWR datagram.
Definition: datagram.c:385