IgH EtherCAT Master  1.5.2
fsm_foe.c
Go to the documentation of this file.
1 /******************************************************************************
2  *
3  * $Id$
4  *
5  * Copyright (C) 2008 Olav Zarges, imc Messsysteme GmbH
6  * 2013 Florian Pose <fp@igh-essen.com>
7  *
8  * This file is part of the IgH EtherCAT Master.
9  *
10  * The IgH EtherCAT Master is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU General Public License version 2, as
12  * published by the Free Software Foundation.
13  *
14  * The IgH EtherCAT Master is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
17  * Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License along
20  * with the IgH EtherCAT Master; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
22  *
23  * ---
24  *
25  * The license mentioned above concerns the source code only. Using the
26  * EtherCAT technology and brand is only permitted in compliance with the
27  * industrial property and similar rights of Beckhoff Automation GmbH.
28  *
29  *****************************************************************************/
30 
35 /*****************************************************************************/
36 
37 #include "globals.h"
38 #include "master.h"
39 #include "mailbox.h"
40 #include "fsm_foe.h"
41 
42 /*****************************************************************************/
43 
47 #define EC_FSM_FOE_TIMEOUT_JIFFIES (3 * HZ)
48 
51 #define EC_FOE_HEADER_SIZE 6
52 // uint8_t OpCode
53 // uint8_t reserved
54 // uint32_t PacketNo, Password, ErrorCode
55 
56 //#define DEBUG_FOE
57 
58 /*****************************************************************************/
59 
62 enum {
69 };
70 
71 /*****************************************************************************/
72 
77 
78 void ec_foe_set_tx_error(ec_fsm_foe_t *, uint32_t);
79 void ec_foe_set_rx_error(ec_fsm_foe_t *, uint32_t);
80 
83 
86 
90 
92 
97 
100 
101 /*****************************************************************************/
102 
106  ec_fsm_foe_t *fsm
107  )
108 {
109  fsm->state = NULL;
110  fsm->datagram = NULL;
111 }
112 
113 /*****************************************************************************/
114 
118 {
119 }
120 
121 /*****************************************************************************/
122 
128  ec_fsm_foe_t *fsm,
129  ec_datagram_t *datagram
130  )
131 {
132  if (fsm->state == ec_fsm_foe_end || fsm->state == ec_fsm_foe_error)
133  return 0;
134 
135  fsm->state(fsm, datagram);
136 
137  if (fsm->state == ec_fsm_foe_end || fsm->state == ec_fsm_foe_error) {
138  fsm->datagram = NULL;
139  return 0;
140  }
141 
142  fsm->datagram = datagram;
143  return 1;
144 }
145 
146 /*****************************************************************************/
147 
152 {
153  return fsm->state == ec_fsm_foe_end;
154 }
155 
156 /*****************************************************************************/
157 
161  ec_fsm_foe_t *fsm,
162  ec_slave_t *slave,
163  ec_foe_request_t *request
164  )
165 {
166  fsm->slave = slave;
167  fsm->request = request;
168 
169  fsm->buffer_offset = 0;
170  if (request->dir == EC_DIR_OUTPUT) {
171  fsm->buffer_size = fsm->request->data_size;
173  } else {
174  fsm->buffer_size = fsm->request->buffer_size;
176  }
177 }
178 
179 /*****************************************************************************/
180 
184  ec_fsm_foe_t *fsm,
185  ec_datagram_t *datagram
186  )
187 {
188 #ifdef DEBUG_FOE
189  EC_SLAVE_DBG(fsm->slave, 0, "%s()\n", __func__);
190 #endif
191 }
192 
193 /*****************************************************************************/
194 
198  ec_fsm_foe_t *fsm,
199  ec_datagram_t *datagram
200  )
201 {
202 #ifdef DEBUG_FOE
203  EC_SLAVE_DBG(fsm->slave, 0, "%s()\n", __func__);
204 #endif
205 }
206 
207 /*****************************************************************************/
208 
214  ec_fsm_foe_t *fsm,
215  ec_datagram_t *datagram
216  )
217 {
218  size_t remaining_size, current_size;
219  uint8_t *data;
220 
221  remaining_size = fsm->buffer_size - fsm->buffer_offset;
222  current_size = fsm->slave->configured_tx_mailbox_size
224 
225  if (remaining_size < current_size) {
226  current_size = remaining_size;
227  fsm->last_packet = 1;
228  }
229 
230  data = ec_slave_mbox_prepare_send(fsm->slave,
231  datagram, EC_MBOX_TYPE_FOE, current_size + EC_FOE_HEADER_SIZE);
232  if (IS_ERR(data)) {
233  return -1;
234  }
235 
236  EC_WRITE_U16(data, EC_FOE_OPCODE_DATA); // OpCode = DataBlock req.
237  EC_WRITE_U32(data + 2, fsm->packet_no); // PacketNo, Password
238 #ifdef DEBUG_FOE
239  EC_SLAVE_DBG(fsm->slave, 0, "sending opcode %u packet %u\n",
241 #endif
242 
243  memcpy(data + EC_FOE_HEADER_SIZE,
244  fsm->request->buffer + fsm->buffer_offset, current_size);
245  fsm->current_size = current_size;
246 
247  return 0;
248 }
249 
250 /*****************************************************************************/
251 
257  ec_fsm_foe_t *fsm,
258  ec_datagram_t *datagram
259  )
260 {
261  size_t current_size;
262  uint8_t *data;
263 
264  current_size = strlen(fsm->request->file_name);
265 
266  data = ec_slave_mbox_prepare_send(fsm->slave, datagram,
267  EC_MBOX_TYPE_FOE, current_size + EC_FOE_HEADER_SIZE);
268  if (IS_ERR(data)) {
269  return -1;
270  }
271 
272  EC_WRITE_U16(data, EC_FOE_OPCODE_WRQ); // fsm write request
273  EC_WRITE_U32(data + 2, fsm->request->password); // password
274 #ifdef DEBUG_FOE
275  EC_SLAVE_DBG(fsm->slave, 0, "sending opcode %u\n",
277 #endif
278 
279  memcpy(data + EC_FOE_HEADER_SIZE, fsm->request->file_name, current_size);
280 
281  return 0;
282 }
283 
284 /*****************************************************************************/
285 
289  ec_fsm_foe_t *fsm,
290  ec_datagram_t *datagram
291  )
292 {
293  ec_slave_t *slave = fsm->slave;
294 
295  fsm->buffer_offset = 0;
296  fsm->current_size = 0;
297  fsm->packet_no = 0;
298  fsm->last_packet = 0;
299 
300 #ifdef DEBUG_FOE
301  EC_SLAVE_DBG(fsm->slave, 0, "%s()\n", __func__);
302 #endif
303 
304  if (!slave->sii_image) {
306  EC_SLAVE_ERR(slave, "Slave cannot process FoE write request."
307  " SII data not available.\n");
308  return;
309  }
310 
311  if (!(slave->sii_image->sii.mailbox_protocols & EC_MBOX_FOE)) {
313  EC_SLAVE_ERR(slave, "Slave does not support FoE!\n");
314  return;
315  }
316 
317  if (ec_foe_prepare_wrq_send(fsm, datagram)) {
319  return;
320  }
321 
323 }
324 
325 /*****************************************************************************/
326 
330  ec_fsm_foe_t *fsm,
331  ec_datagram_t *datagram
332  )
333 {
334  ec_slave_t *slave = fsm->slave;
335 
336 #ifdef DEBUG_FOE
337  EC_SLAVE_DBG(fsm->slave, 0, "%s()\n", __func__);
338 #endif
339 
340  if (fsm->datagram->state != EC_DATAGRAM_RECEIVED) {
343  EC_SLAVE_ERR(slave, "Failed to receive FoE mailbox check datagram: ");
345  return;
346  }
347 
348  if (fsm->datagram->working_counter != 1) {
351  EC_SLAVE_ERR(slave, "Reception of FoE mailbox check datagram"
352  " failed: ");
354  return;
355  }
356 
357  if (!ec_slave_mbox_check(fsm->datagram)) {
358  // slave did not put anything in the mailbox yet
359 
360  // check that data is not already received by another read request
361  if (slave->mbox_foe_data.payload_size > 0) {
364  fsm->state(fsm, datagram);
365  return;
366  }
367 
368  if (time_after(fsm->datagram->jiffies_received,
372  EC_SLAVE_ERR(slave, "Timeout while waiting for ack response.\n");
373  return;
374  }
375 
376  ec_slave_mbox_prepare_check(slave, datagram); // can not fail.
377  fsm->retries = EC_FSM_RETRIES;
378  return;
379  }
380 
381  // Fetch response
382  ec_slave_mbox_prepare_fetch(slave, datagram); // can not fail.
383 
384  fsm->retries = EC_FSM_RETRIES;
386 }
387 
388 /*****************************************************************************/
389 
393  ec_fsm_foe_t *fsm,
394  ec_datagram_t *datagram
395  )
396 {
397  ec_slave_t *slave = fsm->slave;
398 
399 #ifdef DEBUG_FOE
400  EC_SLAVE_DBG(fsm->slave, 0, "%s()\n", __func__);
401 #endif
402 
403  if (fsm->datagram->state != EC_DATAGRAM_RECEIVED) {
406  EC_SLAVE_ERR(slave, "Failed to receive FoE ack response datagram: ");
408  return;
409  }
410 
411  if (fsm->datagram->working_counter != 1) {
412  // only an error if data has not already been read by another read request
413  if (slave->mbox_foe_data.payload_size == 0) {
416  EC_SLAVE_ERR(slave, "Reception of FoE ack response failed: ");
418  return;
419  }
420  }
423  fsm->state(fsm, datagram);
424 }
425 
426 /*****************************************************************************/
427 
431  ec_fsm_foe_t *fsm,
432  ec_datagram_t *datagram
433  )
434 {
435  ec_slave_t *slave = fsm->slave;
436  uint8_t *data, mbox_prot;
437  uint8_t opCode;
438  size_t rec_size;
439 
440  // process the data available or initiate a new mailbox read check
441  if (slave->mbox_foe_data.payload_size > 0) {
442  slave->mbox_foe_data.payload_size = 0;
443  } else {
444  // initiate a new mailbox read check if required data is not available
445  if (ec_read_mbox_locked(slave)) {
446  // await current read request and mark the datagram as invalid
447  datagram->state = EC_DATAGRAM_INVALID;
448  } else {
449  ec_slave_mbox_prepare_check(slave, datagram); // can not fail.
451  }
452  return;
453  }
454 
455  data = ec_slave_mbox_fetch(slave, &slave->mbox_foe_data, &mbox_prot, &rec_size);
456  if (IS_ERR(data)) {
458  return;
459  }
460 
461  if (mbox_prot != EC_MBOX_TYPE_FOE) {
463  EC_SLAVE_ERR(slave, "Received mailbox protocol 0x%02X as response.\n",
464  mbox_prot);
465  return;
466  }
467 
468  opCode = EC_READ_U8(data);
469 #ifdef DEBUG_FOE
470  EC_SLAVE_DBG(fsm->slave, 0, "received opcode %u\n", opCode);
471 #endif
472 
473  if (opCode == EC_FOE_OPCODE_BUSY) {
474  // slave not ready
475  if (ec_foe_prepare_data_send(fsm, datagram)) {
477  EC_SLAVE_ERR(slave, "Slave is busy.\n");
478  return;
479  }
481  return;
482  }
483 
484  if (opCode == EC_FOE_OPCODE_ERR) {
485  fsm->request->error_code = EC_READ_U32(data + 2);
486  EC_SLAVE_ERR(slave, "Received FoE Error Request (code 0x%08x).\n",
487  fsm->request->error_code);
488  if (rec_size > 6 && data[6]) {
489  uint8_t text[256];
490  strncpy(text, data + 6, min(rec_size - 6, sizeof(text)));
491  text[sizeof(text)-1] = 0;
492  EC_SLAVE_ERR(slave, "FoE Error Text: %s\n", text);
493  }
495  return;
496  }
497 
498  if (opCode == EC_FOE_OPCODE_ACK) {
499  fsm->packet_no++;
500  fsm->buffer_offset += fsm->current_size;
501  fsm->request->progress = fsm->buffer_offset;
502 
503  if (fsm->last_packet) {
504  fsm->state = ec_fsm_foe_end;
505  return;
506  }
507 
508  if (ec_foe_prepare_data_send(fsm, datagram)) {
510  return;
511  }
513  return;
514  }
516 }
517 
518 /*****************************************************************************/
519 
526  ec_fsm_foe_t *fsm,
527  ec_datagram_t *datagram
528  )
529 {
530  ec_slave_t *slave = fsm->slave;
531 
532 #ifdef DEBUG_FOE
533  EC_SLAVE_DBG(fsm->slave, 0, "%s()\n", __func__);
534 #endif
535 
536  if (fsm->datagram->state != EC_DATAGRAM_RECEIVED) {
538  EC_SLAVE_ERR(slave, "Failed to send FoE WRQ: ");
540  return;
541  }
542 
543  if (fsm->datagram->working_counter != 1) {
544  // slave did not put anything in the mailbox yet
546  EC_SLAVE_ERR(slave, "Reception of FoE WRQ failed: ");
548  return;
549  }
550 
551  fsm->jiffies_start = fsm->datagram->jiffies_sent;
552 
553  // mailbox read check is skipped if a read request is already ongoing
554  if (ec_read_mbox_locked(slave)) {
556  // the datagram is not used and marked as invalid
557  datagram->state = EC_DATAGRAM_INVALID;
558  } else {
559  ec_slave_mbox_prepare_check(slave, datagram); // can not fail.
560  fsm->retries = EC_FSM_RETRIES;
562  }
563 }
564 
565 /*****************************************************************************/
566 
573  ec_fsm_foe_t *fsm,
574  ec_datagram_t *datagram
575  )
576 {
577  ec_slave_t *slave = fsm->slave;
578 
579 #ifdef DEBUG_FOE
580  EC_SLAVE_DBG(fsm->slave, 0, "%s()\n", __func__);
581 #endif
582 
583  if (fsm->datagram->state != EC_DATAGRAM_RECEIVED) {
585  EC_SLAVE_ERR(slave, "Failed to receive FoE ack response datagram: ");
587  return;
588  }
589 
590  if (fsm->datagram->working_counter != 1) {
592  EC_SLAVE_ERR(slave, "Reception of FoE data send failed: ");
594  return;
595  }
596 
597  fsm->jiffies_start = jiffies;
598 
599  // mailbox read check is skipped if a read request is already ongoing
600  if (ec_read_mbox_locked(slave)) {
602  // the datagram is not used and marked as invalid
603  datagram->state = EC_DATAGRAM_INVALID;
604  } else {
605  ec_slave_mbox_prepare_check(slave, datagram);
606  fsm->retries = EC_FSM_RETRIES;
608  }
609 }
610 
611 /*****************************************************************************/
612 
618  ec_fsm_foe_t *fsm,
619  ec_datagram_t *datagram
620  )
621 {
622  size_t current_size;
623  uint8_t *data;
624 
625  current_size = strlen(fsm->request->file_name);
626 
627  data = ec_slave_mbox_prepare_send(fsm->slave, datagram,
628  EC_MBOX_TYPE_FOE, current_size + EC_FOE_HEADER_SIZE);
629  if (IS_ERR(data)) {
630  return -1;
631  }
632 
633  EC_WRITE_U16(data, EC_FOE_OPCODE_RRQ); // fsm read request
634  EC_WRITE_U32(data + 2, fsm->request->password); // password
635  memcpy(data + EC_FOE_HEADER_SIZE, fsm->request->file_name, current_size);
636 #ifdef DEBUG_FOE
637  EC_SLAVE_DBG(fsm->slave, 0, "sending opcode %u\n", EC_FOE_OPCODE_RRQ);
638 #endif
639 
640  if (fsm->slave->master->debug_level) {
641  EC_SLAVE_DBG(fsm->slave, 1, "FoE Read Request:\n");
642  ec_print_data(data, current_size + EC_FOE_HEADER_SIZE);
643  }
644 
645  return 0;
646 }
647 
648 /*****************************************************************************/
649 
655  ec_fsm_foe_t *fsm,
656  ec_datagram_t *datagram
657  )
658 {
659  uint8_t *data;
660 
661  data = ec_slave_mbox_prepare_send(fsm->slave, datagram,
662  EC_MBOX_TYPE_FOE, EC_FOE_HEADER_SIZE);
663  if (IS_ERR(data)) {
664  return -1;
665  }
666 
668  EC_WRITE_U32(data + 2, fsm->packet_no);
669 #ifdef DEBUG_FOE
670  EC_SLAVE_DBG(fsm->slave, 0, "sending opcode %u packet %u\n",
672 #endif
673 
674  return 0;
675 }
676 
677 /*****************************************************************************/
678 
685  ec_fsm_foe_t *fsm,
686  ec_datagram_t *datagram
687  )
688 {
689  ec_slave_t *slave = fsm->slave;
690 
691 #ifdef DEBUG_FOE
692  EC_SLAVE_DBG(fsm->slave, 0, "%s()\n", __func__);
693 #endif
694 
695  if (fsm->datagram->state != EC_DATAGRAM_RECEIVED) {
698  EC_SLAVE_ERR(slave, "Failed to send FoE RRQ: ");
700  return;
701  }
702 
703  if (fsm->datagram->working_counter != 1) {
704  // slave did not put anything in the mailbox yet
707  EC_SLAVE_ERR(slave, "Reception of FoE RRQ failed: ");
709  return;
710  }
711 
712  fsm->jiffies_start = fsm->datagram->jiffies_sent;
713 
714  // mailbox read check is skipped if a read request is already ongoing
715  if (ec_read_mbox_locked(slave)) {
717  // the datagram is not used and marked as invalid
718  datagram->state = EC_DATAGRAM_INVALID;
719  } else {
720  ec_slave_mbox_prepare_check(slave, datagram); // can not fail.
721  fsm->retries = EC_FSM_RETRIES;
723  }
724 }
725 
726 /*****************************************************************************/
727 
731  ec_fsm_foe_t *fsm,
732  ec_datagram_t *datagram
733  )
734 {
735  ec_slave_t *slave = fsm->slave;
736 
737  fsm->buffer_offset = 0;
738  fsm->packet_no = 1;
739  fsm->last_packet = 0;
740 
741 #ifdef DEBUG_FOE
742  EC_SLAVE_DBG(fsm->slave, 0, "%s()\n", __func__);
743 #endif
744 
745  if (!slave->sii_image) {
747  EC_SLAVE_ERR(slave, "Slave cannot process FoE read request."
748  " SII data not available.\n");
749  return;
750  }
751 
752  if (!(slave->sii_image->sii.mailbox_protocols & EC_MBOX_FOE)) {
754  EC_SLAVE_ERR(slave, "Slave does not support FoE!\n");
755  return;
756  }
757 
758  if (ec_foe_prepare_rrq_send(fsm, datagram)) {
760  return;
761  }
762 
764 }
765 
766 /*****************************************************************************/
767 
771  ec_fsm_foe_t *fsm,
772  ec_datagram_t *datagram
773  )
774 {
775  ec_slave_t *slave = fsm->slave;
776 
777 #ifdef DEBUG_FOE
778  EC_SLAVE_DBG(fsm->slave, 0, "%s()\n", __func__);
779 #endif
780 
781  if (fsm->datagram->state != EC_DATAGRAM_RECEIVED) {
784  EC_SLAVE_ERR(slave, "Failed to send FoE DATA READ: ");
786  return;
787  }
788 
789  if (fsm->datagram->working_counter != 1) {
792  EC_SLAVE_ERR(slave, "Reception of FoE DATA READ: ");
794  return;
795  }
796 
797  if (!ec_slave_mbox_check(fsm->datagram)) {
798  // check that data is not already received by another read request
799  if (slave->mbox_foe_data.payload_size > 0) {
802  fsm->state(fsm, datagram);
803  return;
804  }
805 
806  if (time_after(fsm->datagram->jiffies_received,
810  EC_SLAVE_ERR(slave, "Timeout while waiting for ack response.\n");
811  return;
812  }
813 
814  ec_slave_mbox_prepare_check(slave, datagram); // can not fail.
815  fsm->retries = EC_FSM_RETRIES;
816  return;
817  }
818 
819  // Fetch response
820  ec_slave_mbox_prepare_fetch(slave, datagram); // can not fail.
821 
822  fsm->retries = EC_FSM_RETRIES;
824 }
825 
826 /*****************************************************************************/
827 
831  ec_fsm_foe_t *fsm,
832  ec_datagram_t *datagram
833  )
834 {
835  ec_slave_t *slave = fsm->slave;
836 
837 #ifdef DEBUG_FOE
838  EC_SLAVE_DBG(fsm->slave, 0, "%s()\n", __func__);
839 #endif
840 
841  if (fsm->datagram->state != EC_DATAGRAM_RECEIVED) {
844  EC_SLAVE_ERR(slave, "Failed to receive FoE DATA READ datagram: ");
846  return;
847  }
848 
849  if (fsm->datagram->working_counter != 1) {
850  // only an error if data has not already been read by another read request
851  if (slave->mbox_foe_data.payload_size == 0) {
854  EC_SLAVE_ERR(slave, "Reception of FoE DATA READ failed: ");
856  return;
857  }
858  }
861  fsm->state(fsm, datagram);
862 }
863 
864 /*****************************************************************************/
865 
869  ec_fsm_foe_t *fsm,
870  ec_datagram_t *datagram
871  )
872 {
873  ec_slave_t *slave = fsm->slave;
874  size_t rec_size;
875  uint8_t *data, opCode, packet_no, mbox_prot;
876 
877  // process the data available or initiate a new mailbox read check
878  if (slave->mbox_foe_data.payload_size > 0) {
879  slave->mbox_foe_data.payload_size = 0;
880  } else {
881  // initiate a new mailbox read check if required data is not available
882  if (ec_read_mbox_locked(slave)) {
883  // await current read request and mark the datagram as invalid
884  datagram->state = EC_DATAGRAM_INVALID;
885  } else {
886  ec_slave_mbox_prepare_check(slave, datagram); // can not fail.
888  }
889  return;
890  }
891 
892  data = ec_slave_mbox_fetch(slave, &slave->mbox_foe_data, &mbox_prot, &rec_size);
893  if (IS_ERR(data)) {
895  return;
896  }
897 
898  if (mbox_prot != EC_MBOX_TYPE_FOE) {
899  EC_SLAVE_ERR(slave, "Received mailbox protocol 0x%02X as response.\n",
900  mbox_prot);
902  return;
903  }
904 
905  opCode = EC_READ_U8(data);
906 #ifdef DEBUG_FOE
907  EC_SLAVE_DBG(fsm->slave, 0, "received opcode %u\n", opCode);
908 #endif
909 
910  if (opCode == EC_FOE_OPCODE_BUSY) {
911  fsm->packet_no--;
912  if (ec_foe_prepare_send_ack(fsm, datagram)) {
914  } else {
916  }
917 #ifdef DEBUG_FOE
918  EC_SLAVE_DBG(fsm->slave, 0, "%s() busy. Next pkt %u\n", __func__,
919  fsm->packet_no);
920 #endif
921  return;
922  }
923 
924  if (opCode == EC_FOE_OPCODE_ERR) {
925  fsm->request->error_code = EC_READ_U32(data + 2);
926  EC_SLAVE_ERR(slave, "Received FoE Error Request (code 0x%08x).\n",
927  fsm->request->error_code);
928  if (rec_size > 6 && data[6]) {
929  uint8_t text[256];
930  strncpy(text, data + 6, min(rec_size - 6, sizeof(text)));
931  text[sizeof(text)-1] = 0;
932  EC_SLAVE_ERR(slave, "FoE Error Text: %s\n", text);
933  }
935  return;
936  }
937 
938  if (opCode != EC_FOE_OPCODE_DATA) {
939  EC_SLAVE_ERR(slave, "Received OPCODE %x, expected %x.\n",
940  opCode, EC_FOE_OPCODE_DATA);
941  fsm->request->error_code = 0x00000000;
943  return;
944  }
945 
946  packet_no = EC_READ_U32(data + 2);
947  if (packet_no != fsm->packet_no) {
948  EC_SLAVE_ERR(slave, "Received packet number %u, expected %u.\n",
949  packet_no, fsm->packet_no);
951  return;
952  }
953 
954  rec_size -= EC_FOE_HEADER_SIZE;
955 
956  if (fsm->buffer_size >= fsm->buffer_offset + rec_size) {
957  memcpy(fsm->request->buffer + fsm->buffer_offset,
958  data + EC_FOE_HEADER_SIZE, rec_size);
959  fsm->buffer_offset += rec_size;
960  fsm->request->progress = fsm->buffer_offset;
961  }
962 
963  fsm->last_packet =
965  != slave->configured_rx_mailbox_size);
966 
967  if (fsm->last_packet ||
970  <= fsm->buffer_size) {
971  // either it was the last packet or a new packet will fit into the
972  // delivered buffer
973 #ifdef DEBUG_FOE
974  EC_SLAVE_DBG(fsm->slave, 0, "last_packet=true\n");
975 #endif
976  if (ec_foe_prepare_send_ack(fsm, datagram)) {
978  return;
979  }
980 
982  }
983  else {
984  // no more data fits into the delivered buffer
985  // ... wait for new read request
986  EC_SLAVE_ERR(slave, "Data do not fit in receive buffer!\n");
987  printk(" rx_buffer_size = %d\n", fsm->buffer_size);
988  printk("rx_buffer_offset = %d\n", fsm->buffer_offset);
989  printk(" rec_size = %zd\n", rec_size);
990  printk(" rx_mailbox_size = %d\n", slave->configured_rx_mailbox_size);
991  printk(" rx_last_packet = %d\n", fsm->last_packet);
992  fsm->request->data_size = fsm->buffer_offset;
994  }
995 }
996 
997 /*****************************************************************************/
998 
1002  ec_fsm_foe_t *fsm,
1003  ec_datagram_t *datagram
1004  )
1005 {
1006  ec_slave_t *slave = fsm->slave;
1007 
1008 #ifdef DEBUG_FOE
1009  EC_SLAVE_DBG(fsm->slave, 0, "%s()\n", __func__);
1010 #endif
1011 
1012  if (fsm->datagram->state != EC_DATAGRAM_RECEIVED) {
1014  EC_SLAVE_ERR(slave, "Failed to send FoE ACK: ");
1016  return;
1017  }
1018 
1019  if (fsm->datagram->working_counter != 1) {
1020  // slave did not put anything into the mailbox yet
1022  EC_SLAVE_ERR(slave, "Reception of FoE ACK failed: ");
1024  return;
1025  }
1026 
1027  fsm->jiffies_start = fsm->datagram->jiffies_sent;
1028 
1029  if (fsm->last_packet) {
1030  fsm->packet_no = 0;
1031  fsm->request->data_size = fsm->buffer_offset;
1032  fsm->state = ec_fsm_foe_end;
1033  }
1034  else {
1035  fsm->packet_no++;
1036 
1037  // mailbox read check is skipped if a read request is already ongoing
1038  if (ec_read_mbox_locked(slave)) {
1040  // the datagram is not used and marked as invalid
1041  datagram->state = EC_DATAGRAM_INVALID;
1042  } else {
1043  ec_slave_mbox_prepare_check(slave, datagram); // can not fail.
1044  fsm->retries = EC_FSM_RETRIES;
1046  }
1047  }
1048 }
1049 
1050 /*****************************************************************************/
1051 
1055  ec_fsm_foe_t *fsm,
1056  uint32_t errorcode
1057  )
1058 {
1059  fsm->request->result = errorcode;
1060  fsm->state = ec_fsm_foe_error;
1061 }
1062 
1063 /*****************************************************************************/
1064 
1068  ec_fsm_foe_t *fsm,
1069  uint32_t errorcode
1070  )
1071 {
1072  fsm->request->result = errorcode;
1073  fsm->state = ec_fsm_foe_error;
1074 }
1075 
1076 /*****************************************************************************/
#define EC_FSM_RETRIES
Number of state machine retries on datagram timeout.
Definition: globals.h:59
ec_slave_t * slave
Slave the FSM runs on.
Definition: fsm_foe.h:54
void ec_fsm_foe_read_start(ec_fsm_foe_t *, ec_datagram_t *)
Starting state for read operations.
Definition: fsm_foe.c:730
uint8_t * ec_slave_mbox_prepare_send(const ec_slave_t *slave, ec_datagram_t *datagram, uint8_t type, size_t size)
Prepares a mailbox-send datagram.
Definition: mailbox.c:51
unsigned long jiffies_sent
Jiffies, when the datagram was sent.
Definition: datagram.h:105
int ec_fsm_foe_success(const ec_fsm_foe_t *fsm)
Returns, if the state machine terminated with success.
Definition: fsm_foe.c:151
uint16_t configured_tx_mailbox_size
Configured send mailbox size.
Definition: slave.h:248
uint32_t buffer_offset
Offset of data to transmit/receive next.
Definition: fsm_foe.h:63
void ec_fsm_foe_error(ec_fsm_foe_t *, ec_datagram_t *)
State: ERROR.
Definition: fsm_foe.c:183
void ec_fsm_foe_clear(ec_fsm_foe_t *fsm)
Destructor.
Definition: fsm_foe.c:117
#define EC_SLAVE_DBG(slave, level, fmt, args...)
Convenience macro for printing slave-specific debug messages to syslog.
Definition: slave.h:108
Packet number error.
Definition: ecrt.h:556
Mailbox protocol error.
Definition: ecrt.h:564
unsigned long jiffies_start
FoE timestamp.
Definition: fsm_foe.h:59
Read request.
Definition: fsm_foe.c:63
Error acknowledging received data.
Definition: ecrt.h:560
ec_mbox_data_t mbox_foe_data
Received mailbox data for FoE.
Definition: slave.h:292
int ec_slave_mbox_prepare_fetch(const ec_slave_t *slave, ec_datagram_t *datagram)
Prepares a datagram to fetch mailbox data.
Definition: mailbox.c:134
uint32_t packet_no
FoE packet number.
Definition: fsm_foe.h:65
EtherCAT datagram.
Definition: datagram.h:88
void ec_fsm_foe_state_rrq_sent(ec_fsm_foe_t *, ec_datagram_t *)
State: RRQ SENT.
Definition: fsm_foe.c:684
size_t data_size
Size of FoE data.
Definition: foe_request.h:54
#define EC_FOE_HEADER_SIZE
Size of the FoE header.
Definition: fsm_foe.c:51
uint8_t * ec_slave_mbox_fetch(const ec_slave_t *slave, ec_mbox_data_t *response_data, uint8_t *type, size_t *size)
Processes received mailbox data.
Definition: mailbox.c:172
uint16_t working_counter
Working counter.
Definition: datagram.h:100
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
void ec_foe_set_tx_error(ec_fsm_foe_t *, uint32_t)
Set an error code and go to the send error state.
Definition: fsm_foe.c:1054
void ec_fsm_foe_end(ec_fsm_foe_t *, ec_datagram_t *)
State: END.
Definition: fsm_foe.c:197
int ec_foe_prepare_wrq_send(ec_fsm_foe_t *, ec_datagram_t *)
Prepare a write request (WRQ) with filename.
Definition: fsm_foe.c:256
OpCode error.
Definition: ecrt.h:557
Global definitions and macros.
EtherCAT master structure.
void ec_fsm_foe_state_data_read_data(ec_fsm_foe_t *, ec_datagram_t *)
Process a read data operation.
Definition: fsm_foe.c:868
uint8_t file_name[255]
FoE filename.
Definition: foe_request.h:71
uint32_t buffer_size
Size of transmit/receive buffer.
Definition: fsm_foe.h:62
void ec_fsm_foe_state_ack_read_data(ec_fsm_foe_t *, ec_datagram_t *)
Process a read operation.
Definition: fsm_foe.c:430
EtherCAT slave.
Definition: slave.h:214
void ec_fsm_foe_state_wrq_sent(ec_fsm_foe_t *, ec_datagram_t *)
State: WRQ SENT.
Definition: fsm_foe.c:525
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
ec_datagram_state_t state
State.
Definition: datagram.h:101
#define EC_WRITE_U32(DATA, VAL)
Write a 32-bit unsigned value to EtherCAT data.
Definition: ecrt.h:2676
uint8_t * buffer
Pointer to FoE data.
Definition: foe_request.h:52
uint16_t mailbox_protocols
Supported mailbox protocols.
Definition: slave.h:172
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
void ec_datagram_print_wc_error(const ec_datagram_t *datagram)
Evaluates the working counter of a single-cast datagram.
Definition: datagram.c:627
void ec_foe_set_rx_error(ec_fsm_foe_t *, uint32_t)
Set an error code and go to the receive error state.
Definition: fsm_foe.c:1067
void ec_fsm_foe_write_start(ec_fsm_foe_t *, ec_datagram_t *)
Initializes the FoE write state machine.
Definition: fsm_foe.c:288
#define EC_WRITE_U16(DATA, VAL)
Write a 16-bit unsigned value to EtherCAT data.
Definition: ecrt.h:2659
Read buffer overflow.
Definition: ecrt.h:565
#define EC_READ_U32(DATA)
Read a 32-bit unsigned value from EtherCAT data.
Definition: ecrt.h:2570
ec_master_t * master
Master owning the slave.
Definition: slave.h:216
uint32_t error_code
Error code from an FoE Error Request.
Definition: foe_request.h:70
void ec_fsm_foe_state_sent_ack(ec_fsm_foe_t *, ec_datagram_t *)
Sent an acknowledge.
Definition: fsm_foe.c:1001
int ec_read_mbox_locked(ec_slave_t *slave)
Return the current mailbox lock status and lock it if not locked.
Definition: slave.c:229
ec_foe_error_t result
FoE request abort code.
Definition: foe_request.h:69
int ec_foe_prepare_data_send(ec_fsm_foe_t *, ec_datagram_t *)
Sends a file or the next fragment.
Definition: fsm_foe.c:213
#define EC_MBOX_HEADER_SIZE
Mailbox header size.
Definition: globals.h:100
void ec_fsm_foe_state_data_read(ec_fsm_foe_t *, ec_datagram_t *)
Start reading data.
Definition: fsm_foe.c:830
ec_direction_t dir
Direction.
Definition: foe_request.h:61
void ec_print_data(const uint8_t *, size_t)
Outputs frame contents for debugging purposes.
Definition: module.c:355
void ec_read_mbox_lock_clear(ec_slave_t *slave)
Clears the mailbox lock.
Definition: slave.c:216
unsigned int retries
Retries upon datagram timeout.
Definition: fsm_foe.h:55
int ec_slave_mbox_prepare_check(const ec_slave_t *slave, ec_datagram_t *datagram)
Prepares a datagram for checking the mailbox state.
Definition: mailbox.c:103
size_t buffer_size
Size of FoE data memory.
Definition: foe_request.h:53
ec_datagram_t * datagram
Datagram used in previous step.
Definition: fsm_foe.h:58
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
Error fetching data from mailbox.
Definition: ecrt.h:562
Mailbox functionality.
Acknowledge.
Definition: fsm_foe.c:66
Busy.
Definition: ecrt.h:549
int ec_foe_prepare_rrq_send(ec_fsm_foe_t *, ec_datagram_t *)
Prepare a read request (RRQ) with filename.
Definition: fsm_foe.c:617
ec_foe_request_t * request
FoE request.
Definition: fsm_foe.h:60
void ec_fsm_foe_state_ack_read(ec_fsm_foe_t *, ec_datagram_t *)
Acknowledge a read operation.
Definition: fsm_foe.c:392
Acknowledge error.
Definition: ecrt.h:561
Receive error.
Definition: ecrt.h:553
uint16_t configured_rx_mailbox_size
Configured receive mailbox size.
Definition: slave.h:244
void(* state)(ec_fsm_foe_t *, ec_datagram_t *)
FoE state function.
Definition: fsm_foe.h:57
Timeout error.
Definition: ecrt.h:558
size_t progress
Current position of a BUSY request.
Definition: foe_request.h:55
#define EC_READ_U8(DATA)
Read an 8-bit unsigned value from EtherCAT data.
Definition: ecrt.h:2538
#define EC_FSM_FOE_TIMEOUT_JIFFIES
Maximum time in jiffies to wait for responses when reading out the dictionary.
Definition: fsm_foe.c:47
ec_sii_t sii
Extracted SII data.
Definition: slave.h:207
FoE request.
Definition: foe_request.h:50
void ec_fsm_foe_state_data_sent(ec_fsm_foe_t *, ec_datagram_t *)
State: WRQ SENT.
Definition: fsm_foe.c:572
Unused and should not be queued (dequeued).
Definition: datagram.h:81
Working counter error.
Definition: ecrt.h:552
Protocol error.
Definition: ecrt.h:554
uint32_t last_packet
Current packet is last one to send/receive.
Definition: fsm_foe.h:64
Values written by the master.
Definition: ecrt.h:438
Received (dequeued).
Definition: datagram.h:78
File-Access over EtherCAT.
Definition: globals.h:185
int ec_foe_prepare_send_ack(ec_fsm_foe_t *, ec_datagram_t *)
Prepare to send an acknowledge.
Definition: fsm_foe.c:654
Write request.
Definition: fsm_foe.c:64
void ec_fsm_foe_state_data_check(ec_fsm_foe_t *, ec_datagram_t *)
Check for data.
Definition: fsm_foe.c:770
uint32_t current_size
Size of current packet to send.
Definition: fsm_foe.h:66
EtherCAT FoE state machines.
unsigned long jiffies_received
Jiffies, when the datagram was received.
Definition: datagram.h:110
size_t payload_size
Size of the mailbox response payload data.
Definition: datagram.h:125
int ec_slave_mbox_check(const ec_datagram_t *datagram)
Processes a mailbox state checking datagram.
Definition: mailbox.c:122
uint32_t password
FoE password.
Definition: foe_request.h:68
Finite state machines for the CANopen-over-EtherCAT protocol.
Definition: fsm_foe.h:53
void ec_fsm_foe_state_ack_check(ec_fsm_foe_t *, ec_datagram_t *)
Check for acknowledge.
Definition: fsm_foe.c:329