IgH EtherCAT Master  1.5.2
fsm_slave.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 
41 #include "fsm_slave.h"
42 
43 /*****************************************************************************/
44 
63 #ifdef EC_EOE
66 #endif
69 
70 /*****************************************************************************/
71 
75  ec_fsm_slave_t *fsm,
76  ec_slave_t *slave
77  )
78 {
79  fsm->slave = slave;
80  INIT_LIST_HEAD(&fsm->list); // mark as unlisted
81 
83  fsm->datagram = NULL;
84  fsm->sdo_request = NULL;
85  fsm->reg_request = NULL;
86  fsm->foe_request = NULL;
87  fsm->soe_request = NULL;
88 #ifdef EC_EOE
89  fsm->eoe_request = NULL;
90 #endif
91  fsm->mbg_request = NULL;
92  fsm->dict_request = NULL;
93 
95 
96  // Init sub-state-machines
97  ec_fsm_coe_init(&fsm->fsm_coe);
98  ec_fsm_foe_init(&fsm->fsm_foe);
99  ec_fsm_soe_init(&fsm->fsm_soe);
100 #ifdef EC_EOE
101  ec_fsm_eoe_init(&fsm->fsm_eoe);
102 #endif
103  ec_fsm_mbg_init(&fsm->fsm_mbg);
104  ec_fsm_pdo_init(&fsm->fsm_pdo, &fsm->fsm_coe);
107  &fsm->fsm_change, &fsm->fsm_coe, &fsm->fsm_soe, &fsm->fsm_pdo);
109  &fsm->fsm_slave_config, &fsm->fsm_pdo);
110 }
111 
112 /*****************************************************************************/
113 
117  ec_fsm_slave_t *fsm
118  )
119 {
120  if (fsm->state != ec_fsm_slave_state_idle) {
121  EC_SLAVE_DBG(fsm->slave, 1, "Unready for requests.\n");
122  }
123 
124  // signal requests that are currently in operation
125 
126  if (fsm->sdo_request) {
127  fsm->sdo_request->state = EC_INT_REQUEST_FAILURE;
128  wake_up_all(&fsm->slave->master->request_queue);
129  }
130 
131  if (fsm->reg_request) {
132  fsm->reg_request->state = EC_INT_REQUEST_FAILURE;
133  wake_up_all(&fsm->slave->master->request_queue);
134  }
135 
136  if (fsm->foe_request) {
137  fsm->foe_request->state = EC_INT_REQUEST_FAILURE;
138  wake_up_all(&fsm->slave->master->request_queue);
139  }
140 
141  if (fsm->soe_request) {
142  fsm->soe_request->state = EC_INT_REQUEST_FAILURE;
143  wake_up_all(&fsm->slave->master->request_queue);
144  }
145 
146 #ifdef EC_EOE
147  if (fsm->eoe_request) {
148  fsm->eoe_request->state = EC_INT_REQUEST_FAILURE;
149  wake_up_all(&fsm->slave->master->request_queue);
150  }
151 #endif
152 
153  if (fsm->mbg_request) {
154  fsm->mbg_request->state = EC_INT_REQUEST_FAILURE;
155  wake_up_all(&fsm->slave->master->request_queue);
156  }
157 
158  if (fsm->dict_request) {
159  fsm->dict_request->state = EC_INT_REQUEST_FAILURE;
160  wake_up_all(&fsm->slave->master->request_queue);
161  }
162 
163  // clear sub-state machines
167  ec_fsm_pdo_clear(&fsm->fsm_pdo);
168  ec_fsm_coe_clear(&fsm->fsm_coe);
169  ec_fsm_foe_clear(&fsm->fsm_foe);
170  ec_fsm_soe_clear(&fsm->fsm_soe);
171 #ifdef EC_EOE
172  ec_fsm_eoe_clear(&fsm->fsm_eoe);
173 #endif
174  ec_fsm_mbg_clear(&fsm->fsm_mbg);
175 }
176 
177 /*****************************************************************************/
178 
184  ec_fsm_slave_t *fsm,
185  ec_datagram_t *datagram
186  )
187 {
188  int datagram_used;
189 
190  fsm->state(fsm, datagram);
191 
192  datagram_used = fsm->state != ec_fsm_slave_state_idle &&
194 
195  if (datagram_used) {
196  datagram->device_index = fsm->slave->device_index;
197  fsm->datagram = datagram;
198  } else {
199  fsm->datagram = NULL;
200  }
201 
202  return datagram_used;
203 }
204 
205 /*****************************************************************************/
206 
210  ec_fsm_slave_t *fsm
211  )
212 {
213  if (fsm->state == ec_fsm_slave_state_idle) {
214  EC_SLAVE_DBG(fsm->slave, 1, "Ready for requests.\n");
216  }
217 }
218 
219 /*****************************************************************************/
220 
226  ec_fsm_slave_t *fsm,
227  ec_datagram_t *datagram
228  )
229 {
230  ec_slave_t *slave = fsm->slave;
231 
232  if (!slave->scan_required) {
233  return 0;
234  }
235 
236  EC_SLAVE_DBG(slave, 1, "Scanning slave %u on %s link.\n",
237  slave->ring_position, ec_device_names[slave->device_index != 0]);
240  ec_fsm_slave_scan_exec(&fsm->fsm_slave_scan, datagram); // execute immediately
241  return 1;
242 }
243 
244 /*****************************************************************************/
245 
246 #ifdef EC_EOE
247 
250  ec_slave_t *slave
251  )
252 {
253  ec_master_t *master = slave->master;
254  ec_eoe_t *eoe;
255  char name[EC_DATAGRAM_NAME_SIZE];
256 
257  if (slave->effective_alias) {
258  snprintf(name, EC_DATAGRAM_NAME_SIZE,
259  "eoe%ua%u", master->index, slave->effective_alias);
260  } else {
261  snprintf(name, EC_DATAGRAM_NAME_SIZE,
262  "eoe%us%u", master->index, slave->ring_position);
263  }
264 
265  list_for_each_entry(eoe, &master->eoe_handlers, list) {
266  if ((eoe->slave == NULL) &&
267  (strncmp(name, ec_eoe_name(eoe), EC_DATAGRAM_NAME_SIZE) == 0)) {
268  ec_eoe_link_slave(eoe, slave);
269  return 0;
270  }
271  }
272 
273  // none found
274  return -1;
275 }
276 #endif
277 
278 /*****************************************************************************/
279 
283  ec_fsm_slave_t *fsm,
284  ec_datagram_t *datagram
285  )
286 {
287  ec_slave_t *slave = fsm->slave;
288 
289  if (ec_fsm_slave_scan_exec(&fsm->fsm_slave_scan, datagram)) {
290  return;
291  }
292 
293  // Assume that the slaves mailbox data is valid even if the slave scanning skipped
294  // the clear mailbox state, e.g. if the slave refused to enter state INIT.
295  slave->valid_mbox_data = 1;
296 
297 #ifdef EC_EOE
298  if (slave->sii_image && (slave->sii_image->sii.mailbox_protocols & EC_MBOX_EOE)) {
299  // try to connect to existing eoe handler,
300  // otherwise try to create a new one (if master not active)
301  if (ec_slave_reconnect_to_eoe_handler(slave) == 0) {
302  // reconnected
303  } else if (eoe_autocreate) {
304  // auto create EoE handler for this slave
305  ec_eoe_t *eoe;
306 
307  if (!(eoe = kmalloc(sizeof(ec_eoe_t), GFP_KERNEL))) {
308  EC_SLAVE_ERR(slave, "Failed to allocate EoE handler memory!\n");
309  } else if (ec_eoe_auto_init(eoe, slave)) {
310  EC_SLAVE_ERR(slave, "Failed to init EoE handler!\n");
311  kfree(eoe);
312  } else {
313  list_add_tail(&eoe->list, &slave->master->eoe_handlers);
314  }
315  }
316  }
317 #endif
318 
319  // disable processing after scan, to wait for master FSM to be ready again
320  slave->scan_required = 0;
322 }
323 
324 /*****************************************************************************/
325 
331  ec_fsm_slave_t *fsm,
332  ec_datagram_t *datagram
333  )
334 {
335  ec_slave_t *slave = fsm->slave;
336 
337  if (slave->error_flag) {
338  return 0;
339  }
340 
341  // Check, if new slave state has to be acknowledged
342  if (slave->current_state & EC_SLAVE_STATE_ACK_ERR) {
344  ec_fsm_change_ack(&fsm->fsm_change, slave);
345  fsm->state(fsm, datagram); // execute immediately
346  return 1;
347  }
348 
349  // Does the slave have to be configured?
350  if (slave->current_state != slave->requested_state
351  || slave->force_config) {
352 
353  if (slave->master->debug_level) {
354  char old_state[EC_STATE_STRING_SIZE],
355  new_state[EC_STATE_STRING_SIZE];
356  ec_state_string(slave->current_state, old_state, 0);
357  ec_state_string(slave->requested_state, new_state, 0);
358  EC_SLAVE_DBG(slave, 1, "Changing state from %s to %s%s.\n",
359  old_state, new_state,
360  slave->force_config ? " (forced)" : "");
361  }
362 
363  ec_lock_down(&slave->master->config_sem);
364  ++slave->master->config_busy;
365  ec_lock_up(&slave->master->config_sem);
366 
368 #ifdef EC_QUICK_OP
369  if (!slave->force_config
372  && slave->last_al_error == 0x001B) {
373  // last error was a sync watchdog timeout; assume a comms
374  // interruption and request a quick transition back to OP
376  } else
377 #endif
378  {
380  }
381  fsm->state(fsm, datagram); // execute immediately
382  return 1;
383  }
384  return 0;
385 }
386 
387 /*****************************************************************************/
388 
392  ec_fsm_slave_t *fsm,
393  ec_datagram_t *datagram
394  )
395 {
396  ec_slave_t *slave = fsm->slave;
397 
398  if (ec_fsm_change_exec(&fsm->fsm_change, datagram)) {
399  return;
400  }
401 
402  if (!ec_fsm_change_success(&fsm->fsm_change)) {
403  slave->error_flag = 1;
404  EC_SLAVE_ERR(slave, "Failed to acknowledge state change.\n");
405  }
406 
408 }
409 
410 /*****************************************************************************/
411 
415  ec_fsm_slave_t *fsm,
416  ec_datagram_t *datagram
417  )
418 {
419  ec_slave_t *slave = fsm->slave;
420 
421  if (ec_fsm_slave_config_exec(&fsm->fsm_slave_config, datagram)) {
422  return;
423  }
424 
426  // TODO: mark slave_config as failed.
427  }
428 
429  slave->force_config = 0;
430 
431  ec_lock_down(&slave->master->config_sem);
432  if (slave->master->config_busy) {
433  if (--slave->master->config_busy == 0) {
434  wake_up_interruptible(&slave->master->config_queue);
435  }
436  }
437  ec_lock_up(&slave->master->config_sem);
438 
440 }
441 
442 /*****************************************************************************/
443 
449  ec_fsm_slave_t *fsm,
450  ec_datagram_t *datagram
451  )
452 {
453  ec_slave_t *slave = fsm->slave;
454  ec_dict_request_t *request;
455 
456  // First check if there's an explicit dictionary request to process.
457  if (!list_empty(&slave->dict_requests)) {
458  // take the first request to be processed
459  request = list_entry(slave->dict_requests.next, ec_dict_request_t, list);
460  list_del_init(&request->list); // dequeue
461 
462  if (!slave->sii_image) {
463  EC_SLAVE_ERR(slave, "Slave not ready to process dictionary request\n");
464  request->state = EC_INT_REQUEST_FAILURE;
465  wake_up_all(&slave->master->request_queue);
467  return 1;
468  }
469 
470  if (!(slave->sii_image->sii.mailbox_protocols & EC_MBOX_COE)
471  || (slave->sii_image->sii.has_general
473  {
474  EC_SLAVE_INFO(slave, "Aborting dictionary request,"
475  " slave does not support SDO Info.\n");
476  request->state = EC_INT_REQUEST_SUCCESS;
477  wake_up_all(&slave->master->request_queue);
478  fsm->dict_request = NULL;
480  return 1;
481  }
482 
483  if (slave->sdo_dictionary_fetched)
484  {
485  EC_SLAVE_DBG(slave, 1, "Aborting dictionary request,"
486  " dictionary already uploaded.\n");
487  request->state = EC_INT_REQUEST_SUCCESS;
488  wake_up_all(&slave->master->request_queue);
489  fsm->dict_request = NULL;
491  return 1;
492  }
493 
494  if (slave->current_state & EC_SLAVE_STATE_ACK_ERR) {
495  EC_SLAVE_WARN(slave, "Aborting dictionary request,"
496  " slave has error flag set.\n");
497  request->state = EC_INT_REQUEST_FAILURE;
498  wake_up_all(&slave->master->request_queue);
500  return 1;
501  }
502 
503  if (slave->current_state == EC_SLAVE_STATE_INIT) {
504  EC_SLAVE_WARN(slave, "Aborting dictionary request,"
505  " slave is in INIT.\n");
506  request->state = EC_INT_REQUEST_FAILURE;
507  wake_up_all(&slave->master->request_queue);
509  return 1;
510  }
511 
512  fsm->dict_request = request;
513  request->state = EC_INT_REQUEST_BUSY;
514 
515  // Found pending dictionary request. Execute it!
516  EC_SLAVE_DBG(slave, 1, "Processing dictionary request...\n");
517 
518  // Start dictionary transfer
520  ec_fsm_coe_dictionary(&fsm->fsm_coe, slave);
521  ec_fsm_coe_exec(&fsm->fsm_coe, datagram); // execute immediately
522  return 1;
523  }
524 
525  // Otherwise check if it's time to fetch the dictionary on startup.
526 #if EC_SKIP_SDO_DICT
527  return 0;
528 #else
529  if (!slave->sii_image
530  || slave->sdo_dictionary_fetched
535  || (slave->sii_image->sii.has_general
537  ) {
538  return 0;
539  }
540 
541  fsm->dict_request = &fsm->int_dict_request;
542  fsm->int_dict_request.state = EC_INT_REQUEST_BUSY;
543 
544  EC_SLAVE_DBG(slave, 1, "Fetching SDO dictionary.\n");
545 
546  // Start dictionary transfer
548  ec_fsm_coe_dictionary(&fsm->fsm_coe, slave);
549  ec_fsm_coe_exec(&fsm->fsm_coe, datagram); // execute immediately
550  return 1;
551 #endif
552 }
553 
554 /*****************************************************************************/
555 
559  ec_fsm_slave_t *fsm,
560  ec_datagram_t *datagram
561  )
562 {
563  ec_slave_t *slave = fsm->slave;
564  ec_dict_request_t *request = fsm->dict_request;
565 
566  if (ec_fsm_coe_exec(&fsm->fsm_coe, datagram)) {
567  return;
568  }
569 
570  if (!ec_fsm_coe_success(&fsm->fsm_coe)) {
571  EC_SLAVE_ERR(slave, "Failed to process dictionary request.\n");
572 #if !EC_SKIP_SDO_DICT
573  if (request == &fsm->int_dict_request) {
574  // mark as fetched anyway so we don't retry
575  slave->sdo_dictionary_fetched = 1;
576  }
577 #endif
578  request->state = EC_INT_REQUEST_FAILURE;
579  wake_up_all(&slave->master->request_queue);
580  fsm->dict_request = NULL;
582  return;
583  }
584 
585  if (slave->master->debug_level) {
586  unsigned int sdo_count, entry_count;
587  ec_slave_sdo_dict_info(slave, &sdo_count, &entry_count);
588  EC_SLAVE_DBG(slave, 1, "Fetched %u SDOs and %u entries.\n",
589  sdo_count, entry_count);
590  }
591 
592  // Dictionary request finished
593  slave->sdo_dictionary_fetched = 1;
594 
595  // attach pdo names from dictionary
597 
598  request->state = EC_INT_REQUEST_SUCCESS;
599  wake_up_all(&slave->master->request_queue);
600  fsm->dict_request = NULL;
602 }
603 
604 /*****************************************************************************/
605 
611  ec_fsm_slave_t *fsm,
612  ec_datagram_t *datagram
613  )
614 {
615  ec_slave_t *slave = fsm->slave;
616  ec_sdo_request_t *request;
617 
618  if (!slave->config) {
619  return 0;
620  }
621 
622  list_for_each_entry(request, &slave->config->sdo_requests, list) {
623  if (request->state == EC_INT_REQUEST_QUEUED) {
624  if (ec_sdo_request_timed_out(request)) {
625  request->state = EC_INT_REQUEST_FAILURE;
626  EC_SLAVE_DBG(slave, 1, "Internal SDO request timed out.\n");
627  continue;
628  }
629 
630  if (slave->current_state & EC_SLAVE_STATE_ACK_ERR) {
631  EC_SLAVE_WARN(slave, "Aborting SDO request,"
632  " slave has error flag set.\n");
633  request->state = EC_INT_REQUEST_FAILURE;
634  continue;
635  }
636 
637  if (slave->current_state == EC_SLAVE_STATE_INIT) {
638  EC_SLAVE_WARN(slave, "Aborting SDO request, slave is in INIT.\n");
639  request->state = EC_INT_REQUEST_FAILURE;
640  continue;
641  }
642 
643  request->state = EC_INT_REQUEST_BUSY;
644  EC_SLAVE_DBG(slave, 1, "Processing internal SDO request...\n");
645  fsm->sdo_request = request;
647  ec_fsm_coe_transfer(&fsm->fsm_coe, slave, request);
648  ec_fsm_coe_exec(&fsm->fsm_coe, datagram);
649  return 1;
650  }
651  }
652  return 0;
653 }
654 
655 /*****************************************************************************/
656 
662  ec_fsm_slave_t *fsm
663  )
664 {
665  if (fsm->state == ec_fsm_slave_state_idle) {
666  return 1;
667  } else if (fsm->state == ec_fsm_slave_state_ready) {
668  EC_SLAVE_DBG(fsm->slave, 1, "Unready for requests.\n");
670  return 1;
671  }
672  return 0;
673 }
674 
675 /*****************************************************************************/
676 
682  const ec_fsm_slave_t *fsm
683  )
684 {
685  return fsm->state == ec_fsm_slave_state_ready;
686 }
687 
688 /******************************************************************************
689  * Slave state machine
690  *****************************************************************************/
691 
695  ec_fsm_slave_t *fsm,
696  ec_datagram_t *datagram
697  )
698 {
699  // do nothing
700 }
701 
702 /*****************************************************************************/
703 
707  ec_fsm_slave_t *fsm,
708  ec_datagram_t *datagram
709  )
710 {
711  // Check for pending scan requests
712  if (ec_fsm_slave_action_scan(fsm, datagram)) {
713  return;
714  }
715 
716  // Check for pending configuration requests
717  if (ec_fsm_slave_action_config(fsm, datagram)) {
718  return;
719  }
720 
721  // Check for pending internal SDO requests
722  if (ec_fsm_slave_action_process_config_sdo(fsm, datagram)) {
723  return;
724  }
725 
726  // Check if the slave needs to read the SDO dictionary
727  if (ec_fsm_slave_action_process_dict(fsm, datagram)) {
728  return;
729  }
730 
731  // Check for pending external SDO requests
732  if (ec_fsm_slave_action_process_sdo(fsm, datagram)) {
733  return;
734  }
735 
736  // Check for pending external register requests
737  if (ec_fsm_slave_action_process_reg(fsm, datagram)) {
738  return;
739  }
740 
741  // Check for pending FoE requests
742  if (ec_fsm_slave_action_process_foe(fsm, datagram)) {
743  return;
744  }
745 
746  // Check for pending SoE requests
747  if (ec_fsm_slave_action_process_soe(fsm, datagram)) {
748  return;
749  }
750 
751 #ifdef EC_EOE
752  // Check for pending EoE IP parameter requests
753  if (ec_fsm_slave_action_process_eoe(fsm, datagram)) {
754  return;
755  }
756 #endif
757 
758  // Check for pending MBox Gateway requests
759  if (ec_fsm_slave_action_process_mbg(fsm, datagram)) {
760  return;
761  }
762 }
763 
764 /*****************************************************************************/
765 
771  ec_fsm_slave_t *fsm,
772  ec_datagram_t *datagram
773  )
774 {
775  ec_slave_t *slave = fsm->slave;
776  ec_sdo_request_t *request;
777 
778  if (list_empty(&slave->sdo_requests)) {
779  return 0;
780  }
781 
782  // take the first request to be processed
783  request = list_entry(slave->sdo_requests.next, ec_sdo_request_t, list);
784  list_del_init(&request->list); // dequeue
785 
786  if (slave->current_state & EC_SLAVE_STATE_ACK_ERR) {
787  EC_SLAVE_WARN(slave, "Aborting SDO request,"
788  " slave has error flag set.\n");
789  request->state = EC_INT_REQUEST_FAILURE;
790  wake_up_all(&slave->master->request_queue);
792  return 0;
793  }
794 
795  if (slave->current_state == EC_SLAVE_STATE_INIT) {
796  EC_SLAVE_WARN(slave, "Aborting SDO request, slave is in INIT.\n");
797  request->state = EC_INT_REQUEST_FAILURE;
798  wake_up_all(&slave->master->request_queue);
800  return 0;
801  }
802 
803  fsm->sdo_request = request;
804  request->state = EC_INT_REQUEST_BUSY;
805 
806  // Found pending SDO request. Execute it!
807  EC_SLAVE_DBG(slave, 1, "Processing SDO request...\n");
808 
809  // Start SDO transfer
811  ec_fsm_coe_transfer(&fsm->fsm_coe, slave, request);
812  ec_fsm_coe_exec(&fsm->fsm_coe, datagram); // execute immediately
813  return 1;
814 }
815 
816 /*****************************************************************************/
817 
821  ec_fsm_slave_t *fsm,
822  ec_datagram_t *datagram
823  )
824 {
825  ec_slave_t *slave = fsm->slave;
826  ec_sdo_request_t *request = fsm->sdo_request;
827 
828  if (ec_fsm_coe_exec(&fsm->fsm_coe, datagram)) {
829  return;
830  }
831 
832  if (!ec_fsm_coe_success(&fsm->fsm_coe)) {
833  EC_SLAVE_ERR(slave, "Failed to process SDO request.\n");
834  request->state = EC_INT_REQUEST_FAILURE;
835  wake_up_all(&slave->master->request_queue);
836  fsm->sdo_request = NULL;
838  return;
839  }
840 
841  EC_SLAVE_DBG(slave, 1, "Finished SDO request.\n");
842 
843  // SDO request finished
844  request->state = EC_INT_REQUEST_SUCCESS;
845  wake_up_all(&slave->master->request_queue);
846  fsm->sdo_request = NULL;
848 }
849 
850 /*****************************************************************************/
851 
857  ec_fsm_slave_t *fsm,
858  ec_datagram_t *datagram
859  )
860 {
861  static const char *direction_names[] = {
862  "invalid", //EC_DIR_INVALID
863  "download", //EC_DIR_OUTPUT
864  "upload", //EC_DIR_INPUT
865  "down+up", //EC_DIR_BOTH
866  };
867 
868  ec_slave_t *slave = fsm->slave;
869  ec_reg_request_t *reg;
870 
871  fsm->reg_request = NULL;
872 
873  if (slave->config) {
874  // search the first internal register request to be processed
875  list_for_each_entry(reg, &slave->config->reg_requests, list) {
876  if (reg->state == EC_INT_REQUEST_QUEUED) {
877  fsm->reg_request = reg;
878  break;
879  }
880  }
881  }
882 
883  if (!fsm->reg_request && !list_empty(&slave->reg_requests)) {
884  // take the first external request to be processed
885  fsm->reg_request =
886  list_entry(slave->reg_requests.next, ec_reg_request_t, list);
887  list_del_init(&fsm->reg_request->list); // dequeue
888  }
889 
890  if (!fsm->reg_request) { // no register request to process
891  return 0;
892  }
893 
894  if (slave->current_state & EC_SLAVE_STATE_ACK_ERR) {
895  EC_SLAVE_WARN(slave, "Aborting register request,"
896  " slave has error flag set.\n");
897  fsm->reg_request->state = EC_INT_REQUEST_FAILURE;
898  wake_up_all(&slave->master->request_queue);
899  fsm->reg_request = NULL;
901  return 0;
902  }
903 
904  // Found pending register request. Execute it!
905  EC_SLAVE_DBG(slave, 1, "Processing register request %s 0x%04X-0x%04X...\n",
906  direction_names[fsm->reg_request->dir % EC_DIR_COUNT], fsm->reg_request->address,
907  fsm->reg_request->address + (unsigned)fsm->reg_request->transfer_size - 1u);
908 
909  fsm->reg_request->state = EC_INT_REQUEST_BUSY;
910 
911  // Start register access
912  switch (fsm->reg_request->dir) {
913  case EC_DIR_INPUT:
914  ec_datagram_fprd(datagram, slave->station_address,
916  ec_datagram_zero(datagram);
917  break;
918  case EC_DIR_OUTPUT:
919  ec_datagram_fpwr(datagram, slave->station_address,
921  memcpy(datagram->data, fsm->reg_request->data,
922  fsm->reg_request->transfer_size);
923  break;
924  case EC_DIR_BOTH:
925  ec_datagram_fprw(datagram, slave->station_address,
927  memcpy(datagram->data, fsm->reg_request->data,
928  fsm->reg_request->transfer_size);
929  break;
930  default:
931  EC_SLAVE_WARN(slave, "Aborting register request, unknown direction.\n");
932  fsm->reg_request->state = EC_INT_REQUEST_FAILURE;
933  wake_up_all(&slave->master->request_queue);
934  fsm->reg_request = NULL;
936  return 1;
937  }
938  datagram->device_index = slave->device_index;
940  return 1;
941 }
942 
943 /*****************************************************************************/
944 
948  ec_fsm_slave_t *fsm,
949  ec_datagram_t *datagram
950  )
951 {
952  ec_slave_t *slave = fsm->slave;
953  ec_reg_request_t *reg = fsm->reg_request;
954 
955  if (!reg) {
956  // configuration was cleared in the meantime
958  fsm->reg_request = NULL;
959  return;
960  }
961 
962  if (fsm->datagram->state != EC_DATAGRAM_RECEIVED) {
963  EC_SLAVE_ERR(slave, "Failed to receive register"
964  " request datagram: ");
966  reg->state = EC_INT_REQUEST_FAILURE;
967  wake_up_all(&slave->master->request_queue);
968  fsm->reg_request = NULL;
970  return;
971  }
972 
973  if (fsm->datagram->working_counter == ((reg->dir == EC_DIR_BOTH) ? 3 : 1)) {
974  if (reg->dir != EC_DIR_OUTPUT) { // read/read-write request
975  memcpy(reg->data, fsm->datagram->data, reg->transfer_size);
976  }
977 
978  reg->state = EC_INT_REQUEST_SUCCESS;
979  EC_SLAVE_DBG(slave, 1, "Register request successful.\n");
980  } else {
981  reg->state = EC_INT_REQUEST_FAILURE;
983  EC_SLAVE_ERR(slave, "Register request failed"
984  " (working counter is %u).\n",
985  fsm->datagram->working_counter);
986  }
987 
988  wake_up_all(&slave->master->request_queue);
989  fsm->reg_request = NULL;
991 }
992 
993 /*****************************************************************************/
994 
1000  ec_fsm_slave_t *fsm,
1001  ec_datagram_t *datagram
1002  )
1003 {
1004  ec_slave_t *slave = fsm->slave;
1005  ec_foe_request_t *request;
1006 
1007  if (slave->config) {
1008  // search the first internal file request to be processed
1009  list_for_each_entry(request, &slave->config->foe_requests, list) {
1010  if (request->state == EC_INT_REQUEST_QUEUED) {
1011  fsm->foe_request = request;
1012  break;
1013  }
1014  }
1015  }
1016 
1017  if (!fsm->foe_request && !list_empty(&slave->foe_requests)) {
1018  // take the first external request to be processed
1019  fsm->foe_request =
1020  list_entry(slave->foe_requests.next, ec_foe_request_t, list);
1021  list_del_init(&fsm->foe_request->list); // dequeue
1022  }
1023 
1024  if (!fsm->foe_request) {
1025  return 0;
1026  }
1027 
1028  if (slave->current_state & EC_SLAVE_STATE_ACK_ERR) {
1029  EC_SLAVE_WARN(slave, "Aborting FoE request,"
1030  " slave has error flag set.\n");
1031  fsm->foe_request->state = EC_INT_REQUEST_FAILURE;
1032  wake_up_all(&slave->master->request_queue);
1033  fsm->foe_request = NULL;
1035  return 0;
1036  }
1037 
1038  fsm->foe_request->state = EC_INT_REQUEST_BUSY;
1039 
1040  EC_SLAVE_DBG(slave, 1, "Processing FoE request.\n");
1041 
1043  ec_fsm_foe_transfer(&fsm->fsm_foe, slave, fsm->foe_request);
1044  ec_fsm_foe_exec(&fsm->fsm_foe, datagram);
1045  return 1;
1046 }
1047 
1048 /*****************************************************************************/
1049 
1053  ec_fsm_slave_t *fsm,
1054  ec_datagram_t *datagram
1055  )
1056 {
1057  ec_slave_t *slave = fsm->slave;
1058  ec_foe_request_t *request = fsm->foe_request;
1059 
1060  if (ec_fsm_foe_exec(&fsm->fsm_foe, datagram)) {
1061  return;
1062  }
1063 
1064  if (!ec_fsm_foe_success(&fsm->fsm_foe)) {
1065  EC_SLAVE_ERR(slave, "Failed to handle FoE request.\n");
1066  request->state = EC_INT_REQUEST_FAILURE;
1067  wake_up_all(&slave->master->request_queue);
1068  fsm->foe_request = NULL;
1070  return;
1071  }
1072 
1073  // finished transferring FoE
1074  EC_SLAVE_DBG(slave, 1, "Successfully transferred %zu bytes of FoE"
1075  " data.\n", request->data_size);
1076 
1077  request->state = EC_INT_REQUEST_SUCCESS;
1078  wake_up_all(&slave->master->request_queue);
1079  fsm->foe_request = NULL;
1081 }
1082 
1083 /*****************************************************************************/
1084 
1090  ec_fsm_slave_t *fsm,
1091  ec_datagram_t *datagram
1092  )
1093 {
1094  ec_slave_t *slave = fsm->slave;
1095  ec_soe_request_t *req;
1096 
1097  if (list_empty(&slave->soe_requests)) {
1098  return 0;
1099  }
1100 
1101  // take the first request to be processed
1102  req = list_entry(slave->soe_requests.next, ec_soe_request_t, list);
1103  list_del_init(&req->list); // dequeue
1104 
1105  if (slave->current_state & EC_SLAVE_STATE_ACK_ERR) {
1106  EC_SLAVE_WARN(slave, "Aborting SoE request,"
1107  " slave has error flag set.\n");
1108  req->state = EC_INT_REQUEST_FAILURE;
1109  wake_up_all(&slave->master->request_queue);
1111  return 0;
1112  }
1113 
1114  if (slave->current_state == EC_SLAVE_STATE_INIT) {
1115  EC_SLAVE_WARN(slave, "Aborting SoE request, slave is in INIT.\n");
1116  req->state = EC_INT_REQUEST_FAILURE;
1117  wake_up_all(&slave->master->request_queue);
1119  return 0;
1120  }
1121 
1122  fsm->soe_request = req;
1123  req->state = EC_INT_REQUEST_BUSY;
1124 
1125  // Found pending request. Execute it!
1126  EC_SLAVE_DBG(slave, 1, "Processing SoE request...\n");
1127 
1128  // Start SoE transfer
1130  ec_fsm_soe_transfer(&fsm->fsm_soe, slave, req);
1131  ec_fsm_soe_exec(&fsm->fsm_soe, datagram); // execute immediately
1132  return 1;
1133 }
1134 
1135 /*****************************************************************************/
1136 
1142  ec_fsm_slave_t *fsm,
1143  ec_datagram_t *datagram
1144  )
1145 {
1146  ec_slave_t *slave = fsm->slave;
1147  ec_mbg_request_t *req;
1148 
1149  if (list_empty(&slave->mbg_requests)) {
1150  return 0;
1151  }
1152 
1153  // take the first request to be processed
1154  req = list_entry(slave->mbg_requests.next, ec_mbg_request_t, list);
1155  list_del_init(&req->list); // dequeue
1156 
1157  if (slave->current_state & EC_SLAVE_STATE_ACK_ERR) {
1158  EC_SLAVE_WARN(slave, "Aborting MBox Gateway request,"
1159  " slave has error flag set.\n");
1160  req->state = EC_INT_REQUEST_FAILURE;
1161  wake_up_all(&slave->master->request_queue);
1163  return 0;
1164  }
1165 
1166  if (slave->current_state == EC_SLAVE_STATE_INIT) {
1167  EC_SLAVE_WARN(slave, "Aborting MBox Gateway request,"
1168  " slave is in INIT.\n");
1169  req->state = EC_INT_REQUEST_FAILURE;
1170  wake_up_all(&slave->master->request_queue);
1172  return 0;
1173  }
1174 
1175  fsm->mbg_request = req;
1176  req->state = EC_INT_REQUEST_BUSY;
1177 
1178  // Found pending request. Execute it!
1179  EC_SLAVE_DBG(slave, 1, "Processing MBox Gateway request...\n");
1180 
1181  // Start MBox Gateway transfer
1183  ec_fsm_mbg_transfer(&fsm->fsm_mbg, slave, req);
1184  ec_fsm_mbg_exec(&fsm->fsm_mbg, datagram); // execute immediately
1185  return 1;
1186 }
1187 
1188 /*****************************************************************************/
1189 
1193  ec_fsm_slave_t *fsm,
1194  ec_datagram_t *datagram
1195  )
1196 {
1197  ec_slave_t *slave = fsm->slave;
1198  ec_mbg_request_t *request = fsm->mbg_request;
1199 
1200  if (ec_fsm_mbg_exec(&fsm->fsm_mbg, datagram)) {
1201  return;
1202  }
1203 
1204  if (!ec_fsm_mbg_success(&fsm->fsm_mbg)) {
1205  EC_SLAVE_ERR(slave, "Failed to process MBox Gateway request.\n");
1206  request->state = EC_INT_REQUEST_FAILURE;
1207  wake_up_all(&slave->master->request_queue);
1208  fsm->mbg_request = NULL;
1210  return;
1211  }
1212 
1213  EC_SLAVE_DBG(slave, 1, "Finished MBox Gateway request.\n");
1214 
1215  // MBox Gateway request finished
1216  request->state = EC_INT_REQUEST_SUCCESS;
1217  wake_up_all(&slave->master->request_queue);
1218  fsm->mbg_request = NULL;
1220 }
1221 
1222 /*****************************************************************************/
1223 
1227  ec_fsm_slave_t *fsm,
1228  ec_datagram_t *datagram
1229  )
1230 {
1231  ec_slave_t *slave = fsm->slave;
1232  ec_soe_request_t *request = fsm->soe_request;
1233 
1234  if (ec_fsm_soe_exec(&fsm->fsm_soe, datagram)) {
1235  return;
1236  }
1237 
1238  if (!ec_fsm_soe_success(&fsm->fsm_soe)) {
1239  EC_SLAVE_ERR(slave, "Failed to process SoE request.\n");
1240  request->state = EC_INT_REQUEST_FAILURE;
1241  wake_up_all(&slave->master->request_queue);
1242  fsm->soe_request = NULL;
1244  return;
1245  }
1246 
1247  EC_SLAVE_DBG(slave, 1, "Finished SoE request.\n");
1248 
1249  // SoE request finished
1250  request->state = EC_INT_REQUEST_SUCCESS;
1251  wake_up_all(&slave->master->request_queue);
1252  fsm->soe_request = NULL;
1254 }
1255 
1256 /*****************************************************************************/
1257 #ifdef EC_EOE
1258 
1263  ec_fsm_slave_t *fsm,
1264  ec_datagram_t *datagram
1265  )
1266 {
1267  ec_slave_t *slave = fsm->slave;
1268  ec_eoe_request_t *request;
1269 
1270  if (list_empty(&slave->eoe_requests)) {
1271  return 0;
1272  }
1273 
1274  // take the first request to be processed
1275  request = list_entry(slave->eoe_requests.next, ec_eoe_request_t, list);
1276  list_del_init(&request->list); // dequeue
1277 
1278  if (slave->current_state & EC_SLAVE_STATE_ACK_ERR) {
1279  EC_SLAVE_WARN(slave, "Aborting EoE request,"
1280  " slave has error flag set.\n");
1281  request->state = EC_INT_REQUEST_FAILURE;
1282  wake_up_all(&slave->master->request_queue);
1284  return 0;
1285  }
1286 
1287  if (slave->current_state == EC_SLAVE_STATE_INIT) {
1288  EC_SLAVE_WARN(slave, "Aborting EoE request, slave is in INIT.\n");
1289  request->state = EC_INT_REQUEST_FAILURE;
1290  wake_up_all(&slave->master->request_queue);
1292  return 0;
1293  }
1294 
1295  fsm->eoe_request = request;
1296  request->state = EC_INT_REQUEST_BUSY;
1297 
1298  // Found pending request. Execute it!
1299  EC_SLAVE_DBG(slave, 1, "Processing EoE request...\n");
1300 
1301  // Start EoE command
1303  ec_fsm_eoe_set_ip_param(&fsm->fsm_eoe, slave, request);
1304  ec_fsm_eoe_exec(&fsm->fsm_eoe, datagram); // execute immediately
1305  return 1;
1306 }
1307 
1308 /*****************************************************************************/
1309 
1313  ec_fsm_slave_t *fsm,
1314  ec_datagram_t *datagram
1315  )
1316 {
1317  ec_slave_t *slave = fsm->slave;
1318  ec_eoe_request_t *req = fsm->eoe_request;
1319 
1320  if (ec_fsm_eoe_exec(&fsm->fsm_eoe, datagram)) {
1321  return;
1322  }
1323 
1324  if (ec_fsm_eoe_success(&fsm->fsm_eoe)) {
1325  req->state = EC_INT_REQUEST_SUCCESS;
1326  EC_SLAVE_DBG(slave, 1, "Finished EoE request.\n");
1327  }
1328  else {
1329  req->state = EC_INT_REQUEST_FAILURE;
1330  EC_SLAVE_ERR(slave, "Failed to process EoE request.\n");
1331  }
1332 
1333  wake_up_all(&slave->master->request_queue);
1334  fsm->eoe_request = NULL;
1336 }
1337 #endif
1338 
1339 /*****************************************************************************/
ec_fsm_change_t fsm_change
State change state machine.
Definition: fsm_slave.h:89
struct list_head mbg_requests
EoE set IP parameter requests.
Definition: slave.h:279
int ec_fsm_eoe_exec(ec_fsm_eoe_t *fsm, ec_datagram_t *datagram)
Executes the current state of the state machine.
Definition: fsm_eoe.c:106
ec_internal_request_state_t state
Request state.
Definition: reg_request.h:56
uint16_t ring_position
Ring position.
Definition: slave.h:221
void ec_fsm_slave_config_start(ec_fsm_slave_config_t *fsm)
Start slave configuration state machine.
ec_internal_request_state_t state
Request state.
void ec_fsm_slave_clear(ec_fsm_slave_t *fsm)
Destructor.
Definition: fsm_slave.c:116
#define EC_DATAGRAM_NAME_SIZE
Size of the datagram description string.
Definition: globals.h:142
int ec_fsm_foe_success(const ec_fsm_foe_t *fsm)
Returns, if the state machine terminated with success.
Definition: fsm_foe.c:151
void ec_fsm_slave_state_foe_request(ec_fsm_slave_t *, ec_datagram_t *)
Slave state: FOE REQUEST.
Definition: fsm_slave.c:1052
char * ec_eoe_name(const ec_eoe_t *eoe)
Returns the eoe device name.
Definition: ethernet.c:716
size_t transfer_size
Size of the data to transfer.
Definition: reg_request.h:55
ec_dict_request_t * dict_request
Dictionary request to process.
Definition: fsm_slave.h:79
void ec_slave_attach_pdo_names(ec_slave_t *slave)
Attach PDO names.
Definition: slave.c:969
ec_foe_request_t * foe_request
FoE request to process.
Definition: fsm_slave.h:72
void ec_fsm_foe_clear(ec_fsm_foe_t *fsm)
Destructor.
Definition: fsm_foe.c:117
void ec_fsm_slave_state_eoe_request(ec_fsm_slave_t *, ec_datagram_t *)
Slave state: EOE_REQUEST.
Definition: fsm_slave.c:1312
EtherCAT Mailbox Gateway request.
struct list_head list
List item.
Definition: soe_request.h:49
bool eoe_autocreate
Auto-create EOE interfaces.
Definition: module.c:64
#define EC_SLAVE_DBG(slave, level, fmt, args...)
Convenience macro for printing slave-specific debug messages to syslog.
Definition: slave.h:108
ec_slave_t * slave
pointer to the corresponding slave
Definition: ethernet.h:75
OP (mailbox communication and input/output update)
Definition: globals.h:170
ec_reg_request_t * reg_request
Register request to process.
Definition: fsm_slave.h:71
struct list_head foe_requests
List of FoE requests.
Definition: slave_config.h:147
size_t ec_state_string(uint8_t, char *, uint8_t)
Prints slave states in clear text.
Definition: module.c:408
int ec_fsm_slave_is_ready(const ec_fsm_slave_t *fsm)
Returns, if the FSM is currently not busy and ready to execute.
Definition: fsm_slave.c:681
CANopen SDO request.
Definition: sdo_request.h:48
ec_slave_state_t current_state
Current application state.
Definition: slave.h:237
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
int ec_fsm_slave_action_process_mbg(ec_fsm_slave_t *, ec_datagram_t *)
Check for pending MBox Gateway requests and process one.
Definition: fsm_slave.c:1141
struct list_head eoe_handlers
Ethernet over EtherCAT handlers.
Definition: master.h:320
void ec_fsm_change_init(ec_fsm_change_t *fsm)
Constructor.
Definition: fsm_change.c:65
#define EC_SLAVE_WARN(slave, fmt, args...)
Convenience macro for printing slave-specific warnings to syslog.
Definition: slave.h:91
int ec_fsm_slave_action_process_dict(ec_fsm_slave_t *, ec_datagram_t *)
Check for pending SDO dictionary reads.
Definition: fsm_slave.c:448
EtherCAT datagram.
Definition: datagram.h:88
ec_sii_coe_details_t coe_details
CoE detail flags.
Definition: slave.h:185
void ec_fsm_slave_config_quick_start(ec_fsm_slave_config_t *fsm)
Start slave configuration state machine for "quick" SAFEOP->OP.
void ec_fsm_slave_state_soe_request(ec_fsm_slave_t *, ec_datagram_t *)
Slave state: SOE_REQUEST.
Definition: fsm_slave.c:1226
ec_internal_request_state_t state
Request state.
Definition: soe_request.h:58
static int ec_slave_reconnect_to_eoe_handler(ec_slave_t *slave)
try to reconnect to an existing EoE handler.
Definition: fsm_slave.c:249
size_t data_size
Size of FoE data.
Definition: foe_request.h:54
ec_fsm_soe_t fsm_soe
SoE state machine.
Definition: fsm_slave.h:83
Finite state machine of an EtherCAT slave.
Definition: fsm_slave.h:63
ec_datagram_t * datagram
Previous state datagram.
Definition: fsm_slave.h:69
struct list_head reg_requests
Register access requests.
Definition: slave.h:275
uint16_t working_counter
Working counter.
Definition: datagram.h:100
void ec_fsm_eoe_init(ec_fsm_eoe_t *fsm)
Constructor.
Definition: fsm_eoe.c:63
int ec_sdo_request_timed_out(const ec_sdo_request_t *req)
Checks, if the timeout was exceeded.
Definition: sdo_request.c:177
int ec_fsm_slave_action_process_foe(ec_fsm_slave_t *, ec_datagram_t *)
Check for pending FoE requests and process one.
Definition: fsm_slave.c:999
void ec_fsm_foe_transfer(ec_fsm_foe_t *fsm, ec_slave_t *slave, ec_foe_request_t *request)
Prepares an FoE transfer.
Definition: fsm_foe.c:160
int ec_fsm_slave_scan_exec(ec_fsm_slave_scan_t *fsm, ec_datagram_t *datagram)
Executes the current state of the state machine.
Acknowledge/Error bit (no actual state)
Definition: globals.h:172
int ec_fsm_coe_success(const ec_fsm_coe_t *fsm)
Returns, if the state machine terminated with success.
Definition: fsm_coe.c:259
void ec_fsm_slave_state_scan(ec_fsm_slave_t *, ec_datagram_t *)
Slave state: SCAN.
Definition: fsm_slave.c:282
ec_dict_request_t int_dict_request
Internal dictionary request.
Definition: fsm_slave.h:66
wait_queue_head_t request_queue
Wait queue for external requests from user space.
Definition: master.h:338
ec_sdo_request_t * sdo_request
SDO request to process.
Definition: fsm_slave.h:70
int ec_fsm_slave_action_process_reg(ec_fsm_slave_t *, ec_datagram_t *)
Check for pending register requests and process one.
Definition: fsm_slave.c:856
uint16_t station_address
Configured station address.
Definition: slave.h:222
const char * ec_device_names[2]
Device names.
Definition: module.c:472
int ec_fsm_slave_action_process_soe(ec_fsm_slave_t *, ec_datagram_t *)
Check for pending SoE requests and process one.
Definition: fsm_slave.c:1089
void ec_fsm_eoe_set_ip_param(ec_fsm_eoe_t *fsm, ec_slave_t *slave, ec_eoe_request_t *request)
Starts to set the EoE IP partameters of a slave.
Definition: fsm_eoe.c:89
int ec_fsm_slave_action_process_config_sdo(ec_fsm_slave_t *, ec_datagram_t *)
Check for pending internal SDO requests and process one.
Definition: fsm_slave.c:610
Global definitions and macros.
void ec_fsm_pdo_clear(ec_fsm_pdo_t *fsm)
Destructor.
Definition: fsm_pdo.c:90
EtherCAT master structure.
SAFEOP (mailbox communication and input update)
Definition: globals.h:168
ec_lock_t config_sem
Semaphore protecting the config_busy variable and the allow_config flag.
Definition: master.h:273
void ec_fsm_slave_state_sdo_request(ec_fsm_slave_t *, ec_datagram_t *)
Slave state: SDO_REQUEST.
Definition: fsm_slave.c:820
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:791
EtherCAT slave.
Definition: slave.h:214
ec_eoe_request_t * eoe_request
EoE request to process.
Definition: fsm_slave.h:76
ec_slave_t * slave
slave the FSM runs on
Definition: fsm_slave.h:64
void ec_fsm_mbg_transfer(ec_fsm_mbg_t *fsm, ec_slave_t *slave, ec_mbg_request_t *request)
Starts to transfer a mailbox gateway request to/from a slave.
struct list_head sdo_requests
SDO access requests.
Definition: slave.h:274
void ec_datagram_zero(ec_datagram_t *datagram)
Fills the datagram payload memory with zeros.
Definition: datagram.c:179
void ec_fsm_foe_init(ec_fsm_foe_t *fsm)
Constructor.
Definition: fsm_foe.c:105
ec_sii_image_t * sii_image
Current complete SII image.
Definition: slave.h:267
void ec_fsm_soe_transfer(ec_fsm_soe_t *fsm, ec_slave_t *slave, ec_soe_request_t *request)
Starts to transfer an IDN to/from a slave.
Definition: fsm_soe.c:132
int ec_fsm_soe_success(const ec_fsm_soe_t *fsm)
Returns, if the state machine terminated with success.
Definition: fsm_soe.c:179
struct list_head soe_requests
SoE requests.
Definition: slave.h:277
ec_datagram_state_t state
State.
Definition: datagram.h:101
CANopen over EtherCAT.
Definition: globals.h:184
ec_slave_config_t * config
Current configuration.
Definition: slave.h:235
struct list_head reg_requests
List of register requests.
Definition: slave_config.h:149
uint8_t enable_sdo_info
SDO information service available.
Definition: globals.h:194
uint8_t sdo_dictionary_fetched
Dictionary has been fetched.
Definition: slave.h:271
struct list_head sdo_requests
List of SDO requests.
Definition: slave_config.h:146
uint16_t mailbox_protocols
Supported mailbox protocols.
Definition: slave.h:172
void ec_fsm_slave_state_config(ec_fsm_slave_t *, ec_datagram_t *)
Slave state: CONFIG.
Definition: fsm_slave.c:414
unsigned int debug_level
Master debug level.
Definition: master.h:310
#define EC_SLAVE_ERR(slave, fmt, args...)
Convenience macro for printing slave-specific errors to syslog.
Definition: slave.h:77
struct list_head list
List item.
void ec_fsm_slave_state_reg_request(ec_fsm_slave_t *, ec_datagram_t *)
Slave state: Register request.
Definition: fsm_slave.c:947
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:209
ec_fsm_slave_config_t fsm_slave_config
slave config state machine.
Definition: fsm_slave.h:91
void ec_fsm_mbg_clear(ec_fsm_mbg_t *fsm)
Destructor.
ec_soe_request_t * soe_request
SoE request to process.
Definition: fsm_slave.h:74
void ec_fsm_pdo_init(ec_fsm_pdo_t *fsm, ec_fsm_coe_t *fsm_coe)
Constructor.
Definition: fsm_pdo.c:74
int ec_fsm_mbg_success(const ec_fsm_mbg_t *fsm)
Returns, if the state machine terminated with success.
void ec_fsm_coe_clear(ec_fsm_coe_t *fsm)
Destructor.
Definition: fsm_coe.c:189
ec_fsm_eoe_t fsm_eoe
EoE state machine.
Definition: fsm_slave.h:85
int ec_fsm_eoe_success(const ec_fsm_eoe_t *fsm)
Returns, if the state machine terminated with success.
Definition: fsm_eoe.c:131
Ethernet over EtherCAT.
Definition: globals.h:183
int ec_fsm_slave_exec(ec_fsm_slave_t *fsm, ec_datagram_t *datagram)
Executes the current state of the state machine.
Definition: fsm_slave.c:183
ec_master_t * master
Master owning the slave.
Definition: slave.h:216
void ec_fsm_change_clear(ec_fsm_change_t *fsm)
Destructor.
Definition: fsm_change.c:78
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:320
Values read and written by the master.
Definition: ecrt.h:440
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:295
struct list_head list
List item.
Definition: foe_request.h:51
void ec_fsm_coe_dictionary(ec_fsm_coe_t *fsm, ec_slave_t *slave)
Starts reading a slaves' SDO dictionary.
Definition: fsm_coe.c:199
void ec_fsm_slave_state_dict_request(ec_fsm_slave_t *, ec_datagram_t *)
Slave state: DICT_REQUEST.
Definition: fsm_slave.c:558
Values read by the master.
Definition: ecrt.h:439
CANopen dictionary request.
Definition: dict_request.h:48
ec_device_index_t device_index
Device via which the datagram shall be / was sent.
Definition: datagram.h:91
void ec_fsm_mbg_init(ec_fsm_mbg_t *fsm)
Constructor.
void ec_fsm_slave_state_ready(ec_fsm_slave_t *, ec_datagram_t *)
Slave state: READY.
Definition: fsm_slave.c:706
void ec_fsm_slave_state_acknowledge(ec_fsm_slave_t *, ec_datagram_t *)
Slave state: ACKNOWLEDGE.
Definition: fsm_slave.c:391
#define EC_SLAVE_INFO(slave, fmt, args...)
Convenience macro for printing slave-specific information to syslog.
Definition: slave.h:63
struct list_head list
list item
Definition: ethernet.h:73
struct list_head list
List item.
Definition: dict_request.h:49
void ec_fsm_coe_init(ec_fsm_coe_t *fsm)
Constructor.
Definition: fsm_coe.c:177
Ethernet-over-EtherCAT set IP parameter request.
Definition: eoe_request.h:49
ec_fsm_mbg_t fsm_mbg
MBox Gateway state machine.
Definition: fsm_slave.h:87
void ec_fsm_eoe_clear(ec_fsm_eoe_t *fsm)
Destructor.
Definition: fsm_eoe.c:79
int ec_fsm_mbg_exec(ec_fsm_mbg_t *fsm, ec_datagram_t *datagram)
Executes the current state of the state machine.
uint8_t valid_mbox_data
Received mailbox data is valid.
Definition: slave.h:297
INIT state (no mailbox communication, no IO)
Definition: globals.h:162
int ec_datagram_fprw(ec_datagram_t *datagram, uint16_t configured_address, uint16_t mem_address, size_t data_size)
Initializes an EtherCAT FPRW datagram.
Definition: datagram.c:345
uint16_t effective_alias
Effective alias address.
Definition: slave.h:223
ec_internal_request_state_t state
Request state.
Definition: eoe_request.h:51
struct list_head foe_requests
FoE requests.
Definition: slave.h:276
void ec_eoe_link_slave(ec_eoe_t *eoe, ec_slave_t *slave)
EoE link slave.
Definition: ethernet.c:412
int ec_fsm_slave_action_process_sdo(ec_fsm_slave_t *, ec_datagram_t *)
Check for pending SDO requests and process one.
Definition: fsm_slave.c:770
int ec_fsm_foe_exec(ec_fsm_foe_t *fsm, ec_datagram_t *datagram)
Executes the current state of the state machine.
Definition: fsm_foe.c:127
void ec_datagram_print_state(const ec_datagram_t *datagram)
Prints the state of a datagram.
Definition: datagram.c:587
int ec_eoe_auto_init(ec_eoe_t *eoe, ec_slave_t *slave)
EoE auto constructor for slave.
Definition: ethernet.c:385
void ec_fsm_slave_scan_start(ec_fsm_slave_scan_t *fsm)
Start slave scan state machine.
Mailbox functionality.
struct list_head list
Used for execution list.
Definition: fsm_slave.h:65
uint8_t * data
Pointer to data memory.
Definition: reg_request.h:51
ec_fsm_slave_scan_t fsm_slave_scan
slave scan state machine
Definition: fsm_slave.h:90
#define EC_STATE_STRING_SIZE
Minimum size of a buffer used with ec_state_string().
Definition: globals.h:65
ec_fsm_pdo_t fsm_pdo
PDO configuration state machine.
Definition: fsm_slave.h:88
Number of directions.
Definition: ecrt.h:441
struct list_head list
List item.
Definition: sdo_request.h:49
void ec_fsm_slave_init(ec_fsm_slave_t *fsm, ec_slave_t *slave)
Constructor.
Definition: fsm_slave.c:74
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:235
ec_mbg_request_t * mbg_request
MBox Gateway request to process.
Definition: fsm_slave.h:78
EtherCAT slave request state machine.
int ec_fsm_slave_config_exec(ec_fsm_slave_config_t *fsm, ec_datagram_t *datagram)
Executes the current state of the state machine.
ec_direction_t dir
Direction.
Definition: reg_request.h:52
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:105
int ec_fsm_change_exec(ec_fsm_change_t *fsm, ec_datagram_t *datagram)
Executes the current state of the state machine.
Definition: fsm_change.c:122
wait_queue_head_t config_queue
Queue for processes that wait for slave configuration.
Definition: master.h:275
void ec_fsm_slave_config_clear(ec_fsm_slave_config_t *fsm)
Destructor.
ec_fsm_foe_t fsm_foe
FoE state machine.
Definition: fsm_slave.h:82
void ec_fsm_soe_init(ec_fsm_soe_t *fsm)
Constructor.
Definition: fsm_soe.c:109
void ec_fsm_slave_config_init(ec_fsm_slave_config_t *fsm, ec_slave_t *slave, 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.
void ec_fsm_soe_clear(ec_fsm_soe_t *fsm)
Destructor.
Definition: fsm_soe.c:122
uint8_t * data
Datagram payload.
Definition: datagram.h:95
void ec_dict_request_init(ec_dict_request_t *req)
Dictionary request constructor.
Definition: dict_request.c:43
struct list_head dict_requests
Dictionary read requests.
Definition: slave.h:280
ec_fsm_coe_t fsm_coe
CoE state machine.
Definition: fsm_slave.h:81
int ec_fsm_slave_config_success(const ec_fsm_slave_config_t *fsm)
int ec_fsm_slave_set_unready(ec_fsm_slave_t *fsm)
Sets the current state of the state machine to IDLE.
Definition: fsm_slave.c:661
void ec_fsm_slave_scan_clear(ec_fsm_slave_scan_t *fsm)
Destructor.
EtherCAT slave configuration structure.
ec_sii_t sii
Extracted SII data.
Definition: slave.h:207
FoE request.
Definition: foe_request.h:50
ec_device_index_t device_index
Index of device the slave responds on.
Definition: slave.h:217
int ec_fsm_soe_exec(ec_fsm_soe_t *fsm, ec_datagram_t *datagram)
Executes the current state of the state machine.
Definition: fsm_soe.c:154
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:212
unsigned int index
Index.
Definition: master.h:203
int ec_fsm_slave_action_config(ec_fsm_slave_t *, ec_datagram_t *)
Check for pending configuration.
Definition: fsm_slave.c:330
Values written by the master.
Definition: ecrt.h:438
Received (dequeued).
Definition: datagram.h:78
Ethernet over EtherCAT (EoE) handler.
Definition: ethernet.h:71
int ec_fsm_slave_action_scan(ec_fsm_slave_t *, ec_datagram_t *)
Check for pending scan.
Definition: fsm_slave.c:225
uint8_t scan_required
Scan required.
Definition: slave.h:270
unsigned int error_flag
Stop processing after an error.
Definition: slave.h:239
void ec_fsm_slave_state_idle(ec_fsm_slave_t *, ec_datagram_t *)
Slave state: IDLE.
Definition: fsm_slave.c:694
void ec_fsm_slave_scan_init(ec_fsm_slave_scan_t *fsm, ec_slave_t *slave, ec_fsm_slave_config_t *fsm_slave_config, ec_fsm_pdo_t *fsm_pdo)
Constructor.
EtherCAT master.
Definition: master.h:202
struct list_head list
List item.
Definition: reg_request.h:49
ec_slave_state_t requested_state
Requested application state.
Definition: slave.h:236
struct list_head eoe_requests
EoE set IP parameter requests.
Definition: slave.h:278
void ec_fsm_slave_state_mbg_request(ec_fsm_slave_t *, ec_datagram_t *)
Slave state: MBG_REQUEST.
Definition: fsm_slave.c:1192
int ec_fsm_slave_action_process_eoe(ec_fsm_slave_t *, ec_datagram_t *)
Check for pending EoE IP parameter requests and process one.
Definition: fsm_slave.c:1262
uint16_t last_al_error
Last AL state error code.
Definition: slave.h:238
void(* state)(ec_fsm_slave_t *, ec_datagram_t *)
State function.
Definition: fsm_slave.h:68
unsigned int config_busy
State of slave configuration.
Definition: master.h:272
struct list_head list
List item.
Definition: eoe_request.h:50
unknown state
Definition: globals.h:160
unsigned int force_config
Force (re-)configuration.
Definition: slave.h:240
ec_internal_request_state_t state
FoE request state.
Definition: foe_request.h:64
int ec_fsm_change_success(ec_fsm_change_t *fsm)
Returns, if the state machine terminated with success.
Definition: fsm_change.c:148
unsigned int has_general
General category present.
Definition: slave.h:179
Sercos-over-EtherCAT request.
Definition: soe_request.h:48
ec_internal_request_state_t state
SDO request state.
Definition: dict_request.h:50