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 
69 
72 
73 /*****************************************************************************/
74 
78  ec_fsm_master_t *fsm,
79  ec_master_t *master,
80  ec_datagram_t *datagram
81  )
82 {
83  fsm->master = master;
84  fsm->datagram = datagram;
85 
87 
88  // init sub-state-machines
89  ec_fsm_coe_init(&fsm->fsm_coe);
90  ec_fsm_soe_init(&fsm->fsm_soe);
91  ec_fsm_pdo_init(&fsm->fsm_pdo, &fsm->fsm_coe);
94  &fsm->fsm_change, &fsm->fsm_coe, &fsm->fsm_soe, &fsm->fsm_pdo);
96  &fsm->fsm_slave_config, &fsm->fsm_pdo);
97  ec_fsm_sii_init(&fsm->fsm_sii, fsm->datagram);
98 }
99 
100 /*****************************************************************************/
101 
105  ec_fsm_master_t *fsm
106  )
107 {
108  // clear sub-state machines
109  ec_fsm_coe_clear(&fsm->fsm_coe);
110  ec_fsm_soe_clear(&fsm->fsm_soe);
111  ec_fsm_pdo_clear(&fsm->fsm_pdo);
115  ec_fsm_sii_clear(&fsm->fsm_sii);
116 }
117 
118 /*****************************************************************************/
119 
123  ec_fsm_master_t *fsm
124  )
125 {
126  ec_device_index_t dev_idx;
127 
129  fsm->idle = 0;
130  fsm->dev_idx = EC_DEVICE_MAIN;
131 
132  for (dev_idx = EC_DEVICE_MAIN;
133  dev_idx < ec_master_num_devices(fsm->master); dev_idx++) {
134  fsm->link_state[dev_idx] = 0;
135  fsm->slaves_responding[dev_idx] = 0;
136  fsm->slave_states[dev_idx] = EC_SLAVE_STATE_UNKNOWN;
137  }
138 
139  fsm->rescan_required = 0;
140 }
141 
142 /*****************************************************************************/
143 
152  ec_fsm_master_t *fsm
153  )
154 {
155  if (fsm->datagram->state == EC_DATAGRAM_SENT
156  || fsm->datagram->state == EC_DATAGRAM_QUEUED) {
157  // datagram was not sent or received yet.
158  return 0;
159  }
160 
161  fsm->state(fsm);
162  return 1;
163 }
164 
165 /*****************************************************************************/
166 
171  const ec_fsm_master_t *fsm
172  )
173 {
174  return fsm->idle;
175 }
176 
177 /*****************************************************************************/
178 
182  ec_fsm_master_t *fsm
183  )
184 {
185  fsm->dev_idx = EC_DEVICE_MAIN;
187  fsm->state(fsm); // execute immediately
188 }
189 
190 /******************************************************************************
191  * Master state machine
192  *****************************************************************************/
193 
199  ec_fsm_master_t *fsm
200  )
201 {
202  ec_master_t *master = fsm->master;
203 
204  fsm->idle = 1;
205 
206  // check for emergency requests
207  if (!list_empty(&master->emerg_reg_requests)) {
208  ec_reg_request_t *request;
209 
210  // get first request
211  request = list_entry(master->emerg_reg_requests.next,
212  ec_reg_request_t, list);
213  list_del_init(&request->list); // dequeue
214  request->state = EC_INT_REQUEST_BUSY;
215 
216  if (request->transfer_size > fsm->datagram->mem_size) {
217  EC_MASTER_ERR(master, "Emergency request data too large!\n");
218  request->state = EC_INT_REQUEST_FAILURE;
219  wake_up_all(&master->request_queue);
220  fsm->state(fsm); // continue
221  return;
222  }
223 
224  if (request->dir != EC_DIR_OUTPUT) {
225  EC_MASTER_ERR(master, "Emergency requests must be"
226  " write requests!\n");
227  request->state = EC_INT_REQUEST_FAILURE;
228  wake_up_all(&master->request_queue);
229  fsm->state(fsm); // continue
230  return;
231  }
232 
233  EC_MASTER_DBG(master, 1, "Writing emergency register request...\n");
234  ec_datagram_apwr(fsm->datagram, request->ring_position,
235  request->address, request->transfer_size);
236  memcpy(fsm->datagram->data, request->data, request->transfer_size);
238  request->state = EC_INT_REQUEST_SUCCESS;
239  wake_up_all(&master->request_queue);
240  return;
241  }
242 
243  ec_datagram_brd(fsm->datagram, 0x0130, 2);
245  fsm->datagram->device_index = fsm->dev_idx;
246  fsm->retries = EC_FSM_RETRIES;
248 }
249 
250 /*****************************************************************************/
251 
257  ec_fsm_master_t *fsm
258  )
259 {
260  ec_datagram_t *datagram = fsm->datagram;
261  unsigned int i, size;
262  ec_slave_t *slave;
263  ec_master_t *master = fsm->master;
264 
265  if (datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--) {
266  return;
267  }
268 
269  // bus topology change?
270  if (datagram->working_counter != fsm->slaves_responding[fsm->dev_idx]) {
271  fsm->rescan_required = 1;
272  fsm->slaves_responding[fsm->dev_idx] = datagram->working_counter;
273  EC_MASTER_INFO(master, "%u slave(s) responding on %s device.\n",
274  fsm->slaves_responding[fsm->dev_idx],
275  ec_device_names[fsm->dev_idx != 0]);
276  }
277 
278  if (fsm->link_state[fsm->dev_idx] &&
279  !master->devices[fsm->dev_idx].link_state) {
280  ec_device_index_t dev_idx;
281 
282  EC_MASTER_DBG(master, 1, "Master state machine detected "
283  "link down on %s device. Clearing slave list.\n",
284  ec_device_names[fsm->dev_idx != 0]);
285 
286 #ifdef EC_EOE
287  ec_master_eoe_stop(master);
289 #endif
290  ec_master_clear_slaves(master);
291 
292  for (dev_idx = EC_DEVICE_MAIN;
293  dev_idx < ec_master_num_devices(master); dev_idx++) {
294  fsm->slave_states[dev_idx] = 0x00;
295  fsm->slaves_responding[dev_idx] = 0; /* Reset to trigger rescan on
296  next link up. */
297  }
298  }
299  fsm->link_state[fsm->dev_idx] = master->devices[fsm->dev_idx].link_state;
300 
301  if (datagram->state == EC_DATAGRAM_RECEIVED &&
302  fsm->slaves_responding[fsm->dev_idx]) {
303  uint8_t states = EC_READ_U8(datagram->data);
304  if (states != fsm->slave_states[fsm->dev_idx]) {
305  // slave states changed
306  char state_str[EC_STATE_STRING_SIZE];
307  fsm->slave_states[fsm->dev_idx] = states;
308  ec_state_string(states, state_str, 1);
309  EC_MASTER_INFO(master, "Slave states on %s device: %s.\n",
310  ec_device_names[fsm->dev_idx != 0], state_str);
311  }
312  } else {
313  fsm->slave_states[fsm->dev_idx] = 0x00;
314  }
315 
316  fsm->dev_idx++;
317  if (fsm->dev_idx < ec_master_num_devices(master)) {
318  // check number of responding slaves on next device
320  fsm->state(fsm); // execute immediately
321  return;
322  }
323 
324  if (fsm->rescan_required) {
325  down(&master->scan_sem);
326  if (!master->allow_scan) {
327  up(&master->scan_sem);
328  } else {
329  unsigned int count = 0, next_dev_slave, ring_position;
330  ec_device_index_t dev_idx;
331 
332  master->scan_busy = 1;
333  up(&master->scan_sem);
334 
335  // clear all slaves and scan the bus
336  fsm->rescan_required = 0;
337  fsm->idle = 0;
338  fsm->scan_jiffies = jiffies;
339 
340 #ifdef EC_EOE
341  ec_master_eoe_stop(master);
343 #endif
344  ec_master_clear_slaves(master);
345 
346  for (dev_idx = EC_DEVICE_MAIN;
347  dev_idx < ec_master_num_devices(master); dev_idx++) {
348  count += fsm->slaves_responding[dev_idx];
349  }
350 
351  if (!count) {
352  // no slaves present -> finish state machine.
353  master->scan_busy = 0;
354  wake_up_interruptible(&master->scan_queue);
356  return;
357  }
358 
359  size = sizeof(ec_slave_t) * count;
360  if (!(master->slaves =
361  (ec_slave_t *) kmalloc(size, GFP_KERNEL))) {
362  EC_MASTER_ERR(master, "Failed to allocate %u bytes"
363  " of slave memory!\n", size);
364  master->scan_busy = 0;
365  wake_up_interruptible(&master->scan_queue);
367  return;
368  }
369 
370  // init slaves
371  dev_idx = EC_DEVICE_MAIN;
372  next_dev_slave = fsm->slaves_responding[dev_idx];
373  ring_position = 0;
374  for (i = 0; i < count; i++, ring_position++) {
375  slave = master->slaves + i;
376  while (i >= next_dev_slave) {
377  dev_idx++;
378  next_dev_slave += fsm->slaves_responding[dev_idx];
379  ring_position = 0;
380  }
381 
382  ec_slave_init(slave, master, dev_idx, ring_position, i + 1);
383 
384  // do not force reconfiguration in operation phase to avoid
385  // unnecesssary process data interruptions
386  if (master->phase != EC_OPERATION) {
387  slave->force_config = 1;
388  }
389  }
390  master->slave_count = count;
391  master->fsm_slave = master->slaves;
392 
393  /* start with first device with slaves responding; at least one
394  * has responding slaves, otherwise count would be zero. */
395  fsm->dev_idx = EC_DEVICE_MAIN;
396  while (!fsm->slaves_responding[fsm->dev_idx]) {
397  fsm->dev_idx++;
398  }
399 
401  return;
402  }
403  }
404 
405  if (master->slave_count) {
406 
407  // application applied configurations
408  if (master->config_changed) {
409  master->config_changed = 0;
410 
411  EC_MASTER_DBG(master, 1, "Configuration changed.\n");
412 
413  fsm->slave = master->slaves; // begin with first slave
415 
416  } else {
417  // fetch state from first slave
418  fsm->slave = master->slaves;
420  0x0130, 2);
421  ec_datagram_zero(datagram);
422  fsm->datagram->device_index = fsm->slave->device_index;
423  fsm->retries = EC_FSM_RETRIES;
425  }
426  } else {
428  }
429 }
430 
431 /*****************************************************************************/
432 
438  ec_fsm_master_t *fsm
439  )
440 {
441  ec_master_t *master = fsm->master;
442  ec_sii_write_request_t *request;
443  ec_slave_config_t *config;
444  ec_flag_t *flag;
445  int assign_to_pdi;
446 
447  // search the first request to be processed
448  while (1) {
449  if (list_empty(&master->sii_requests))
450  break;
451 
452  // get first request
453  request = list_entry(master->sii_requests.next,
454  ec_sii_write_request_t, list);
455  list_del_init(&request->list); // dequeue
456  request->state = EC_INT_REQUEST_BUSY;
457 
458  assign_to_pdi = 0;
459  config = request->slave->config;
460  if (config) {
461  flag = ec_slave_config_find_flag(config, "AssignToPdi");
462  if (flag) {
463  assign_to_pdi = flag->value;
464  }
465  }
466 
467  if (assign_to_pdi) {
468  fsm->sii_request = request;
469  EC_SLAVE_DBG(request->slave, 1,
470  "Assigning SII back to EtherCAT.\n");
472  0x0500, 0x01);
473  EC_WRITE_U8(fsm->datagram->data, 0x00); // EtherCAT
474  fsm->retries = EC_FSM_RETRIES;
476  return 1;
477  }
478 
479  // found pending SII write operation. execute it!
480  EC_SLAVE_DBG(request->slave, 1, "Writing SII data...\n");
481  fsm->sii_request = request;
482  fsm->sii_index = 0;
483  ec_fsm_sii_write(&fsm->fsm_sii, request->slave, request->offset,
486  fsm->state(fsm); // execute immediately
487  return 1;
488  }
489 
490  return 0;
491 }
492 
493 /*****************************************************************************/
494 
500  ec_fsm_master_t *fsm
501  )
502 {
503  ec_master_t *master = fsm->master;
504  ec_slave_t *slave;
505  ec_sdo_request_t *req;
506 
507  // search for internal requests to be processed
508  for (slave = master->slaves;
509  slave < master->slaves + master->slave_count;
510  slave++) {
511 
512  if (!slave->config) {
513  continue;
514  }
515 
516  list_for_each_entry(req, &slave->config->sdo_requests, list) {
517  if (req->state == EC_INT_REQUEST_QUEUED) {
518 
519  if (ec_sdo_request_timed_out(req)) {
520  req->state = EC_INT_REQUEST_FAILURE;
521  EC_SLAVE_DBG(slave, 1, "Internal SDO request"
522  " timed out.\n");
523  continue;
524  }
525 
526  if (slave->current_state == EC_SLAVE_STATE_INIT) {
527  req->state = EC_INT_REQUEST_FAILURE;
528  continue;
529  }
530 
531  req->state = EC_INT_REQUEST_BUSY;
532  EC_SLAVE_DBG(slave, 1, "Processing internal"
533  " SDO request...\n");
534  fsm->idle = 0;
535  fsm->sdo_request = req;
536  fsm->slave = slave;
538  ec_fsm_coe_transfer(&fsm->fsm_coe, slave, req);
539  ec_fsm_coe_exec(&fsm->fsm_coe, fsm->datagram);
540  return 1;
541  }
542  }
543  }
544  return 0;
545 }
546 
547 /*****************************************************************************/
548 
554  ec_fsm_master_t *fsm
555  )
556 {
557  ec_master_t *master = fsm->master;
558  ec_slave_t *slave;
559 
560  // Check for pending internal SDO requests
562  return;
563  }
564 
565  // enable processing of requests
566  for (slave = master->slaves;
567  slave < master->slaves + master->slave_count;
568  slave++) {
569  ec_fsm_slave_set_ready(&slave->fsm);
570  }
571 
572  // check, if slaves have an SDO dictionary to read out.
573  for (slave = master->slaves;
574  slave < master->slaves + master->slave_count;
575  slave++) {
576  if (!(slave->sii.mailbox_protocols & EC_MBOX_COE)
577  || (slave->sii.has_general
578  && !slave->sii.coe_details.enable_sdo_info)
579  || slave->sdo_dictionary_fetched
582  || jiffies - slave->jiffies_preop < EC_WAIT_SDO_DICT * HZ
583  ) continue;
584 
585  EC_SLAVE_DBG(slave, 1, "Fetching SDO dictionary.\n");
586 
587  slave->sdo_dictionary_fetched = 1;
588 
589  // start fetching SDO dictionary
590  fsm->idle = 0;
591  fsm->slave = slave;
593  ec_fsm_coe_dictionary(&fsm->fsm_coe, slave);
594  ec_fsm_coe_exec(&fsm->fsm_coe, fsm->datagram); // execute immediately
595  fsm->datagram->device_index = fsm->slave->device_index;
596  return;
597  }
598 
599  // check for pending SII write operations.
601  return; // SII write request found
602  }
603 
605 }
606 
607 /*****************************************************************************/
608 
612  ec_fsm_master_t *fsm
613  )
614 {
615  ec_master_t *master = fsm->master;
616 
617  // is there another slave to query?
618  fsm->slave++;
619  if (fsm->slave < master->slaves + master->slave_count) {
620  // fetch state from next slave
621  fsm->idle = 1;
623  fsm->slave->station_address, 0x0130, 2);
625  fsm->datagram->device_index = fsm->slave->device_index;
626  fsm->retries = EC_FSM_RETRIES;
628  return;
629  }
630 
631  // all slaves processed
633 }
634 
635 /*****************************************************************************/
636 
640  ec_fsm_master_t *fsm
641  )
642 {
643  ec_master_t *master = fsm->master;
644  ec_slave_t *slave = fsm->slave;
645 
646  if (master->config_changed) {
647  master->config_changed = 0;
648 
649  // abort iterating through slaves,
650  // first compensate DC system time offsets,
651  // then begin configuring at slave 0
652  EC_MASTER_DBG(master, 1, "Configuration changed"
653  " (aborting state check).\n");
654 
655  fsm->slave = master->slaves; // begin with first slave
657  return;
658  }
659 
660  // Does the slave have to be configured?
661  if ((slave->current_state != slave->requested_state
662  || slave->force_config) && !slave->error_flag) {
663 
664  // Start slave configuration
665  down(&master->config_sem);
666  master->config_busy = 1;
667  up(&master->config_sem);
668 
669  if (master->debug_level) {
670  char old_state[EC_STATE_STRING_SIZE],
671  new_state[EC_STATE_STRING_SIZE];
672  ec_state_string(slave->current_state, old_state, 0);
673  ec_state_string(slave->requested_state, new_state, 0);
674  EC_SLAVE_DBG(slave, 1, "Changing state from %s to %s%s.\n",
675  old_state, new_state,
676  slave->force_config ? " (forced)" : "");
677  }
678 
679  fsm->idle = 0;
682  fsm->state(fsm); // execute immediately
683  fsm->datagram->device_index = fsm->slave->device_index;
684  return;
685  }
686 
687  // process next slave
689 }
690 
691 /*****************************************************************************/
692 
698  ec_fsm_master_t *fsm
699  )
700 {
701  ec_slave_t *slave = fsm->slave;
702  ec_datagram_t *datagram = fsm->datagram;
703 
704  if (datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--) {
705  return;
706  }
707 
708  if (datagram->state != EC_DATAGRAM_RECEIVED) {
709  EC_SLAVE_ERR(slave, "Failed to receive AL state datagram: ");
710  ec_datagram_print_state(datagram);
712  return;
713  }
714 
715  // did the slave not respond to its station address?
716  if (datagram->working_counter != 1) {
717  if (!slave->error_flag) {
718  slave->error_flag = 1;
719  EC_SLAVE_DBG(slave, 1, "Slave did not respond to state query.\n");
720  }
721  fsm->rescan_required = 1;
723  return;
724  }
725 
726  // A single slave responded
727  ec_slave_set_state(slave, EC_READ_U8(datagram->data));
728 
729  if (!slave->error_flag) {
730  // Check, if new slave state has to be acknowledged
731  if (slave->current_state & EC_SLAVE_STATE_ACK_ERR) {
732  fsm->idle = 0;
734  ec_fsm_change_ack(&fsm->fsm_change, slave);
735  fsm->state(fsm); // execute immediately
736  return;
737  }
738 
739  // No acknowlegde necessary; check for configuration
741  return;
742  }
743 
744  // slave has error flag set; process next one
746 }
747 
748 /*****************************************************************************/
749 
753  ec_fsm_master_t *fsm
754  )
755 {
756  ec_slave_t *slave = fsm->slave;
757 
758  if (ec_fsm_change_exec(&fsm->fsm_change)) {
759  return;
760  }
761 
762  if (!ec_fsm_change_success(&fsm->fsm_change)) {
763  fsm->slave->error_flag = 1;
764  EC_SLAVE_ERR(slave, "Failed to acknowledge state change.\n");
765  }
766 
768 }
769 
770 /*****************************************************************************/
771 
775  ec_fsm_master_t *fsm
776  )
777 {
778  // broadcast clear all station addresses
779  ec_datagram_bwr(fsm->datagram, 0x0010, 2);
780  EC_WRITE_U16(fsm->datagram->data, 0x0000);
781  fsm->datagram->device_index = fsm->dev_idx;
782  fsm->retries = EC_FSM_RETRIES;
784 }
785 
786 /*****************************************************************************/
787 
791  ec_fsm_master_t *fsm
792  )
793 {
794  ec_master_t *master = fsm->master;
795  ec_datagram_t *datagram = fsm->datagram;
796 
797  if (datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--) {
798  return;
799  }
800 
801  if (datagram->state != EC_DATAGRAM_RECEIVED) {
802  EC_MASTER_ERR(master, "Failed to receive address"
803  " clearing datagram on %s link: ",
804  ec_device_names[fsm->dev_idx != 0]);
805  ec_datagram_print_state(datagram);
806  master->scan_busy = 0;
807  wake_up_interruptible(&master->scan_queue);
809  return;
810  }
811 
812  if (datagram->working_counter != fsm->slaves_responding[fsm->dev_idx]) {
813  EC_MASTER_WARN(master, "Failed to clear station addresses on %s link:"
814  " Cleared %u of %u",
815  ec_device_names[fsm->dev_idx != 0], datagram->working_counter,
816  fsm->slaves_responding[fsm->dev_idx]);
817  }
818 
819  EC_MASTER_DBG(master, 1, "Sending broadcast-write"
820  " to measure transmission delays on %s link.\n",
821  ec_device_names[fsm->dev_idx != 0]);
822 
823  ec_datagram_bwr(datagram, 0x0900, 1);
824  ec_datagram_zero(datagram);
825  fsm->datagram->device_index = fsm->dev_idx;
826  fsm->retries = EC_FSM_RETRIES;
828 }
829 
830 /*****************************************************************************/
831 
835  ec_fsm_master_t *fsm
836  )
837 {
838  ec_master_t *master = fsm->master;
839  ec_datagram_t *datagram = fsm->datagram;
840 
841  if (datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--) {
842  return;
843  }
844 
845  if (datagram->state != EC_DATAGRAM_RECEIVED) {
846  EC_MASTER_ERR(master, "Failed to receive delay measuring datagram"
847  " on %s link: ", ec_device_names[fsm->dev_idx != 0]);
848  ec_datagram_print_state(datagram);
849  master->scan_busy = 0;
850  wake_up_interruptible(&master->scan_queue);
852  return;
853  }
854 
855  EC_MASTER_DBG(master, 1, "%u slaves responded to delay measuring"
856  " on %s link.\n",
857  datagram->working_counter, ec_device_names[fsm->dev_idx != 0]);
858 
859  do {
860  fsm->dev_idx++;
861  } while (fsm->dev_idx < ec_master_num_devices(master) &&
862  !fsm->slaves_responding[fsm->dev_idx]);
863  if (fsm->dev_idx < ec_master_num_devices(master)) {
865  return;
866  }
867 
868  EC_MASTER_INFO(master, "Scanning bus.\n");
869 
870  // begin scanning of slaves
871  fsm->slave = master->slaves;
872  EC_MASTER_DBG(master, 1, "Scanning slave %u on %s link.\n",
873  fsm->slave->ring_position,
874  ec_device_names[fsm->slave->device_index != 0]);
877  ec_fsm_slave_scan_exec(&fsm->fsm_slave_scan); // execute immediately
878  fsm->datagram->device_index = fsm->slave->device_index;
879 }
880 
881 /*****************************************************************************/
882 
888  ec_fsm_master_t *fsm
889  )
890 {
891  ec_master_t *master = fsm->master;
892 #ifdef EC_EOE
893  ec_slave_t *slave = fsm->slave;
894 #endif
895 
897  return;
898  }
899 
900 #ifdef EC_EOE
901  if (slave->sii.mailbox_protocols & EC_MBOX_EOE) {
902  // create EoE handler for this slave
903  ec_eoe_t *eoe;
904  if (!(eoe = kmalloc(sizeof(ec_eoe_t), GFP_KERNEL))) {
905  EC_SLAVE_ERR(slave, "Failed to allocate EoE handler memory!\n");
906  } else if (ec_eoe_init(eoe, slave)) {
907  EC_SLAVE_ERR(slave, "Failed to init EoE handler!\n");
908  kfree(eoe);
909  } else {
910  list_add_tail(&eoe->list, &master->eoe_handlers);
911  }
912  }
913 #endif
914 
915  // another slave to fetch?
916  fsm->slave++;
917  if (fsm->slave < master->slaves + master->slave_count) {
918  EC_MASTER_DBG(master, 1, "Scanning slave %u on %s link.\n",
919  fsm->slave->ring_position,
920  ec_device_names[fsm->slave->device_index != 0]);
922  ec_fsm_slave_scan_exec(&fsm->fsm_slave_scan); // execute immediately
923  fsm->datagram->device_index = fsm->slave->device_index;
924  return;
925  }
926 
927  EC_MASTER_INFO(master, "Bus scanning completed in %lu ms.\n",
928  (jiffies - fsm->scan_jiffies) * 1000 / HZ);
929 
930  master->scan_busy = 0;
931  wake_up_interruptible(&master->scan_queue);
932 
933  ec_master_calc_dc(master);
934 
935  // Attach slave configurations
937 
938 #ifdef EC_EOE
939  // check if EoE processing has to be started
940  ec_master_eoe_start(master);
941 #endif
942 
943  if (master->slave_count) {
944  master->config_changed = 0;
945 
946  fsm->slave = master->slaves; // begin with first slave
948  } else {
950  }
951 }
952 
953 /*****************************************************************************/
954 
960  ec_fsm_master_t *fsm
961  )
962 {
963  ec_master_t *master = fsm->master;
964 
966  return;
967  }
968 
969  fsm->slave->force_config = 0;
970 
971  // configuration finished
972  master->config_busy = 0;
973  wake_up_interruptible(&master->config_queue);
974 
976  // TODO: mark slave_config as failed.
977  }
978 
979  fsm->idle = 1;
981 }
982 
983 /*****************************************************************************/
984 
988  ec_fsm_master_t *fsm
989  )
990 {
991  ec_master_t *master = fsm->master;
992 
993  if (master->dc_ref_time) {
994 
995  while (fsm->slave < master->slaves + master->slave_count) {
996  if (!fsm->slave->base_dc_supported
997  || !fsm->slave->has_dc_system_time) {
998  fsm->slave++;
999  continue;
1000  }
1001 
1002  EC_SLAVE_DBG(fsm->slave, 1, "Checking system time offset.\n");
1003 
1004  // read DC system time (0x0910, 64 bit)
1005  // gap (64 bit)
1006  // and time offset (0x0920, 64 bit)
1008  0x0910, 24);
1009  fsm->datagram->device_index = fsm->slave->device_index;
1010  fsm->retries = EC_FSM_RETRIES;
1012  return;
1013  }
1014 
1015  } else {
1016  if (master->active) {
1017  EC_MASTER_WARN(master, "No application time received up to now,"
1018  " but master already active.\n");
1019  } else {
1020  EC_MASTER_DBG(master, 1, "No app_time received up to now.\n");
1021  }
1022  }
1023 
1024  // scanning and setting system times complete
1025  ec_master_request_op(master);
1026  ec_fsm_master_restart(fsm);
1027 }
1028 
1029 /*****************************************************************************/
1030 
1036  ec_fsm_master_t *fsm,
1037  u64 system_time,
1038  u64 old_offset,
1039  unsigned long jiffies_since_read
1040  )
1041 {
1042  ec_slave_t *slave = fsm->slave;
1043  u32 correction, system_time32, old_offset32, new_offset;
1044  s32 time_diff;
1045 
1046  system_time32 = (u32) system_time;
1047  old_offset32 = (u32) old_offset;
1048 
1049  // correct read system time by elapsed time since read operation
1050  correction = jiffies_since_read * 1000 / HZ * 1000000;
1051  system_time32 += correction;
1052  time_diff = (u32) slave->master->app_time - system_time32;
1053 
1054  EC_SLAVE_DBG(slave, 1, "DC 32 bit system time offset calculation:"
1055  " system_time=%u (corrected with %u),"
1056  " app_time=%llu, diff=%i\n",
1057  system_time32, correction,
1058  slave->master->app_time, time_diff);
1059 
1060  if (EC_ABS(time_diff) > EC_SYSTEM_TIME_TOLERANCE_NS) {
1061  new_offset = time_diff + old_offset32;
1062  EC_SLAVE_DBG(slave, 1, "Setting time offset to %u (was %u)\n",
1063  new_offset, old_offset32);
1064  return (u64) new_offset;
1065  } else {
1066  EC_SLAVE_DBG(slave, 1, "Not touching time offset.\n");
1067  return old_offset;
1068  }
1069 }
1070 
1071 /*****************************************************************************/
1072 
1078  ec_fsm_master_t *fsm,
1079  u64 system_time,
1080  u64 old_offset,
1081  unsigned long jiffies_since_read
1082  )
1083 {
1084  ec_slave_t *slave = fsm->slave;
1085  u64 new_offset, correction;
1086  s64 time_diff;
1087 
1088  // correct read system time by elapsed time since read operation
1089  correction = (u64) (jiffies_since_read * 1000 / HZ) * 1000000;
1090  system_time += correction;
1091  time_diff = fsm->slave->master->app_time - system_time;
1092 
1093  EC_SLAVE_DBG(slave, 1, "DC 64 bit system time offset calculation:"
1094  " system_time=%llu (corrected with %llu),"
1095  " app_time=%llu, diff=%lli\n",
1096  system_time, correction,
1097  slave->master->app_time, time_diff);
1098 
1099  if (EC_ABS(time_diff) > EC_SYSTEM_TIME_TOLERANCE_NS) {
1100  new_offset = time_diff + old_offset;
1101  EC_SLAVE_DBG(slave, 1, "Setting time offset to %llu (was %llu)\n",
1102  new_offset, old_offset);
1103  } else {
1104  new_offset = old_offset;
1105  EC_SLAVE_DBG(slave, 1, "Not touching time offset.\n");
1106  }
1107 
1108  return new_offset;
1109 }
1110 
1111 /*****************************************************************************/
1112 
1116  ec_fsm_master_t *fsm
1117  )
1118 {
1119  ec_datagram_t *datagram = fsm->datagram;
1120  ec_slave_t *slave = fsm->slave;
1121  u64 system_time, old_offset, new_offset;
1122  unsigned long jiffies_since_read;
1123 
1124  if (datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--)
1125  return;
1126 
1127  if (datagram->state != EC_DATAGRAM_RECEIVED) {
1128  EC_SLAVE_ERR(slave, "Failed to receive DC times datagram: ");
1129  ec_datagram_print_state(datagram);
1130  fsm->slave++;
1132  return;
1133  }
1134 
1135  if (datagram->working_counter != 1) {
1136  EC_SLAVE_WARN(slave, "Failed to get DC times: ");
1137  ec_datagram_print_wc_error(datagram);
1138  fsm->slave++;
1140  return;
1141  }
1142 
1143  system_time = EC_READ_U64(datagram->data); // 0x0910
1144  old_offset = EC_READ_U64(datagram->data + 16); // 0x0920
1145  jiffies_since_read = jiffies - datagram->jiffies_sent;
1146 
1147  if (slave->base_dc_range == EC_DC_32) {
1148  new_offset = ec_fsm_master_dc_offset32(fsm,
1149  system_time, old_offset, jiffies_since_read);
1150  } else {
1151  new_offset = ec_fsm_master_dc_offset64(fsm,
1152  system_time, old_offset, jiffies_since_read);
1153  }
1154 
1155  // set DC system time offset and transmission delay
1156  ec_datagram_fpwr(datagram, slave->station_address, 0x0920, 12);
1157  EC_WRITE_U64(datagram->data, new_offset);
1158  EC_WRITE_U32(datagram->data + 8, slave->transmission_delay);
1159  fsm->datagram->device_index = slave->device_index;
1160  fsm->retries = EC_FSM_RETRIES;
1162 }
1163 
1164 /*****************************************************************************/
1165 
1169  ec_fsm_master_t *fsm
1170  )
1171 {
1172  ec_datagram_t *datagram = fsm->datagram;
1173  ec_slave_t *slave = fsm->slave;
1174 
1175  if (datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--)
1176  return;
1177 
1178  if (datagram->state != EC_DATAGRAM_RECEIVED) {
1179  EC_SLAVE_ERR(slave,
1180  "Failed to receive DC system time offset datagram: ");
1181  ec_datagram_print_state(datagram);
1182  fsm->slave++;
1184  return;
1185  }
1186 
1187  if (datagram->working_counter != 1) {
1188  EC_SLAVE_ERR(slave, "Failed to set DC system time offset: ");
1189  ec_datagram_print_wc_error(datagram);
1190  fsm->slave++;
1192  return;
1193  }
1194 
1195  fsm->slave++;
1197 }
1198 
1199 /*****************************************************************************/
1200 
1204  ec_fsm_master_t *fsm
1205  )
1206 {
1207  ec_datagram_t *datagram = fsm->datagram;
1208  ec_sii_write_request_t *request = fsm->sii_request;
1209  ec_slave_t *slave = request->slave;
1210 
1211  if (datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--)
1212  return;
1213 
1214  if (datagram->state != EC_DATAGRAM_RECEIVED) {
1215  EC_SLAVE_ERR(slave, "Failed to receive SII assignment datagram: ");
1216  ec_datagram_print_state(datagram);
1217  goto cont;
1218  }
1219 
1220  if (datagram->working_counter != 1) {
1221  EC_SLAVE_ERR(slave, "Failed to assign SII back to EtherCAT: ");
1222  ec_datagram_print_wc_error(datagram);
1223  goto cont;
1224  }
1225 
1226 cont:
1227  // found pending SII write operation. execute it!
1228  EC_SLAVE_DBG(slave, 1, "Writing SII data (after assignment)...\n");
1229  fsm->sii_index = 0;
1230  ec_fsm_sii_write(&fsm->fsm_sii, slave, request->offset,
1233  fsm->state(fsm); // execute immediately
1234 }
1235 
1236 /*****************************************************************************/
1237 
1241  ec_fsm_master_t *fsm
1242  )
1243 {
1244  ec_master_t *master = fsm->master;
1245  ec_sii_write_request_t *request = fsm->sii_request;
1246  ec_slave_t *slave = request->slave;
1247 
1248  if (ec_fsm_sii_exec(&fsm->fsm_sii)) return;
1249 
1250  if (!ec_fsm_sii_success(&fsm->fsm_sii)) {
1251  EC_SLAVE_ERR(slave, "Failed to write SII data.\n");
1252  request->state = EC_INT_REQUEST_FAILURE;
1253  wake_up_all(&master->request_queue);
1254  ec_fsm_master_restart(fsm);
1255  return;
1256  }
1257 
1258  fsm->sii_index++;
1259  if (fsm->sii_index < request->nwords) {
1260  ec_fsm_sii_write(&fsm->fsm_sii, slave,
1261  request->offset + fsm->sii_index,
1262  request->words + fsm->sii_index,
1264  ec_fsm_sii_exec(&fsm->fsm_sii); // execute immediately
1265  return;
1266  }
1267 
1268  // finished writing SII
1269  EC_SLAVE_DBG(slave, 1, "Finished writing %zu words of SII data.\n",
1270  request->nwords);
1271 
1272  if (request->offset <= 4 && request->offset + request->nwords > 4) {
1273  // alias was written
1274  slave->sii.alias = EC_READ_U16(request->words + 4);
1275  // TODO: read alias from register 0x0012
1276  slave->effective_alias = slave->sii.alias;
1277  }
1278  // TODO: Evaluate other SII contents!
1279 
1280  request->state = EC_INT_REQUEST_SUCCESS;
1281  wake_up_all(&master->request_queue);
1282 
1283  // check for another SII write request
1285  return; // processing another request
1286 
1287  ec_fsm_master_restart(fsm);
1288 }
1289 
1290 /*****************************************************************************/
1291 
1295  ec_fsm_master_t *fsm
1296  )
1297 {
1298  ec_slave_t *slave = fsm->slave;
1299  ec_master_t *master = fsm->master;
1300 
1301  if (ec_fsm_coe_exec(&fsm->fsm_coe, fsm->datagram)) {
1302  return;
1303  }
1304 
1305  if (!ec_fsm_coe_success(&fsm->fsm_coe)) {
1306  ec_fsm_master_restart(fsm);
1307  return;
1308  }
1309 
1310  // SDO dictionary fetching finished
1311 
1312  if (master->debug_level) {
1313  unsigned int sdo_count, entry_count;
1314  ec_slave_sdo_dict_info(slave, &sdo_count, &entry_count);
1315  EC_SLAVE_DBG(slave, 1, "Fetched %u SDOs and %u entries.\n",
1316  sdo_count, entry_count);
1317  }
1318 
1319  // attach pdo names from dictionary
1321 
1322  ec_fsm_master_restart(fsm);
1323 }
1324 
1325 /*****************************************************************************/
1326 
1330  ec_fsm_master_t *fsm
1331  )
1332 {
1333  ec_sdo_request_t *request = fsm->sdo_request;
1334 
1335  if (!request) {
1336  // configuration was cleared in the meantime
1337  ec_fsm_master_restart(fsm);
1338  return;
1339  }
1340 
1341  if (ec_fsm_coe_exec(&fsm->fsm_coe, fsm->datagram)) {
1342  return;
1343  }
1344 
1345  if (!ec_fsm_coe_success(&fsm->fsm_coe)) {
1346  EC_SLAVE_DBG(fsm->slave, 1,
1347  "Failed to process internal SDO request.\n");
1348  request->state = EC_INT_REQUEST_FAILURE;
1349  wake_up_all(&fsm->master->request_queue);
1350  ec_fsm_master_restart(fsm);
1351  return;
1352  }
1353 
1354  // SDO request finished
1355  request->state = EC_INT_REQUEST_SUCCESS;
1356  wake_up_all(&fsm->master->request_queue);
1357 
1358  EC_SLAVE_DBG(fsm->slave, 1, "Finished internal SDO request.\n");
1359 
1360  // check for another SDO request
1362  return; // processing another request
1363  }
1364 
1365  ec_fsm_master_restart(fsm);
1366 }
1367 
1368 /*****************************************************************************/
#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:959
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:136
struct semaphore config_sem
Semaphore protecting the config_busy variable and the allow_config flag.
Definition: master.h:258
CANopen over EtherCAT.
Definition: globals.h:137
void ec_master_calc_dc(ec_master_t *master)
Distributed-clocks calculations.
Definition: master.c:2223
size_t transfer_size
Size of the data to transfer.
Definition: reg_request.h:55
void ec_slave_attach_pdo_names(ec_slave_t *slave)
Attach PDO names.
Definition: slave.c:781
struct list_head sii_requests
SII write requests.
Definition: master.h:307
#define EC_SLAVE_DBG(slave, level, fmt, args...)
Convenience macro for printing slave-specific debug messages to syslog.
Definition: slave.h:106
ec_fsm_pdo_t fsm_pdo
PDO configuration state machine.
Definition: fsm_master.h: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:405
void ec_fsm_master_reset(ec_fsm_master_t *fsm)
Reset state machine.
Definition: fsm_master.c:122
struct ec_slave ec_slave_t
Definition: globals.h:301
void ec_master_request_op(ec_master_t *master)
Request OP state for configured slaves.
Definition: master.c:2240
CANopen SDO request.
Definition: sdo_request.h: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:1077
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:251
#define EC_SLAVE_WARN(slave, fmt, args...)
Convenience macro for printing slave-specific warnings to syslog.
Definition: slave.h:90
void ec_fsm_master_restart(ec_fsm_master_t *fsm)
Restarts the master state machine.
Definition: fsm_master.c:181
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
#define EC_WRITE_U8(DATA, VAL)
Write an 8-bit unsigned value to EtherCAT data.
Definition: ecrt.h:2266
u64 dc_ref_time
Common reference timestamp for DC start times.
Definition: master.h:239
ec_slave_state_t slave_states[EC_MAX_NUM_DEVICES]
AL states of responding slaves for every device.
Definition: fsm_master.h: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:553
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:128
int ec_fsm_coe_success(const ec_fsm_coe_t *fsm)
Returns, if the state machine terminated with success.
Definition: fsm_coe.c:262
uint8_t link_state
device link state
Definition: device.h:88
void ec_fsm_master_state_dc_write_offset(ec_fsm_master_t *)
Master state: DC WRITE OFFSET.
Definition: fsm_master.c:1168
Sent (still in the queue).
Definition: datagram.h:77
wait_queue_head_t request_queue
Wait queue for external requests from user space.
Definition: master.h:311
void ec_fsm_sii_init(ec_fsm_sii_t *fsm, ec_datagram_t *datagram)
Constructor.
Definition: fsm_sii.c:74
EtherCAT master state machine.
uint16_t station_address
Configured station address.
Definition: slave.h:184
const char * ec_device_names[2]
Device names.
Definition: module.c:469
struct list_head list
List head.
Definition: fsm_master.h: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:611
#define EC_WAIT_SDO_DICT
Seconds to wait before fetching SDO dictionary after slave entered PREOP state.
Definition: globals.h:51
void ec_fsm_slave_config_init(ec_fsm_slave_config_t *fsm, ec_datagram_t *datagram, ec_fsm_change_t *fsm_change, ec_fsm_coe_t *fsm_coe, ec_fsm_soe_t *fsm_soe, ec_fsm_pdo_t *fsm_pdo)
Constructor.
int ec_fsm_slave_scan_exec(ec_fsm_slave_scan_t *fsm)
Executes the current state of the state machine.
Global definitions and macros.
void ec_fsm_pdo_clear(ec_fsm_pdo_t *fsm)
Destructor.
Definition: fsm_pdo.c:90
void ec_fsm_master_enter_clear_addresses(ec_fsm_master_t *)
Start clearing slave addresses.
Definition: fsm_master.c:774
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:77
#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:437
ec_slave_t * fsm_slave
Slave that is queried next for FSM exec.
Definition: master.h:281
ec_slave_t * slave
EtherCAT slave.
Definition: fsm_master.h: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:1035
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:499
void ec_master_attach_slave_configs(ec_master_t *master)
Attaches the slave configurations to the slaves.
Definition: master.c:1808
int ec_datagram_apwr(ec_datagram_t *datagram, uint16_t ring_position, uint16_t mem_address, size_t data_size)
Initializes an EtherCAT APWR datagram.
Definition: datagram.c:210
void ec_fsm_master_state_read_state(ec_fsm_master_t *)
Master state: READ STATE.
Definition: fsm_master.c:697
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:1329
void ec_fsm_master_state_scan_slave(ec_fsm_master_t *)
Master state: SCAN SLAVE.
Definition: fsm_master.c:887
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:2300
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:147
Use configured addresses.
Definition: fsm_sii.h:50
Slave configutation feature flag.
Definition: flag.h:38
ec_fsm_slave_scan_t fsm_slave_scan
slave state machine
Definition: fsm_master.h: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:145
void ec_fsm_master_action_configure(ec_fsm_master_t *fsm)
Master action: Configure.
Definition: fsm_master.c:639
uint16_t mailbox_protocols
Supported mailbox protocols.
Definition: slave.h:147
ec_flag_t * ec_slave_config_find_flag(ec_slave_config_t *sc, const char *key)
Finds a flag.
Definition: slave_config.c:580
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:285
#define EC_SLAVE_ERR(slave, fmt, args...)
Convenience macro for printing slave-specific errors to syslog.
Definition: slave.h:76
void ec_datagram_print_wc_error(const ec_datagram_t *datagram)
Evaluates the working counter of a single-cast datagram.
Definition: datagram.c:602
ec_slave_dc_range_t base_dc_range
DC range.
Definition: slave.h:211
void ec_fsm_slave_set_ready(ec_fsm_slave_t *fsm)
Sets the current state of the state machine to READY.
Definition: fsm_slave.c: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:250
ec_device_index_t
Master devices.
Definition: globals.h:189
void ec_fsm_master_state_dc_measure_delays(ec_fsm_master_t *)
Master state: DC MEASURE DELAYS.
Definition: fsm_master.c:834
void ec_fsm_master_state_broadcast(ec_fsm_master_t *)
Master state: BROADCAST.
Definition: fsm_master.c:256
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:2283
unsigned long scan_jiffies
beginning of slave scanning
Definition: fsm_master.h:77
#define EC_ABS(X)
Absolute value.
Definition: globals.h:242
Main device.
Definition: globals.h:190
void ec_fsm_master_state_assign_sii(ec_fsm_master_t *)
Master state: ASSIGN SII.
Definition: fsm_master.c:1203
#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:254
#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:170
32 bit.
Definition: globals.h:164
void ec_master_clear_slaves(ec_master_t *master)
Clear all slaves.
Definition: master.c:478
void ec_fsm_change_init(ec_fsm_change_t *fsm, ec_datagram_t *datagram)
Constructor.
Definition: fsm_change.c:65
struct list_head list
list item
Definition: ethernet.h:78
void ec_fsm_coe_init(ec_fsm_coe_t *fsm)
Constructor.
Definition: fsm_coe.c:170
void ec_fsm_master_state_acknowledge(ec_fsm_master_t *)
Master state: ACKNOWLEDGE.
Definition: fsm_master.c:752
void ec_fsm_sii_clear(ec_fsm_sii_t *fsm)
Destructor.
Definition: fsm_sii.c:88
INIT state (no mailbox communication, no IO)
Definition: globals.h:118
int idle
state machine is in idle phase
Definition: fsm_master.h:76
struct semaphore scan_sem
Semaphore protecting the scan_busy variable and the allow_scan flag.
Definition: master.h:252
void ec_fsm_master_state_start(ec_fsm_master_t *)
Master state: START.
Definition: fsm_master.c:198
uint16_t effective_alias
Effective alias address.
Definition: slave.h:185
void ec_master_clear_eoe_handlers(ec_master_t *master)
Clear and free all EoE handlers.
Definition: master.c:442
ec_fsm_slave_config_t fsm_slave_config
slave state machine
Definition: fsm_master.h: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:2178
void ec_master_eoe_start(ec_master_t *master)
Starts Ethernet over EtherCAT processing on demand.
Definition: master.c:1694
void ec_datagram_print_state(const ec_datagram_t *datagram)
Prints the state of a datagram.
Definition: datagram.c:565
Mailbox functionality.
ec_master_t * master
master the FSM runs on
Definition: fsm_master.h:69
void ec_fsm_master_state_sdo_dictionary(ec_fsm_master_t *)
Master state: SDO DICTIONARY.
Definition: fsm_master.c:1294
uint8_t * data
Pointer to data memory.
Definition: reg_request.h:51
#define EC_STATE_STRING_SIZE
Minimum size of a buffer used with ec_state_string().
Definition: globals.h:54
#define EC_WRITE_U64(DATA, VAL)
Write a 64-bit unsigned value to EtherCAT data.
Definition: ecrt.h:2317
void ec_fsm_master_state_clear_addresses(ec_fsm_master_t *)
Master state: CLEAR ADDRESSES.
Definition: fsm_master.c:790
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
wait_queue_head_t config_queue
Queue for processes that wait for slave configuration.
Definition: master.h:260
int32_t value
Flag value (meaning depends on key).
Definition: flag.h:41
unsigned int retries
retries on datagram timeout.
Definition: fsm_master.h: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:105
uint8_t base_dc_supported
Distributed clocks are supported.
Definition: slave.h:210
void ec_fsm_soe_clear(ec_fsm_soe_t *fsm)
Destructor.
Definition: fsm_soe.c:118
void ec_fsm_slave_scan_start(ec_fsm_slave_scan_t *fsm, ec_slave_t *slave)
Start slave scan state machine.
void ec_fsm_master_state_write_sii(ec_fsm_master_t *)
Master state: WRITE SII.
Definition: fsm_master.c:1240
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:2162
EtherCAT slave configuration.
Definition: slave_config.h:119
int ec_fsm_master_exec(ec_fsm_master_t *fsm)
Executes the current state of the state machine.
Definition: fsm_master.c:151
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:432
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:2210
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:257
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:104
EtherCAT FoE state machines.
unknown state
Definition: globals.h:116
void ec_fsm_master_enter_write_system_times(ec_fsm_master_t *)
Start writing DC system times.
Definition: fsm_master.c:987
void ec_master_eoe_stop(ec_master_t *master)
Stops the Ethernet over EtherCAT processing.
Definition: master.c:1728
uint8_t link_state[EC_MAX_NUM_DEVICES]
Last link state for every device.
Definition: fsm_master.h: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:1115
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