IgH EtherCAT Master  1.5.2
fsm_master.c
Go to the documentation of this file.
1 /******************************************************************************
2  *
3  * $Id$
4  *
5  * Copyright (C) 2006-2012 Florian Pose, Ingenieurgemeinschaft IgH
6  *
7  * This file is part of the IgH EtherCAT Master.
8  *
9  * The IgH EtherCAT Master is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU General Public License version 2, as
11  * published by the Free Software Foundation.
12  *
13  * The IgH EtherCAT Master is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
16  * Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License along
19  * with the IgH EtherCAT Master; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
21  *
22  * ---
23  *
24  * The license mentioned above concerns the source code only. Using the
25  * EtherCAT technology and brand is only permitted in compliance with the
26  * industrial property and similar rights of Beckhoff Automation GmbH.
27  *
28  *****************************************************************************/
29 
34 /*****************************************************************************/
35 
36 #include "globals.h"
37 #include "master.h"
38 #include "mailbox.h"
39 #include "slave_config.h"
40 #ifdef EC_EOE
41 #include "ethernet.h"
42 #endif
43 
44 #include "fsm_master.h"
45 #include "fsm_foe.h"
46 
47 /*****************************************************************************/
48 
51 #define EC_SYSTEM_TIME_TOLERANCE_NS 1000000
52 
53 /*****************************************************************************/
54 
68 
71 
72 /*****************************************************************************/
73 
77  ec_fsm_master_t *fsm,
78  ec_master_t *master,
79  ec_datagram_t *datagram
80  )
81 {
82  fsm->master = master;
83  fsm->datagram = datagram;
84 
86 
87  // init sub-state-machines
88  ec_fsm_coe_init(&fsm->fsm_coe);
89  ec_fsm_soe_init(&fsm->fsm_soe);
90  ec_fsm_pdo_init(&fsm->fsm_pdo, &fsm->fsm_coe);
93  &fsm->fsm_change, &fsm->fsm_coe, &fsm->fsm_soe, &fsm->fsm_pdo);
95  &fsm->fsm_slave_config, &fsm->fsm_pdo);
96  ec_fsm_sii_init(&fsm->fsm_sii, fsm->datagram);
97 }
98 
99 /*****************************************************************************/
100 
104  ec_fsm_master_t *fsm
105  )
106 {
107  // clear sub-state machines
108  ec_fsm_coe_clear(&fsm->fsm_coe);
109  ec_fsm_soe_clear(&fsm->fsm_soe);
110  ec_fsm_pdo_clear(&fsm->fsm_pdo);
114  ec_fsm_sii_clear(&fsm->fsm_sii);
115 }
116 
117 /*****************************************************************************/
118 
122  ec_fsm_master_t *fsm
123  )
124 {
125  ec_device_index_t dev_idx;
126 
128  fsm->idle = 0;
129  fsm->dev_idx = EC_DEVICE_MAIN;
130 
131  for (dev_idx = EC_DEVICE_MAIN;
132  dev_idx < ec_master_num_devices(fsm->master); dev_idx++) {
133  fsm->link_state[dev_idx] = 0;
134  fsm->slaves_responding[dev_idx] = 0;
135  fsm->slave_states[dev_idx] = EC_SLAVE_STATE_UNKNOWN;
136  }
137 
138  fsm->rescan_required = 0;
139 }
140 
141 /*****************************************************************************/
142 
151  ec_fsm_master_t *fsm
152  )
153 {
154  if (fsm->datagram->state == EC_DATAGRAM_SENT
155  || fsm->datagram->state == EC_DATAGRAM_QUEUED) {
156  // datagram was not sent or received yet.
157  return 0;
158  }
159 
160  fsm->state(fsm);
161  return 1;
162 }
163 
164 /*****************************************************************************/
165 
170  const ec_fsm_master_t *fsm
171  )
172 {
173  return fsm->idle;
174 }
175 
176 /*****************************************************************************/
177 
181  ec_fsm_master_t *fsm
182  )
183 {
184  fsm->dev_idx = EC_DEVICE_MAIN;
186  fsm->state(fsm); // execute immediately
187 }
188 
189 /******************************************************************************
190  * Master state machine
191  *****************************************************************************/
192 
198  ec_fsm_master_t *fsm
199  )
200 {
201  ec_master_t *master = fsm->master;
202 
203  fsm->idle = 1;
204 
205  // check for emergency requests
206  if (!list_empty(&master->emerg_reg_requests)) {
207  ec_reg_request_t *request;
208 
209  // get first request
210  request = list_entry(master->emerg_reg_requests.next,
211  ec_reg_request_t, list);
212  list_del_init(&request->list); // dequeue
213  request->state = EC_INT_REQUEST_BUSY;
214 
215  if (request->transfer_size > fsm->datagram->mem_size) {
216  EC_MASTER_ERR(master, "Emergency request data too large!\n");
217  request->state = EC_INT_REQUEST_FAILURE;
218  wake_up_all(&master->request_queue);
219  fsm->state(fsm); // continue
220  return;
221  }
222 
223  if (request->dir != EC_DIR_OUTPUT) {
224  EC_MASTER_ERR(master, "Emergency requests must be"
225  " write requests!\n");
226  request->state = EC_INT_REQUEST_FAILURE;
227  wake_up_all(&master->request_queue);
228  fsm->state(fsm); // continue
229  return;
230  }
231 
232  EC_MASTER_DBG(master, 1, "Writing emergency register request...\n");
233  ec_datagram_apwr(fsm->datagram, request->ring_position,
234  request->address, request->transfer_size);
235  memcpy(fsm->datagram->data, request->data, request->transfer_size);
237  request->state = EC_INT_REQUEST_SUCCESS;
238  wake_up_all(&master->request_queue);
239  return;
240  }
241 
242  ec_datagram_brd(fsm->datagram, 0x0130, 2);
244  fsm->datagram->device_index = fsm->dev_idx;
246 }
247 
248 /*****************************************************************************/
249 
255  ec_fsm_master_t *fsm
256  )
257 {
258  ec_datagram_t *datagram = fsm->datagram;
259  unsigned int i, size;
260  ec_slave_t *slave;
261  ec_master_t *master = fsm->master;
262 
263  // bus topology change?
264  if (datagram->working_counter != fsm->slaves_responding[fsm->dev_idx]) {
265  fsm->rescan_required = 1;
266  fsm->slaves_responding[fsm->dev_idx] = datagram->working_counter;
267  EC_MASTER_INFO(master, "%u slave(s) responding on %s device.\n",
268  fsm->slaves_responding[fsm->dev_idx],
269  ec_device_names[fsm->dev_idx != 0]);
270  }
271 
272  if (fsm->link_state[fsm->dev_idx] &&
273  !master->devices[fsm->dev_idx].link_state) {
274  ec_device_index_t dev_idx;
275 
276  EC_MASTER_DBG(master, 1, "Master state machine detected "
277  "link down on %s device. Clearing slave list.\n",
278  ec_device_names[fsm->dev_idx != 0]);
279 
280 #ifdef EC_EOE
281  ec_master_eoe_stop(master);
283 #endif
284  ec_master_clear_slaves(master);
285 
286  for (dev_idx = EC_DEVICE_MAIN;
287  dev_idx < ec_master_num_devices(master); dev_idx++) {
288  fsm->slave_states[dev_idx] = 0x00;
289  fsm->slaves_responding[dev_idx] = 0; /* Reset to trigger rescan on
290  next link up. */
291  }
292  }
293  fsm->link_state[fsm->dev_idx] = master->devices[fsm->dev_idx].link_state;
294 
295  if (datagram->state == EC_DATAGRAM_RECEIVED &&
296  fsm->slaves_responding[fsm->dev_idx]) {
297  uint8_t states = EC_READ_U8(datagram->data);
298  if (states != fsm->slave_states[fsm->dev_idx]) {
299  // slave states changed
300  char state_str[EC_STATE_STRING_SIZE];
301  fsm->slave_states[fsm->dev_idx] = states;
302  ec_state_string(states, state_str, 1);
303  EC_MASTER_INFO(master, "Slave states on %s device: %s.\n",
304  ec_device_names[fsm->dev_idx != 0], state_str);
305  }
306  } else {
307  fsm->slave_states[fsm->dev_idx] = 0x00;
308  }
309 
310  fsm->dev_idx++;
311  if (fsm->dev_idx < ec_master_num_devices(master)) {
312  // check number of responding slaves on next device
314  fsm->state(fsm); // execute immediately
315  return;
316  }
317 
318  if (fsm->rescan_required) {
319  down(&master->scan_sem);
320  if (!master->allow_scan) {
321  up(&master->scan_sem);
322  } else {
323  unsigned int count = 0, next_dev_slave, ring_position;
324  ec_device_index_t dev_idx;
325 
326  master->scan_busy = 1;
327  up(&master->scan_sem);
328 
329  // clear all slaves and scan the bus
330  fsm->rescan_required = 0;
331  fsm->idle = 0;
332  fsm->scan_jiffies = jiffies;
333 
334 #ifdef EC_EOE
335  ec_master_eoe_stop(master);
337 #endif
338  ec_master_clear_slaves(master);
339 
340  for (dev_idx = EC_DEVICE_MAIN;
341  dev_idx < ec_master_num_devices(master); dev_idx++) {
342  count += fsm->slaves_responding[dev_idx];
343  }
344 
345  if (!count) {
346  // no slaves present -> finish state machine.
347  master->scan_busy = 0;
348  wake_up_interruptible(&master->scan_queue);
350  return;
351  }
352 
353  size = sizeof(ec_slave_t) * count;
354  if (!(master->slaves =
355  (ec_slave_t *) kmalloc(size, GFP_KERNEL))) {
356  EC_MASTER_ERR(master, "Failed to allocate %u bytes"
357  " of slave memory!\n", size);
358  master->scan_busy = 0;
359  wake_up_interruptible(&master->scan_queue);
361  return;
362  }
363 
364  // init slaves
365  dev_idx = EC_DEVICE_MAIN;
366  next_dev_slave = fsm->slaves_responding[dev_idx];
367  ring_position = 0;
368  for (i = 0; i < count; i++, ring_position++) {
369  slave = master->slaves + i;
370  while (i >= next_dev_slave) {
371  dev_idx++;
372  next_dev_slave += fsm->slaves_responding[dev_idx];
373  ring_position = 0;
374  }
375 
376  ec_slave_init(slave, master, dev_idx, ring_position, i + 1);
377 
378  // do not force reconfiguration in operation phase to avoid
379  // unnecesssary process data interruptions
380  if (master->phase != EC_OPERATION) {
381  slave->force_config = 1;
382  }
383  }
384  master->slave_count = count;
385  master->fsm_slave = master->slaves;
386 
387  /* start with first device with slaves responding; at least one
388  * has responding slaves, otherwise count would be zero. */
389  fsm->dev_idx = EC_DEVICE_MAIN;
390  while (!fsm->slaves_responding[fsm->dev_idx]) {
391  fsm->dev_idx++;
392  }
393 
395  return;
396  }
397  }
398 
399  if (master->slave_count) {
400 
401  // application applied configurations
402  if (master->config_changed) {
403  master->config_changed = 0;
404 
405  EC_MASTER_DBG(master, 1, "Configuration changed.\n");
406 
407  fsm->slave = master->slaves; // begin with first slave
409 
410  } else {
411  // fetch state from first slave
412  fsm->slave = master->slaves;
414  0x0130, 2);
415  ec_datagram_zero(datagram);
416  fsm->datagram->device_index = fsm->slave->device_index;
417  fsm->retries = EC_FSM_RETRIES;
419  }
420  } else {
422  }
423 }
424 
425 /*****************************************************************************/
426 
432  ec_fsm_master_t *fsm
433  )
434 {
435  ec_master_t *master = fsm->master;
436  ec_sii_write_request_t *request;
437 
438  // search the first request to be processed
439  while (1) {
440  if (list_empty(&master->sii_requests))
441  break;
442 
443  // get first request
444  request = list_entry(master->sii_requests.next,
445  ec_sii_write_request_t, list);
446  list_del_init(&request->list); // dequeue
447  request->state = EC_INT_REQUEST_BUSY;
448 
449  // found pending SII write operation. execute it!
450  EC_SLAVE_DBG(request->slave, 1, "Writing SII data...\n");
451  fsm->sii_request = request;
452  fsm->sii_index = 0;
453  ec_fsm_sii_write(&fsm->fsm_sii, request->slave, request->offset,
456  fsm->state(fsm); // execute immediately
457  return 1;
458  }
459 
460  return 0;
461 }
462 
463 /*****************************************************************************/
464 
470  ec_fsm_master_t *fsm
471  )
472 {
473  ec_master_t *master = fsm->master;
474  ec_slave_t *slave;
475  ec_sdo_request_t *req;
476 
477  // search for internal requests to be processed
478  for (slave = master->slaves;
479  slave < master->slaves + master->slave_count;
480  slave++) {
481 
482  if (!slave->config) {
483  continue;
484  }
485 
486  list_for_each_entry(req, &slave->config->sdo_requests, list) {
487  if (req->state == EC_INT_REQUEST_QUEUED) {
488 
489  if (ec_sdo_request_timed_out(req)) {
490  req->state = EC_INT_REQUEST_FAILURE;
491  EC_SLAVE_DBG(slave, 1, "Internal SDO request"
492  " timed out.\n");
493  continue;
494  }
495 
496  if (slave->current_state == EC_SLAVE_STATE_INIT) {
497  req->state = EC_INT_REQUEST_FAILURE;
498  continue;
499  }
500 
501  req->state = EC_INT_REQUEST_BUSY;
502  EC_SLAVE_DBG(slave, 1, "Processing internal"
503  " SDO request...\n");
504  fsm->idle = 0;
505  fsm->sdo_request = req;
506  fsm->slave = slave;
508  ec_fsm_coe_transfer(&fsm->fsm_coe, slave, req);
509  ec_fsm_coe_exec(&fsm->fsm_coe, fsm->datagram);
510  return 1;
511  }
512  }
513  }
514  return 0;
515 }
516 
517 /*****************************************************************************/
518 
524  ec_fsm_master_t *fsm
525  )
526 {
527  ec_master_t *master = fsm->master;
528  ec_slave_t *slave;
529 
530  // Check for pending internal SDO requests
532  return;
533  }
534 
535  // enable processing of requests
536  for (slave = master->slaves;
537  slave < master->slaves + master->slave_count;
538  slave++) {
539  ec_fsm_slave_set_ready(&slave->fsm);
540  }
541 
542  // check, if slaves have an SDO dictionary to read out.
543  for (slave = master->slaves;
544  slave < master->slaves + master->slave_count;
545  slave++) {
546  if (!(slave->sii.mailbox_protocols & EC_MBOX_COE)
547  || (slave->sii.has_general
548  && !slave->sii.coe_details.enable_sdo_info)
549  || slave->sdo_dictionary_fetched
552  || jiffies - slave->jiffies_preop < EC_WAIT_SDO_DICT * HZ
553  ) continue;
554 
555  EC_SLAVE_DBG(slave, 1, "Fetching SDO dictionary.\n");
556 
557  slave->sdo_dictionary_fetched = 1;
558 
559  // start fetching SDO dictionary
560  fsm->idle = 0;
561  fsm->slave = slave;
563  ec_fsm_coe_dictionary(&fsm->fsm_coe, slave);
564  ec_fsm_coe_exec(&fsm->fsm_coe, fsm->datagram); // execute immediately
565  fsm->datagram->device_index = fsm->slave->device_index;
566  return;
567  }
568 
569  // check for pending SII write operations.
571  return; // SII write request found
572  }
573 
575 }
576 
577 /*****************************************************************************/
578 
582  ec_fsm_master_t *fsm
583  )
584 {
585  ec_master_t *master = fsm->master;
586 
587  // is there another slave to query?
588  fsm->slave++;
589  if (fsm->slave < master->slaves + master->slave_count) {
590  // fetch state from next slave
591  fsm->idle = 1;
593  fsm->slave->station_address, 0x0130, 2);
595  fsm->datagram->device_index = fsm->slave->device_index;
596  fsm->retries = EC_FSM_RETRIES;
598  return;
599  }
600 
601  // all slaves processed
603 }
604 
605 /*****************************************************************************/
606 
610  ec_fsm_master_t *fsm
611  )
612 {
613  ec_master_t *master = fsm->master;
614  ec_slave_t *slave = fsm->slave;
615 
616  if (master->config_changed) {
617  master->config_changed = 0;
618 
619  // abort iterating through slaves,
620  // first compensate DC system time offsets,
621  // then begin configuring at slave 0
622  EC_MASTER_DBG(master, 1, "Configuration changed"
623  " (aborting state check).\n");
624 
625  fsm->slave = master->slaves; // begin with first slave
627  return;
628  }
629 
630  // Does the slave have to be configured?
631  if ((slave->current_state != slave->requested_state
632  || slave->force_config) && !slave->error_flag) {
633 
634  // Start slave configuration
635  down(&master->config_sem);
636  master->config_busy = 1;
637  up(&master->config_sem);
638 
639  if (master->debug_level) {
640  char old_state[EC_STATE_STRING_SIZE],
641  new_state[EC_STATE_STRING_SIZE];
642  ec_state_string(slave->current_state, old_state, 0);
643  ec_state_string(slave->requested_state, new_state, 0);
644  EC_SLAVE_DBG(slave, 1, "Changing state from %s to %s%s.\n",
645  old_state, new_state,
646  slave->force_config ? " (forced)" : "");
647  }
648 
649  fsm->idle = 0;
652  fsm->state(fsm); // execute immediately
653  fsm->datagram->device_index = fsm->slave->device_index;
654  return;
655  }
656 
657  // process next slave
659 }
660 
661 /*****************************************************************************/
662 
668  ec_fsm_master_t *fsm
669  )
670 {
671  ec_slave_t *slave = fsm->slave;
672  ec_datagram_t *datagram = fsm->datagram;
673 
674  if (datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--) {
675  return;
676  }
677 
678  if (datagram->state != EC_DATAGRAM_RECEIVED) {
679  EC_SLAVE_ERR(slave, "Failed to receive AL state datagram: ");
680  ec_datagram_print_state(datagram);
682  return;
683  }
684 
685  // did the slave not respond to its station address?
686  if (datagram->working_counter != 1) {
687  if (!slave->error_flag) {
688  slave->error_flag = 1;
689  EC_SLAVE_DBG(slave, 1, "Slave did not respond to state query.\n");
690  }
691  fsm->rescan_required = 1;
693  return;
694  }
695 
696  // A single slave responded
697  ec_slave_set_state(slave, EC_READ_U8(datagram->data));
698 
699  if (!slave->error_flag) {
700  // Check, if new slave state has to be acknowledged
701  if (slave->current_state & EC_SLAVE_STATE_ACK_ERR) {
702  fsm->idle = 0;
704  ec_fsm_change_ack(&fsm->fsm_change, slave);
705  fsm->state(fsm); // execute immediately
706  return;
707  }
708 
709  // No acknowlegde necessary; check for configuration
711  return;
712  }
713 
714  // slave has error flag set; process next one
716 }
717 
718 /*****************************************************************************/
719 
723  ec_fsm_master_t *fsm
724  )
725 {
726  ec_slave_t *slave = fsm->slave;
727 
728  if (ec_fsm_change_exec(&fsm->fsm_change)) {
729  return;
730  }
731 
732  if (!ec_fsm_change_success(&fsm->fsm_change)) {
733  fsm->slave->error_flag = 1;
734  EC_SLAVE_ERR(slave, "Failed to acknowledge state change.\n");
735  }
736 
738 }
739 
740 /*****************************************************************************/
741 
745  ec_fsm_master_t *fsm
746  )
747 {
748  // broadcast clear all station addresses
749  ec_datagram_bwr(fsm->datagram, 0x0010, 2);
750  EC_WRITE_U16(fsm->datagram->data, 0x0000);
751  fsm->datagram->device_index = fsm->dev_idx;
752  fsm->retries = EC_FSM_RETRIES;
754 }
755 
756 /*****************************************************************************/
757 
761  ec_fsm_master_t *fsm
762  )
763 {
764  ec_master_t *master = fsm->master;
765  ec_datagram_t *datagram = fsm->datagram;
766 
767  if (datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--) {
768  return;
769  }
770 
771  if (datagram->state != EC_DATAGRAM_RECEIVED) {
772  EC_MASTER_ERR(master, "Failed to receive address"
773  " clearing datagram on %s link: ",
774  ec_device_names[fsm->dev_idx != 0]);
775  ec_datagram_print_state(datagram);
776  master->scan_busy = 0;
777  wake_up_interruptible(&master->scan_queue);
779  return;
780  }
781 
782  if (datagram->working_counter != fsm->slaves_responding[fsm->dev_idx]) {
783  EC_MASTER_WARN(master, "Failed to clear station addresses on %s link:"
784  " Cleared %u of %u",
785  ec_device_names[fsm->dev_idx != 0], datagram->working_counter,
786  fsm->slaves_responding[fsm->dev_idx]);
787  }
788 
789  EC_MASTER_DBG(master, 1, "Sending broadcast-write"
790  " to measure transmission delays on %s link.\n",
791  ec_device_names[fsm->dev_idx != 0]);
792 
793  ec_datagram_bwr(datagram, 0x0900, 1);
794  ec_datagram_zero(datagram);
795  fsm->datagram->device_index = fsm->dev_idx;
796  fsm->retries = EC_FSM_RETRIES;
798 }
799 
800 /*****************************************************************************/
801 
805  ec_fsm_master_t *fsm
806  )
807 {
808  ec_master_t *master = fsm->master;
809  ec_datagram_t *datagram = fsm->datagram;
810 
811  if (datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--) {
812  return;
813  }
814 
815  if (datagram->state != EC_DATAGRAM_RECEIVED) {
816  EC_MASTER_ERR(master, "Failed to receive delay measuring datagram"
817  " on %s link: ", ec_device_names[fsm->dev_idx != 0]);
818  ec_datagram_print_state(datagram);
819  master->scan_busy = 0;
820  wake_up_interruptible(&master->scan_queue);
822  return;
823  }
824 
825  EC_MASTER_DBG(master, 1, "%u slaves responded to delay measuring"
826  " on %s link.\n",
827  datagram->working_counter, ec_device_names[fsm->dev_idx != 0]);
828 
829  do {
830  fsm->dev_idx++;
831  } while (fsm->dev_idx < ec_master_num_devices(master) &&
832  !fsm->slaves_responding[fsm->dev_idx]);
833  if (fsm->dev_idx < ec_master_num_devices(master)) {
835  return;
836  }
837 
838  EC_MASTER_INFO(master, "Scanning bus.\n");
839 
840  // begin scanning of slaves
841  fsm->slave = master->slaves;
842  EC_MASTER_DBG(master, 1, "Scanning slave %u on %s link.\n",
843  fsm->slave->ring_position,
844  ec_device_names[fsm->slave->device_index != 0]);
847  ec_fsm_slave_scan_exec(&fsm->fsm_slave_scan); // execute immediately
848  fsm->datagram->device_index = fsm->slave->device_index;
849 }
850 
851 /*****************************************************************************/
852 
858  ec_fsm_master_t *fsm
859  )
860 {
861  ec_master_t *master = fsm->master;
862 #ifdef EC_EOE
863  ec_slave_t *slave = fsm->slave;
864 #endif
865 
867  return;
868  }
869 
870 #ifdef EC_EOE
871  if (slave->sii.mailbox_protocols & EC_MBOX_EOE) {
872  // create EoE handler for this slave
873  ec_eoe_t *eoe;
874  if (!(eoe = kmalloc(sizeof(ec_eoe_t), GFP_KERNEL))) {
875  EC_SLAVE_ERR(slave, "Failed to allocate EoE handler memory!\n");
876  } else if (ec_eoe_init(eoe, slave)) {
877  EC_SLAVE_ERR(slave, "Failed to init EoE handler!\n");
878  kfree(eoe);
879  } else {
880  list_add_tail(&eoe->list, &master->eoe_handlers);
881  }
882  }
883 #endif
884 
885  // another slave to fetch?
886  fsm->slave++;
887  if (fsm->slave < master->slaves + master->slave_count) {
888  EC_MASTER_DBG(master, 1, "Scanning slave %u on %s link.\n",
889  fsm->slave->ring_position,
890  ec_device_names[fsm->slave->device_index != 0]);
892  ec_fsm_slave_scan_exec(&fsm->fsm_slave_scan); // execute immediately
893  fsm->datagram->device_index = fsm->slave->device_index;
894  return;
895  }
896 
897  EC_MASTER_INFO(master, "Bus scanning completed in %lu ms.\n",
898  (jiffies - fsm->scan_jiffies) * 1000 / HZ);
899 
900  master->scan_busy = 0;
901  wake_up_interruptible(&master->scan_queue);
902 
903  ec_master_calc_dc(master);
904 
905  // Attach slave configurations
907 
908 #ifdef EC_EOE
909  // check if EoE processing has to be started
910  ec_master_eoe_start(master);
911 #endif
912 
913  if (master->slave_count) {
914  master->config_changed = 0;
915 
916  fsm->slave = master->slaves; // begin with first slave
918  } else {
920  }
921 }
922 
923 /*****************************************************************************/
924 
930  ec_fsm_master_t *fsm
931  )
932 {
933  ec_master_t *master = fsm->master;
934 
936  return;
937  }
938 
939  fsm->slave->force_config = 0;
940 
941  // configuration finished
942  master->config_busy = 0;
943  wake_up_interruptible(&master->config_queue);
944 
946  // TODO: mark slave_config as failed.
947  }
948 
949  fsm->idle = 1;
951 }
952 
953 /*****************************************************************************/
954 
958  ec_fsm_master_t *fsm
959  )
960 {
961  ec_master_t *master = fsm->master;
962 
963  if (master->has_app_time) {
964 
965  while (fsm->slave < master->slaves + master->slave_count) {
966  if (!fsm->slave->base_dc_supported
967  || !fsm->slave->has_dc_system_time) {
968  fsm->slave++;
969  continue;
970  }
971 
972  EC_SLAVE_DBG(fsm->slave, 1, "Checking system time offset.\n");
973 
974  // read DC system time (0x0910, 64 bit)
975  // gap (64 bit)
976  // and time offset (0x0920, 64 bit)
978  0x0910, 24);
979  fsm->datagram->device_index = fsm->slave->device_index;
980  fsm->retries = EC_FSM_RETRIES;
982  return;
983  }
984 
985  } else {
986  if (master->active) {
987  EC_MASTER_WARN(master, "No app_time received up to now,"
988  " but master already active.\n");
989  } else {
990  EC_MASTER_DBG(master, 1, "No app_time received up to now.\n");
991  }
992  }
993 
994  // scanning and setting system times complete
995  ec_master_request_op(master);
997 }
998 
999 /*****************************************************************************/
1000 
1006  ec_fsm_master_t *fsm,
1007  u64 system_time,
1008  u64 old_offset,
1009  unsigned long jiffies_since_read
1010  )
1011 {
1012  ec_slave_t *slave = fsm->slave;
1013  u32 correction, system_time32, old_offset32, new_offset;
1014  s32 time_diff;
1015 
1016  system_time32 = (u32) system_time;
1017  old_offset32 = (u32) old_offset;
1018 
1019  // correct read system time by elapsed time since read operation
1020  correction = jiffies_since_read * 1000 / HZ * 1000000;
1021  system_time32 += correction;
1022  time_diff = (u32) slave->master->app_time - system_time32;
1023 
1024  EC_SLAVE_DBG(slave, 1, "DC 32 bit system time offset calculation:"
1025  " system_time=%u (corrected with %u),"
1026  " app_time=%llu, diff=%i\n",
1027  system_time32, correction,
1028  slave->master->app_time, time_diff);
1029 
1030  if (EC_ABS(time_diff) > EC_SYSTEM_TIME_TOLERANCE_NS) {
1031  new_offset = time_diff + old_offset32;
1032  EC_SLAVE_DBG(slave, 1, "Setting time offset to %u (was %u)\n",
1033  new_offset, old_offset32);
1034  return (u64) new_offset;
1035  } else {
1036  EC_SLAVE_DBG(slave, 1, "Not touching time offset.\n");
1037  return old_offset;
1038  }
1039 }
1040 
1041 /*****************************************************************************/
1042 
1048  ec_fsm_master_t *fsm,
1049  u64 system_time,
1050  u64 old_offset,
1051  unsigned long jiffies_since_read
1052  )
1053 {
1054  ec_slave_t *slave = fsm->slave;
1055  u64 new_offset, correction;
1056  s64 time_diff;
1057 
1058  // correct read system time by elapsed time since read operation
1059  correction = (u64) (jiffies_since_read * 1000 / HZ) * 1000000;
1060  system_time += correction;
1061  time_diff = fsm->slave->master->app_time - system_time;
1062 
1063  EC_SLAVE_DBG(slave, 1, "DC 64 bit system time offset calculation:"
1064  " system_time=%llu (corrected with %llu),"
1065  " app_time=%llu, diff=%lli\n",
1066  system_time, correction,
1067  slave->master->app_time, time_diff);
1068 
1069  if (EC_ABS(time_diff) > EC_SYSTEM_TIME_TOLERANCE_NS) {
1070  new_offset = time_diff + old_offset;
1071  EC_SLAVE_DBG(slave, 1, "Setting time offset to %llu (was %llu)\n",
1072  new_offset, old_offset);
1073  } else {
1074  new_offset = old_offset;
1075  EC_SLAVE_DBG(slave, 1, "Not touching time offset.\n");
1076  }
1077 
1078  return new_offset;
1079 }
1080 
1081 /*****************************************************************************/
1082 
1086  ec_fsm_master_t *fsm
1087  )
1088 {
1089  ec_datagram_t *datagram = fsm->datagram;
1090  ec_slave_t *slave = fsm->slave;
1091  u64 system_time, old_offset, new_offset;
1092  unsigned long jiffies_since_read;
1093 
1094  if (datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--)
1095  return;
1096 
1097  if (datagram->state != EC_DATAGRAM_RECEIVED) {
1098  EC_SLAVE_ERR(slave, "Failed to receive DC times datagram: ");
1099  ec_datagram_print_state(datagram);
1100  fsm->slave++;
1102  return;
1103  }
1104 
1105  if (datagram->working_counter != 1) {
1106  EC_SLAVE_WARN(slave, "Failed to get DC times: ");
1107  ec_datagram_print_wc_error(datagram);
1108  fsm->slave++;
1110  return;
1111  }
1112 
1113  system_time = EC_READ_U64(datagram->data); // 0x0910
1114  old_offset = EC_READ_U64(datagram->data + 16); // 0x0920
1115  jiffies_since_read = jiffies - datagram->jiffies_sent;
1116 
1117  if (slave->base_dc_range == EC_DC_32) {
1118  new_offset = ec_fsm_master_dc_offset32(fsm,
1119  system_time, old_offset, jiffies_since_read);
1120  } else {
1121  new_offset = ec_fsm_master_dc_offset64(fsm,
1122  system_time, old_offset, jiffies_since_read);
1123  }
1124 
1125  // set DC system time offset and transmission delay
1126  ec_datagram_fpwr(datagram, slave->station_address, 0x0920, 12);
1127  EC_WRITE_U64(datagram->data, new_offset);
1128  EC_WRITE_U32(datagram->data + 8, slave->transmission_delay);
1129  fsm->datagram->device_index = slave->device_index;
1130  fsm->retries = EC_FSM_RETRIES;
1132 }
1133 
1134 /*****************************************************************************/
1135 
1139  ec_fsm_master_t *fsm
1140  )
1141 {
1142  ec_datagram_t *datagram = fsm->datagram;
1143  ec_slave_t *slave = fsm->slave;
1144 
1145  if (datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--)
1146  return;
1147 
1148  if (datagram->state != EC_DATAGRAM_RECEIVED) {
1149  EC_SLAVE_ERR(slave,
1150  "Failed to receive DC system time offset datagram: ");
1151  ec_datagram_print_state(datagram);
1152  fsm->slave++;
1154  return;
1155  }
1156 
1157  if (datagram->working_counter != 1) {
1158  EC_SLAVE_ERR(slave, "Failed to set DC system time offset: ");
1159  ec_datagram_print_wc_error(datagram);
1160  fsm->slave++;
1162  return;
1163  }
1164 
1165  fsm->slave++;
1167 }
1168 
1169 /*****************************************************************************/
1170 
1174  ec_fsm_master_t *fsm
1175  )
1176 {
1177  ec_master_t *master = fsm->master;
1178  ec_sii_write_request_t *request = fsm->sii_request;
1179  ec_slave_t *slave = request->slave;
1180 
1181  if (ec_fsm_sii_exec(&fsm->fsm_sii)) return;
1182 
1183  if (!ec_fsm_sii_success(&fsm->fsm_sii)) {
1184  EC_SLAVE_ERR(slave, "Failed to write SII data.\n");
1185  request->state = EC_INT_REQUEST_FAILURE;
1186  wake_up_all(&master->request_queue);
1187  ec_fsm_master_restart(fsm);
1188  return;
1189  }
1190 
1191  fsm->sii_index++;
1192  if (fsm->sii_index < request->nwords) {
1193  ec_fsm_sii_write(&fsm->fsm_sii, slave,
1194  request->offset + fsm->sii_index,
1195  request->words + fsm->sii_index,
1197  ec_fsm_sii_exec(&fsm->fsm_sii); // execute immediately
1198  return;
1199  }
1200 
1201  // finished writing SII
1202  EC_SLAVE_DBG(slave, 1, "Finished writing %zu words of SII data.\n",
1203  request->nwords);
1204 
1205  if (request->offset <= 4 && request->offset + request->nwords > 4) {
1206  // alias was written
1207  slave->sii.alias = EC_READ_U16(request->words + 4);
1208  // TODO: read alias from register 0x0012
1209  slave->effective_alias = slave->sii.alias;
1210  }
1211  // TODO: Evaluate other SII contents!
1212 
1213  request->state = EC_INT_REQUEST_SUCCESS;
1214  wake_up_all(&master->request_queue);
1215 
1216  // check for another SII write request
1218  return; // processing another request
1219 
1220  ec_fsm_master_restart(fsm);
1221 }
1222 
1223 /*****************************************************************************/
1224 
1228  ec_fsm_master_t *fsm
1229  )
1230 {
1231  ec_slave_t *slave = fsm->slave;
1232  ec_master_t *master = fsm->master;
1233 
1234  if (ec_fsm_coe_exec(&fsm->fsm_coe, fsm->datagram)) {
1235  return;
1236  }
1237 
1238  if (!ec_fsm_coe_success(&fsm->fsm_coe)) {
1239  ec_fsm_master_restart(fsm);
1240  return;
1241  }
1242 
1243  // SDO dictionary fetching finished
1244 
1245  if (master->debug_level) {
1246  unsigned int sdo_count, entry_count;
1247  ec_slave_sdo_dict_info(slave, &sdo_count, &entry_count);
1248  EC_SLAVE_DBG(slave, 1, "Fetched %u SDOs and %u entries.\n",
1249  sdo_count, entry_count);
1250  }
1251 
1252  // attach pdo names from dictionary
1254 
1255  ec_fsm_master_restart(fsm);
1256 }
1257 
1258 /*****************************************************************************/
1259 
1263  ec_fsm_master_t *fsm
1264  )
1265 {
1266  ec_sdo_request_t *request = fsm->sdo_request;
1267 
1268  if (!request) {
1269  // configuration was cleared in the meantime
1270  ec_fsm_master_restart(fsm);
1271  return;
1272  }
1273 
1274  if (ec_fsm_coe_exec(&fsm->fsm_coe, fsm->datagram)) {
1275  return;
1276  }
1277 
1278  if (!ec_fsm_coe_success(&fsm->fsm_coe)) {
1279  EC_SLAVE_DBG(fsm->slave, 1,
1280  "Failed to process internal SDO request.\n");
1281  request->state = EC_INT_REQUEST_FAILURE;
1282  wake_up_all(&fsm->master->request_queue);
1283  ec_fsm_master_restart(fsm);
1284  return;
1285  }
1286 
1287  // SDO request finished
1288  request->state = EC_INT_REQUEST_SUCCESS;
1289  wake_up_all(&fsm->master->request_queue);
1290 
1291  EC_SLAVE_DBG(fsm->slave, 1, "Finished internal SDO request.\n");
1292 
1293  // check for another SDO request
1295  return; // processing another request
1296  }
1297 
1298  ec_fsm_master_restart(fsm);
1299 }
1300 
1301 /*****************************************************************************/
#define EC_FSM_RETRIES
Number of state machine retries on datagram timeout.
Definition: globals.h:59
void ec_fsm_master_state_configure_slave(ec_fsm_master_t *)
Master state: CONFIGURE SLAVE.
Definition: fsm_master.c:929
uint16_t ring_position
Ring position for emergency requests.
Definition: reg_request.h:57
ec_internal_request_state_t state
Request state.
Definition: reg_request.h:56
uint16_t offset
SII word offset.
Definition: fsm_master.h:56
uint16_t ring_position
Ring position.
Definition: slave.h:183
unsigned long jiffies_sent
Jiffies, when the datagram was sent.
Definition: datagram.h:104
ec_datagram_t * datagram
datagram used in the state machine
Definition: fsm_master.h:70
ec_sii_write_request_t * sii_request
SII write request.
Definition: fsm_master.h:88
ec_sii_t sii
Extracted SII data.
Definition: slave.h:223
void ec_fsm_slave_config_start(ec_fsm_slave_config_t *fsm, ec_slave_t *slave)
Start slave configuration state machine.
ec_fsm_soe_t fsm_soe
SoE state machine.
Definition: fsm_master.h:93
Ethernet over EtherCAT.
Definition: globals.h:148
struct semaphore config_sem
Semaphore protecting the config_busy variable and the allow_config flag.
Definition: master.h:259
CANopen over EtherCAT.
Definition: globals.h:149
void ec_master_calc_dc(ec_master_t *master)
Distributed-clocks calculations.
Definition: master.c:2190
size_t transfer_size
Size of the data to transfer.
Definition: reg_request.h:55
void ec_slave_attach_pdo_names(ec_slave_t *slave)
Attach PDO names.
Definition: slave.c:781
struct list_head sii_requests
SII write requests.
Definition: master.h:307
#define EC_SLAVE_DBG(slave, level, fmt, args...)
Convenience macro for printing slave-specific debug messages to syslog.
Definition: slave.h:106
ec_fsm_pdo_t fsm_pdo
PDO configuration state machine.
Definition: fsm_master.h:94
Finite state machine of an EtherCAT master.
Definition: fsm_master.h:68
ec_internal_request_state_t state
State of the request.
Definition: fsm_master.h:59
unsigned int slaves_responding[EC_MAX_NUM_DEVICES]
Number of responding slaves for every device.
Definition: fsm_master.h:80
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:394
void ec_fsm_master_reset(ec_fsm_master_t *fsm)
Reset state machine.
Definition: fsm_master.c:121
struct ec_slave ec_slave_t
Definition: globals.h:313
void ec_master_request_op(ec_master_t *master)
Request OP state for configured slaves.
Definition: master.c:2207
CANopen SDO request.
Definition: sdo_request.h:48
ec_slave_state_t current_state
Current application state.
Definition: slave.h:192
#define ec_master_num_devices(MASTER)
Number of Ethernet devices.
Definition: master.h:330
u64 ec_fsm_master_dc_offset64(ec_fsm_master_t *fsm, u64 system_time, u64 old_offset, unsigned long jiffies_since_read)
Configure 64 bit time offset.
Definition: fsm_master.c:1047
size_t nwords
Number of words.
Definition: fsm_master.h:57
ec_internal_request_state_t state
SDO request state.
Definition: sdo_request.h:63
uint16_t address
Register address.
Definition: reg_request.h:54
Register request.
Definition: reg_request.h:48
struct list_head eoe_handlers
Ethernet over EtherCAT handlers.
Definition: master.h:293
Operation phase.
Definition: master.h:135
unsigned int allow_scan
True, if slave scanning is allowed.
Definition: master.h:252
#define EC_SLAVE_WARN(slave, fmt, args...)
Convenience macro for printing slave-specific warnings to syslog.
Definition: slave.h:90
void ec_fsm_master_restart(ec_fsm_master_t *fsm)
Restarts the master state machine.
Definition: fsm_master.c:180
void(* state)(ec_fsm_master_t *)
master state function
Definition: fsm_master.h:73
unsigned int rescan_required
A bus rescan is required.
Definition: fsm_master.h:83
EtherCAT datagram.
Definition: datagram.h:87
ec_sii_coe_details_t coe_details
CoE detail flags.
Definition: slave.h:160
void ec_fsm_sii_write(ec_fsm_sii_t *fsm, ec_slave_t *slave, uint16_t word_offset, const uint16_t *value, ec_fsm_sii_addressing_t mode)
Initializes the SII write state machine.
Definition: fsm_sii.c:116
ec_slave_state_t slave_states[EC_MAX_NUM_DEVICES]
AL states of responding slaves for every device.
Definition: fsm_master.h:84
struct list_head emerg_reg_requests
Emergency register access requests.
Definition: master.h:308
#define EC_SYSTEM_TIME_TOLERANCE_NS
Time difference [ns] to tolerate without setting a new system time offset.
Definition: fsm_master.c:51
ec_fsm_slave_t fsm
Slave state machine.
Definition: slave.h:234
void ec_slave_set_state(ec_slave_t *slave, ec_slave_state_t new_state)
Sets the application state of a slave.
Definition: slave.c:274
uint16_t working_counter
Working counter.
Definition: datagram.h:99
int ec_sdo_request_timed_out(const ec_sdo_request_t *req)
Checks, if the timeout was exceeded.
Definition: sdo_request.c:177
void ec_fsm_master_action_idle(ec_fsm_master_t *fsm)
Master action: IDLE.
Definition: fsm_master.c:523
int ec_eoe_init(ec_eoe_t *eoe, ec_slave_t *slave)
EoE constructor.
Definition: ethernet.c:104
Acknowledge/Error bit (no actual state)
Definition: globals.h:140
int ec_fsm_coe_success(const ec_fsm_coe_t *fsm)
Returns, if the state machine terminated with success.
Definition: fsm_coe.c:262
uint8_t link_state
device link state
Definition: device.h:88
void ec_fsm_master_state_dc_write_offset(ec_fsm_master_t *)
Master state: DC WRITE OFFSET.
Definition: fsm_master.c:1138
Sent (still in the queue).
Definition: datagram.h:77
wait_queue_head_t request_queue
Wait queue for external requests from user space.
Definition: master.h:311
void ec_fsm_sii_init(ec_fsm_sii_t *fsm, ec_datagram_t *datagram)
Constructor.
Definition: fsm_sii.c:74
EtherCAT master state machine.
uint16_t station_address
Configured station address.
Definition: slave.h:184
const char * ec_device_names[2]
Device names.
Definition: module.c:458
struct list_head list
List head.
Definition: fsm_master.h:54
SII write request.
Definition: fsm_master.h:53
void ec_fsm_master_action_next_slave_state(ec_fsm_master_t *fsm)
Master action: Get state of next slave.
Definition: fsm_master.c:581
#define EC_WAIT_SDO_DICT
Seconds to wait before fetching SDO dictionary after slave entered PREOP state.
Definition: globals.h:63
void ec_fsm_slave_config_init(ec_fsm_slave_config_t *fsm, ec_datagram_t *datagram, ec_fsm_change_t *fsm_change, ec_fsm_coe_t *fsm_coe, ec_fsm_soe_t *fsm_soe, ec_fsm_pdo_t *fsm_pdo)
Constructor.
int ec_fsm_slave_scan_exec(ec_fsm_slave_scan_t *fsm)
Executes the current state of the state machine.
Global definitions and macros.
void ec_fsm_pdo_clear(ec_fsm_pdo_t *fsm)
Destructor.
Definition: fsm_pdo.c:90
void ec_fsm_master_enter_clear_addresses(ec_fsm_master_t *)
Start clearing slave addresses.
Definition: fsm_master.c:744
EtherCAT master structure.
void ec_fsm_master_init(ec_fsm_master_t *fsm, ec_master_t *master, ec_datagram_t *datagram)
Constructor.
Definition: fsm_master.c:76
#define EC_MASTER_DBG(master, level, fmt, args...)
Convenience macro for printing master-specific debug messages to syslog.
Definition: master.h:111
int ec_fsm_master_action_process_sii(ec_fsm_master_t *fsm)
Check for pending SII write requests and process one.
Definition: fsm_master.c:431
ec_slave_t * fsm_slave
Slave that is queried next for FSM exec.
Definition: master.h:282
ec_slave_t * slave
EtherCAT slave.
Definition: fsm_master.h:55
u64 ec_fsm_master_dc_offset32(ec_fsm_master_t *fsm, u64 system_time, u64 old_offset, unsigned long jiffies_since_read)
Configure 32 bit time offset.
Definition: fsm_master.c:1005
void ec_slave_sdo_dict_info(const ec_slave_t *slave, unsigned int *sdo_count, unsigned int *entry_count)
Counts the total number of SDOs and entries in the dictionary.
Definition: slave.c:608
EtherCAT slave.
Definition: slave.h:176
int ec_fsm_master_action_process_sdo(ec_fsm_master_t *fsm)
Check for pending SDO requests and process one.
Definition: fsm_master.c:469
void ec_master_attach_slave_configs(ec_master_t *master)
Attaches the slave configurations to the slaves.
Definition: master.c:1775
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:667
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:1262
void ec_fsm_master_state_scan_slave(ec_fsm_master_t *)
Master state: SCAN SLAVE.
Definition: fsm_master.c:857
Ethernet over EtherCAT (EoE)
ec_datagram_state_t state
State.
Definition: datagram.h:100
ec_slave_config_t * config
Current configuration.
Definition: slave.h:190
ec_master_phase_t phase
Master phase.
Definition: master.h:223
#define EC_WRITE_U32(DATA, VAL)
Write a 32-bit unsigned value to EtherCAT data.
Definition: ecrt.h:2221
ec_fsm_sii_t fsm_sii
SII state machine.
Definition: fsm_master.h:98
ec_slave_t * slaves
Array of slaves on the bus.
Definition: master.h:231
uint8_t enable_sdo_info
SDO information service available.
Definition: globals.h:159
Use configured addresses.
Definition: fsm_sii.h:50
ec_fsm_slave_scan_t fsm_slave_scan
slave state machine
Definition: fsm_master.h:97
uint8_t sdo_dictionary_fetched
Dictionary has been fetched.
Definition: slave.h:226
struct list_head sdo_requests
List of SDO requests.
Definition: slave_config.h:144
void ec_fsm_master_action_configure(ec_fsm_master_t *fsm)
Master action: Configure.
Definition: fsm_master.c:609
uint16_t mailbox_protocols
Supported mailbox protocols.
Definition: slave.h:147
ec_sdo_request_t * sdo_request
SDO request to process.
Definition: fsm_master.h:90
unsigned int debug_level
Master debug level.
Definition: master.h:286
#define EC_SLAVE_ERR(slave, fmt, args...)
Convenience macro for printing slave-specific errors to syslog.
Definition: slave.h:76
void ec_datagram_print_wc_error(const ec_datagram_t *datagram)
Evaluates the working counter of a single-cast datagram.
Definition: datagram.c:602
ec_slave_dc_range_t base_dc_range
DC range.
Definition: slave.h:211
void ec_fsm_slave_set_ready(ec_fsm_slave_t *fsm)
Sets the current state of the state machine to READY.
Definition: fsm_slave.c:148
int ec_fsm_change_exec(ec_fsm_change_t *fsm)
Executes the current state of the state machine.
Definition: fsm_change.c:124
uint32_t transmission_delay
DC system time transmission delay (offset from reference clock).
Definition: slave.h:215
unsigned int slave_count
Number of slaves on the bus.
Definition: master.h:232
unsigned int scan_busy
Current scan state.
Definition: master.h:251
ec_device_index_t
Master devices.
Definition: globals.h:201
void ec_fsm_master_state_dc_measure_delays(ec_fsm_master_t *)
Master state: DC MEASURE DELAYS.
Definition: fsm_master.c:804
void ec_fsm_master_state_broadcast(ec_fsm_master_t *)
Master state: BROADCAST.
Definition: fsm_master.c:254
void ec_fsm_pdo_init(ec_fsm_pdo_t *fsm, ec_fsm_coe_t *fsm_coe)
Constructor.
Definition: fsm_pdo.c:74
void ec_fsm_coe_clear(ec_fsm_coe_t *fsm)
Destructor.
Definition: fsm_coe.c:182
uint16_t alias
Configured station alias.
Definition: slave.h:134
#define EC_WRITE_U16(DATA, VAL)
Write a 16-bit unsigned value to EtherCAT data.
Definition: ecrt.h:2204
unsigned long scan_jiffies
beginning of slave scanning
Definition: fsm_master.h:77
#define EC_ABS(X)
Absolute value.
Definition: globals.h:254
Main device.
Definition: globals.h:202
#define EC_MASTER_WARN(master, fmt, args...)
Convenience macro for printing master-specific warnings to syslog.
Definition: master.h:97
unsigned int active
Master has been activated.
Definition: master.h:224
ec_master_t * master
Master owning the slave.
Definition: slave.h:178
void ec_fsm_change_clear(ec_fsm_change_t *fsm)
Destructor.
Definition: fsm_change.c:80
int ec_datagram_brd(ec_datagram_t *datagram, uint16_t mem_address, size_t data_size)
Initializes an EtherCAT BRD datagram.
Definition: datagram.c:373
int ec_datagram_fpwr(ec_datagram_t *datagram, uint16_t configured_address, uint16_t mem_address, size_t data_size)
Initializes an EtherCAT FPWR datagram.
Definition: datagram.c:298
uint8_t has_dc_system_time
The slave supports the DC system time register.
Definition: slave.h:212
wait_queue_head_t scan_queue
Queue for processes that wait for slave scanning.
Definition: master.h:255
#define EC_MASTER_ERR(master, fmt, args...)
Convenience macro for printing master-specific errors to syslog.
Definition: master.h:85
int ec_datagram_fprd(ec_datagram_t *datagram, uint16_t configured_address, uint16_t mem_address, size_t data_size)
Initializes an EtherCAT FPRD datagram.
Definition: datagram.c:273
void ec_fsm_coe_dictionary(ec_fsm_coe_t *fsm, ec_slave_t *slave)
Starts reading a slaves' SDO dictionary.
Definition: fsm_coe.c:192
ec_device_index_t device_index
Device via which the datagram shall be / was sent.
Definition: datagram.h:90
int ec_fsm_master_idle(const ec_fsm_master_t *fsm)
Definition: fsm_master.c:169
32 bit.
Definition: globals.h:176
void ec_master_clear_slaves(ec_master_t *master)
Clear all slaves.
Definition: master.c:468
void ec_fsm_change_init(ec_fsm_change_t *fsm, ec_datagram_t *datagram)
Constructor.
Definition: fsm_change.c:65
struct list_head list
list item
Definition: ethernet.h:78
void ec_fsm_coe_init(ec_fsm_coe_t *fsm)
Constructor.
Definition: fsm_coe.c:170
void ec_fsm_master_state_acknowledge(ec_fsm_master_t *)
Master state: ACKNOWLEDGE.
Definition: fsm_master.c:722
void ec_fsm_sii_clear(ec_fsm_sii_t *fsm)
Destructor.
Definition: fsm_sii.c:88
INIT state (no mailbox communication, no IO)
Definition: globals.h:130
int idle
state machine is in idle phase
Definition: fsm_master.h:76
struct semaphore scan_sem
Semaphore protecting the scan_busy variable and the allow_scan flag.
Definition: master.h:253
void ec_fsm_master_state_start(ec_fsm_master_t *)
Master state: START.
Definition: fsm_master.c:197
uint16_t effective_alias
Effective alias address.
Definition: slave.h:185
void ec_master_clear_eoe_handlers(ec_master_t *master)
Clear and free all EoE handlers.
Definition: master.c:432
ec_fsm_slave_config_t fsm_slave_config
slave state machine
Definition: fsm_master.h:96
int ec_fsm_sii_exec(ec_fsm_sii_t *fsm)
Executes the SII state machine.
Definition: fsm_sii.c:137
int ec_fsm_sii_success(ec_fsm_sii_t *fsm)
Returns, if the master startup state machine terminated with success.
Definition: fsm_sii.c:152
#define EC_READ_U16(DATA)
Read a 16-bit unsigned value from EtherCAT data.
Definition: ecrt.h:2135
void ec_master_eoe_start(ec_master_t *master)
Starts Ethernet over EtherCAT processing on demand.
Definition: master.c:1659
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:69
void ec_fsm_master_state_sdo_dictionary(ec_fsm_master_t *)
Master state: SDO DICTIONARY.
Definition: fsm_master.c:1227
uint8_t * data
Pointer to data memory.
Definition: reg_request.h:51
#define EC_STATE_STRING_SIZE
Minimum size of a buffer used with ec_state_string().
Definition: globals.h:66
#define EC_WRITE_U64(DATA, VAL)
Write a 64-bit unsigned value to EtherCAT data.
Definition: ecrt.h:2238
void ec_fsm_master_state_clear_addresses(ec_fsm_master_t *)
Master state: CLEAR ADDRESSES.
Definition: fsm_master.c:760
int ec_fsm_slave_config_exec(ec_fsm_slave_config_t *fsm)
Executes the current state of the state machine.
int ec_fsm_coe_exec(ec_fsm_coe_t *fsm, ec_datagram_t *datagram)
Executes the current state of the state machine.
Definition: fsm_coe.c:228
void ec_slave_init(ec_slave_t *slave, ec_master_t *master, ec_device_index_t dev_idx, uint16_t ring_position, uint16_t station_address)
Slave constructor.
Definition: slave.c:62
ec_direction_t dir
Direction.
Definition: reg_request.h:52
Queued for sending.
Definition: datagram.h:76
void ec_fsm_change_ack(ec_fsm_change_t *fsm, ec_slave_t *slave)
Starts the change state machine to only acknowlegde a slave's state.
Definition: fsm_change.c:107
Timed out (dequeued).
Definition: datagram.h:79
u8 has_app_time
Application time is valid.
Definition: master.h:240
wait_queue_head_t config_queue
Queue for processes that wait for slave configuration.
Definition: master.h:261
unsigned int retries
retries on datagram timeout.
Definition: fsm_master.h:71
void ec_fsm_slave_config_clear(ec_fsm_slave_config_t *fsm)
Destructor.
u64 app_time
Time of the last ecrt_master_sync() call.
Definition: master.h:238
unsigned long jiffies_preop
Time, the slave went to PREOP.
Definition: slave.h:227
void ec_fsm_soe_init(ec_fsm_soe_t *fsm)
Constructor.
Definition: fsm_soe.c:111
uint8_t base_dc_supported
Distributed clocks are supported.
Definition: slave.h:210
void ec_fsm_soe_clear(ec_fsm_soe_t *fsm)
Destructor.
Definition: fsm_soe.c:124
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:1173
uint8_t * data
Datagram payload.
Definition: datagram.h:94
#define EC_READ_U8(DATA)
Read an 8-bit unsigned value from EtherCAT data.
Definition: ecrt.h:2119
int ec_fsm_master_exec(ec_fsm_master_t *fsm)
Executes the current state of the state machine.
Definition: fsm_master.c:150
int ec_fsm_slave_config_success(const ec_fsm_slave_config_t *fsm)
void ec_fsm_slave_scan_clear(ec_fsm_slave_scan_t *fsm)
Destructor.
EtherCAT slave configuration structure.
size_t mem_size
Datagram data memory size.
Definition: datagram.h:96
ec_device_index_t device_index
Index of device the slave responds on.
Definition: slave.h:179
void ec_fsm_coe_transfer(ec_fsm_coe_t *fsm, ec_slave_t *slave, ec_sdo_request_t *request)
Starts to transfer an SDO to/from a slave.
Definition: fsm_coe.c:205
ec_slave_t * slave
current slave
Definition: fsm_master.h:87
Values written by the master.
Definition: ecrt.h:419
ec_fsm_change_t fsm_change
State change state machine.
Definition: fsm_master.h:95
Received (dequeued).
Definition: datagram.h:78
Ethernet over EtherCAT (EoE) handler.
Definition: ethernet.h:76
off_t sii_index
index to SII write request data
Definition: fsm_master.h:89
#define EC_MASTER_INFO(master, fmt, args...)
Convenience macro for printing master-specific information to syslog.
Definition: master.h:73
unsigned int error_flag
Stop processing after an error.
Definition: slave.h:193
unsigned int config_changed
The configuration changed.
Definition: master.h:225
EtherCAT master.
Definition: master.h:194
struct list_head list
List item.
Definition: reg_request.h:49
ec_slave_state_t requested_state
Requested application state.
Definition: slave.h:191
ec_device_index_t dev_idx
Current device index (for scanning etc.).
Definition: fsm_master.h:74
#define EC_READ_U64(DATA)
Read a 64-bit unsigned value from EtherCAT data.
Definition: ecrt.h:2167
ec_device_t devices[EC_MAX_NUM_DEVICES]
EtherCAT devices.
Definition: master.h:211
unsigned int config_busy
State of slave configuration.
Definition: master.h:258
const uint16_t * words
Pointer to the data words.
Definition: fsm_master.h:58
void ec_fsm_master_clear(ec_fsm_master_t *fsm)
Destructor.
Definition: fsm_master.c:103
EtherCAT FoE state machines.
unknown state
Definition: globals.h:128
void ec_fsm_master_enter_write_system_times(ec_fsm_master_t *)
Start writing DC system times.
Definition: fsm_master.c:957
void ec_master_eoe_stop(ec_master_t *master)
Stops the Ethernet over EtherCAT processing.
Definition: master.c:1696
uint8_t link_state[EC_MAX_NUM_DEVICES]
Last link state for every device.
Definition: fsm_master.h:78
ec_fsm_coe_t fsm_coe
CoE state machine.
Definition: fsm_master.h:92
void ec_fsm_master_state_dc_read_offset(ec_fsm_master_t *)
Master state: DC READ OFFSET.
Definition: fsm_master.c:1085
unsigned int force_config
Force (re-)configuration.
Definition: slave.h:194
int ec_fsm_change_success(ec_fsm_change_t *fsm)
Returns, if the state machine terminated with success.
Definition: fsm_change.c:139
unsigned int has_general
General category present.
Definition: slave.h:154
int ec_datagram_bwr(ec_datagram_t *datagram, uint16_t mem_address, size_t data_size)
Initializes an EtherCAT BWR datagram.
Definition: datagram.c:393