IgH EtherCAT Master  1.6.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 
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 
47 // prototypes for private methods
54 u64 ec_fsm_master_dc_offset32(ec_fsm_master_t *, u64, u64, unsigned long);
55 u64 ec_fsm_master_dc_offset64(ec_fsm_master_t *, u64, u64, unsigned long);
56 
57 /****************************************************************************/
58 
74 
77 
78 /****************************************************************************/
79 
83  ec_fsm_master_t *fsm,
84  ec_master_t *master,
85  ec_datagram_t *datagram
86  )
87 {
88  fsm->master = master;
89  fsm->datagram = datagram;
90 
91  // inits the member variables state, idle, dev_idx, link_state,
92  // slaves_responding, slave_states and rescan_required
94 
95  fsm->retries = 0;
96  fsm->scan_jiffies = 0;
97  fsm->slave = NULL;
98  fsm->sii_request = NULL;
99  fsm->sii_index = 0;
100  fsm->sdo_request = NULL;
101  fsm->soe_request = NULL;
102 
103  // init sub-state-machines
104  ec_fsm_coe_init(&fsm->fsm_coe);
105  ec_fsm_soe_init(&fsm->fsm_soe);
106  ec_fsm_pdo_init(&fsm->fsm_pdo, &fsm->fsm_coe);
107 #ifdef EC_EOE
108  ec_fsm_eoe_init(&fsm->fsm_eoe);
109 #endif
112  &fsm->fsm_change, &fsm->fsm_coe, &fsm->fsm_soe, &fsm->fsm_pdo,
113  &fsm->fsm_eoe);
115  &fsm->fsm_slave_config, &fsm->fsm_pdo);
116  ec_fsm_sii_init(&fsm->fsm_sii, fsm->datagram);
117 }
118 
119 /****************************************************************************/
120 
124  ec_fsm_master_t *fsm
125  )
126 {
127  // clear sub-state machines
128  ec_fsm_coe_clear(&fsm->fsm_coe);
129  ec_fsm_soe_clear(&fsm->fsm_soe);
130  ec_fsm_pdo_clear(&fsm->fsm_pdo);
131 #ifdef EC_EOE
132  ec_fsm_eoe_clear(&fsm->fsm_eoe);
133 #endif
137  ec_fsm_sii_clear(&fsm->fsm_sii);
138 }
139 
140 /****************************************************************************/
141 
145  ec_fsm_master_t *fsm
146  )
147 {
148  ec_device_index_t dev_idx;
149 
151  fsm->idle = 0;
152  fsm->dev_idx = EC_DEVICE_MAIN;
153 
154  for (dev_idx = EC_DEVICE_MAIN;
155  dev_idx < ec_master_num_devices(fsm->master); dev_idx++) {
156  fsm->link_state[dev_idx] = 0;
157  fsm->slaves_responding[dev_idx] = 0;
158  fsm->slave_states[dev_idx] = EC_SLAVE_STATE_UNKNOWN;
159  }
160 
161  fsm->rescan_required = 0;
162 }
163 
164 /****************************************************************************/
165 
174  ec_fsm_master_t *fsm
175  )
176 {
177  if (fsm->datagram->state == EC_DATAGRAM_SENT
178  || fsm->datagram->state == EC_DATAGRAM_QUEUED) {
179  // datagram was not sent or received yet.
180  return 0;
181  }
182 
183  fsm->state(fsm);
184  return 1;
185 }
186 
187 /****************************************************************************/
188 
193  const ec_fsm_master_t *fsm
194  )
195 {
196  return fsm->idle;
197 }
198 
199 /****************************************************************************/
200 
204  ec_fsm_master_t *fsm
205  )
206 {
207  fsm->dev_idx = EC_DEVICE_MAIN;
209  fsm->state(fsm); // execute immediately
210 }
211 
212 /*****************************************************************************
213  * Master state machine
214  ****************************************************************************/
215 
221  ec_fsm_master_t *fsm
222  )
223 {
224  ec_master_t *master = fsm->master;
225 
226  fsm->idle = 1;
227 
228  // check for emergency requests
229  if (!list_empty(&master->emerg_reg_requests)) {
230  ec_reg_request_t *request;
231 
232  // get first request
233  request = list_entry(master->emerg_reg_requests.next,
234  ec_reg_request_t, list);
235  list_del_init(&request->list); // dequeue
236  request->state = EC_INT_REQUEST_BUSY;
237 
238  if (request->transfer_size > fsm->datagram->mem_size) {
239  EC_MASTER_ERR(master, "Emergency request data too large!\n");
240  request->state = EC_INT_REQUEST_FAILURE;
241  wake_up_all(&master->request_queue);
242  fsm->state(fsm); // continue
243  return;
244  }
245 
246  if (request->dir != EC_DIR_OUTPUT) {
247  EC_MASTER_ERR(master, "Emergency requests must be"
248  " write requests!\n");
249  request->state = EC_INT_REQUEST_FAILURE;
250  wake_up_all(&master->request_queue);
251  fsm->state(fsm); // continue
252  return;
253  }
254 
255  EC_MASTER_DBG(master, 1, "Writing emergency register request...\n");
256  ec_datagram_apwr(fsm->datagram, request->ring_position,
257  request->address, request->transfer_size);
258  memcpy(fsm->datagram->data, request->data, request->transfer_size);
260  request->state = EC_INT_REQUEST_SUCCESS;
261  wake_up_all(&master->request_queue);
262  return;
263  }
264 
265  ec_datagram_brd(fsm->datagram, 0x0130, 2);
267  fsm->datagram->device_index = fsm->dev_idx;
268  fsm->retries = EC_FSM_RETRIES;
270 }
271 
272 /****************************************************************************/
273 
279  ec_fsm_master_t *fsm
280  )
281 {
282  ec_datagram_t *datagram = fsm->datagram;
283  unsigned int i, size;
284  ec_slave_t *slave;
285  ec_master_t *master = fsm->master;
286 
287  if (datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--) {
288  return;
289  }
290 
291  // bus topology change?
292  if (datagram->working_counter != fsm->slaves_responding[fsm->dev_idx]) {
293  fsm->rescan_required = 1;
294  fsm->slaves_responding[fsm->dev_idx] = datagram->working_counter;
295  EC_MASTER_INFO(master, "%u slave(s) responding on %s device. "
296  "Re-scanning on next possibility.\n",
297  fsm->slaves_responding[fsm->dev_idx],
298  ec_device_names[fsm->dev_idx != 0]);
299  }
300 
301  if (fsm->link_state[fsm->dev_idx] &&
302  !master->devices[fsm->dev_idx].link_state) {
303  ec_device_index_t dev_idx;
304 
305  EC_MASTER_DBG(master, 1, "Master state machine detected "
306  "link down on %s device. Clearing slave list.\n",
307  ec_device_names[fsm->dev_idx != 0]);
308 
309 #ifdef EC_EOE
310  ec_master_eoe_stop(master);
312 #endif
313  ec_master_clear_slaves(master);
314 
315  for (dev_idx = EC_DEVICE_MAIN;
316  dev_idx < ec_master_num_devices(master); dev_idx++) {
317  fsm->slave_states[dev_idx] = 0x00;
318  fsm->slaves_responding[dev_idx] = 0; /* Reset to trigger rescan on
319  next link up. */
320  }
321  }
322  fsm->link_state[fsm->dev_idx] = master->devices[fsm->dev_idx].link_state;
323 
324  if (datagram->state == EC_DATAGRAM_RECEIVED &&
325  fsm->slaves_responding[fsm->dev_idx]) {
326  uint8_t states = EC_READ_U8(datagram->data);
327  if (states != fsm->slave_states[fsm->dev_idx]) {
328  // slave states changed
329  char state_str[EC_STATE_STRING_SIZE];
330  fsm->slave_states[fsm->dev_idx] = states;
331  ec_state_string(states, state_str, 1);
332  EC_MASTER_INFO(master, "Slave states on %s device: %s.\n",
333  ec_device_names[fsm->dev_idx != 0], state_str);
334  }
335  } else {
336  fsm->slave_states[fsm->dev_idx] = 0x00;
337  }
338 
339  fsm->dev_idx++;
340  if (fsm->dev_idx < ec_master_num_devices(master)) {
341  // check number of responding slaves on next device
343  fsm->state(fsm); // execute immediately
344  return;
345  }
346 
347  if (fsm->rescan_required) {
348  down(&master->scan_sem);
349  if (!master->allow_scan) {
350  up(&master->scan_sem);
351  } else {
352  unsigned int count = 0, next_dev_slave, ring_position;
353  ec_device_index_t dev_idx;
354 
355  master->scan_busy = 1;
356  master->scan_index = 0;
357  up(&master->scan_sem);
358 
359  EC_MASTER_INFO(master, "Re-scanning now.\n");
360 
361  // clear all slaves and scan the bus
362  fsm->rescan_required = 0;
363  fsm->idle = 0;
364  fsm->scan_jiffies = jiffies;
365 
366 #ifdef EC_EOE
367  ec_master_eoe_stop(master);
369 #endif
370  ec_master_clear_slaves(master);
371 
372  for (dev_idx = EC_DEVICE_MAIN;
373  dev_idx < ec_master_num_devices(master); dev_idx++) {
374  count += fsm->slaves_responding[dev_idx];
375  }
376 
377  if (!count) {
378  // no slaves present -> finish state machine.
379  master->scan_busy = 0;
380  wake_up_interruptible(&master->scan_queue);
382  return;
383  }
384 
385  size = sizeof(ec_slave_t) * count;
386  if (!(master->slaves =
387  (ec_slave_t *) kmalloc(size, GFP_KERNEL))) {
388  EC_MASTER_ERR(master, "Failed to allocate %u bytes"
389  " of slave memory!\n", size);
390  master->scan_busy = 0;
391  wake_up_interruptible(&master->scan_queue);
393  return;
394  }
395 
396  // init slaves
397  dev_idx = EC_DEVICE_MAIN;
398  next_dev_slave = fsm->slaves_responding[dev_idx];
399  ring_position = 0;
400  for (i = 0; i < count; i++, ring_position++) {
401  slave = master->slaves + i;
402  while (i >= next_dev_slave) {
403  dev_idx++;
404  next_dev_slave += fsm->slaves_responding[dev_idx];
405  ring_position = 0;
406  }
407 
408  ec_slave_init(slave, master, dev_idx, ring_position, i + 1);
409 
410  // do not force reconfiguration in operation phase to avoid
411  // unnecesssary process data interruptions
412  if (master->phase != EC_OPERATION) {
413  slave->force_config = 1;
414  }
415  }
416  master->slave_count = count;
417  master->fsm_slave = master->slaves;
418 
419  /* start with first device with slaves responding; at least one
420  * has responding slaves, otherwise count would be zero. */
421  fsm->dev_idx = EC_DEVICE_MAIN;
422  while (!fsm->slaves_responding[fsm->dev_idx]) {
423  fsm->dev_idx++;
424  }
425 
427  return;
428  }
429  }
430 
431  if (master->slave_count) {
432 
433  // application applied configurations
434  if (master->config_changed) {
435  master->config_changed = 0;
436 
437  EC_MASTER_DBG(master, 1, "Configuration changed.\n");
438 
439  fsm->slave = master->slaves; // begin with first slave
441 
442  } else {
443  // fetch state from first slave
444  fsm->slave = master->slaves;
446  0x0130, 2);
447  ec_datagram_zero(datagram);
448  fsm->datagram->device_index = fsm->slave->device_index;
449  fsm->retries = EC_FSM_RETRIES;
451  }
452  } else {
454  }
455 }
456 
457 /****************************************************************************/
458 
464  ec_fsm_master_t *fsm
465  )
466 {
467  ec_master_t *master = fsm->master;
468  ec_sii_write_request_t *request;
469  ec_slave_config_t *config;
470  ec_flag_t *flag;
471  int assign_to_pdi;
472 
473  // search the first request to be processed
474  while (1) {
475  if (list_empty(&master->sii_requests))
476  break;
477 
478  // get first request
479  request = list_entry(master->sii_requests.next,
480  ec_sii_write_request_t, list);
481  list_del_init(&request->list); // dequeue
482  request->state = EC_INT_REQUEST_BUSY;
483 
484  assign_to_pdi = 0;
485  config = request->slave->config;
486  if (config) {
487  flag = ec_slave_config_find_flag(config, "AssignToPdi");
488  if (flag) {
489  assign_to_pdi = flag->value;
490  }
491  }
492 
493  if (assign_to_pdi) {
494  fsm->sii_request = request;
495  EC_SLAVE_DBG(request->slave, 1,
496  "Assigning SII back to EtherCAT.\n");
498  0x0500, 0x01);
499  EC_WRITE_U8(fsm->datagram->data, 0x00); // EtherCAT
500  fsm->retries = EC_FSM_RETRIES;
502  return 1;
503  }
504 
505  // found pending SII write operation. execute it!
506  EC_SLAVE_DBG(request->slave, 1, "Writing SII data...\n");
507  fsm->sii_request = request;
508  fsm->sii_index = 0;
509  ec_fsm_sii_write(&fsm->fsm_sii, request->slave, request->offset,
512  fsm->state(fsm); // execute immediately
513  return 1;
514  }
515 
516  return 0;
517 }
518 
519 /****************************************************************************/
520 
526  ec_fsm_master_t *fsm
527  )
528 {
529  ec_master_t *master = fsm->master;
530  ec_slave_t *slave;
531  ec_sdo_request_t *sdo_req;
532  ec_soe_request_t *soe_req;
533 
534  // search for internal requests to be processed
535  for (slave = master->slaves;
536  slave < master->slaves + master->slave_count;
537  slave++) {
538 
539  if (!slave->config) {
540  continue;
541  }
542 
543  list_for_each_entry(sdo_req, &slave->config->sdo_requests, list) {
544  if (sdo_req->state == EC_INT_REQUEST_QUEUED) {
545 
546  if (ec_sdo_request_timed_out(sdo_req)) {
547  sdo_req->state = EC_INT_REQUEST_FAILURE;
548  EC_SLAVE_DBG(slave, 1, "Internal SDO request"
549  " timed out.\n");
550  continue;
551  }
552 
553  if (slave->current_state == EC_SLAVE_STATE_INIT) {
554  sdo_req->state = EC_INT_REQUEST_FAILURE;
555  continue;
556  }
557 
558  sdo_req->state = EC_INT_REQUEST_BUSY;
559  EC_SLAVE_DBG(slave, 1, "Processing internal"
560  " SDO request...\n");
561  fsm->idle = 0;
562  fsm->sdo_request = sdo_req;
563  fsm->slave = slave;
565  ec_fsm_coe_transfer(&fsm->fsm_coe, slave, sdo_req);
566  ec_fsm_coe_exec(&fsm->fsm_coe, fsm->datagram);
567  return 1;
568  }
569  }
570 
571  list_for_each_entry(soe_req, &slave->config->soe_requests, list) {
572  if (soe_req->state == EC_INT_REQUEST_QUEUED) {
573 
574  if (ec_soe_request_timed_out(soe_req)) {
575  soe_req->state = EC_INT_REQUEST_FAILURE;
576  EC_SLAVE_DBG(slave, 1, "Internal SoE request"
577  " timed out.\n");
578  continue;
579  }
580 
581  if (slave->current_state == EC_SLAVE_STATE_INIT) {
582  soe_req->state = EC_INT_REQUEST_FAILURE;
583  continue;
584  }
585 
586  soe_req->state = EC_INT_REQUEST_BUSY;
587  EC_SLAVE_DBG(slave, 1, "Processing internal"
588  " SoE request...\n");
589  fsm->idle = 0;
590  fsm->soe_request = soe_req;
591  fsm->slave = slave;
593  ec_fsm_soe_transfer(&fsm->fsm_soe, slave, soe_req);
594  ec_fsm_soe_exec(&fsm->fsm_soe, fsm->datagram);
595  return 1;
596  }
597  }
598  }
599  return 0;
600 }
601 
602 /****************************************************************************/
603 
609  ec_fsm_master_t *fsm
610  )
611 {
612  ec_master_t *master = fsm->master;
613  ec_slave_t *slave;
614 
615  // Check for pending internal SDO or SoE requests
617  return;
618  }
619 
620  // enable processing of requests
621  for (slave = master->slaves;
622  slave < master->slaves + master->slave_count;
623  slave++) {
624  ec_fsm_slave_set_ready(&slave->fsm);
625  }
626 
627  // check, if slaves have an SDO dictionary to read out.
628  for (slave = master->slaves;
629  slave < master->slaves + master->slave_count;
630  slave++) {
631  if (!(slave->sii.mailbox_protocols & EC_MBOX_COE)
632  || (slave->sii.has_general
633  && !slave->sii.coe_details.enable_sdo_info)
634  || slave->sdo_dictionary_fetched
637  || jiffies - slave->jiffies_preop < EC_WAIT_SDO_DICT * HZ
638  ) continue;
639 
640  EC_SLAVE_DBG(slave, 1, "Fetching SDO dictionary.\n");
641 
642  slave->sdo_dictionary_fetched = 1;
643 
644  // start fetching SDO dictionary
645  fsm->idle = 0;
646  fsm->slave = slave;
648  ec_fsm_coe_dictionary(&fsm->fsm_coe, slave);
649  ec_fsm_coe_exec(&fsm->fsm_coe, fsm->datagram); // execute immediately
650  fsm->datagram->device_index = fsm->slave->device_index;
651  return;
652  }
653 
654  // check for pending SII write operations.
656  return; // SII write request found
657  }
658 
660 }
661 
662 /****************************************************************************/
663 
667  ec_fsm_master_t *fsm
668  )
669 {
670  ec_master_t *master = fsm->master;
671 
672  // is there another slave to query?
673  fsm->slave++;
674  if (fsm->slave < master->slaves + master->slave_count) {
675  // fetch state from next slave
676  fsm->idle = 1;
678  fsm->slave->station_address, 0x0130, 2);
680  fsm->datagram->device_index = fsm->slave->device_index;
681  fsm->retries = EC_FSM_RETRIES;
683  return;
684  }
685 
686  // all slaves processed
688 }
689 
690 /****************************************************************************/
691 
695  ec_fsm_master_t *fsm
696  )
697 {
698  ec_master_t *master = fsm->master;
699  ec_slave_t *slave = fsm->slave;
700 
701  if (master->config_changed) {
702  master->config_changed = 0;
703 
704  // abort iterating through slaves,
705  // first compensate DC system time offsets,
706  // then begin configuring at slave 0
707  EC_MASTER_DBG(master, 1, "Configuration changed"
708  " (aborting state check).\n");
709 
710  fsm->slave = master->slaves; // begin with first slave
712  return;
713  }
714 
715  // Does the slave have to be configured?
716  if ((slave->current_state != slave->requested_state
717  || slave->force_config) && !slave->error_flag) {
718 
719  // Start slave configuration
720  down(&master->config_sem);
721  master->config_busy = 1;
722  up(&master->config_sem);
723 
724  if (master->debug_level) {
725  char old_state[EC_STATE_STRING_SIZE],
726  new_state[EC_STATE_STRING_SIZE];
727  ec_state_string(slave->current_state, old_state, 0);
728  ec_state_string(slave->requested_state, new_state, 0);
729  EC_SLAVE_DBG(slave, 1, "Changing state from %s to %s%s.\n",
730  old_state, new_state,
731  slave->force_config ? " (forced)" : "");
732  }
733 
734  fsm->idle = 0;
737  fsm->state(fsm); // execute immediately
738  fsm->datagram->device_index = fsm->slave->device_index;
739  return;
740  }
741 
742  // process next slave
744 }
745 
746 /****************************************************************************/
747 
753  ec_fsm_master_t *fsm
754  )
755 {
756  ec_slave_t *slave = fsm->slave;
757  ec_datagram_t *datagram = fsm->datagram;
758 
759  if (datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--) {
760  return;
761  }
762 
763  if (datagram->state != EC_DATAGRAM_RECEIVED) {
764  EC_SLAVE_ERR(slave, "Failed to receive AL state datagram: ");
765  ec_datagram_print_state(datagram);
767  return;
768  }
769 
770  // did the slave not respond to its station address?
771  if (datagram->working_counter != 1) {
772  if (!slave->error_flag) {
773  slave->error_flag = 1;
774  EC_SLAVE_DBG(slave, 1, "Slave did not respond to state query. "
775  "Re-scanning on next possibility...\n");
776  }
777  fsm->rescan_required = 1;
779  return;
780  }
781 
782  // A single slave responded
783  ec_slave_set_state(slave, EC_READ_U8(datagram->data));
784 
785  if (!slave->error_flag) {
786  // Check, if new slave state has to be acknowledged
787  if (slave->current_state & EC_SLAVE_STATE_ACK_ERR) {
788  fsm->idle = 0;
790  ec_fsm_change_ack(&fsm->fsm_change, slave);
791  fsm->state(fsm); // execute immediately
792  return;
793  }
794 
795  // No acknowlegde necessary; check for configuration
797  return;
798  }
799 
800  // slave has error flag set; process next one
802 }
803 
804 /****************************************************************************/
805 
809  ec_fsm_master_t *fsm
810  )
811 {
812  ec_slave_t *slave = fsm->slave;
813 
814  if (ec_fsm_change_exec(&fsm->fsm_change)) {
815  return;
816  }
817 
818  if (!ec_fsm_change_success(&fsm->fsm_change)) {
819  fsm->slave->error_flag = 1;
820  EC_SLAVE_ERR(slave, "Failed to acknowledge state change.\n");
821  }
822 
824 }
825 
826 /****************************************************************************/
827 
831  ec_fsm_master_t *fsm
832  )
833 {
834  // broadcast clear all station addresses
835  ec_datagram_bwr(fsm->datagram, 0x0010, 2);
836  EC_WRITE_U16(fsm->datagram->data, 0x0000);
837  fsm->datagram->device_index = fsm->dev_idx;
838  fsm->retries = EC_FSM_RETRIES;
840 }
841 
842 /****************************************************************************/
843 
847  ec_fsm_master_t *fsm
848  )
849 {
850  ec_master_t *master = fsm->master;
851  ec_datagram_t *datagram = fsm->datagram;
852 
853  if (datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--) {
854  return;
855  }
856 
857  if (datagram->state != EC_DATAGRAM_RECEIVED) {
858  EC_MASTER_ERR(master, "Failed to receive address"
859  " clearing datagram on %s link: ",
860  ec_device_names[fsm->dev_idx != 0]);
861  ec_datagram_print_state(datagram);
862  master->scan_busy = 0;
863  master->scan_index = master->slave_count;
864  wake_up_interruptible(&master->scan_queue);
866  return;
867  }
868 
869  if (datagram->working_counter != fsm->slaves_responding[fsm->dev_idx]) {
870  EC_MASTER_WARN(master, "Failed to clear station addresses on %s link:"
871  " Cleared %u of %u",
872  ec_device_names[fsm->dev_idx != 0], datagram->working_counter,
873  fsm->slaves_responding[fsm->dev_idx]);
874  }
875 
876  EC_MASTER_DBG(master, 1, "Sending broadcast-write"
877  " to measure transmission delays on %s link.\n",
878  ec_device_names[fsm->dev_idx != 0]);
879 
880  ec_datagram_bwr(datagram, 0x0900, 1);
881  ec_datagram_zero(datagram);
882  fsm->datagram->device_index = fsm->dev_idx;
883  fsm->retries = EC_FSM_RETRIES;
885 }
886 
887 /****************************************************************************/
888 
892  ec_fsm_master_t *fsm
893  )
894 {
895  ec_master_t *master = fsm->master;
896  ec_datagram_t *datagram = fsm->datagram;
897 
898  if (datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--) {
899  return;
900  }
901 
902  if (datagram->state != EC_DATAGRAM_RECEIVED) {
903  EC_MASTER_ERR(master, "Failed to receive delay measuring datagram"
904  " on %s link: ", ec_device_names[fsm->dev_idx != 0]);
905  ec_datagram_print_state(datagram);
906  master->scan_busy = 0;
907  master->scan_index = master->slave_count;
908  wake_up_interruptible(&master->scan_queue);
910  return;
911  }
912 
913  EC_MASTER_DBG(master, 1, "%u slaves responded to delay measuring"
914  " on %s link.\n",
915  datagram->working_counter, ec_device_names[fsm->dev_idx != 0]);
916 
917  do {
918  fsm->dev_idx++;
919  } while (fsm->dev_idx < ec_master_num_devices(master) &&
920  !fsm->slaves_responding[fsm->dev_idx]);
921  if (fsm->dev_idx < ec_master_num_devices(master)) {
923  return;
924  }
925 
926  EC_MASTER_INFO(master, "Scanning bus.\n");
927 
928  // begin scanning of slaves
929  fsm->slave = master->slaves;
930  master->scan_index = 0;
931  EC_MASTER_DBG(master, 1, "Scanning slave %u on %s link.\n",
932  fsm->slave->ring_position,
933  ec_device_names[fsm->slave->device_index != 0]);
936  ec_fsm_slave_scan_exec(&fsm->fsm_slave_scan); // execute immediately
937  fsm->datagram->device_index = fsm->slave->device_index;
938 }
939 
940 /****************************************************************************/
941 
947  ec_fsm_master_t *fsm
948  )
949 {
950  ec_master_t *master = fsm->master;
951 #ifdef EC_EOE
952  ec_slave_t *slave = fsm->slave;
953 #endif
954 
956  return;
957  }
958 
959 #ifdef EC_EOE
960  if (slave->sii.mailbox_protocols & EC_MBOX_EOE) {
961  // create EoE handler for this slave
962  ec_eoe_t *eoe;
963  if (!(eoe = kmalloc(sizeof(ec_eoe_t), GFP_KERNEL))) {
964  EC_SLAVE_ERR(slave, "Failed to allocate EoE handler memory!\n");
965  } else if (ec_eoe_init(eoe, slave)) {
966  EC_SLAVE_ERR(slave, "Failed to init EoE handler!\n");
967  kfree(eoe);
968  } else {
969  list_add_tail(&eoe->list, &master->eoe_handlers);
970  }
971  }
972 #endif
973 
974  // another slave to fetch?
975  fsm->slave++;
976  master->scan_index++;
977  if (fsm->slave < master->slaves + master->slave_count) {
978  EC_MASTER_DBG(master, 1, "Scanning slave %u on %s link.\n",
979  fsm->slave->ring_position,
980  ec_device_names[fsm->slave->device_index != 0]);
982  ec_fsm_slave_scan_exec(&fsm->fsm_slave_scan); // execute immediately
983  fsm->datagram->device_index = fsm->slave->device_index;
984  return;
985  }
986 
987  EC_MASTER_INFO(master, "Bus scanning completed in %lu ms.\n",
988  (jiffies - fsm->scan_jiffies) * 1000 / HZ);
989 
990  master->scan_busy = 0;
991  master->scan_index = master->slave_count;
992  wake_up_interruptible(&master->scan_queue);
993 
994  ec_master_calc_dc(master);
995 
996  // Attach slave configurations
998 
999 #ifdef EC_EOE
1000  // check if EoE processing has to be started
1001  ec_master_eoe_start(master);
1002 #endif
1003 
1004  if (master->slave_count) {
1005  master->config_changed = 0;
1006 
1007  fsm->slave = master->slaves; // begin with first slave
1009  } else {
1010  ec_fsm_master_restart(fsm);
1011  }
1012 }
1013 
1014 /****************************************************************************/
1015 
1021  ec_fsm_master_t *fsm
1022  )
1023 {
1024  ec_master_t *master = fsm->master;
1025 
1027  return;
1028  }
1029 
1030  fsm->slave->force_config = 0;
1031 
1032  // configuration finished
1033  master->config_busy = 0;
1034  wake_up_interruptible(&master->config_queue);
1035 
1037  // TODO: mark slave_config as failed.
1038  }
1039 
1040  fsm->idle = 1;
1042 }
1043 
1044 /****************************************************************************/
1045 
1049  ec_fsm_master_t *fsm
1050  )
1051 {
1052  ec_master_t *master = fsm->master;
1053 
1054  if (master->dc_ref_time) {
1055 
1056  while (fsm->slave < master->slaves + master->slave_count) {
1057  if (!fsm->slave->base_dc_supported
1058  || !fsm->slave->has_dc_system_time) {
1059  fsm->slave++;
1060  continue;
1061  }
1062 
1063  EC_SLAVE_DBG(fsm->slave, 1, "Checking system time offset.\n");
1064 
1065  // read DC system time (0x0910, 64 bit)
1066  // gap (64 bit)
1067  // and time offset (0x0920, 64 bit)
1069  0x0910, 24);
1070  fsm->datagram->device_index = fsm->slave->device_index;
1071  fsm->retries = EC_FSM_RETRIES;
1073  return;
1074  }
1075 
1076  } else {
1077  if (master->active) {
1078  EC_MASTER_WARN(master, "No application time received up to now,"
1079  " but master already active.\n");
1080  } else {
1081  EC_MASTER_DBG(master, 1, "No app_time received up to now.\n");
1082  }
1083  }
1084 
1085  // scanning and setting system times complete
1086  ec_master_request_op(master);
1087  EC_MASTER_DBG(master, 1, "After requesting OP, rescan_required is %u.\n",
1088  fsm->rescan_required);
1089  ec_fsm_master_restart(fsm);
1090 }
1091 
1092 /****************************************************************************/
1093 
1099  ec_fsm_master_t *fsm,
1100  u64 system_time,
1101  u64 old_offset,
1102  unsigned long jiffies_since_read
1103  )
1104 {
1105  ec_slave_t *slave = fsm->slave;
1106  u32 correction, system_time32, old_offset32, new_offset;
1107  s32 time_diff;
1108 
1109  system_time32 = (u32) system_time;
1110  old_offset32 = (u32) old_offset;
1111 
1112  // correct read system time by elapsed time since read operation
1113  correction = jiffies_since_read * 1000 / HZ * 1000000;
1114  system_time32 += correction;
1115  time_diff = (u32) slave->master->app_time - system_time32;
1116 
1117  EC_SLAVE_DBG(slave, 1, "DC 32 bit system time offset calculation:"
1118  " system_time=%u (corrected with %u),"
1119  " app_time=%llu, diff=%i\n",
1120  system_time32, correction,
1121  slave->master->app_time, time_diff);
1122 
1123  if (EC_ABS(time_diff) > EC_SYSTEM_TIME_TOLERANCE_NS) {
1124  new_offset = time_diff + old_offset32;
1125  EC_SLAVE_DBG(slave, 1, "Setting time offset to %u (was %u)\n",
1126  new_offset, old_offset32);
1127  return (u64) new_offset;
1128  } else {
1129  EC_SLAVE_DBG(slave, 1, "Not touching time offset.\n");
1130  return old_offset;
1131  }
1132 }
1133 
1134 /****************************************************************************/
1135 
1141  ec_fsm_master_t *fsm,
1142  u64 system_time,
1143  u64 old_offset,
1144  unsigned long jiffies_since_read
1145  )
1146 {
1147  ec_slave_t *slave = fsm->slave;
1148  u64 new_offset, correction;
1149  s64 time_diff;
1150 
1151  // correct read system time by elapsed time since read operation
1152  correction = (u64) (jiffies_since_read * 1000 / HZ) * 1000000;
1153  system_time += correction;
1154  time_diff = fsm->slave->master->app_time - system_time;
1155 
1156  EC_SLAVE_DBG(slave, 1, "DC 64 bit system time offset calculation:"
1157  " system_time=%llu (corrected with %llu),"
1158  " app_time=%llu, diff=%lli\n",
1159  system_time, correction,
1160  slave->master->app_time, time_diff);
1161 
1162  if (EC_ABS(time_diff) > EC_SYSTEM_TIME_TOLERANCE_NS) {
1163  new_offset = time_diff + old_offset;
1164  EC_SLAVE_DBG(slave, 1, "Setting time offset to %llu (was %llu)\n",
1165  new_offset, old_offset);
1166  } else {
1167  new_offset = old_offset;
1168  EC_SLAVE_DBG(slave, 1, "Not touching time offset.\n");
1169  }
1170 
1171  return new_offset;
1172 }
1173 
1174 /****************************************************************************/
1175 
1179  ec_fsm_master_t *fsm
1180  )
1181 {
1182  ec_datagram_t *datagram = fsm->datagram;
1183  ec_slave_t *slave = fsm->slave;
1184  u64 system_time, old_offset, new_offset;
1185  unsigned long jiffies_since_read;
1186 
1187  if (datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--)
1188  return;
1189 
1190  if (datagram->state != EC_DATAGRAM_RECEIVED) {
1191  EC_SLAVE_ERR(slave, "Failed to receive DC times datagram: ");
1192  ec_datagram_print_state(datagram);
1193  fsm->slave++;
1195  return;
1196  }
1197 
1198  if (datagram->working_counter != 1) {
1199  EC_SLAVE_WARN(slave, "Failed to get DC times: ");
1200  ec_datagram_print_wc_error(datagram);
1201  fsm->slave++;
1203  return;
1204  }
1205 
1206  system_time = EC_READ_U64(datagram->data); // 0x0910
1207  old_offset = EC_READ_U64(datagram->data + 16); // 0x0920
1208  jiffies_since_read = jiffies - datagram->jiffies_sent;
1209 
1210  if (slave->base_dc_range == EC_DC_32) {
1211  new_offset = ec_fsm_master_dc_offset32(fsm,
1212  system_time, old_offset, jiffies_since_read);
1213  } else {
1214  new_offset = ec_fsm_master_dc_offset64(fsm,
1215  system_time, old_offset, jiffies_since_read);
1216  }
1217 
1218  // set DC system time offset and transmission delay
1219  ec_datagram_fpwr(datagram, slave->station_address, 0x0920, 12);
1220  EC_WRITE_U64(datagram->data, new_offset);
1221  EC_WRITE_U32(datagram->data + 8, slave->transmission_delay);
1222  fsm->datagram->device_index = slave->device_index;
1223  fsm->retries = EC_FSM_RETRIES;
1225 }
1226 
1227 /****************************************************************************/
1228 
1232  ec_fsm_master_t *fsm
1233  )
1234 {
1235  ec_datagram_t *datagram = fsm->datagram;
1236  ec_slave_t *slave = fsm->slave;
1237 
1238  if (datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--)
1239  return;
1240 
1241  if (datagram->state != EC_DATAGRAM_RECEIVED) {
1242  EC_SLAVE_ERR(slave,
1243  "Failed to receive DC system time offset datagram: ");
1244  ec_datagram_print_state(datagram);
1245  fsm->slave++;
1247  return;
1248  }
1249 
1250  if (datagram->working_counter != 1) {
1251  EC_SLAVE_ERR(slave, "Failed to set DC system time offset: ");
1252  ec_datagram_print_wc_error(datagram);
1253  fsm->slave++;
1255  return;
1256  }
1257 
1258  fsm->slave++;
1260 }
1261 
1262 /****************************************************************************/
1263 
1267  ec_fsm_master_t *fsm
1268  )
1269 {
1270  ec_datagram_t *datagram = fsm->datagram;
1271  ec_sii_write_request_t *request = fsm->sii_request;
1272  ec_slave_t *slave = request->slave;
1273 
1274  if (datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--)
1275  return;
1276 
1277  if (datagram->state != EC_DATAGRAM_RECEIVED) {
1278  EC_SLAVE_ERR(slave, "Failed to receive SII assignment datagram: ");
1279  ec_datagram_print_state(datagram);
1280  goto cont;
1281  }
1282 
1283  if (datagram->working_counter != 1) {
1284  EC_SLAVE_ERR(slave, "Failed to assign SII back to EtherCAT: ");
1285  ec_datagram_print_wc_error(datagram);
1286  goto cont;
1287  }
1288 
1289 cont:
1290  // found pending SII write operation. execute it!
1291  EC_SLAVE_DBG(slave, 1, "Writing SII data (after assignment)...\n");
1292  fsm->sii_index = 0;
1293  ec_fsm_sii_write(&fsm->fsm_sii, slave, request->offset,
1296  fsm->state(fsm); // execute immediately
1297 }
1298 
1299 /****************************************************************************/
1300 
1304  ec_fsm_master_t *fsm
1305  )
1306 {
1307  ec_master_t *master = fsm->master;
1308  ec_sii_write_request_t *request = fsm->sii_request;
1309  ec_slave_t *slave = request->slave;
1310 
1311  if (ec_fsm_sii_exec(&fsm->fsm_sii)) return;
1312 
1313  if (!ec_fsm_sii_success(&fsm->fsm_sii)) {
1314  EC_SLAVE_ERR(slave, "Failed to write SII data.\n");
1315  request->state = EC_INT_REQUEST_FAILURE;
1316  wake_up_all(&master->request_queue);
1317  ec_fsm_master_restart(fsm);
1318  return;
1319  }
1320 
1321  fsm->sii_index++;
1322  if (fsm->sii_index < request->nwords) {
1323  ec_fsm_sii_write(&fsm->fsm_sii, slave,
1324  request->offset + fsm->sii_index,
1325  request->words + fsm->sii_index,
1327  ec_fsm_sii_exec(&fsm->fsm_sii); // execute immediately
1328  return;
1329  }
1330 
1331  // finished writing SII
1332  EC_SLAVE_DBG(slave, 1, "Finished writing %zu words of SII data.\n",
1333  request->nwords);
1334 
1335  if (request->offset <= 4 && request->offset + request->nwords > 4) {
1336  // alias was written
1337  slave->sii.alias = EC_READ_U16(request->words + 4);
1338  // TODO: read alias from register 0x0012
1339  slave->effective_alias = slave->sii.alias;
1340  }
1341  // TODO: Evaluate other SII contents!
1342 
1343  request->state = EC_INT_REQUEST_SUCCESS;
1344  wake_up_all(&master->request_queue);
1345 
1346  // check for another SII write request
1348  return; // processing another request
1349 
1350  ec_fsm_master_restart(fsm);
1351 }
1352 
1353 /****************************************************************************/
1354 
1358  ec_fsm_master_t *fsm
1359  )
1360 {
1361  ec_slave_t *slave = fsm->slave;
1362  ec_master_t *master = fsm->master;
1363 
1364  if (ec_fsm_coe_exec(&fsm->fsm_coe, fsm->datagram)) {
1365  return;
1366  }
1367 
1368  if (!ec_fsm_coe_success(&fsm->fsm_coe)) {
1369  ec_fsm_master_restart(fsm);
1370  return;
1371  }
1372 
1373  // SDO dictionary fetching finished
1374 
1375  if (master->debug_level) {
1376  unsigned int sdo_count, entry_count;
1377  ec_slave_sdo_dict_info(slave, &sdo_count, &entry_count);
1378  EC_SLAVE_DBG(slave, 1, "Fetched %u SDOs and %u entries.\n",
1379  sdo_count, entry_count);
1380  }
1381 
1382  // attach pdo names from dictionary
1384 
1385  ec_fsm_master_restart(fsm);
1386 }
1387 
1388 /****************************************************************************/
1389 
1393  ec_fsm_master_t *fsm
1394  )
1395 {
1396  ec_sdo_request_t *request = fsm->sdo_request;
1397 
1398  if (!request) {
1399  // configuration was cleared in the meantime
1400  ec_fsm_master_restart(fsm);
1401  return;
1402  }
1403 
1404  if (ec_fsm_coe_exec(&fsm->fsm_coe, fsm->datagram)) {
1405  return;
1406  }
1407 
1408  if (!ec_fsm_coe_success(&fsm->fsm_coe)) {
1409  EC_SLAVE_DBG(fsm->slave, 1,
1410  "Failed to process internal SDO request.\n");
1411  request->state = EC_INT_REQUEST_FAILURE;
1412  wake_up_all(&fsm->master->request_queue);
1413  ec_fsm_master_restart(fsm);
1414  return;
1415  }
1416 
1417  // SDO request finished
1418  request->state = EC_INT_REQUEST_SUCCESS;
1419  wake_up_all(&fsm->master->request_queue);
1420 
1421  EC_SLAVE_DBG(fsm->slave, 1, "Finished internal SDO request.\n");
1422 
1423  // check for another SDO/SoE request
1425  return; // processing another request
1426  }
1427 
1428  ec_fsm_master_restart(fsm);
1429 }
1430 
1431 /****************************************************************************/
1432 
1436  ec_fsm_master_t *fsm
1437  )
1438 {
1439  ec_soe_request_t *request = fsm->soe_request;
1440 
1441  if (!request) {
1442  // configuration was cleared in the meantime
1443  ec_fsm_master_restart(fsm);
1444  return;
1445  }
1446 
1447  if (ec_fsm_soe_exec(&fsm->fsm_soe, fsm->datagram)) {
1448  return;
1449  }
1450 
1451  if (!ec_fsm_soe_success(&fsm->fsm_soe)) {
1452  EC_SLAVE_DBG(fsm->slave, 1,
1453  "Failed to process internal SoE request.\n");
1454  request->state = EC_INT_REQUEST_FAILURE;
1455  wake_up_all(&fsm->master->request_queue);
1456  ec_fsm_master_restart(fsm);
1457  return;
1458  }
1459 
1460  // SoE request finished
1461  request->state = EC_INT_REQUEST_SUCCESS;
1462  wake_up_all(&fsm->master->request_queue);
1463 
1464  EC_SLAVE_DBG(fsm->slave, 1, "Finished internal SoE request.\n");
1465 
1466  // check for another CoE/SoE request
1468  return; // processing another request
1469  }
1470 
1471  ec_fsm_master_restart(fsm);
1472 }
1473 
1474 /****************************************************************************/
#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:1020
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:98
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:248
void ec_master_calc_dc(ec_master_t *master)
Distributed-clocks calculations.
Definition: master.c:2187
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:791
struct list_head sii_requests
SII write requests.
Definition: master.h:297
#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:401
void ec_fsm_master_reset(ec_fsm_master_t *fsm)
Reset state machine.
Definition: fsm_master.c:144
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:2204
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:321
u64 ec_fsm_master_dc_offset64(ec_fsm_master_t *, u64, u64, unsigned long)
Configure 64 bit time offset.
Definition: fsm_master.c:1140
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:283
Operation phase.
Definition: master.h:128
unsigned int allow_scan
True, if slave scanning is allowed.
Definition: master.h:241
#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 *)
Restarts the master state machine.
Definition: fsm_master.c:203
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:3137
unsigned int scan_index
Index of slave currently scanned.
Definition: master.h:240
u64 dc_ref_time
Common reference timestamp for DC start times.
Definition: master.h:228
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:298
#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:284
uint16_t working_counter
Working counter.
Definition: datagram.h:93
void ec_fsm_eoe_init(ec_fsm_eoe_t *fsm)
Constructor.
Definition: fsm_eoe.c:77
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 *)
Check for pending internal SDO/SoE requests and process one.
Definition: fsm_master.c:525
void ec_fsm_master_action_idle(ec_fsm_master_t *)
Master action: IDLE.
Definition: fsm_master.c:608
int ec_eoe_init(ec_eoe_t *eoe, ec_slave_t *slave)
EoE constructor.
Definition: ethernet.c:111
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:267
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:1231
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:301
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:465
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 *)
Master action: Get state of next slave.
Definition: fsm_master.c:666
#define EC_WAIT_SDO_DICT
Seconds to wait before fetching SDO dictionary after slave entered PREOP state.
Definition: globals.h:51
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:830
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:82
#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 *)
Check for pending SII write requests and process one.
Definition: fsm_master.c:463
ec_slave_t * fsm_slave
Slave that is queried next for FSM exec.
Definition: master.h:271
ec_slave_t * slave
EtherCAT slave.
Definition: fsm_master.h:47
u64 ec_fsm_master_dc_offset32(ec_fsm_master_t *, u64, u64, unsigned long)
Configure 32 bit time offset.
Definition: fsm_master.c:1098
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:618
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:1772
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:752
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:1392
void ec_fsm_master_state_scan_slave(ec_fsm_master_t *)
Master state: SCAN SLAVE.
Definition: fsm_master.c:946
void ec_fsm_soe_transfer(ec_fsm_soe_t *fsm, ec_slave_t *slave, ec_soe_request_t *request)
Starts to transfer an IDN to/from a slave.
Definition: fsm_soe.c:130
int ec_fsm_soe_success(const ec_fsm_soe_t *fsm)
Returns, if the state machine terminated with success.
Definition: fsm_soe.c:187
Ethernet over EtherCAT (EoE)
ec_datagram_state_t state
State.
Definition: datagram.h:94
ec_slave_config_t * config
Current configuration.
Definition: slave.h:182
ec_master_phase_t phase
Master phase.
Definition: master.h:212
#define EC_WRITE_U32(DATA, VAL)
Write a 32-bit unsigned value to EtherCAT data.
Definition: ecrt.h:3171
ec_fsm_sii_t fsm_sii
SII state machine.
Definition: fsm_master.h:92
ec_slave_t * slaves
Array of slaves on the bus.
Definition: master.h:220
uint8_t enable_sdo_info
SDO information service available.
Definition: globals.h:156
Use configured addresses.
Definition: fsm_sii.h:42
ec_fsm_eoe_t fsm_eoe
EoE state machine.
Definition: fsm_master.h:88
Slave configutation feature flag.
Definition: flag.h:38
ec_fsm_slave_scan_t fsm_slave_scan
slave state machine
Definition: fsm_master.h:91
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
uint16_t mailbox_protocols
Supported mailbox protocols.
Definition: slave.h:139
void ec_fsm_master_action_configure(ec_fsm_master_t *)
Master action: Configure.
Definition: fsm_master.c:694
ec_flag_t * ec_slave_config_find_flag(ec_slave_config_t *sc, const char *key)
Finds a flag.
Definition: slave_config.c:638
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:275
#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:157
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:221
unsigned int scan_busy
Current scan state.
Definition: master.h:239
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:891
void ec_fsm_master_state_broadcast(ec_fsm_master_t *)
Master state: BROADCAST.
Definition: fsm_master.c:278
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:83
void ec_fsm_coe_clear(ec_fsm_coe_t *fsm)
Destructor.
Definition: fsm_coe.c:187
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:3154
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:1266
#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:213
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:69
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:244
#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:197
void ec_fsm_master_state_soe_request(ec_fsm_master_t *)
Master state: SoE REQUEST.
Definition: fsm_master.c:1435
ec_device_index_t device_index
Device via which the datagram shall be / was sent.
Definition: datagram.h:84
void ec_fsm_slave_config_init(ec_fsm_slave_config_t *fsm, ec_datagram_t *datagram, ec_fsm_change_t *fsm_change, ec_fsm_coe_t *fsm_coe, ec_fsm_soe_t *fsm_soe, ec_fsm_pdo_t *fsm_pdo, ec_fsm_eoe_t *fsm_eoe)
Constructor.
int ec_fsm_master_idle(const ec_fsm_master_t *fsm)
Definition: fsm_master.c:192
32 bit.
Definition: globals.h:173
void ec_master_clear_slaves(ec_master_t *master)
Clear all slaves.
Definition: master.c:479
void ec_fsm_change_init(ec_fsm_change_t *fsm, ec_datagram_t *datagram)
Constructor.
Definition: fsm_change.c:54
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:175
void ec_fsm_master_state_acknowledge(ec_fsm_master_t *)
Master state: ACKNOWLEDGE.
Definition: fsm_master.c:808
void ec_fsm_eoe_clear(ec_fsm_eoe_t *fsm)
Destructor.
Definition: fsm_eoe.c:94
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:242
void ec_fsm_master_state_start(ec_fsm_master_t *)
Master state: START.
Definition: fsm_master.c:220
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:443
ec_fsm_slave_config_t fsm_slave_config
slave state machine
Definition: fsm_master.h:90
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:3045
void ec_master_eoe_start(ec_master_t *master)
Starts Ethernet over EtherCAT processing on demand.
Definition: master.c:1660
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:1357
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:3188
void ec_fsm_master_state_clear_addresses(ec_fsm_master_t *)
Master state: CLEAR ADDRESSES.
Definition: fsm_master.c:846
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:233
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:60
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:140
Timed out (dequeued).
Definition: datagram.h:71
wait_queue_head_t config_queue
Queue for processes that wait for slave configuration.
Definition: master.h:250
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:227
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:107
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:120
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:1303
uint8_t * data
Datagram payload.
Definition: datagram.h:88
#define EC_READ_U8(DATA)
Read an 8-bit unsigned value from EtherCAT data.
Definition: ecrt.h:3029
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:173
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:90
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:152
void ec_fsm_coe_transfer(ec_fsm_coe_t *fsm, ec_slave_t *slave, ec_sdo_request_t *request)
Starts to transfer an SDO to/from a slave.
Definition: fsm_coe.c:210
ec_slave_t * slave
current slave
Definition: fsm_master.h:79
Values written by the master.
Definition: ecrt.h:506
ec_fsm_change_t fsm_change
State change state machine.
Definition: fsm_master.h:89
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:214
EtherCAT master.
Definition: master.h:187
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:3077
ec_device_t devices[EC_MAX_NUM_DEVICES]
EtherCAT devices.
Definition: master.h:200
ec_internal_request_state_t state
Request state.
Definition: soe_request.h:52
unsigned int config_busy
State of slave configuration.
Definition: master.h:247
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:123
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:1048
void ec_master_eoe_stop(ec_master_t *master)
Stops the Ethernet over EtherCAT processing.
Definition: master.c:1694
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:1178
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:172
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