IgH EtherCAT Master  1.6.10
fsm_master.c
Go to the documentation of this file.
1 /*****************************************************************************
2  *
3  * Copyright (C) 2006-2026 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 #include "smp.h"
36 
37 #include "fsm_master.h"
38 #include "fsm_foe.h"
39 
40 /****************************************************************************/
41 
44 #define EC_SYSTEM_TIME_TOLERANCE_NS 1000000
45 
46 /****************************************************************************/
47 
48 // prototypes for private methods
55 u64 ec_fsm_master_dc_offset32(ec_fsm_master_t *, u64, u64, unsigned long);
56 u64 ec_fsm_master_dc_offset64(ec_fsm_master_t *, u64, u64, unsigned long);
57 
58 /****************************************************************************/
59 
75 
78 
79 /****************************************************************************/
80 
84  ec_fsm_master_t *fsm,
85  ec_master_t *master,
86  ec_datagram_t *datagram
87  )
88 {
89  fsm->master = master;
90  fsm->datagram = datagram;
91 
92  // inits the member variables state, idle, dev_idx, link_state,
93  // slaves_responding, slave_states and rescan_required
95 
96  fsm->retries = 0;
97  fsm->scan_jiffies = 0;
98  fsm->slave = NULL;
99  fsm->sii_request = NULL;
100  fsm->sii_index = 0;
101  fsm->sdo_request = NULL;
102  fsm->soe_request = NULL;
103 
104  // init sub-state-machines
105  ec_fsm_coe_init(&fsm->fsm_coe);
106  ec_fsm_soe_init(&fsm->fsm_soe);
107  ec_fsm_pdo_init(&fsm->fsm_pdo, &fsm->fsm_coe);
108 #ifdef EC_EOE
109  ec_fsm_eoe_init(&fsm->fsm_eoe);
110 #endif
113  &fsm->fsm_change, &fsm->fsm_coe, &fsm->fsm_soe, &fsm->fsm_pdo,
114  &fsm->fsm_eoe);
116  &fsm->fsm_slave_config, &fsm->fsm_pdo);
117  ec_fsm_sii_init(&fsm->fsm_sii, fsm->datagram);
118 }
119 
120 /****************************************************************************/
121 
125  ec_fsm_master_t *fsm
126  )
127 {
128  // clear sub-state machines
129  ec_fsm_coe_clear(&fsm->fsm_coe);
130  ec_fsm_soe_clear(&fsm->fsm_soe);
131  ec_fsm_pdo_clear(&fsm->fsm_pdo);
132 #ifdef EC_EOE
133  ec_fsm_eoe_clear(&fsm->fsm_eoe);
134 #endif
138  ec_fsm_sii_clear(&fsm->fsm_sii);
139 }
140 
141 /****************************************************************************/
142 
146  ec_fsm_master_t *fsm
147  )
148 {
149  ec_device_index_t dev_idx;
150 
152  fsm->idle = 0;
153  fsm->dev_idx = EC_DEVICE_MAIN;
154 
155  for (dev_idx = EC_DEVICE_MAIN;
156  dev_idx < ec_master_num_devices(fsm->master); dev_idx++) {
157  fsm->link_state[dev_idx] = 0;
158  fsm->slaves_responding[dev_idx] = 0;
159  fsm->slave_states[dev_idx] = EC_SLAVE_STATE_UNKNOWN;
160  }
161 
162  fsm->rescan_required = 0;
163 }
164 
165 /****************************************************************************/
166 
175  ec_fsm_master_t *fsm
176  )
177 {
178  ec_datagram_state_t state = smp_load_acquire(&fsm->datagram->state);
179 
180  if (state == EC_DATAGRAM_SENT || state == EC_DATAGRAM_QUEUED) {
181  // datagram was not sent or received yet.
182  return 0;
183  }
184 
185  fsm->state(fsm);
186  return 1;
187 }
188 
189 /****************************************************************************/
190 
195  const ec_fsm_master_t *fsm
196  )
197 {
198  return fsm->idle;
199 }
200 
201 /****************************************************************************/
202 
206  ec_fsm_master_t *fsm
207  )
208 {
209  fsm->dev_idx = EC_DEVICE_MAIN;
211  fsm->state(fsm); // execute immediately
212 }
213 
214 /*****************************************************************************
215  * Master state machine
216  ****************************************************************************/
217 
223  ec_fsm_master_t *fsm
224  )
225 {
226  ec_master_t *master = fsm->master;
227 
228  fsm->idle = 1;
229 
230  // check for emergency requests
231  if (!list_empty(&master->emerg_reg_requests)) {
232  ec_reg_request_t *request;
233 
234  // get first request
235  request = list_entry(master->emerg_reg_requests.next,
236  ec_reg_request_t, list);
237  list_del_init(&request->list); // dequeue
238  request->state = EC_INT_REQUEST_BUSY;
239 
240  if (request->transfer_size > fsm->datagram->mem_size) {
241  EC_MASTER_ERR(master, "Emergency request data too large!\n");
242  request->state = EC_INT_REQUEST_FAILURE;
243  wake_up_all(&master->request_queue);
244  fsm->state(fsm); // continue
245  return;
246  }
247 
248  if (request->dir != EC_DIR_OUTPUT) {
249  EC_MASTER_ERR(master, "Emergency requests must be"
250  " write requests!\n");
251  request->state = EC_INT_REQUEST_FAILURE;
252  wake_up_all(&master->request_queue);
253  fsm->state(fsm); // continue
254  return;
255  }
256 
257  EC_MASTER_DBG(master, 1, "Writing emergency register request...\n");
258  ec_datagram_apwr(fsm->datagram, request->ring_position,
259  request->address, request->transfer_size);
260  memcpy(fsm->datagram->data, request->data, request->transfer_size);
262  request->state = EC_INT_REQUEST_SUCCESS;
263  wake_up_all(&master->request_queue);
264  return;
265  }
266 
267  ec_datagram_brd(fsm->datagram, 0x0130, 2);
269  fsm->datagram->device_index = fsm->dev_idx;
270  fsm->retries = EC_FSM_RETRIES;
272 }
273 
274 /****************************************************************************/
275 
281  ec_fsm_master_t *fsm
282  )
283 {
284  ec_datagram_t *datagram = fsm->datagram;
285  unsigned int i, size;
286  ec_slave_t *slave;
287  ec_master_t *master = fsm->master;
288 
289  if (datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--) {
290  return;
291  }
292 
293  // bus topology change?
294  if (datagram->working_counter != fsm->slaves_responding[fsm->dev_idx]) {
295  fsm->rescan_required = 1;
296  fsm->slaves_responding[fsm->dev_idx] = datagram->working_counter;
297  EC_MASTER_INFO(master, "%u slave(s) responding on %s device. "
298  "Re-scanning on next possibility.\n",
299  fsm->slaves_responding[fsm->dev_idx],
300  ec_device_names[fsm->dev_idx != 0]);
301  }
302 
303  if (fsm->link_state[fsm->dev_idx] &&
304  !master->devices[fsm->dev_idx].link_state) {
305  ec_device_index_t dev_idx;
306 
307  EC_MASTER_DBG(master, 1, "Master state machine detected "
308  "link down on %s device. Clearing slave list.\n",
309  ec_device_names[fsm->dev_idx != 0]);
310 
311 #ifdef EC_EOE
312  ec_master_eoe_stop(master);
314 #endif
315  ec_master_clear_slaves(master);
316 
317  for (dev_idx = EC_DEVICE_MAIN;
318  dev_idx < ec_master_num_devices(master); dev_idx++) {
319  fsm->slave_states[dev_idx] = 0x00;
320  /* Reset to trigger rescan on next link up. */
321  fsm->slaves_responding[dev_idx] = 0;
322  }
323  }
324  fsm->link_state[fsm->dev_idx] = master->devices[fsm->dev_idx].link_state;
325 
326  if (datagram->state == EC_DATAGRAM_RECEIVED &&
327  fsm->slaves_responding[fsm->dev_idx]) {
328  uint8_t states = EC_READ_U8(datagram->data);
329  if (states != fsm->slave_states[fsm->dev_idx]) {
330  // slave states changed
331  char state_str[EC_STATE_STRING_SIZE];
332  fsm->slave_states[fsm->dev_idx] = states;
333  ec_state_string(states, state_str, 1);
334  EC_MASTER_INFO(master, "Slave states on %s device: %s.\n",
335  ec_device_names[fsm->dev_idx != 0], state_str);
336  }
337  } else {
338  fsm->slave_states[fsm->dev_idx] = 0x00;
339  }
340 
341  fsm->dev_idx++;
342  if (fsm->dev_idx < ec_master_num_devices(master)) {
343  // check number of responding slaves on next device
345  fsm->state(fsm); // execute immediately
346  return;
347  }
348 
349  if (fsm->rescan_required) {
350  down(&master->scan_sem);
351  if (!master->allow_scan) {
352  up(&master->scan_sem);
353  } else {
354  unsigned int count = 0, next_dev_slave, ring_position;
355  ec_device_index_t dev_idx;
356 
357  master->scan_busy = 1;
358  master->scan_index = 0;
359  up(&master->scan_sem);
360 
361  EC_MASTER_INFO(master, "Re-scanning now.\n");
362 
363  // clear all slaves and scan the bus
364  fsm->rescan_required = 0;
365  fsm->idle = 0;
366  fsm->scan_jiffies = jiffies;
367 
368 #ifdef EC_EOE
369  ec_master_eoe_stop(master);
371 #endif
372  ec_master_clear_slaves(master);
373 
374  for (dev_idx = EC_DEVICE_MAIN;
375  dev_idx < ec_master_num_devices(master); dev_idx++) {
376  count += fsm->slaves_responding[dev_idx];
377  }
378 
379  if (!count) {
380  // no slaves present -> finish state machine.
381  master->scan_busy = 0;
382  wake_up_interruptible(&master->scan_queue);
384  return;
385  }
386 
387  size = sizeof(ec_slave_t) * count;
388  if (!(master->slaves =
389  (ec_slave_t *) kmalloc(size, GFP_KERNEL))) {
390  EC_MASTER_ERR(master, "Failed to allocate %u bytes"
391  " of slave memory!\n", size);
392  master->scan_busy = 0;
393  wake_up_interruptible(&master->scan_queue);
395  return;
396  }
397 
398  // init slaves
399  dev_idx = EC_DEVICE_MAIN;
400  next_dev_slave = fsm->slaves_responding[dev_idx];
401  ring_position = 0;
402  for (i = 0; i < count; i++, ring_position++) {
403  slave = master->slaves + i;
404  while (i >= next_dev_slave) {
405  dev_idx++;
406  next_dev_slave += fsm->slaves_responding[dev_idx];
407  ring_position = 0;
408  }
409 
410  ec_slave_init(slave, master, dev_idx, ring_position, i + 1);
411 
412  // do not force reconfiguration in operation phase to avoid
413  // unnecesssary process data interruptions
414  if (master->phase != EC_OPERATION) {
415  slave->force_config = 1;
416  }
417  }
418  master->slave_count = count;
419  master->fsm_slave = master->slaves;
420 
421  /* start with first device with slaves responding; at least one
422  * has responding slaves, otherwise count would be zero. */
423  fsm->dev_idx = EC_DEVICE_MAIN;
424  while (!fsm->slaves_responding[fsm->dev_idx]) {
425  fsm->dev_idx++;
426  }
427 
429  return;
430  }
431  }
432 
433  if (master->slave_count) {
434  // application applied configurations
435  if (master->config_changed) {
436  master->config_changed = 0;
437 
438  EC_MASTER_DBG(master, 1, "Configuration changed.\n");
439 
440  fsm->slave = master->slaves; // begin with first slave
442  }
443  else {
444  // fetch state from first slave
445  fsm->slave = master->slaves;
447  0x0130, 2);
448  ec_datagram_zero(datagram);
449  fsm->datagram->device_index = fsm->slave->device_index;
450  fsm->retries = EC_FSM_RETRIES;
452  }
453  } else {
455  }
456 }
457 
458 /****************************************************************************/
459 
465  ec_fsm_master_t *fsm
466  )
467 {
468  ec_master_t *master = fsm->master;
469  ec_sii_write_request_t *request;
470  ec_slave_config_t *config;
471  ec_flag_t *flag;
472  int assign_to_pdi;
473 
474  // search the first request to be processed
475  while (1) {
476  if (list_empty(&master->sii_requests))
477  break;
478 
479  // get first request
480  request = list_entry(master->sii_requests.next,
481  ec_sii_write_request_t, list);
482  list_del_init(&request->list); // dequeue
483  request->state = EC_INT_REQUEST_BUSY;
484 
485  assign_to_pdi = 0;
486  config = request->slave->config;
487  if (config) {
488  flag = ec_slave_config_find_flag(config, "AssignToPdi");
489  if (flag) {
490  assign_to_pdi = flag->value;
491  }
492  }
493 
494  if (assign_to_pdi) {
495  fsm->sii_request = request;
496  EC_SLAVE_DBG(request->slave, 1,
497  "Assigning SII back to EtherCAT.\n");
499  0x0500, 0x01);
500  EC_WRITE_U8(fsm->datagram->data, 0x00); // EtherCAT
501  fsm->retries = EC_FSM_RETRIES;
503  return 1;
504  }
505 
506  // found pending SII write operation. execute it!
507  EC_SLAVE_DBG(request->slave, 1, "Writing SII data...\n");
508  fsm->sii_request = request;
509  fsm->sii_index = 0;
510  ec_fsm_sii_write(&fsm->fsm_sii, request->slave, request->offset,
513  fsm->state(fsm); // execute immediately
514  return 1;
515  }
516 
517  return 0;
518 }
519 
520 /****************************************************************************/
521 
527  ec_fsm_master_t *fsm
528  )
529 {
530  ec_master_t *master = fsm->master;
531  ec_slave_t *slave;
532  ec_sdo_request_t *sdo_req;
533  ec_soe_request_t *soe_req;
534 
535  // search for internal requests to be processed
536  for (slave = master->slaves;
537  slave < master->slaves + master->slave_count;
538  slave++) {
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  if (ec_sdo_request_timed_out(sdo_req)) {
546  sdo_req->state = EC_INT_REQUEST_FAILURE;
547  EC_SLAVE_DBG(slave, 1, "Internal SDO request"
548  " timed out.\n");
549  continue;
550  }
551 
552  if (slave->current_state == EC_SLAVE_STATE_INIT) {
553  sdo_req->state = EC_INT_REQUEST_FAILURE;
554  continue;
555  }
556 
557  sdo_req->state = EC_INT_REQUEST_BUSY;
558  EC_SLAVE_DBG(slave, 1, "Processing internal"
559  " SDO request...\n");
560  fsm->idle = 0;
561  fsm->sdo_request = sdo_req;
562  fsm->slave = slave;
564  ec_fsm_coe_transfer(&fsm->fsm_coe, slave, sdo_req);
565  ec_fsm_coe_exec(&fsm->fsm_coe, fsm->datagram);
566  return 1;
567  }
568  }
569 
570  list_for_each_entry(soe_req, &slave->config->soe_requests, list) {
571  if (soe_req->state == EC_INT_REQUEST_QUEUED) {
572  if (ec_soe_request_timed_out(soe_req)) {
573  soe_req->state = EC_INT_REQUEST_FAILURE;
574  EC_SLAVE_DBG(slave, 1, "Internal SoE request"
575  " timed out.\n");
576  continue;
577  }
578 
579  if (slave->current_state == EC_SLAVE_STATE_INIT) {
580  soe_req->state = EC_INT_REQUEST_FAILURE;
581  continue;
582  }
583 
584  soe_req->state = EC_INT_REQUEST_BUSY;
585  EC_SLAVE_DBG(slave, 1, "Processing internal"
586  " SoE request...\n");
587  fsm->idle = 0;
588  fsm->soe_request = soe_req;
589  fsm->slave = slave;
591  ec_fsm_soe_transfer(&fsm->fsm_soe, slave, soe_req);
592  ec_fsm_soe_exec(&fsm->fsm_soe, fsm->datagram);
593  return 1;
594  }
595  }
596  }
597  return 0;
598 }
599 
600 /****************************************************************************/
601 
607  ec_fsm_master_t *fsm
608  )
609 {
610  ec_master_t *master = fsm->master;
611  ec_slave_t *slave;
612 
613  // Check for pending internal SDO or SoE requests
615  return;
616  }
617 
618  // enable processing of requests
619  for (slave = master->slaves;
620  slave < master->slaves + master->slave_count;
621  slave++) {
622  ec_fsm_slave_set_ready(&slave->fsm);
623  }
624 
625  // check, if slaves have an SDO dictionary to read out.
626  for (slave = master->slaves;
627  slave < master->slaves + master->slave_count;
628  slave++) {
629  if (!(slave->sii.mailbox_protocols & EC_MBOX_COE)
630  || (slave->sii.has_general
631  && !slave->sii.coe_details.enable_sdo_info)
632  || slave->sdo_dictionary_fetched
635  || jiffies - slave->jiffies_preop < EC_WAIT_SDO_DICT * HZ) {
636  continue;
637  }
638 
639  EC_SLAVE_DBG(slave, 1, "Fetching SDO dictionary.\n");
640 
641  slave->sdo_dictionary_fetched = 1;
642 
643  // start fetching SDO dictionary
644  fsm->idle = 0;
645  fsm->slave = slave;
647  ec_fsm_coe_dictionary(&fsm->fsm_coe, slave);
648  ec_fsm_coe_exec(&fsm->fsm_coe, fsm->datagram); // execute immediately
649  fsm->datagram->device_index = fsm->slave->device_index;
650  return;
651  }
652 
653  // check for pending SII write operations.
655  return; // SII write request found
656  }
657 
659 }
660 
661 /****************************************************************************/
662 
666  ec_fsm_master_t *fsm
667  )
668 {
669  ec_master_t *master = fsm->master;
670 
671  // is there another slave to query?
672  fsm->slave++;
673  if (fsm->slave < master->slaves + master->slave_count) {
674  // fetch state from next slave
675  fsm->idle = 1;
677  fsm->slave->station_address, 0x0130, 2);
679  fsm->datagram->device_index = fsm->slave->device_index;
680  fsm->retries = EC_FSM_RETRIES;
682  return;
683  }
684 
685  // all slaves processed
687 }
688 
689 /****************************************************************************/
690 
694  ec_fsm_master_t *fsm
695  )
696 {
697  ec_master_t *master = fsm->master;
698  ec_slave_t *slave = fsm->slave;
699 
700  if (master->config_changed) {
701  master->config_changed = 0;
702 
703  // abort iterating through slaves,
704  // first compensate DC system time offsets,
705  // then begin configuring at slave 0
706  EC_MASTER_DBG(master, 1, "Configuration changed"
707  " (aborting state check).\n");
708 
709  fsm->slave = master->slaves; // begin with first slave
711  return;
712  }
713 
714  // Does the slave have to be configured?
715  if ((slave->current_state != slave->requested_state
716  || slave->force_config) && !slave->error_flag) {
717  // Start slave configuration
718  down(&master->config_sem);
719  master->config_busy = 1;
720  up(&master->config_sem);
721 
722  if (master->debug_level) {
723  char old_state[EC_STATE_STRING_SIZE],
724  new_state[EC_STATE_STRING_SIZE];
725  ec_state_string(slave->current_state, old_state, 0);
726  ec_state_string(slave->requested_state, new_state, 0);
727  EC_SLAVE_DBG(slave, 1, "Changing state from %s to %s%s.\n",
728  old_state, new_state,
729  slave->force_config ? " (forced)" : "");
730  }
731 
732  fsm->idle = 0;
735  fsm->state(fsm); // execute immediately
736  fsm->datagram->device_index = fsm->slave->device_index;
737  return;
738  }
739 
740  // process next slave
742 }
743 
744 /****************************************************************************/
745 
751  ec_fsm_master_t *fsm
752  )
753 {
754  ec_slave_t *slave = fsm->slave;
755  ec_datagram_t *datagram = fsm->datagram;
756 
757  if (datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--) {
758  return;
759  }
760 
761  if (datagram->state != EC_DATAGRAM_RECEIVED) {
762  EC_SLAVE_ERR(slave, "Failed to receive AL state datagram: ");
763  ec_datagram_print_state(datagram);
765  return;
766  }
767 
768  // did the slave not respond to its station address?
769  if (datagram->working_counter != 1) {
770  if (!slave->error_flag) {
771  slave->error_flag = 1;
772  EC_SLAVE_DBG(slave, 1, "Slave did not respond to state query.\n");
773  }
775  return;
776  }
777 
778  // A single slave responded
779  ec_slave_set_state(slave, EC_READ_U8(datagram->data));
780 
781  if (!slave->error_flag) {
782  // Check, if new slave state has to be acknowledged
783  if (slave->current_state & EC_SLAVE_STATE_ACK_ERR) {
784  fsm->idle = 0;
786  ec_fsm_change_ack(&fsm->fsm_change, slave);
787  fsm->state(fsm); // execute immediately
788  return;
789  }
790 
791  // No acknowlegde necessary; check for configuration
793  return;
794  }
795 
796  // slave has error flag set; process next one
798 }
799 
800 /****************************************************************************/
801 
805  ec_fsm_master_t *fsm
806  )
807 {
808  ec_slave_t *slave = fsm->slave;
809 
810  if (ec_fsm_change_exec(&fsm->fsm_change)) {
811  return;
812  }
813 
814  if (!ec_fsm_change_success(&fsm->fsm_change)) {
815  fsm->slave->error_flag = 1;
816  EC_SLAVE_ERR(slave, "Failed to acknowledge state change.\n");
817  }
818 
820 }
821 
822 /****************************************************************************/
823 
827  ec_fsm_master_t *fsm
828  )
829 {
830  // broadcast clear all station addresses
831  ec_datagram_bwr(fsm->datagram, 0x0010, 2);
832  EC_WRITE_U16(fsm->datagram->data, 0x0000);
833  fsm->datagram->device_index = fsm->dev_idx;
834  fsm->retries = EC_FSM_RETRIES;
836 }
837 
838 /****************************************************************************/
839 
843  ec_fsm_master_t *fsm
844  )
845 {
846  ec_master_t *master = fsm->master;
847  ec_datagram_t *datagram = fsm->datagram;
848 
849  if (datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--) {
850  return;
851  }
852 
853  if (datagram->state != EC_DATAGRAM_RECEIVED) {
854  EC_MASTER_ERR(master, "Failed to receive address"
855  " clearing datagram on %s link: ",
856  ec_device_names[fsm->dev_idx != 0]);
857  ec_datagram_print_state(datagram);
858  master->scan_busy = 0;
859  master->scan_index = master->slave_count;
860  wake_up_interruptible(&master->scan_queue);
862  return;
863  }
864 
865  if (datagram->working_counter != fsm->slaves_responding[fsm->dev_idx]) {
866  EC_MASTER_WARN(master, "Failed to clear station addresses on %s link:"
867  " Cleared %u of %u",
868  ec_device_names[fsm->dev_idx != 0], datagram->working_counter,
869  fsm->slaves_responding[fsm->dev_idx]);
870  }
871 
872  EC_MASTER_DBG(master, 1, "Sending broadcast-write"
873  " to measure transmission delays on %s link.\n",
874  ec_device_names[fsm->dev_idx != 0]);
875 
876  ec_datagram_bwr(datagram, 0x0900, 1);
877  ec_datagram_zero(datagram);
878  fsm->datagram->device_index = fsm->dev_idx;
879  fsm->retries = EC_FSM_RETRIES;
881 }
882 
883 /****************************************************************************/
884 
888  ec_fsm_master_t *fsm
889  )
890 {
891  ec_master_t *master = fsm->master;
892  ec_datagram_t *datagram = fsm->datagram;
893 
894  if (datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--) {
895  return;
896  }
897 
898  if (datagram->state != EC_DATAGRAM_RECEIVED) {
899  EC_MASTER_ERR(master, "Failed to receive delay measuring datagram"
900  " on %s link: ", ec_device_names[fsm->dev_idx != 0]);
901  ec_datagram_print_state(datagram);
902  master->scan_busy = 0;
903  master->scan_index = master->slave_count;
904  wake_up_interruptible(&master->scan_queue);
906  return;
907  }
908 
909  EC_MASTER_DBG(master, 1, "%u slaves responded to delay measuring"
910  " on %s link.\n",
911  datagram->working_counter, ec_device_names[fsm->dev_idx != 0]);
912 
913  do {
914  fsm->dev_idx++;
915  } while (fsm->dev_idx < ec_master_num_devices(master) &&
916  !fsm->slaves_responding[fsm->dev_idx]);
917  if (fsm->dev_idx < ec_master_num_devices(master)) {
919  return;
920  }
921 
922  EC_MASTER_INFO(master, "Scanning bus.\n");
923 
924  // begin scanning of slaves
925  fsm->slave = master->slaves;
926  master->scan_index = 0;
927  EC_MASTER_DBG(master, 1, "Scanning slave %u on %s link.\n",
928  fsm->slave->ring_position,
929  ec_device_names[fsm->slave->device_index != 0]);
932  ec_fsm_slave_scan_exec(&fsm->fsm_slave_scan); // execute immediately
933  fsm->datagram->device_index = fsm->slave->device_index;
934 }
935 
936 /****************************************************************************/
937 
943  ec_fsm_master_t *fsm
944  )
945 {
946  ec_master_t *master = fsm->master;
947 #ifdef EC_EOE
948  ec_slave_t *slave = fsm->slave;
949 #endif
950 
952  return;
953  }
954 
955 #ifdef EC_EOE
956  if (slave->sii.mailbox_protocols & EC_MBOX_EOE) {
957  // create EoE handler for this slave
958  ec_eoe_t *eoe;
959  if (!(eoe = kmalloc(sizeof(ec_eoe_t), GFP_KERNEL))) {
960  EC_SLAVE_ERR(slave, "Failed to allocate EoE handler memory!\n");
961  } else if (ec_eoe_init(eoe, slave)) {
962  EC_SLAVE_ERR(slave, "Failed to init EoE handler!\n");
963  kfree(eoe);
964  } else {
965  list_add_tail(&eoe->list, &master->eoe_handlers);
966  }
967  }
968 #endif
969 
970  // another slave to fetch?
971  fsm->slave++;
972  master->scan_index++;
973  if (fsm->slave < master->slaves + master->slave_count) {
974  EC_MASTER_DBG(master, 1, "Scanning slave %u on %s link.\n",
975  fsm->slave->ring_position,
976  ec_device_names[fsm->slave->device_index != 0]);
978  ec_fsm_slave_scan_exec(&fsm->fsm_slave_scan); // execute immediately
979  fsm->datagram->device_index = fsm->slave->device_index;
980  return;
981  }
982 
983  EC_MASTER_INFO(master, "Bus scanning completed in %lu ms.\n",
984  (jiffies - fsm->scan_jiffies) * 1000 / HZ);
985 
986  master->scan_busy = 0;
987  master->scan_index = master->slave_count;
988  wake_up_interruptible(&master->scan_queue);
989 
990  // Attach slave configurations
992 
993  // Calculate DC (needs attached slaves due to reference clock selection)
994  ec_master_calc_dc(master);
995 
996 #ifdef EC_EOE
997  // check if EoE processing has to be started
998  ec_master_eoe_start(master);
999 #endif
1000 
1001  if (master->slave_count) {
1002  master->config_changed = 0;
1003 
1004  fsm->slave = master->slaves; // begin with first slave
1006  } else {
1007  ec_fsm_master_restart(fsm);
1008  }
1009 }
1010 
1011 /****************************************************************************/
1012 
1018  ec_fsm_master_t *fsm
1019  )
1020 {
1021  ec_master_t *master = fsm->master;
1022 
1024  return;
1025  }
1026 
1027  fsm->slave->force_config = 0;
1028 
1029  // configuration finished
1030  master->config_busy = 0;
1031  wake_up_interruptible(&master->config_queue);
1032 
1034  // TODO(fp): mark slave_config as failed.
1035  }
1036 
1037  fsm->idle = 1;
1039 }
1040 
1041 /****************************************************************************/
1042 
1046  ec_fsm_master_t *fsm
1047  )
1048 {
1049  ec_master_t *master = fsm->master;
1050 
1051  if (master->dc_ref_time) {
1052  while (fsm->slave < master->slaves + master->slave_count) {
1053  if (!fsm->slave->base_dc_supported
1054  || !fsm->slave->has_dc_system_time) {
1055  fsm->slave++;
1056  continue;
1057  }
1058 
1059  EC_SLAVE_DBG(fsm->slave, 1, "Checking system time offset.\n");
1060 
1061  // read DC system time (0x0910, 64 bit)
1062  // gap (64 bit)
1063  // and time offset (0x0920, 64 bit)
1065  0x0910, 24);
1066  fsm->datagram->device_index = fsm->slave->device_index;
1067  fsm->retries = EC_FSM_RETRIES;
1069  return;
1070  }
1071 
1072  } else {
1073  if (master->active) {
1074  EC_MASTER_WARN(master, "No application time received up to now,"
1075  " but master already active.\n");
1076  } else {
1077  EC_MASTER_DBG(master, 1, "No app_time received up to now.\n");
1078  }
1079  }
1080 
1081  // scanning and setting system times complete
1082  ec_master_request_op(master);
1083  EC_MASTER_DBG(master, 1, "After requesting OP, rescan_required is %u.\n",
1084  fsm->rescan_required);
1085  ec_fsm_master_restart(fsm);
1086 }
1087 
1088 /****************************************************************************/
1089 
1095  ec_fsm_master_t *fsm,
1096  u64 system_time,
1097  u64 old_offset,
1098  unsigned long jiffies_since_read
1099  )
1100 {
1101  ec_slave_t *slave = fsm->slave;
1102  u32 correction, system_time32, old_offset32, new_offset;
1103  s32 time_diff;
1104 
1105  system_time32 = (u32) system_time;
1106  old_offset32 = (u32) old_offset;
1107 
1108  // correct read system time by elapsed time since read operation
1109  correction = jiffies_since_read * 1000 / HZ * 1000000;
1110  system_time32 += correction;
1111  time_diff = (u32) slave->master->app_time - system_time32;
1112 
1113  EC_SLAVE_DBG(slave, 1, "DC 32 bit system time offset calculation:"
1114  " system_time=%u (corrected with %u),"
1115  " app_time=%llu, diff=%i\n",
1116  system_time32, correction,
1117  slave->master->app_time, time_diff);
1118 
1119  if (EC_ABS(time_diff) > EC_SYSTEM_TIME_TOLERANCE_NS) {
1120  new_offset = time_diff + old_offset32;
1121  EC_SLAVE_DBG(slave, 1, "Setting time offset to %u (was %u)\n",
1122  new_offset, old_offset32);
1123  return (u64) new_offset;
1124  } else {
1125  EC_SLAVE_DBG(slave, 1, "Not touching time offset.\n");
1126  return old_offset;
1127  }
1128 }
1129 
1130 /****************************************************************************/
1131 
1137  ec_fsm_master_t *fsm,
1138  u64 system_time,
1139  u64 old_offset,
1140  unsigned long jiffies_since_read
1141  )
1142 {
1143  ec_slave_t *slave = fsm->slave;
1144  u64 new_offset, correction;
1145  s64 time_diff;
1146 
1147  // correct read system time by elapsed time since read operation
1148  correction = (u64) (jiffies_since_read * 1000 / HZ) * 1000000;
1149  system_time += correction;
1150  time_diff = fsm->slave->master->app_time - system_time;
1151 
1152  EC_SLAVE_DBG(slave, 1, "DC 64 bit system time offset calculation:"
1153  " system_time=%llu (corrected with %llu),"
1154  " app_time=%llu, diff=%lli\n",
1155  system_time, correction,
1156  slave->master->app_time, time_diff);
1157 
1158  if (EC_ABS(time_diff) > EC_SYSTEM_TIME_TOLERANCE_NS) {
1159  new_offset = time_diff + old_offset;
1160  EC_SLAVE_DBG(slave, 1, "Setting time offset to %llu (was %llu)\n",
1161  new_offset, old_offset);
1162  } else {
1163  new_offset = old_offset;
1164  EC_SLAVE_DBG(slave, 1, "Not touching time offset.\n");
1165  }
1166 
1167  return new_offset;
1168 }
1169 
1170 /****************************************************************************/
1171 
1175  ec_fsm_master_t *fsm
1176  )
1177 {
1178  ec_datagram_t *datagram = fsm->datagram;
1179  ec_slave_t *slave = fsm->slave;
1180  u64 system_time, old_offset, new_offset;
1181  unsigned long jiffies_since_read;
1182 
1183  if (datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--)
1184  return;
1185 
1186  if (datagram->state != EC_DATAGRAM_RECEIVED) {
1187  EC_SLAVE_ERR(slave, "Failed to receive DC times datagram: ");
1188  ec_datagram_print_state(datagram);
1189  fsm->slave++;
1191  return;
1192  }
1193 
1194  if (datagram->working_counter != 1) {
1195  EC_SLAVE_WARN(slave, "Failed to get DC times: ");
1196  ec_datagram_print_wc_error(datagram);
1197  fsm->slave++;
1199  return;
1200  }
1201 
1202  system_time = EC_READ_U64(datagram->data); // 0x0910
1203  old_offset = EC_READ_U64(datagram->data + 16); // 0x0920
1204  jiffies_since_read = jiffies - datagram->jiffies_sent;
1205 
1206  if (slave->base_dc_range == EC_DC_32) {
1207  new_offset = ec_fsm_master_dc_offset32(fsm,
1208  system_time, old_offset, jiffies_since_read);
1209  } else {
1210  new_offset = ec_fsm_master_dc_offset64(fsm,
1211  system_time, old_offset, jiffies_since_read);
1212  }
1213 
1214  // set DC system time offset and transmission delay
1215  ec_datagram_fpwr(datagram, slave->station_address, 0x0920, 12);
1216  EC_WRITE_U64(datagram->data, new_offset);
1217  EC_WRITE_U32(datagram->data + 8, slave->transmission_delay);
1218  fsm->datagram->device_index = slave->device_index;
1219  fsm->retries = EC_FSM_RETRIES;
1221 }
1222 
1223 /****************************************************************************/
1224 
1228  ec_fsm_master_t *fsm
1229  )
1230 {
1231  ec_datagram_t *datagram = fsm->datagram;
1232  ec_slave_t *slave = fsm->slave;
1233 
1234  if (datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--)
1235  return;
1236 
1237  if (datagram->state != EC_DATAGRAM_RECEIVED) {
1238  EC_SLAVE_ERR(slave,
1239  "Failed to receive DC system time offset datagram: ");
1240  ec_datagram_print_state(datagram);
1241  fsm->slave++;
1243  return;
1244  }
1245 
1246  if (datagram->working_counter != 1) {
1247  EC_SLAVE_ERR(slave, "Failed to set DC system time offset: ");
1248  ec_datagram_print_wc_error(datagram);
1249  fsm->slave++;
1251  return;
1252  }
1253 
1254  fsm->slave++;
1256 }
1257 
1258 /****************************************************************************/
1259 
1263  ec_fsm_master_t *fsm
1264  )
1265 {
1266  ec_datagram_t *datagram = fsm->datagram;
1267  ec_sii_write_request_t *request = fsm->sii_request;
1268  ec_slave_t *slave = request->slave;
1269 
1270  if (datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--)
1271  return;
1272 
1273  if (datagram->state != EC_DATAGRAM_RECEIVED) {
1274  EC_SLAVE_ERR(slave, "Failed to receive SII assignment datagram: ");
1275  ec_datagram_print_state(datagram);
1276  goto cont;
1277  }
1278 
1279  if (datagram->working_counter != 1) {
1280  EC_SLAVE_ERR(slave, "Failed to assign SII back to EtherCAT: ");
1281  ec_datagram_print_wc_error(datagram);
1282  goto cont;
1283  }
1284 
1285 cont:
1286  // found pending SII write operation. execute it!
1287  EC_SLAVE_DBG(slave, 1, "Writing SII data (after assignment)...\n");
1288  fsm->sii_index = 0;
1289  ec_fsm_sii_write(&fsm->fsm_sii, slave, request->offset,
1292  fsm->state(fsm); // execute immediately
1293 }
1294 
1295 /****************************************************************************/
1296 
1300  ec_fsm_master_t *fsm
1301  )
1302 {
1303  ec_master_t *master = fsm->master;
1304  ec_sii_write_request_t *request = fsm->sii_request;
1305  ec_slave_t *slave = request->slave;
1306 
1307  if (ec_fsm_sii_exec(&fsm->fsm_sii)) return;
1308 
1309  if (!ec_fsm_sii_success(&fsm->fsm_sii)) {
1310  EC_SLAVE_ERR(slave, "Failed to write SII data.\n");
1311  request->state = EC_INT_REQUEST_FAILURE;
1312  wake_up_all(&master->request_queue);
1313  ec_fsm_master_restart(fsm);
1314  return;
1315  }
1316 
1317  fsm->sii_index++;
1318  if (fsm->sii_index < request->nwords) {
1319  ec_fsm_sii_write(&fsm->fsm_sii, slave,
1320  request->offset + fsm->sii_index,
1321  request->words + fsm->sii_index,
1323  ec_fsm_sii_exec(&fsm->fsm_sii); // execute immediately
1324  return;
1325  }
1326 
1327  // finished writing SII
1328  EC_SLAVE_DBG(slave, 1, "Finished writing %zu words of SII data.\n",
1329  request->nwords);
1330 
1331  if (request->offset <= 4 && request->offset + request->nwords > 4) {
1332  // alias was written
1333  slave->sii.alias = EC_READ_U16(request->words + 4);
1334  // TODO(fp): read alias from register 0x0012
1335  slave->effective_alias = slave->sii.alias;
1336  }
1337  // TODO(fp): Evaluate other SII contents!
1338 
1339  request->state = EC_INT_REQUEST_SUCCESS;
1340  wake_up_all(&master->request_queue);
1341 
1342  // check for another SII write request
1344  return; // processing another request
1345 
1346  ec_fsm_master_restart(fsm);
1347 }
1348 
1349 /****************************************************************************/
1350 
1354  ec_fsm_master_t *fsm
1355  )
1356 {
1357  ec_slave_t *slave = fsm->slave;
1358  ec_master_t *master = fsm->master;
1359 
1360  if (ec_fsm_coe_exec(&fsm->fsm_coe, fsm->datagram)) {
1361  return;
1362  }
1363 
1364  if (!ec_fsm_coe_success(&fsm->fsm_coe)) {
1365  ec_fsm_master_restart(fsm);
1366  return;
1367  }
1368 
1369  // SDO dictionary fetching finished
1370 
1371  if (master->debug_level) {
1372  unsigned int sdo_count, entry_count;
1373  ec_slave_sdo_dict_info(slave, &sdo_count, &entry_count);
1374  EC_SLAVE_DBG(slave, 1, "Fetched %u SDOs and %u entries.\n",
1375  sdo_count, entry_count);
1376  }
1377 
1378  // attach pdo names from dictionary
1380 
1381  ec_fsm_master_restart(fsm);
1382 }
1383 
1384 /****************************************************************************/
1385 
1389  ec_fsm_master_t *fsm
1390  )
1391 {
1392  ec_sdo_request_t *request = fsm->sdo_request;
1393 
1394  if (!request) {
1395  // configuration was cleared in the meantime
1396  ec_fsm_master_restart(fsm);
1397  return;
1398  }
1399 
1400  if (ec_fsm_coe_exec(&fsm->fsm_coe, fsm->datagram)) {
1401  return;
1402  }
1403 
1404  if (!ec_fsm_coe_success(&fsm->fsm_coe)) {
1405  EC_SLAVE_DBG(fsm->slave, 1,
1406  "Failed to process internal SDO request.\n");
1407  request->state = EC_INT_REQUEST_FAILURE;
1408  wake_up_all(&fsm->master->request_queue);
1409  ec_fsm_master_restart(fsm);
1410  return;
1411  }
1412 
1413  // SDO request finished
1414  request->state = EC_INT_REQUEST_SUCCESS;
1415  wake_up_all(&fsm->master->request_queue);
1416 
1417  EC_SLAVE_DBG(fsm->slave, 1, "Finished internal SDO request.\n");
1418 
1419  // check for another SDO/SoE request
1421  return; // processing another request
1422  }
1423 
1424  ec_fsm_master_restart(fsm);
1425 }
1426 
1427 /****************************************************************************/
1428 
1432  ec_fsm_master_t *fsm
1433  )
1434 {
1435  ec_soe_request_t *request = fsm->soe_request;
1436 
1437  if (!request) {
1438  // configuration was cleared in the meantime
1439  ec_fsm_master_restart(fsm);
1440  return;
1441  }
1442 
1443  if (ec_fsm_soe_exec(&fsm->fsm_soe, fsm->datagram)) {
1444  return;
1445  }
1446 
1447  if (!ec_fsm_soe_success(&fsm->fsm_soe)) {
1448  EC_SLAVE_DBG(fsm->slave, 1,
1449  "Failed to process internal SoE request.\n");
1450  request->state = EC_INT_REQUEST_FAILURE;
1451  wake_up_all(&fsm->master->request_queue);
1452  ec_fsm_master_restart(fsm);
1453  return;
1454  }
1455 
1456  // SoE request finished
1457  request->state = EC_INT_REQUEST_SUCCESS;
1458  wake_up_all(&fsm->master->request_queue);
1459 
1460  EC_SLAVE_DBG(fsm->slave, 1, "Finished internal SoE request.\n");
1461 
1462  // check for another CoE/SoE request
1464  return; // processing another request
1465  }
1466 
1467  ec_fsm_master_restart(fsm);
1468 }
1469 
1470 /****************************************************************************/
#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:1017
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:2204
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:145
struct ec_slave ec_slave_t
Definition: globals.h:309
void ec_master_request_op(ec_master_t *master)
Request OP state for configured slaves.
Definition: master.c:2221
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:1136
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:205
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:44
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:526
void ec_fsm_master_action_idle(ec_fsm_master_t *)
Master action: IDLE.
Definition: fsm_master.c:606
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:1227
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:665
#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:826
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:83
#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:464
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:1094
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
Definitions of Kernel SMP macros.
void ec_master_attach_slave_configs(ec_master_t *master)
Attaches the slave configurations to the slaves.
Definition: master.c:1790
int ec_datagram_apwr(ec_datagram_t *datagram, uint16_t ring_position, uint16_t mem_address, size_t data_size)
Initializes an EtherCAT APWR datagram.
Definition: datagram.c:210
void ec_fsm_master_state_read_state(ec_fsm_master_t *)
Master state: READ STATE.
Definition: fsm_master.c:750
void ec_datagram_zero(ec_datagram_t *datagram)
Fills the datagram payload memory with zeros.
Definition: datagram.c:178
void ec_fsm_master_state_sdo_request(ec_fsm_master_t *)
Master state: SDO REQUEST.
Definition: fsm_master.c:1388
void ec_fsm_master_state_scan_slave(ec_fsm_master_t *)
Master state: SCAN SLAVE.
Definition: fsm_master.c:942
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:693
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:602
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:197
void ec_fsm_master_state_dc_measure_delays(ec_fsm_master_t *)
Master state: DC MEASURE DELAYS.
Definition: fsm_master.c:887
void ec_fsm_master_state_broadcast(ec_fsm_master_t *)
Master state: BROADCAST.
Definition: fsm_master.c:280
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:250
Main device.
Definition: globals.h:198
ec_datagram_state_t
EtherCAT datagram state.
Definition: datagram.h:66
void ec_fsm_master_state_assign_sii(ec_fsm_master_t *)
Master state: ASSIGN SII.
Definition: fsm_master.c:1262
#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:373
int ec_datagram_fpwr(ec_datagram_t *datagram, uint16_t configured_address, uint16_t mem_address, size_t data_size)
Initializes an EtherCAT FPWR datagram.
Definition: datagram.c:298
uint8_t has_dc_system_time
The slave supports the DC system time register.
Definition: slave.h: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:273
void ec_fsm_coe_dictionary(ec_fsm_coe_t *fsm, ec_slave_t *slave)
Starts reading a slaves&#39; SDO dictionary.
Definition: fsm_coe.c:197
void ec_fsm_master_state_soe_request(ec_fsm_master_t *)
Master state: SoE REQUEST.
Definition: fsm_master.c:1431
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:194
32 bit.
Definition: globals.h:173
void ec_master_clear_slaves(ec_master_t *master)
Clear all slaves.
Definition: master.c:482
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:804
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:222
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:446
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:1678
void ec_datagram_print_state(const ec_datagram_t *datagram)
Prints the state of a datagram.
Definition: datagram.c:565
Mailbox functionality.
ec_master_t * master
master the FSM runs on
Definition: fsm_master.h:61
void ec_fsm_master_state_sdo_dictionary(ec_fsm_master_t *)
Master state: SDO DICTIONARY.
Definition: fsm_master.c:1353
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:842
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:1299
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:268
int ec_fsm_master_exec(ec_fsm_master_t *fsm)
Executes the current state of the state machine.
Definition: fsm_master.c:174
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:124
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:1045
void ec_master_eoe_stop(ec_master_t *master)
Stops the Ethernet over EtherCAT processing.
Definition: master.c:1712
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:1174
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:393