IgH EtherCAT Master  1.7.0
fsm_coe.c
Go to the documentation of this file.
1 /*****************************************************************************
2  *
3  * Copyright (C) 2006-2008 Florian Pose, Ingenieurgemeinschaft IgH
4  *
5  * This file is part of the IgH EtherCAT Master.
6  *
7  * The IgH EtherCAT Master is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License version 2, as
9  * published by the Free Software Foundation.
10  *
11  * The IgH EtherCAT Master is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
14  * Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License along
17  * with the IgH EtherCAT Master; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19  *
20  ****************************************************************************/
21 
26 /****************************************************************************/
27 
28 #include "globals.h"
29 #include "master.h"
30 #include "mailbox.h"
31 #include "fsm_coe.h"
32 #include "slave_config.h"
33 
34 /****************************************************************************/
35 
38 #define EC_FSM_COE_DICT_TIMEOUT 1000
39 
42 #define EC_COE_DOWN_REQ_HEADER_SIZE 10
43 
46 #define EC_COE_DOWN_SEG_REQ_HEADER_SIZE 3
47 
50 #define EC_COE_DOWN_SEG_MIN_DATA_SIZE 7
51 
54 #define DEBUG_RETRIES 0
55 
58 #define DEBUG_LONG 0
59 
60 /****************************************************************************/
61 
62 // prototypes for private methods
63 void ec_canopen_abort_msg(const ec_slave_t *, uint32_t);
64 int ec_fsm_coe_check_emergency(const ec_fsm_coe_t *, const uint8_t *, size_t);
72 
73 /****************************************************************************/
74 
82 
88 
94 
97 
98 /****************************************************************************/
99 
107  {0x05030000, "Toggle bit not changed"},
108  {0x05040000, "SDO protocol timeout"},
109  {0x05040001, "Client/Server command specifier not valid or unknown"},
110  {0x05040005, "Out of memory"},
111  {0x06010000, "Unsupported access to an object"},
112  {0x06010001, "Attempt to read a write-only object"},
113  {0x06010002, "Attempt to write a read-only object"},
114  {0x06020000, "This object does not exist in the object directory"},
115  {0x06040041, "The object cannot be mapped into the PDO"},
116  {0x06040042, "The number and length of the objects to be mapped would"
117  " exceed the PDO length"},
118  {0x06040043, "General parameter incompatibility reason"},
119  {0x06040047, "Gerneral internal incompatibility in device"},
120  {0x06060000, "Access failure due to a hardware error"},
121  {0x06070010, "Data type does not match, length of service parameter does"
122  " not match"},
123  {0x06070012, "Data type does not match, length of service parameter too"
124  " high"},
125  {0x06070013, "Data type does not match, length of service parameter too"
126  " low"},
127  {0x06090011, "Subindex does not exist"},
128  {0x06090030, "Value range of parameter exceeded"},
129  {0x06090031, "Value of parameter written too high"},
130  {0x06090032, "Value of parameter written too low"},
131  {0x06090036, "Maximum value is less than minimum value"},
132  {0x08000000, "General error"},
133  {0x08000020, "Data cannot be transferred or stored to the application"},
134  {0x08000021, "Data cannot be transferred or stored to the application"
135  " because of local control"},
136  {0x08000022, "Data cannot be transferred or stored to the application"
137  " because of the present device state"},
138  {0x08000023, "Object dictionary dynamic generation fails or no object"
139  " dictionary is present"},
140  {}
141 };
142 
143 /****************************************************************************/
144 
148  const ec_slave_t *slave,
149  uint32_t abort_code
150  )
151 {
152  const ec_code_msg_t *abort_msg;
153 
154  for (abort_msg = sdo_abort_messages; abort_msg->code; abort_msg++) {
155  if (abort_msg->code == abort_code) {
156  EC_SLAVE_ERR(slave, "SDO abort message 0x%08X: \"%s\".\n",
157  abort_msg->code, abort_msg->message);
158  return;
159  }
160  }
161 
162  EC_SLAVE_ERR(slave, "Unknown SDO abort code 0x%08X.\n", abort_code);
163 }
164 
165 /****************************************************************************/
166 
170  ec_fsm_coe_t *fsm
171  )
172 {
173  fsm->state = NULL;
174  fsm->datagram = NULL;
175  ec_fsm_mbox_init(&fsm->fsm_mbox);
176 }
177 
178 /****************************************************************************/
179 
183  ec_fsm_coe_t *fsm
184  )
185 {
187 }
188 
189 /****************************************************************************/
190 
194  ec_fsm_coe_t *fsm,
195  ec_slave_t *slave
196  )
197 {
198  fsm->slave = slave;
200 }
201 
202 /****************************************************************************/
203 
207  ec_fsm_coe_t *fsm,
208  ec_slave_t *slave,
209  ec_sdo_request_t *request
210  )
211 {
212  fsm->slave = slave;
213  fsm->request = request;
214 
215  if (request->dir == EC_DIR_OUTPUT) {
217  }
218  else {
219  fsm->state = ec_fsm_coe_up_start;
220  }
221 }
222 
223 /****************************************************************************/
224 
230  ec_fsm_coe_t *fsm,
231  ec_datagram_t *datagram
232  )
233 {
234  if (fsm->state == ec_fsm_coe_end || fsm->state == ec_fsm_coe_error)
235  return 0;
236  if (fsm->datagram &&
237  (fsm->datagram->state == EC_DATAGRAM_INIT ||
238  fsm->datagram->state == EC_DATAGRAM_QUEUED ||
239  fsm->datagram->state == EC_DATAGRAM_SENT)) {
240  // datagram not received yet
241  if (datagram != fsm->datagram)
242  datagram->state = EC_DATAGRAM_UNUSED;
243  return 1;
244  }
245 
246  fsm->state(fsm, datagram);
247 
248  if (fsm->state == ec_fsm_coe_end || fsm->state == ec_fsm_coe_error) {
249  fsm->datagram = NULL;
250  return 0;
251  }
252 
253  fsm->datagram = datagram;
254  return 1;
255 }
256 
257 /****************************************************************************/
258 
263  const ec_fsm_coe_t *fsm
264  )
265 {
266  return fsm->state == ec_fsm_coe_end;
267 }
268 
269 /****************************************************************************/
270 
277  ec_fsm_coe_t *fsm
278  )
279 {
281  fsm->state = ec_fsm_coe_error;
282  fsm->datagram = NULL;
283 }
284 
285 /****************************************************************************/
286 
294  const ec_fsm_coe_t *fsm,
295  const uint8_t *data,
296  size_t size
297  )
298 {
299  if (size < 2 || ((EC_READ_U16(data) >> 12) & 0x0F) != 0x01)
300  return 0;
301 
302  if (size < 10) {
303  EC_SLAVE_WARN(fsm->slave, "Received incomplete CoE Emergency"
304  " request:\n");
305  ec_print_data(data, size);
306  return 1;
307  }
308 
309  {
310  ec_slave_config_t *sc = fsm->slave->config;
311  if (sc) {
312  ec_coe_emerg_ring_push(&sc->emerg_ring, data + 2);
313  }
314  }
315 
316  EC_SLAVE_WARN(fsm->slave, "CoE Emergency Request received:\n"
317  "Error code 0x%04X, Error register 0x%02X, data:\n",
318  EC_READ_U16(data + 2), EC_READ_U8(data + 4));
319  ec_print_data(data + 5, 5);
320  return 1;
321 }
322 
323 /****************************************************************************/
324 
336 static void ec_fsm_coe_receive(
337  ec_fsm_coe_t *fsm,
338  ec_datagram_t *datagram,
339  unsigned long timeout_ms,
340  void (*state)(ec_fsm_coe_t *, ec_datagram_t *)
341  )
342 {
343  ec_fsm_mbox_receive(&fsm->fsm_mbox, fsm->slave,
344  &fsm->slave->mbox_coe_data, fsm->jiffies_start, timeout_ms);
345  fsm->state = state;
346  fsm->state(fsm, datagram);
347 }
348 
349 /****************************************************************************/
350 
355 static unsigned long ec_fsm_coe_elapsed_ms(
356  const ec_fsm_coe_t *fsm
357  )
358 {
359  return (jiffies - fsm->jiffies_start) * 1000 / HZ;
360 }
361 
362 /*****************************************************************************
363  * CoE dictionary state machine
364  ****************************************************************************/
365 
371  ec_fsm_coe_t *fsm,
372  ec_datagram_t *datagram
373  )
374 {
375  ec_slave_t *slave = fsm->slave;
376  uint8_t *data = ec_slave_mbox_prepare_send(slave, datagram,
377  EC_MBOX_TYPE_COE, 8);
378  if (IS_ERR(data)) {
379  return PTR_ERR(data);
380  }
381 
382  EC_WRITE_U16(data, 0x8 << 12); // SDO information
383  EC_WRITE_U8 (data + 2, 0x01); // Get OD List Request
384  EC_WRITE_U8 (data + 3, 0x00);
385  EC_WRITE_U16(data + 4, 0x0000);
386  EC_WRITE_U16(data + 6, 0x0001); // deliver all SDOs!
387 
389  return 0;
390 }
391 
392 /****************************************************************************/
393 
397  ec_fsm_coe_t *fsm,
398  ec_datagram_t *datagram
399  )
400 {
401  ec_slave_t *slave = fsm->slave;
402 
403  if (!(slave->sii.mailbox_protocols & EC_MBOX_COE)) {
404  EC_SLAVE_ERR(slave, "Slave does not support CoE!\n");
405  fsm->state = ec_fsm_coe_error;
406  return;
407  }
408 
409  if (slave->sii.has_general && !slave->sii.coe_details.enable_sdo_info) {
410  EC_SLAVE_ERR(slave, "Slave does not support"
411  " SDO information service!\n");
412  fsm->state = ec_fsm_coe_error;
413  return;
414  }
415 
416  fsm->retries = EC_FSM_RETRIES;
417 
418  if (ec_fsm_coe_prepare_dict(fsm, datagram)) {
419  fsm->state = ec_fsm_coe_error;
420  }
421 }
422 
423 /****************************************************************************/
424 
429  ec_fsm_coe_t *fsm,
430  ec_datagram_t *datagram
431  )
432 {
433  ec_slave_t *slave = fsm->slave;
434 
435  if (fsm->datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--) {
436  if (ec_fsm_coe_prepare_dict(fsm, datagram)) {
437  fsm->state = ec_fsm_coe_error;
438  }
439  return;
440  }
441 
442  if (fsm->datagram->state != EC_DATAGRAM_RECEIVED) {
443  fsm->state = ec_fsm_coe_error;
444  EC_SLAVE_ERR(slave, "Failed to receive CoE dictionary"
445  " request datagram: ");
447  return;
448  }
449 
450  if (fsm->datagram->working_counter != 1) {
451  fsm->state = ec_fsm_coe_error;
452  EC_SLAVE_ERR(slave, "Reception of CoE dictionary request failed: ");
454  return;
455  }
456 
457  fsm->jiffies_start = fsm->datagram->jiffies_sent;
458 
461 }
462 
463 /****************************************************************************/
464 
470  ec_fsm_coe_t *fsm,
471  ec_datagram_t *datagram
472  )
473 {
474  ec_slave_t *slave = fsm->slave;
475  u8 *data = ec_slave_mbox_prepare_send(slave, datagram, EC_MBOX_TYPE_COE,
476  8);
477  if (IS_ERR(data)) {
478  return PTR_ERR(data);
479  }
480 
481  EC_WRITE_U16(data, 0x8 << 12); // SDO information
482  EC_WRITE_U8 (data + 2, 0x03); // Get object description request
483  EC_WRITE_U8 (data + 3, 0x00);
484  EC_WRITE_U16(data + 4, 0x0000);
485  EC_WRITE_U16(data + 6, fsm->sdo->index); // SDO index
486 
488  return 0;
489 }
490 
491 /****************************************************************************/
492 
498  ec_fsm_coe_t *fsm,
499  ec_datagram_t *datagram
500  )
501 {
502  ec_slave_t *slave = fsm->slave;
503  uint8_t *data, mbox_prot;
504  size_t rec_size;
505  unsigned int sdo_count, i;
506  uint16_t sdo_index, fragments_left;
507  ec_sdo_t *sdo;
508  bool first_segment;
509  size_t index_list_offset;
510 
511  if (ec_fsm_mbox_exec(&fsm->fsm_mbox, datagram)) {
512  return;
513  }
514 
515  if (ec_fsm_mbox_result(&fsm->fsm_mbox)) {
516  fsm->state = ec_fsm_coe_error;
517  if (ec_fsm_mbox_result(&fsm->fsm_mbox) == -ETIMEDOUT) {
518  EC_SLAVE_ERR(slave, "Timeout while waiting for"
519  " SDO dictionary list response.\n");
520  }
521  return;
522  }
523 
524  data = ec_slave_mbox_fetch(slave, &slave->mbox_coe_data,
525  &mbox_prot, &rec_size);
526  if (IS_ERR(data)) {
527  fsm->state = ec_fsm_coe_error;
528  return;
529  }
530 
531  if (mbox_prot != EC_MBOX_TYPE_COE) {
532  EC_SLAVE_ERR(slave, "Received mailbox protocol 0x%02X as response.\n",
533  mbox_prot);
534  fsm->state = ec_fsm_coe_error;
535  return;
536  }
537 
538  if (ec_fsm_coe_check_emergency(fsm, data, rec_size)) {
539  // check for CoE response again
542  return;
543  }
544 
545  if (rec_size < 3) {
546  EC_SLAVE_ERR(slave, "Received corrupted SDO dictionary response"
547  " (size %zu).\n", rec_size);
548  fsm->state = ec_fsm_coe_error;
549  return;
550  }
551 
552  if (EC_READ_U16(data) >> 12 == 0x8 && // SDO information
553  (EC_READ_U8(data + 2) & 0x7F) == 0x07) { // error response
554  EC_SLAVE_ERR(slave, "SDO information error response!\n");
555  if (rec_size < 10) {
556  EC_SLAVE_ERR(slave, "Incomplete SDO information"
557  " error response:\n");
558  ec_print_data(data, rec_size);
559  } else {
560  ec_canopen_abort_msg(slave, EC_READ_U32(data + 6));
561  }
562  fsm->state = ec_fsm_coe_error;
563  return;
564  }
565 
566  if (EC_READ_U16(data) >> 12 != 0x8 || // SDO information
567  (EC_READ_U8 (data + 2) & 0x7F) != 0x02) { // Get OD List response
568  if (fsm->slave->master->debug_level) {
569  EC_SLAVE_DBG(slave, 1, "Invalid SDO list response!"
570  " Retrying...\n");
571  ec_print_data(data, rec_size);
572  }
575  return;
576  }
577 
578  first_segment = list_empty(&slave->sdo_dictionary) ? true : false;
579  index_list_offset = first_segment ? 8 : 6;
580 
581  if (rec_size < index_list_offset || rec_size % 2) {
582  EC_SLAVE_ERR(slave, "Invalid data size %zu!\n", rec_size);
583  ec_print_data(data, rec_size);
584  fsm->state = ec_fsm_coe_error;
585  return;
586  }
587 
588  sdo_count = (rec_size - index_list_offset) / 2;
589 
590  for (i = 0; i < sdo_count; i++) {
591  sdo_index = EC_READ_U16(data + index_list_offset + i * 2);
592  if (!sdo_index) {
593  EC_SLAVE_DBG(slave, 1, "SDO dictionary contains index 0x0000.\n");
594  continue;
595  }
596 
597  if (!(sdo = (ec_sdo_t *) kmalloc(sizeof(ec_sdo_t), GFP_KERNEL))) {
598  EC_SLAVE_ERR(slave, "Failed to allocate memory for SDO!\n");
599  fsm->state = ec_fsm_coe_error;
600  return;
601  }
602 
603  ec_sdo_init(sdo, slave, sdo_index);
604  list_add_tail(&sdo->list, &slave->sdo_dictionary);
605  }
606 
607  fragments_left = EC_READ_U16(data + 4);
608  if (fragments_left) {
609  EC_SLAVE_DBG(slave, 1, "SDO list fragments left: %u\n",
610  fragments_left);
611  }
612 
613  if (EC_READ_U8(data + 2) & 0x80 || fragments_left) {
614  // more messages waiting. check again.
615  fsm->jiffies_start = jiffies;
618  return;
619  }
620 
621  if (list_empty(&slave->sdo_dictionary)) {
622  // no SDOs in dictionary. finished.
623  fsm->state = ec_fsm_coe_end; // success
624  return;
625  }
626 
627  // fetch SDO descriptions
628  fsm->sdo = list_entry(slave->sdo_dictionary.next, ec_sdo_t, list);
629 
630  fsm->retries = EC_FSM_RETRIES;
631  if (ec_fsm_coe_dict_prepare_desc(fsm, datagram)) {
632  fsm->state = ec_fsm_coe_error;
633  }
634 }
635 
636 /****************************************************************************/
637 
644  ec_fsm_coe_t *fsm,
645  ec_datagram_t *datagram
646  )
647 {
648  ec_slave_t *slave = fsm->slave;
649 
650  if (fsm->datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--) {
651  if (ec_fsm_coe_dict_prepare_desc(fsm, datagram)) {
652  fsm->state = ec_fsm_coe_error;
653  }
654  return;
655  }
656 
657  if (fsm->datagram->state != EC_DATAGRAM_RECEIVED) {
658  fsm->state = ec_fsm_coe_error;
659  EC_SLAVE_ERR(slave, "Failed to receive CoE SDO"
660  " description request datagram: ");
662  return;
663  }
664 
665  if (fsm->datagram->working_counter != 1) {
666  fsm->state = ec_fsm_coe_error;
667  EC_SLAVE_ERR(slave, "Reception of CoE SDO description"
668  " request failed: ");
670  return;
671  }
672 
673  fsm->jiffies_start = fsm->datagram->jiffies_sent;
674 
677 }
678 
679 /****************************************************************************/
680 
686  ec_fsm_coe_t *fsm,
687  ec_datagram_t *datagram
688  )
689 {
690  ec_slave_t *slave = fsm->slave;
691  u8 *data = ec_slave_mbox_prepare_send(slave, datagram, EC_MBOX_TYPE_COE,
692  10);
693  if (IS_ERR(data)) {
694  return PTR_ERR(data);
695  }
696 
697  EC_WRITE_U16(data, 0x8 << 12); // SDO information
698  EC_WRITE_U8 (data + 2, 0x05); // Get entry description request
699  EC_WRITE_U8 (data + 3, 0x00);
700  EC_WRITE_U16(data + 4, 0x0000);
701  EC_WRITE_U16(data + 6, fsm->sdo->index); // SDO index
702  EC_WRITE_U8 (data + 8, fsm->subindex); // SDO subindex
703  EC_WRITE_U8 (data + 9, 0x01); // value info (access rights only)
704 
706  return 0;
707 }
708 
709 /****************************************************************************/
710 
716  ec_fsm_coe_t *fsm,
717  ec_datagram_t *datagram
718  )
719 {
720  ec_slave_t *slave = fsm->slave;
721  ec_sdo_t *sdo = fsm->sdo;
722  uint8_t *data, mbox_prot;
723  size_t rec_size, name_size;
724 
725  if (ec_fsm_mbox_exec(&fsm->fsm_mbox, datagram)) {
726  return;
727  }
728 
729  if (ec_fsm_mbox_result(&fsm->fsm_mbox)) {
730  fsm->state = ec_fsm_coe_error;
731  if (ec_fsm_mbox_result(&fsm->fsm_mbox) == -ETIMEDOUT) {
732  EC_SLAVE_ERR(slave, "Timeout while waiting for"
733  " SDO 0x%04x object description response.\n",
734  fsm->sdo->index);
735  }
736  return;
737  }
738 
739  data = ec_slave_mbox_fetch(slave, &slave->mbox_coe_data,
740  &mbox_prot, &rec_size);
741  if (IS_ERR(data)) {
742  fsm->state = ec_fsm_coe_error;
743  return;
744  }
745 
746  if (mbox_prot != EC_MBOX_TYPE_COE) {
747  EC_SLAVE_ERR(slave, "Received mailbox protocol 0x%02X as response.\n",
748  mbox_prot);
749  fsm->state = ec_fsm_coe_error;
750  return;
751  }
752 
753  if (ec_fsm_coe_check_emergency(fsm, data, rec_size)) {
754  // check for CoE response again
757  return;
758  }
759 
760  if (rec_size < 3) {
761  EC_SLAVE_ERR(slave, "Received corrupted SDO description response"
762  " (size %zu).\n", rec_size);
763  fsm->state = ec_fsm_coe_error;
764  return;
765  }
766 
767  if (EC_READ_U16(data) >> 12 == 0x8 && // SDO information
768  (EC_READ_U8 (data + 2) & 0x7F) == 0x07) { // error response
769  EC_SLAVE_ERR(slave, "SDO information error response while"
770  " fetching SDO 0x%04X!\n", sdo->index);
771  ec_canopen_abort_msg(slave, EC_READ_U32(data + 6));
772  fsm->state = ec_fsm_coe_error;
773  return;
774  }
775 
776  if (rec_size < 8) {
777  EC_SLAVE_ERR(slave, "Received corrupted SDO"
778  " description response (size %zu).\n", rec_size);
779  fsm->state = ec_fsm_coe_error;
780  return;
781  }
782 
783  if (EC_READ_U16(data) >> 12 != 0x8 || // SDO information
784  (EC_READ_U8 (data + 2) & 0x7F) != 0x04 || // Object desc. response
785  EC_READ_U16(data + 6) != sdo->index) { // SDO index
786  if (fsm->slave->master->debug_level) {
787  EC_SLAVE_DBG(slave, 1, "Invalid object description response while"
788  " fetching SDO 0x%04X!\n", sdo->index);
789  ec_print_data(data, rec_size);
790  }
791  // check for CoE response again
794  return;
795  }
796 
797  if (rec_size < 12) {
798  EC_SLAVE_ERR(slave, "Invalid data size!\n");
799  ec_print_data(data, rec_size);
800  fsm->state = ec_fsm_coe_error;
801  return;
802  }
803 
804  sdo->max_subindex = EC_READ_U8(data + 10);
805  sdo->object_code = EC_READ_U8(data + 11);
806 
807  name_size = rec_size - 12;
808  if (name_size) {
809  if (!(sdo->name = kmalloc(name_size + 1, GFP_KERNEL))) {
810  EC_SLAVE_ERR(slave, "Failed to allocate SDO name!\n");
811  fsm->state = ec_fsm_coe_error;
812  return;
813  }
814 
815  memcpy(sdo->name, data + 12, name_size);
816  sdo->name[name_size] = 0;
817  }
818 
819  if (EC_READ_U8(data + 2) & 0x80) {
820  EC_SLAVE_ERR(slave, "Fragment follows (not implemented)!\n");
821  fsm->state = ec_fsm_coe_error;
822  return;
823  }
824 
825  // start fetching entries
826 
827  fsm->subindex = 0;
828  fsm->retries = EC_FSM_RETRIES;
829 
830  if (ec_fsm_coe_dict_prepare_entry(fsm, datagram)) {
831  fsm->state = ec_fsm_coe_error;
832  }
833 }
834 
835 /****************************************************************************/
836 
843  ec_fsm_coe_t *fsm,
844  ec_datagram_t *datagram
845  )
846 {
847  ec_slave_t *slave = fsm->slave;
848 
849  if (fsm->datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--) {
850  if (ec_fsm_coe_dict_prepare_entry(fsm, datagram)) {
851  fsm->state = ec_fsm_coe_error;
852  }
853  return;
854  }
855 
856  if (fsm->datagram->state != EC_DATAGRAM_RECEIVED) {
857  fsm->state = ec_fsm_coe_error;
858  EC_SLAVE_ERR(slave, "Failed to receive CoE SDO entry"
859  " request datagram: ");
861  return;
862  }
863 
864  if (fsm->datagram->working_counter != 1) {
865  fsm->state = ec_fsm_coe_error;
866  EC_SLAVE_ERR(slave, "Reception of CoE SDO entry request failed: ");
868  return;
869  }
870 
871  fsm->jiffies_start = fsm->datagram->jiffies_sent;
872 
875 }
876 
877 /****************************************************************************/
878 
884  ec_fsm_coe_t *fsm,
885  ec_datagram_t *datagram
886  )
887 {
888  ec_slave_t *slave = fsm->slave;
889  ec_sdo_t *sdo = fsm->sdo;
890  uint8_t *data, mbox_prot;
891  size_t rec_size, data_size;
892  ec_sdo_entry_t *entry;
893  u16 word;
894 
895  if (ec_fsm_mbox_exec(&fsm->fsm_mbox, datagram)) {
896  return;
897  }
898 
899  if (ec_fsm_mbox_result(&fsm->fsm_mbox)) {
900  fsm->state = ec_fsm_coe_error;
901  if (ec_fsm_mbox_result(&fsm->fsm_mbox) == -ETIMEDOUT) {
902  EC_SLAVE_ERR(slave, "Timeout while waiting for"
903  " SDO entry 0x%04x:%x description response.\n",
904  fsm->sdo->index, fsm->subindex);
905  }
906  return;
907  }
908 
909  data = ec_slave_mbox_fetch(slave, &slave->mbox_coe_data,
910  &mbox_prot, &rec_size);
911  if (IS_ERR(data)) {
912  fsm->state = ec_fsm_coe_error;
913  return;
914  }
915 
916  if (mbox_prot != EC_MBOX_TYPE_COE) {
917  EC_SLAVE_ERR(slave, "Received mailbox protocol"
918  " 0x%02X as response.\n", mbox_prot);
919  fsm->state = ec_fsm_coe_error;
920  return;
921  }
922 
923  if (ec_fsm_coe_check_emergency(fsm, data, rec_size)) {
924  // check for CoE response again
927  return;
928  }
929 
930  if (rec_size < 3) {
931  EC_SLAVE_ERR(slave, "Received corrupted SDO entry"
932  " description response (size %zu).\n", rec_size);
933  fsm->state = ec_fsm_coe_error;
934  return;
935  }
936 
937  if (EC_READ_U16(data) >> 12 == 0x8 && // SDO information
938  (EC_READ_U8 (data + 2) & 0x7F) == 0x07) { // error response
939  EC_SLAVE_WARN(slave, "SDO information error response while"
940  " fetching SDO entry 0x%04X:%02X!\n",
941  sdo->index, fsm->subindex);
942  ec_canopen_abort_msg(slave, EC_READ_U32(data + 6));
943 
944  /* There may be gaps in the subindices, so try to continue with next
945  * subindex. */
946 
947  } else {
948  if (rec_size < 9) {
949  EC_SLAVE_ERR(slave, "Received corrupted SDO entry"
950  " description response (size %zu).\n", rec_size);
951  fsm->state = ec_fsm_coe_error;
952  return;
953  }
954 
955  if (EC_READ_U16(data) >> 12 != 0x8 || // SDO information
956  (EC_READ_U8(data + 2) & 0x7F) != 0x06 || // Entry desc. response
957  EC_READ_U16(data + 6) != sdo->index || // SDO index
958  EC_READ_U8(data + 8) != fsm->subindex) { // SDO subindex
959  if (fsm->slave->master->debug_level) {
960  EC_SLAVE_DBG(slave, 1, "Invalid entry description response"
961  " while fetching SDO entry 0x%04X:%02X!\n",
962  sdo->index, fsm->subindex);
963  ec_print_data(data, rec_size);
964  }
965  // check for CoE response again
968  return;
969  }
970 
971  if (rec_size < 16) {
972  EC_SLAVE_ERR(slave, "Invalid data size %zu!\n", rec_size);
973  ec_print_data(data, rec_size);
974  fsm->state = ec_fsm_coe_error;
975  return;
976  }
977 
978  data_size = rec_size - 16;
979 
980  if (!(entry = (ec_sdo_entry_t *)
981  kmalloc(sizeof(ec_sdo_entry_t), GFP_KERNEL))) {
982  EC_SLAVE_ERR(slave, "Failed to allocate entry!\n");
983  fsm->state = ec_fsm_coe_error;
984  return;
985  }
986 
987  ec_sdo_entry_init(entry, sdo, fsm->subindex);
988  entry->data_type = EC_READ_U16(data + 10);
989  entry->bit_length = EC_READ_U16(data + 12);
990 
991  // read access rights
992  word = EC_READ_U16(data + 14);
993  entry->read_access[EC_SDO_ENTRY_ACCESS_PREOP] = word & 0x0001;
995  (word >> 1) & 0x0001;
996  entry->read_access[EC_SDO_ENTRY_ACCESS_OP] = (word >> 2) & 0x0001;
997  entry->write_access[EC_SDO_ENTRY_ACCESS_PREOP] = (word >> 3) & 0x0001;
999  (word >> 4) & 0x0001;
1000  entry->write_access[EC_SDO_ENTRY_ACCESS_OP] = (word >> 5) & 0x0001;
1001 
1002  if (data_size) {
1003  uint8_t *desc;
1004  if (!(desc = kmalloc(data_size + 1, GFP_KERNEL))) {
1005  EC_SLAVE_ERR(slave, "Failed to allocate SDO entry name!\n");
1006  fsm->state = ec_fsm_coe_error;
1007  return;
1008  }
1009  memcpy(desc, data + 16, data_size);
1010  desc[data_size] = 0;
1011  entry->description = desc;
1012  }
1013 
1014  list_add_tail(&entry->list, &sdo->entries);
1015  }
1016 
1017  if (fsm->subindex < sdo->max_subindex) {
1018  fsm->subindex++;
1019  fsm->retries = EC_FSM_RETRIES;
1020 
1021  if (ec_fsm_coe_dict_prepare_entry(fsm, datagram)) {
1022  fsm->state = ec_fsm_coe_error;
1023  }
1024 
1025  return;
1026  }
1027 
1028  // another SDO description to fetch?
1029  if (fsm->sdo->list.next != &slave->sdo_dictionary) {
1030  fsm->sdo = list_entry(fsm->sdo->list.next, ec_sdo_t, list);
1031  fsm->retries = EC_FSM_RETRIES;
1032 
1033  if (ec_fsm_coe_dict_prepare_desc(fsm, datagram)) {
1034  fsm->state = ec_fsm_coe_error;
1035  }
1036 
1037  return;
1038  }
1039 
1040  fsm->state = ec_fsm_coe_end;
1041 }
1042 
1043 /*****************************************************************************
1044  * CoE state machine
1045  ****************************************************************************/
1046 
1052  ec_fsm_coe_t *fsm,
1053  ec_datagram_t *datagram
1054  )
1055 {
1056  u8 *data;
1057  ec_slave_t *slave = fsm->slave;
1058  ec_sdo_request_t *request = fsm->request;
1059  uint8_t data_set_size;
1060 
1061  if (request->data_size > 0 && request->data_size <= 4) {
1062  // use expedited transfer mode for lengths between 1 and 4 bytes
1063  data = ec_slave_mbox_prepare_send(slave, datagram, EC_MBOX_TYPE_COE,
1065  if (IS_ERR(data)) {
1066  request->errno = PTR_ERR(data);
1067  return PTR_ERR(data);
1068  }
1069 
1070  fsm->remaining = 0;
1071 
1072  data_set_size = 4 - request->data_size;
1073 
1074  EC_WRITE_U16(data, 0x2 << 12); // SDO request
1075  EC_WRITE_U8 (data + 2, (0x3 // size specified, expedited
1076  | data_set_size << 2
1077  | ((request->complete_access ? 1 : 0) << 4)
1078  | 0x1 << 5)); // Download request
1079  EC_WRITE_U16(data + 3, request->index);
1080  EC_WRITE_U8 (data + 5,
1081  request->complete_access ? 0x00 : request->subindex);
1082  memcpy(data + 6, request->data, request->data_size);
1083  memset(data + 6 + request->data_size, 0x00, 4 - request->data_size);
1084 
1085  if (slave->master->debug_level) {
1086  EC_SLAVE_DBG(slave, 1, "Expedited download request:\n");
1088  }
1089  }
1090  else { // data_size < 1 or data_size > 4, use normal transfer type
1091  size_t data_size,
1092  max_data_size =
1094  required_data_size =
1096 
1097  if (max_data_size < required_data_size) {
1098  // segmenting needed
1099  data_size = max_data_size;
1100  } else {
1101  data_size = required_data_size;
1102  }
1103 
1104  data = ec_slave_mbox_prepare_send(slave, datagram, EC_MBOX_TYPE_COE,
1105  data_size);
1106  if (IS_ERR(data)) {
1107  request->errno = PTR_ERR(data);
1108  return PTR_ERR(data);
1109  }
1110 
1111  fsm->offset = 0;
1112  fsm->remaining = request->data_size;
1113 
1114  EC_WRITE_U16(data, 0x2 << 12); // SDO request
1115  EC_WRITE_U8(data + 2,
1116  0x1 // size indicator, normal
1117  | ((request->complete_access ? 1 : 0) << 4)
1118  | 0x1 << 5); // Download request
1119  EC_WRITE_U16(data + 3, request->index);
1120  EC_WRITE_U8 (data + 5,
1121  request->complete_access ? 0x00 : request->subindex);
1122  EC_WRITE_U32(data + 6, request->data_size);
1123 
1124  if (data_size > EC_COE_DOWN_REQ_HEADER_SIZE) {
1125  size_t segment_size = data_size - EC_COE_DOWN_REQ_HEADER_SIZE;
1126  memcpy(data + EC_COE_DOWN_REQ_HEADER_SIZE,
1127  request->data, segment_size);
1128  fsm->offset += segment_size;
1129  fsm->remaining -= segment_size;
1130  }
1131 
1132  if (slave->master->debug_level) {
1133  EC_SLAVE_DBG(slave, 1, "Normal download request:\n");
1134  ec_print_data(data, data_size);
1135  }
1136  }
1137 
1139  return 0;
1140 }
1141 
1142 /****************************************************************************/
1143 
1147  ec_fsm_coe_t *fsm,
1148  ec_datagram_t *datagram
1149  )
1150 {
1151  ec_slave_t *slave = fsm->slave;
1152  ec_sdo_request_t *request = fsm->request;
1153 
1154  if (fsm->slave->master->debug_level) {
1155  char subidxstr[10];
1156  if (request->complete_access) {
1157  subidxstr[0] = 0x00;
1158  } else {
1159  sprintf(subidxstr, ":%02X", request->subindex);
1160  }
1161  EC_SLAVE_DBG(slave, 1, "Downloading SDO 0x%04X%s.\n",
1162  request->index, subidxstr);
1163  ec_print_data(request->data, request->data_size);
1164  }
1165 
1166  if (!(slave->sii.mailbox_protocols & EC_MBOX_COE)) {
1167  EC_SLAVE_ERR(slave, "Slave does not support CoE!\n");
1168  request->errno = EPROTONOSUPPORT;
1169  fsm->state = ec_fsm_coe_error;
1170  return;
1171  }
1172 
1173  if (slave->configured_rx_mailbox_size <
1175  EC_SLAVE_ERR(slave, "Mailbox too small!\n");
1176  request->errno = ENOBUFS;
1177  fsm->state = ec_fsm_coe_error;
1178  return;
1179  }
1180 
1181 
1182  fsm->request->jiffies_sent = jiffies;
1183  fsm->retries = EC_FSM_RETRIES;
1184 
1185  if (ec_fsm_coe_prepare_down_start(fsm, datagram)) {
1186  fsm->state = ec_fsm_coe_error;
1187  }
1188 }
1189 
1190 /****************************************************************************/
1191 
1198  ec_fsm_coe_t *fsm,
1199  ec_datagram_t *datagram
1200  )
1201 {
1202  ec_slave_t *slave = fsm->slave;
1203  unsigned long diff_ms;
1204 
1205  if (fsm->datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--) {
1206  if (ec_fsm_coe_prepare_down_start(fsm, datagram)) {
1207  fsm->state = ec_fsm_coe_error;
1208  }
1209  return;
1210  }
1211 
1212  if (fsm->datagram->state != EC_DATAGRAM_RECEIVED) {
1213  fsm->request->errno = EIO;
1214  fsm->state = ec_fsm_coe_error;
1215  EC_SLAVE_ERR(slave, "Failed to receive CoE download"
1216  " request datagram: ");
1218  return;
1219  }
1220 
1221  diff_ms = (jiffies - fsm->request->jiffies_sent) * 1000 / HZ;
1222 
1223  if (fsm->datagram->working_counter != 1) {
1224  if (!fsm->datagram->working_counter) {
1225  if (diff_ms < fsm->request->response_timeout) {
1226 #if DEBUG_RETRIES
1227  EC_SLAVE_DBG(slave, 1, "Slave did not respond to SDO"
1228  " download request. Retrying after %lu ms...\n",
1229  diff_ms);
1230 #endif
1231  // no response; send request datagram again
1232  if (ec_fsm_coe_prepare_down_start(fsm, datagram)) {
1233  fsm->state = ec_fsm_coe_error;
1234  }
1235  return;
1236  }
1237  }
1238  fsm->request->errno = EIO;
1239  fsm->state = ec_fsm_coe_error;
1240  EC_SLAVE_ERR(slave, "Reception of CoE download request"
1241  " for SDO 0x%04x:%x failed with timeout after %lu ms: ",
1242  fsm->request->index, fsm->request->subindex, diff_ms);
1244  return;
1245  }
1246 
1247 #if DEBUG_LONG
1248  if (diff_ms > 200) {
1249  EC_SLAVE_WARN(slave, "SDO 0x%04x:%x download took %lu ms.\n",
1250  fsm->request->index, fsm->request->subindex, diff_ms);
1251  }
1252 #endif
1253 
1254  fsm->jiffies_start = fsm->datagram->jiffies_sent;
1255 
1256  ec_fsm_coe_receive(fsm, datagram, fsm->request->response_timeout,
1258 }
1259 
1260 /****************************************************************************/
1261 
1265  ec_fsm_coe_t *fsm,
1266  ec_datagram_t *datagram
1267  )
1268 {
1269  ec_slave_t *slave = fsm->slave;
1270  ec_sdo_request_t *request = fsm->request;
1271  size_t max_segment_size =
1275  size_t data_size;
1276  uint8_t last_segment, seg_data_size, *data;
1277 
1278  if (fsm->remaining > max_segment_size) {
1279  fsm->segment_size = max_segment_size;
1280  last_segment = 0;
1281  } else {
1282  fsm->segment_size = fsm->remaining;
1283  last_segment = 1;
1284  }
1285 
1287  seg_data_size = 0x00;
1288  data_size = EC_COE_DOWN_SEG_REQ_HEADER_SIZE + fsm->segment_size;
1289  } else {
1290  seg_data_size = EC_COE_DOWN_SEG_MIN_DATA_SIZE - fsm->segment_size;
1293  }
1294 
1295  data = ec_slave_mbox_prepare_send(slave, datagram, EC_MBOX_TYPE_COE,
1296  data_size);
1297  if (IS_ERR(data)) {
1298  request->errno = PTR_ERR(data);
1299  fsm->state = ec_fsm_coe_error;
1300  return;
1301  }
1302 
1303  EC_WRITE_U16(data, 0x2 << 12); // SDO request
1304  EC_WRITE_U8(data + 2, (last_segment ? 1 : 0)
1305  | (seg_data_size << 1)
1306  | (fsm->toggle << 4)
1307  | (0x00 << 5)); // Download segment request
1308  memcpy(data + EC_COE_DOWN_SEG_REQ_HEADER_SIZE,
1309  request->data + fsm->offset, fsm->segment_size);
1311  memset(data + EC_COE_DOWN_SEG_REQ_HEADER_SIZE + fsm->segment_size,
1313  }
1314 
1315  if (slave->master->debug_level) {
1316  EC_SLAVE_DBG(slave, 1, "Download segment request:\n");
1317  ec_print_data(data, data_size);
1318  }
1319 
1321 }
1322 
1323 /****************************************************************************/
1324 
1330  ec_fsm_coe_t *fsm,
1331  ec_datagram_t *datagram
1332  )
1333 {
1334  ec_slave_t *slave = fsm->slave;
1335  uint8_t *data, mbox_prot;
1336  size_t rec_size;
1337  ec_sdo_request_t *request = fsm->request;
1338 
1339  if (ec_fsm_mbox_exec(&fsm->fsm_mbox, datagram)) {
1340  return;
1341  }
1342 
1343  if (ec_fsm_mbox_result(&fsm->fsm_mbox)) {
1344  request->errno = EIO;
1345  fsm->state = ec_fsm_coe_error;
1346  if (ec_fsm_mbox_result(&fsm->fsm_mbox) == -ETIMEDOUT) {
1347  EC_SLAVE_ERR(slave, "Timeout after %lu ms while waiting"
1348  " for SDO 0x%04x:%x download response.\n",
1349  ec_fsm_coe_elapsed_ms(fsm),
1350  request->index, request->subindex);
1351  }
1352  return;
1353  }
1354 
1355  data = ec_slave_mbox_fetch(slave, &slave->mbox_coe_data,
1356  &mbox_prot, &rec_size);
1357 
1358  if (IS_ERR(data)) {
1359  request->errno = PTR_ERR(data);
1360  fsm->state = ec_fsm_coe_error;
1361  return;
1362  }
1363 
1364  if (mbox_prot != EC_MBOX_TYPE_COE) {
1365  request->errno = EIO;
1366  fsm->state = ec_fsm_coe_error;
1367  EC_SLAVE_ERR(slave, "Received mailbox protocol 0x%02X as response.\n",
1368  mbox_prot);
1369  return;
1370  }
1371 
1372  if (ec_fsm_coe_check_emergency(fsm, data, rec_size)) {
1373  // check for CoE response again
1374  ec_fsm_coe_receive(fsm, datagram, fsm->request->response_timeout,
1376  return;
1377  }
1378 
1379  if (slave->master->debug_level) {
1380  EC_SLAVE_DBG(slave, 1, "Download response:\n");
1381  ec_print_data(data, rec_size);
1382  }
1383 
1384  if (rec_size < 6) {
1385  request->errno = EIO;
1386  fsm->state = ec_fsm_coe_error;
1387  EC_SLAVE_ERR(slave, "Received data are too small (%zu bytes):\n",
1388  rec_size);
1389  ec_print_data(data, rec_size);
1390  return;
1391  }
1392 
1393  if (EC_READ_U16(data) >> 12 == 0x2 && // SDO request
1394  EC_READ_U8 (data + 2) >> 5 == 0x4) { // abort SDO transfer request
1395  char subidxstr[10];
1396  request->errno = EIO;
1397  fsm->state = ec_fsm_coe_error;
1398  if (request->complete_access) {
1399  subidxstr[0] = 0x00;
1400  } else {
1401  sprintf(subidxstr, ":%02X", request->subindex);
1402  }
1403  EC_SLAVE_ERR(slave, "SDO download 0x%04X%s (%zu bytes) aborted.\n",
1404  request->index, subidxstr, request->data_size);
1405  if (rec_size < 10) {
1406  EC_SLAVE_ERR(slave, "Incomplete abort command:\n");
1407  ec_print_data(data, rec_size);
1408  } else {
1409  fsm->request->abort_code = EC_READ_U32(data + 6);
1410  ec_canopen_abort_msg(slave, fsm->request->abort_code);
1411  }
1412  return;
1413  }
1414 
1415  if (EC_READ_U16(data) >> 12 != 0x3 || // SDO response
1416  EC_READ_U8 (data + 2) >> 5 != 0x3 || // Download response
1417  EC_READ_U16(data + 3) != request->index || // index
1418  EC_READ_U8 (data + 5) != request->subindex) { // subindex
1419  if (slave->master->debug_level) {
1420  EC_SLAVE_DBG(slave, 1, "Invalid SDO download response!"
1421  " Retrying...\n");
1422  ec_print_data(data, rec_size);
1423  }
1424  // check for CoE response again
1425  ec_fsm_coe_receive(fsm, datagram, fsm->request->response_timeout,
1427  return;
1428  }
1429 
1430  if (fsm->remaining) { // more segments to download
1431  fsm->toggle = 0;
1432  fsm->retries = EC_FSM_RETRIES;
1434  } else {
1435  fsm->state = ec_fsm_coe_end; // success
1436  }
1437 }
1438 
1439 /****************************************************************************/
1440 
1446  ec_fsm_coe_t *fsm,
1447  ec_datagram_t *datagram
1448  )
1449 {
1450  ec_slave_t *slave = fsm->slave;
1451 
1452  if (fsm->datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--) {
1454  return;
1455  }
1456 
1457  if (fsm->datagram->state != EC_DATAGRAM_RECEIVED) {
1458  fsm->request->errno = EIO;
1459  fsm->state = ec_fsm_coe_error;
1460  EC_SLAVE_ERR(slave, "Failed to receive CoE download segment"
1461  " request datagram: ");
1463  return;
1464  }
1465 
1466  if (fsm->datagram->working_counter != 1) {
1467  fsm->request->errno = EIO;
1468  fsm->state = ec_fsm_coe_error;
1469  EC_SLAVE_ERR(slave, "Reception of CoE download segment"
1470  " request failed: ");
1472  return;
1473  }
1474 
1475  fsm->jiffies_start = fsm->datagram->jiffies_sent;
1476 
1477  ec_fsm_coe_receive(fsm, datagram, fsm->request->response_timeout,
1479 }
1480 
1481 /****************************************************************************/
1482 
1488  ec_fsm_coe_t *fsm,
1489  ec_datagram_t *datagram
1490  )
1491 {
1492  ec_slave_t *slave = fsm->slave;
1493  uint8_t *data, mbox_prot;
1494  size_t rec_size;
1495  ec_sdo_request_t *request = fsm->request;
1496 
1497  if (ec_fsm_mbox_exec(&fsm->fsm_mbox, datagram)) {
1498  return;
1499  }
1500 
1501  if (ec_fsm_mbox_result(&fsm->fsm_mbox)) {
1502  request->errno = EIO;
1503  fsm->state = ec_fsm_coe_error;
1504  if (ec_fsm_mbox_result(&fsm->fsm_mbox) == -ETIMEDOUT) {
1505  EC_SLAVE_ERR(slave, "Timeout while waiting for SDO download"
1506  " segment response.\n");
1507  }
1508  return;
1509  }
1510 
1511  data = ec_slave_mbox_fetch(slave, &slave->mbox_coe_data,
1512  &mbox_prot, &rec_size);
1513  if (IS_ERR(data)) {
1514  request->errno = PTR_ERR(data);
1515  fsm->state = ec_fsm_coe_error;
1516  return;
1517  }
1518 
1519  if (mbox_prot != EC_MBOX_TYPE_COE) {
1520  request->errno = EIO;
1521  fsm->state = ec_fsm_coe_error;
1522  EC_SLAVE_ERR(slave, "Received mailbox protocol 0x%02X as response.\n",
1523  mbox_prot);
1524  return;
1525  }
1526 
1527  if (ec_fsm_coe_check_emergency(fsm, data, rec_size)) {
1528  // check for CoE response again
1529  ec_fsm_coe_receive(fsm, datagram, fsm->request->response_timeout,
1531  return;
1532  }
1533 
1534  if (slave->master->debug_level) {
1535  EC_SLAVE_DBG(slave, 1, "Download response:\n");
1536  ec_print_data(data, rec_size);
1537  }
1538 
1539  if (rec_size < 6) {
1540  request->errno = EIO;
1541  fsm->state = ec_fsm_coe_error;
1542  EC_SLAVE_ERR(slave, "Received data are too small (%zu bytes):\n",
1543  rec_size);
1544  ec_print_data(data, rec_size);
1545  return;
1546  }
1547 
1548  if (EC_READ_U16(data) >> 12 == 0x2 && // SDO request
1549  EC_READ_U8 (data + 2) >> 5 == 0x4) { // abort SDO transfer request
1550  char subidxstr[10];
1551  request->errno = EIO;
1552  fsm->state = ec_fsm_coe_error;
1553  if (request->complete_access) {
1554  subidxstr[0] = 0x00;
1555  } else {
1556  sprintf(subidxstr, ":%02X", request->subindex);
1557  }
1558  EC_SLAVE_ERR(slave, "SDO download 0x%04X%s (%zu bytes) aborted.\n",
1559  request->index, subidxstr, request->data_size);
1560  if (rec_size < 10) {
1561  EC_SLAVE_ERR(slave, "Incomplete abort command:\n");
1562  ec_print_data(data, rec_size);
1563  } else {
1564  fsm->request->abort_code = EC_READ_U32(data + 6);
1565  ec_canopen_abort_msg(slave, fsm->request->abort_code);
1566  }
1567  return;
1568  }
1569 
1570  if (EC_READ_U16(data) >> 12 != 0x3 ||
1571  ((EC_READ_U8(data + 2) >> 5) != 0x01)) { // segment response
1572  if (slave->master->debug_level) {
1573  EC_SLAVE_DBG(slave, 1, "Invalid SDO download response!"
1574  " Retrying...\n");
1575  ec_print_data(data, rec_size);
1576  }
1577  // check for CoE response again
1578  ec_fsm_coe_receive(fsm, datagram, fsm->request->response_timeout,
1580  return;
1581  }
1582 
1583  if (((EC_READ_U8(data + 2) >> 4) & 0x01) != fsm->toggle) {
1584  EC_SLAVE_ERR(slave, "Invalid toggle received during"
1585  " segmented download:\n");
1586  ec_print_data(data, rec_size);
1587  request->errno = EIO;
1588  fsm->state = ec_fsm_coe_error;
1589  return;
1590  }
1591 
1592  fsm->offset += fsm->segment_size;
1593  fsm->remaining -= fsm->segment_size;
1594 
1595  if (fsm->remaining) { // more segments to download
1596  fsm->toggle = !fsm->toggle;
1597  fsm->retries = EC_FSM_RETRIES;
1599  } else {
1600  fsm->state = ec_fsm_coe_end; // success
1601  }
1602 }
1603 
1604 /****************************************************************************/
1605 
1611  ec_fsm_coe_t *fsm,
1612  ec_datagram_t *datagram
1613  )
1614 {
1615  ec_slave_t *slave = fsm->slave;
1616  ec_sdo_request_t *request = fsm->request;
1617  ec_master_t *master = slave->master;
1618 
1619  u8 *data = ec_slave_mbox_prepare_send(slave, datagram, EC_MBOX_TYPE_COE,
1620  10);
1621  if (IS_ERR(data)) {
1622  request->errno = PTR_ERR(data);
1623  return PTR_ERR(data);
1624  }
1625 
1626  EC_WRITE_U16(data, 0x2 << 12); // SDO request
1627  EC_WRITE_U8 (data + 2, 0x2 << 5); // initiate upload request
1628  EC_WRITE_U16(data + 3, request->index);
1629  EC_WRITE_U8 (data + 5, request->subindex);
1630  memset(data + 6, 0x00, 4);
1631 
1632  if (master->debug_level) {
1633  EC_SLAVE_DBG(slave, 1, "Upload request:\n");
1634  ec_print_data(data, 10);
1635  }
1636 
1638  return 0;
1639 }
1640 
1641 /****************************************************************************/
1642 
1648  ec_fsm_coe_t *fsm,
1649  ec_datagram_t *datagram
1650  )
1651 {
1652  ec_slave_t *slave = fsm->slave;
1653  ec_sdo_request_t *request = fsm->request;
1654 
1655  EC_SLAVE_DBG(slave, 1, "Uploading SDO 0x%04X:%02X.\n",
1656  request->index, request->subindex);
1657 
1658  if (!(slave->sii.mailbox_protocols & EC_MBOX_COE)) {
1659  EC_SLAVE_ERR(slave, "Slave does not support CoE!\n");
1660  request->errno = EPROTONOSUPPORT;
1661  fsm->state = ec_fsm_coe_error;
1662  return;
1663  }
1664 
1665  fsm->retries = EC_FSM_RETRIES;
1666  fsm->request->jiffies_sent = jiffies;
1667 
1668  if (ec_fsm_coe_prepare_up(fsm, datagram)) {
1669  fsm->state = ec_fsm_coe_error;
1670  }
1671 }
1672 
1673 /****************************************************************************/
1680  ec_fsm_coe_t *fsm,
1681  ec_datagram_t *datagram
1682  )
1683 {
1684  ec_slave_t *slave = fsm->slave;
1685  unsigned long diff_ms;
1686 
1687  if (fsm->datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--) {
1688  if (ec_fsm_coe_prepare_up(fsm, datagram)) {
1689  fsm->state = ec_fsm_coe_error;
1690  }
1691  return;
1692  }
1693 
1694  if (fsm->datagram->state != EC_DATAGRAM_RECEIVED) {
1695  fsm->request->errno = EIO;
1696  fsm->state = ec_fsm_coe_error;
1697  EC_SLAVE_ERR(slave, "Failed to receive CoE upload request: ");
1699  return;
1700  }
1701 
1702  diff_ms = (jiffies - fsm->request->jiffies_sent) * 1000 / HZ;
1703 
1704  if (fsm->datagram->working_counter != 1) {
1705  if (!fsm->datagram->working_counter) {
1706  if (diff_ms < fsm->request->response_timeout) {
1707 #if DEBUG_RETRIES
1708  EC_SLAVE_DBG(slave, 1, "Slave did not respond to"
1709  " SDO upload request. Retrying after %lu ms...\n",
1710  diff_ms);
1711 #endif
1712  // no response; send request datagram again
1713  if (ec_fsm_coe_prepare_up(fsm, datagram)) {
1714  fsm->state = ec_fsm_coe_error;
1715  }
1716  return;
1717  }
1718  }
1719  fsm->request->errno = EIO;
1720  fsm->state = ec_fsm_coe_error;
1721  EC_SLAVE_ERR(slave, "Reception of CoE upload request for"
1722  " SDO 0x%04x:%x failed with timeout after %lu ms: ",
1723  fsm->request->index, fsm->request->subindex, diff_ms);
1725  return;
1726  }
1727 
1728 #if DEBUG_LONG
1729  if (diff_ms > 200) {
1730  EC_SLAVE_WARN(slave, "SDO 0x%04x:%x upload took %lu ms.\n",
1731  fsm->request->index, fsm->request->subindex, diff_ms);
1732  }
1733 #endif
1734 
1735  fsm->jiffies_start = fsm->datagram->jiffies_sent;
1736  ec_fsm_coe_receive(fsm, datagram, fsm->request->response_timeout,
1738 }
1739 
1740 /****************************************************************************/
1741 
1745  ec_fsm_coe_t *fsm,
1746  ec_datagram_t *datagram
1747  )
1748 {
1749  uint8_t *data =
1750  ec_slave_mbox_prepare_send(fsm->slave, datagram, EC_MBOX_TYPE_COE,
1751  10);
1752  if (IS_ERR(data)) {
1753  fsm->request->errno = PTR_ERR(data);
1754  fsm->state = ec_fsm_coe_error;
1755  return;
1756  }
1757 
1758  EC_WRITE_U16(data, 0x2 << 12); // SDO request
1759  EC_WRITE_U8 (data + 2, (fsm->toggle << 4 // toggle
1760  | 0x3 << 5)); // upload segment request
1761  memset(data + 3, 0x00, 7);
1762 
1763  if (fsm->slave->master->debug_level) {
1764  EC_SLAVE_DBG(fsm->slave, 1, "Upload segment request:\n");
1765  ec_print_data(data, 10);
1766  }
1767 }
1768 
1769 /****************************************************************************/
1770 
1776  ec_fsm_coe_t *fsm,
1777  ec_datagram_t *datagram
1778  )
1779 {
1780  ec_slave_t *slave = fsm->slave;
1781  ec_master_t *master = slave->master;
1782  uint16_t rec_index;
1783  uint8_t *data, mbox_prot, rec_subindex;
1784  size_t rec_size, data_size;
1785  ec_sdo_request_t *request = fsm->request;
1786  unsigned int expedited, size_specified;
1787  int ret;
1788 
1789  if (ec_fsm_mbox_exec(&fsm->fsm_mbox, datagram)) {
1790  return;
1791  }
1792 
1793  if (ec_fsm_mbox_result(&fsm->fsm_mbox)) {
1794  request->errno = EIO;
1795  fsm->state = ec_fsm_coe_error;
1796  if (ec_fsm_mbox_result(&fsm->fsm_mbox) == -ETIMEDOUT) {
1797  EC_SLAVE_ERR(slave, "Timeout after %lu ms while waiting for"
1798  " SDO 0x%04x:%x upload response.\n",
1799  ec_fsm_coe_elapsed_ms(fsm),
1800  request->index, request->subindex);
1801  }
1802  return;
1803  }
1804 
1805  data = ec_slave_mbox_fetch(slave, &slave->mbox_coe_data,
1806  &mbox_prot, &rec_size);
1807 
1808  if (IS_ERR(data)) {
1809  request->errno = PTR_ERR(data);
1810  fsm->state = ec_fsm_coe_error;
1811  return;
1812  }
1813 
1814  if (mbox_prot != EC_MBOX_TYPE_COE) {
1815  request->errno = EIO;
1816  fsm->state = ec_fsm_coe_error;
1817  EC_SLAVE_WARN(slave, "Received mailbox protocol 0x%02X"
1818  " as response.\n", mbox_prot);
1819  return;
1820  }
1821 
1822  if (ec_fsm_coe_check_emergency(fsm, data, rec_size)) {
1823  // check for CoE response again
1824  ec_fsm_coe_receive(fsm, datagram, fsm->request->response_timeout,
1826  return;
1827  }
1828 
1829  if (master->debug_level) {
1830  EC_SLAVE_DBG(slave, 1, "Upload response:\n");
1831  ec_print_data(data, rec_size);
1832  }
1833 
1834  if (rec_size < 6) {
1835  request->errno = EIO;
1836  fsm->state = ec_fsm_coe_error;
1837  EC_SLAVE_ERR(slave, "Received corrupted SDO upload response"
1838  " (%zu bytes)!\n", rec_size);
1839  ec_print_data(data, rec_size);
1840  return;
1841  }
1842 
1843  if (EC_READ_U16(data) >> 12 == 0x2 && // SDO request
1844  EC_READ_U8(data + 2) >> 5 == 0x4) { // abort SDO transfer request
1845  EC_SLAVE_ERR(slave, "SDO upload 0x%04X:%02X aborted.\n",
1846  request->index, request->subindex);
1847  if (rec_size >= 10) {
1848  request->abort_code = EC_READ_U32(data + 6);
1849  ec_canopen_abort_msg(slave, request->abort_code);
1850  } else {
1851  EC_SLAVE_ERR(slave, "No abort message.\n");
1852  }
1853  request->errno = EIO;
1854  fsm->state = ec_fsm_coe_error;
1855  return;
1856  }
1857 
1858  if (EC_READ_U16(data) >> 12 != 0x3 || // SDO response
1859  EC_READ_U8(data + 2) >> 5 != 0x2) { // upload response
1860  EC_SLAVE_ERR(slave, "Received unknown response while"
1861  " uploading SDO 0x%04X:%02X.\n",
1862  request->index, request->subindex);
1863  ec_print_data(data, rec_size);
1864  request->errno = EIO;
1865  fsm->state = ec_fsm_coe_error;
1866  return;
1867  }
1868 
1869  rec_index = EC_READ_U16(data + 3);
1870  rec_subindex = EC_READ_U8(data + 5);
1871 
1872  if (rec_index != request->index || rec_subindex != request->subindex) {
1873  EC_SLAVE_ERR(slave, "Received upload response for wrong SDO"
1874  " (0x%04X:%02X, requested: 0x%04X:%02X).\n",
1875  rec_index, rec_subindex, request->index, request->subindex);
1876  ec_print_data(data, rec_size);
1877 
1878  // check for CoE response again
1879  ec_fsm_coe_receive(fsm, datagram, fsm->request->response_timeout,
1881  return;
1882  }
1883 
1884  // normal or expedited?
1885  expedited = EC_READ_U8(data + 2) & 0x02;
1886 
1887  if (expedited) {
1888  size_specified = EC_READ_U8(data + 2) & 0x01;
1889  if (size_specified) {
1890  fsm->complete_size = 4 - ((EC_READ_U8(data + 2) & 0x0C) >> 2);
1891  } else {
1892  fsm->complete_size = 4;
1893  }
1894 
1895  if (rec_size < 6 + fsm->complete_size) {
1896  request->errno = EIO;
1897  fsm->state = ec_fsm_coe_error;
1898  EC_SLAVE_ERR(slave, "Received corrupted SDO expedited upload"
1899  " response (only %zu bytes)!\n", rec_size);
1900  ec_print_data(data, rec_size);
1901  return;
1902  }
1903 
1904  ret = ec_sdo_request_copy_data(request, data + 6, fsm->complete_size);
1905  if (ret) {
1906  request->errno = -ret;
1907  fsm->state = ec_fsm_coe_error;
1908  return;
1909  }
1910  } else { // normal
1911  if (rec_size < 10) {
1912  request->errno = EIO;
1913  fsm->state = ec_fsm_coe_error;
1914  EC_SLAVE_ERR(slave, "Received corrupted SDO normal upload"
1915  " response (only %zu bytes)!\n", rec_size);
1916  ec_print_data(data, rec_size);
1917  return;
1918  }
1919 
1920  data_size = rec_size - 10;
1921  fsm->complete_size = EC_READ_U32(data + 6);
1922 
1923  ret = ec_sdo_request_alloc(request, fsm->complete_size);
1924  if (ret) {
1925  request->errno = -ret;
1926  fsm->state = ec_fsm_coe_error;
1927  return;
1928  }
1929 
1930  ret = ec_sdo_request_copy_data(request, data + 10, data_size);
1931  if (ret) {
1932  request->errno = -ret;
1933  fsm->state = ec_fsm_coe_error;
1934  return;
1935  }
1936 
1937  fsm->toggle = 0;
1938 
1939  if (data_size < fsm->complete_size) {
1940  EC_SLAVE_DBG(slave, 1, "SDO data incomplete (%zu / %u)."
1941  " Segmenting...\n", data_size, fsm->complete_size);
1943  fsm->retries = EC_FSM_RETRIES;
1945  return;
1946  }
1947  }
1948 
1949  if (master->debug_level) {
1950  EC_SLAVE_DBG(slave, 1, "Uploaded data:\n");
1951  ec_print_data(request->data, request->data_size);
1952  }
1953 
1954  fsm->state = ec_fsm_coe_end; // success
1955 }
1956 
1957 /****************************************************************************/
1958 
1965  ec_fsm_coe_t *fsm,
1966  ec_datagram_t *datagram
1967  )
1968 {
1969  ec_slave_t *slave = fsm->slave;
1970 
1971  if (fsm->datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--) {
1973  return;
1974  }
1975 
1976  if (fsm->datagram->state != EC_DATAGRAM_RECEIVED) {
1977  fsm->request->errno = EIO;
1978  fsm->state = ec_fsm_coe_error;
1979  EC_SLAVE_ERR(slave, "Failed to receive CoE upload segment"
1980  " request datagram: ");
1982  return;
1983  }
1984 
1985  if (fsm->datagram->working_counter != 1) {
1986  fsm->request->errno = EIO;
1987  fsm->state = ec_fsm_coe_error;
1988  EC_SLAVE_ERR(slave, "Reception of CoE upload segment"
1989  " request failed: ");
1991  return;
1992  }
1993 
1994  fsm->jiffies_start = fsm->datagram->jiffies_sent;
1995 
1996  ec_fsm_coe_receive(fsm, datagram, fsm->request->response_timeout,
1998 }
1999 
2000 /****************************************************************************/
2001 
2007  ec_fsm_coe_t *fsm,
2008  ec_datagram_t *datagram
2009  )
2010 {
2011  ec_slave_t *slave = fsm->slave;
2012  ec_master_t *master = slave->master;
2013  uint8_t *data, mbox_prot;
2014  size_t rec_size, data_size;
2015  ec_sdo_request_t *request = fsm->request;
2016  unsigned int last_segment;
2017 
2018  if (ec_fsm_mbox_exec(&fsm->fsm_mbox, datagram)) {
2019  return;
2020  }
2021 
2022  if (ec_fsm_mbox_result(&fsm->fsm_mbox)) {
2023  request->errno = EIO;
2024  fsm->state = ec_fsm_coe_error;
2025  if (ec_fsm_mbox_result(&fsm->fsm_mbox) == -ETIMEDOUT) {
2026  EC_SLAVE_ERR(slave, "Timeout while waiting for SDO upload"
2027  " segment response.\n");
2028  }
2029  return;
2030  }
2031 
2032  data = ec_slave_mbox_fetch(slave, &slave->mbox_coe_data,
2033  &mbox_prot, &rec_size);
2034 
2035  if (IS_ERR(data)) {
2036  request->errno = PTR_ERR(data);
2037  fsm->state = ec_fsm_coe_error;
2038  return;
2039  }
2040 
2041  if (mbox_prot != EC_MBOX_TYPE_COE) {
2042  EC_SLAVE_ERR(slave, "Received mailbox protocol 0x%02X as response.\n",
2043  mbox_prot);
2044  request->errno = EIO;
2045  fsm->state = ec_fsm_coe_error;
2046  return;
2047  }
2048 
2049  if (ec_fsm_coe_check_emergency(fsm, data, rec_size)) {
2050  // check for CoE response again
2051  ec_fsm_coe_receive(fsm, datagram, fsm->request->response_timeout,
2053  return;
2054  }
2055 
2056  if (master->debug_level) {
2057  EC_SLAVE_DBG(slave, 1, "Upload segment response:\n");
2058  ec_print_data(data, rec_size);
2059  }
2060 
2061 
2062  if (rec_size < 10) {
2063  EC_SLAVE_ERR(slave, "Received corrupted SDO upload"
2064  " segment response!\n");
2065  ec_print_data(data, rec_size);
2066  request->errno = EIO;
2067  fsm->state = ec_fsm_coe_error;
2068  return;
2069  }
2070 
2071  if (EC_READ_U16(data) >> 12 == 0x2 && // SDO request
2072  EC_READ_U8 (data + 2) >> 5 == 0x4) { // abort SDO transfer request
2073  EC_SLAVE_ERR(slave, "SDO upload 0x%04X:%02X aborted.\n",
2074  request->index, request->subindex);
2075  request->abort_code = EC_READ_U32(data + 6);
2076  ec_canopen_abort_msg(slave, request->abort_code);
2077  request->errno = EIO;
2078  fsm->state = ec_fsm_coe_error;
2079  return;
2080  }
2081 
2082  if (EC_READ_U16(data) >> 12 != 0x3 || // SDO response
2083  EC_READ_U8 (data + 2) >> 5 != 0x0) { // upload segment response
2084  if (fsm->slave->master->debug_level) {
2085  EC_SLAVE_DBG(slave, 1, "Invalid SDO upload segment response!\n");
2086  ec_print_data(data, rec_size);
2087  }
2088  // check for CoE response again
2089  ec_fsm_coe_receive(fsm, datagram, fsm->request->response_timeout,
2091  return;
2092  }
2093 
2094  data_size = rec_size - 3; /* Header of segment upload is smaller than
2095  normal upload */
2096  if (rec_size == 10) {
2097  uint8_t seg_size = (EC_READ_U8(data + 2) & 0xE) >> 1;
2098  data_size -= seg_size;
2099  }
2100 
2101  if (request->data_size + data_size > fsm->complete_size) {
2102  EC_SLAVE_ERR(slave, "SDO upload 0x%04X:%02X failed: Fragment"
2103  " exceeding complete size!\n",
2104  request->index, request->subindex);
2105  request->errno = ENOBUFS;
2106  fsm->state = ec_fsm_coe_error;
2107  return;
2108  }
2109 
2110  memcpy(request->data + request->data_size, data + 3, data_size);
2111  request->data_size += data_size;
2112 
2113  last_segment = EC_READ_U8(data + 2) & 0x01;
2114  if (!last_segment) {
2115  fsm->toggle = !fsm->toggle;
2117  fsm->retries = EC_FSM_RETRIES;
2119  return;
2120  }
2121 
2122  if (request->data_size != fsm->complete_size) {
2123  EC_SLAVE_WARN(slave, "SDO upload 0x%04X:%02X: Assembled data"
2124  " size (%zu) does not match complete size (%u)!\n",
2125  request->index, request->subindex,
2126  request->data_size, fsm->complete_size);
2127  }
2128 
2129  if (master->debug_level) {
2130  EC_SLAVE_DBG(slave, 1, "Uploaded data:\n");
2131  ec_print_data(request->data, request->data_size);
2132  }
2133 
2134  fsm->state = ec_fsm_coe_end; // success
2135 }
2136 
2137 /****************************************************************************/
2138 
2144  ec_fsm_coe_t *fsm,
2145  ec_datagram_t *datagram
2146  )
2147 {
2148 }
2149 
2150 /****************************************************************************/
2151 
2157  ec_fsm_coe_t *fsm,
2158  ec_datagram_t *datagram
2159  )
2160 {
2161 }
2162 
2163 /****************************************************************************/
int ec_fsm_coe_prepare_down_start(ec_fsm_coe_t *, ec_datagram_t *)
Prepare a donwnload request.
Definition: fsm_coe.c:1051
#define EC_FSM_RETRIES
Number of state machine retries on datagram timeout.
Definition: globals.h:47
void ec_fsm_coe_up_seg_response(ec_fsm_coe_t *, ec_datagram_t *)
CoE state: UP SEG RESPONSE.
Definition: fsm_coe.c:2006
CANopen over EtherCAT.
Definition: globals.h:152
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:143
unsigned long jiffies_sent
Jiffies, when the datagram was sent.
Definition: datagram.h:101
ec_sii_t sii
Extracted SII data.
Definition: slave.h:218
static void ec_fsm_coe_receive(ec_fsm_coe_t *fsm, ec_datagram_t *datagram, unsigned long timeout_ms, void(*state)(ec_fsm_coe_t *, ec_datagram_t *))
Waits for a CoE response.
Definition: fsm_coe.c:336
int ec_fsm_coe_prepare_up(ec_fsm_coe_t *, ec_datagram_t *)
Prepare an upload request.
Definition: fsm_coe.c:1610
void ec_fsm_coe_up_start(ec_fsm_coe_t *, ec_datagram_t *)
CoE state: UP START.
Definition: fsm_coe.c:1647
uint32_t offset
Data offset during segmented download.
Definition: fsm_coe.h:58
#define EC_SLAVE_DBG(slave, level, fmt, args...)
Convenience macro for printing slave-specific debug messages to syslog.
Definition: slave.h:100
CANopen SDO entry.
Definition: sdo_entry.h:46
void ec_fsm_coe_end(ec_fsm_coe_t *, ec_datagram_t *)
State: END.
Definition: fsm_coe.c:2156
size_t segment_size
Current segment size.
Definition: fsm_coe.h:60
int ec_fsm_mbox_exec(ec_fsm_mbox_t *fsm, ec_datagram_t *datagram)
Executes the current state of the state machine.
Definition: fsm_mbox.c:161
void ec_fsm_coe_dict_response(ec_fsm_coe_t *, ec_datagram_t *)
CoE state: DICT RESPONSE.
Definition: fsm_coe.c:497
CANopen SDO request.
Definition: sdo_request.h:40
void ec_fsm_coe_error(ec_fsm_coe_t *, ec_datagram_t *)
State: ERROR.
Definition: fsm_coe.c:2143
uint16_t bit_length
Data size in bit.
Definition: sdo_entry.h:51
uint32_t response_timeout
Maximum time in ms, the transfer is retried, if the slave does not respond.
Definition: sdo_request.h:50
void ec_fsm_mbox_receive(ec_fsm_mbox_t *fsm, ec_slave_t *slave, ec_mbox_data_t *mbox_data, unsigned long jiffies_start, unsigned long timeout_ms)
Starts waiting for a mailbox response.
Definition: fsm_mbox.c:102
uint32_t code
Code.
Definition: globals.h:281
#define EC_SLAVE_WARN(slave, fmt, args...)
Convenience macro for printing slave-specific warnings to syslog.
Definition: slave.h:84
void ec_fsm_coe_dict_entry_response(ec_fsm_coe_t *, ec_datagram_t *)
CoE state: DICT ENTRY RESPONSE.
Definition: fsm_coe.c:883
Not used by its state machine in this cycle and not to be queued.
Definition: datagram.h:73
EtherCAT datagram.
Definition: datagram.h:81
ec_sii_coe_details_t coe_details
CoE detail flags.
Definition: slave.h:154
uint16_t index
SDO index.
Definition: sdo_request.h:42
#define EC_WRITE_U8(DATA, VAL)
Write an 8-bit unsigned value to EtherCAT data.
Definition: ecrt.h:3353
uint32_t abort_code
SDO request abort code.
Definition: sdo_request.h:60
void(* state)(ec_fsm_coe_t *, ec_datagram_t *)
CoE state function.
Definition: fsm_coe.h:49
void ec_fsm_coe_down_prepare_segment_request(ec_fsm_coe_t *, ec_datagram_t *)
Prepare a download segment request.
Definition: fsm_coe.c:1264
void ec_fsm_coe_up_seg_request(ec_fsm_coe_t *, ec_datagram_t *)
CoE state: UP REQUEST.
Definition: fsm_coe.c:1964
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:290
uint16_t working_counter
Working counter.
Definition: datagram.h:96
struct list_head list
List item.
Definition: sdo.h:42
#define EC_COE_DOWN_SEG_MIN_DATA_SIZE
Minimum size of download segment.
Definition: fsm_coe.c:50
CANopen SDO.
Definition: sdo.h:41
uint16_t index
SDO index.
Definition: sdo.h:44
uint8_t * data
Pointer to SDO data.
Definition: sdo_request.h:44
int ec_fsm_coe_success(const ec_fsm_coe_t *fsm)
Returns, if the state machine terminated with success.
Definition: fsm_coe.c:262
#define EC_FSM_COE_DICT_TIMEOUT
Maximum time in ms to wait for responses when reading out the dictionary.
Definition: fsm_coe.c:38
Sent (still in the queue).
Definition: datagram.h:69
#define EC_COE_DOWN_SEG_REQ_HEADER_SIZE
CoE download segment request header size.
Definition: fsm_coe.c:46
struct list_head list
List item.
Definition: sdo_entry.h:47
void ec_fsm_coe_dict_entry_request(ec_fsm_coe_t *, ec_datagram_t *)
CoE state: DICT ENTRY REQUEST.
Definition: fsm_coe.c:842
static unsigned long ec_fsm_coe_elapsed_ms(const ec_fsm_coe_t *fsm)
Time elapsed since the request was sent.
Definition: fsm_coe.c:355
const char * message
Message belonging to code.
Definition: globals.h:282
struct list_head sdo_dictionary
SDO dictionary list.
Definition: slave.h:220
Global definitions and macros.
void ec_fsm_coe_up_request(ec_fsm_coe_t *, ec_datagram_t *)
CoE state: UP REQUEST.
Definition: fsm_coe.c:1679
ec_direction_t dir
Direction.
Definition: sdo_request.h:52
EtherCAT master structure.
uint8_t object_code
Object code.
Definition: sdo.h:45
ec_sdo_t * sdo
current SDO
Definition: fsm_coe.h:53
Initial state of a new datagram.
Definition: datagram.h:67
EtherCAT CoE state machines.
EtherCAT slave.
Definition: slave.h:170
int ec_fsm_mbox_result(const ec_fsm_mbox_t *fsm)
Returns the result of the terminated state machine.
Definition: fsm_mbox.c:195
int ec_sdo_request_copy_data(ec_sdo_request_t *req, const uint8_t *source, size_t size)
Copies SDO data from an external source.
Definition: sdo_request.c:150
char * description
Description.
Definition: sdo_entry.h:54
int ec_fsm_coe_check_emergency(const ec_fsm_coe_t *, const uint8_t *, size_t)
Check if the received data are a CoE emergency request.
Definition: fsm_coe.c:293
Code/Message pair.
Definition: globals.h:280
ec_datagram_state_t state
State.
Definition: datagram.h:97
void ec_fsm_coe_dict_desc_request(ec_fsm_coe_t *, ec_datagram_t *)
CoE state: DICT DESC REQUEST.
Definition: fsm_coe.c:643
ec_slave_config_t * config
Current configuration.
Definition: slave.h:184
#define EC_WRITE_U32(DATA, VAL)
Write a 32-bit unsigned value to EtherCAT data.
Definition: ecrt.h:3387
void ec_fsm_mbox_abort(ec_fsm_mbox_t *fsm)
Aborts the state machine and releases the mailbox read lock, if held.
Definition: fsm_mbox.c:220
void ec_fsm_coe_up_prepare_segment_request(ec_fsm_coe_t *, ec_datagram_t *)
Prepare an SDO upload segment request.
Definition: fsm_coe.c:1744
uint8_t enable_sdo_info
SDO information service available.
Definition: globals.h:162
uint16_t mailbox_protocols
Supported mailbox protocols.
Definition: slave.h:141
ec_sdo_request_t * request
SDO request.
Definition: fsm_coe.h:55
int ec_fsm_coe_dict_prepare_desc(ec_fsm_coe_t *, ec_datagram_t *)
Prepare an object description request.
Definition: fsm_coe.c:469
unsigned int debug_level
Master debug level.
Definition: master.h:284
void ec_fsm_coe_dict_desc_response(ec_fsm_coe_t *, ec_datagram_t *)
CoE state: DICT DESC RESPONSE.
Definition: fsm_coe.c:715
#define EC_SLAVE_ERR(slave, fmt, args...)
Convenience macro for printing slave-specific errors to syslog.
Definition: slave.h:70
void ec_datagram_print_wc_error(const ec_datagram_t *datagram)
Evaluates the working counter of a single-cast datagram.
Definition: datagram.c:605
void ec_fsm_coe_up_response(ec_fsm_coe_t *, ec_datagram_t *)
CoE state: UP RESPONSE.
Definition: fsm_coe.c:1775
unsigned long jiffies_sent
Jiffies, when the upload/download request was sent.
Definition: sdo_request.h:57
uint8_t subindex
current subindex
Definition: fsm_coe.h:54
char * name
SDO name.
Definition: sdo.h:46
void ec_fsm_coe_clear(ec_fsm_coe_t *fsm)
Destructor.
Definition: fsm_coe.c:182
#define EC_WRITE_U16(DATA, VAL)
Write a 16-bit unsigned value to EtherCAT data.
Definition: ecrt.h:3370
ec_datagram_t * datagram
Datagram used in last step.
Definition: fsm_coe.h:50
uint32_t remaining
Remaining bytes during segmented download.
Definition: fsm_coe.h:59
#define EC_READ_U32(DATA)
Read a 32-bit unsigned value from EtherCAT data.
Definition: ecrt.h:3277
uint32_t complete_size
Used when segmenting.
Definition: fsm_coe.h:56
int ec_fsm_coe_dict_prepare_entry(ec_fsm_coe_t *, ec_datagram_t *)
Prepare an entry description request.
Definition: fsm_coe.c:685
ec_master_t * master
Master owning the slave.
Definition: slave.h:172
int errno
Error number.
Definition: sdo_request.h:59
unsigned long jiffies_start
CoE timestamp.
Definition: fsm_coe.h:51
void ec_fsm_coe_dictionary(ec_fsm_coe_t *fsm, ec_slave_t *slave)
Starts reading a slaves&#39; SDO dictionary.
Definition: fsm_coe.c:193
void ec_fsm_coe_dict_start(ec_fsm_coe_t *, ec_datagram_t *)
CoE state: DICT START.
Definition: fsm_coe.c:396
void ec_fsm_coe_down_request(ec_fsm_coe_t *, ec_datagram_t *)
CoE state: DOWN REQUEST.
Definition: fsm_coe.c:1197
void ec_canopen_abort_msg(const ec_slave_t *, uint32_t)
Outputs an SDO abort message.
Definition: fsm_coe.c:147
void ec_fsm_coe_down_seg_request(ec_fsm_coe_t *, ec_datagram_t *)
CoE state: DOWN SEG REQUEST.
Definition: fsm_coe.c:1445
uint16_t data_type
Data type.
Definition: sdo_entry.h:50
Access rights in OP.
Definition: globals.h:197
#define EC_MBOX_HEADER_SIZE
Mailbox header size.
Definition: globals.h:83
void ec_sdo_init(ec_sdo_t *sdo, ec_slave_t *slave, uint16_t index)
Constructor.
Definition: sdo.c:39
Access rights in SAFEOP.
Definition: globals.h:196
int ec_fsm_coe_prepare_dict(ec_fsm_coe_t *, ec_datagram_t *)
Prepare a dictionary request.
Definition: fsm_coe.c:370
void ec_fsm_coe_init(ec_fsm_coe_t *fsm)
Constructor.
Definition: fsm_coe.c:169
void ec_print_data(const uint8_t *, size_t)
Outputs frame contents for debugging purposes.
Definition: module.c:348
uint8_t read_access[EC_SDO_ENTRY_ACCESS_COUNT]
Read access.
Definition: sdo_entry.h:52
uint8_t subindex
SDO subindex.
Definition: sdo_request.h:43
struct list_head entries
List of entries.
Definition: sdo.h:48
size_t data_size
Size of SDO data.
Definition: sdo_request.h:46
#define EC_READ_U16(DATA)
Read a 16-bit unsigned value from EtherCAT data.
Definition: ecrt.h:3261
ec_coe_emerg_ring_t emerg_ring
CoE emergency ring buffer.
Definition: slave_config.h:156
void ec_datagram_print_state(const ec_datagram_t *datagram)
Prints the state of a datagram.
Definition: datagram.c:565
Mailbox functionality.
void ec_coe_emerg_ring_push(ec_coe_emerg_ring_t *ring, const u8 *msg)
Add a new emergency message.
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:229
ec_fsm_mbox_t fsm_mbox
Mailbox receive state machine.
Definition: fsm_coe.h:52
void ec_fsm_coe_dict_request(ec_fsm_coe_t *, ec_datagram_t *)
CoE state: DICT REQUEST.
Definition: fsm_coe.c:428
Access rights in PREOP.
Definition: globals.h:195
Queued for sending.
Definition: datagram.h:68
void ec_fsm_coe_down_start(ec_fsm_coe_t *, ec_datagram_t *)
CoE state: DOWN START.
Definition: fsm_coe.c:1146
Timed out (dequeued).
Definition: datagram.h:71
uint8_t max_subindex
Maximum subindex.
Definition: sdo.h:47
void ec_fsm_mbox_init(ec_fsm_mbox_t *fsm)
Constructor.
Definition: fsm_mbox.c:45
void ec_fsm_coe_down_seg_response(ec_fsm_coe_t *, ec_datagram_t *)
CoE state: DOWN SEG RESPONSE.
Definition: fsm_coe.c:1487
uint16_t configured_rx_mailbox_size
Configured receive mailbox size.
Definition: slave.h:191
uint8_t toggle
toggle bit for segment commands
Definition: fsm_coe.h:57
void ec_sdo_entry_init(ec_sdo_entry_t *entry, ec_sdo_t *sdo, uint8_t subindex)
Constructor.
Definition: sdo_entry.c:37
#define EC_READ_U8(DATA)
Read an 8-bit unsigned value from EtherCAT data.
Definition: ecrt.h:3245
EtherCAT slave configuration.
Definition: slave_config.h:111
void ec_fsm_coe_down_response(ec_fsm_coe_t *, ec_datagram_t *)
CoE state: DOWN RESPONSE.
Definition: fsm_coe.c:1329
#define EC_COE_DOWN_REQ_HEADER_SIZE
CoE download request header size.
Definition: fsm_coe.c:42
unsigned int retries
retries upon datagram timeout
Definition: fsm_coe.h:47
EtherCAT slave configuration structure.
uint8_t write_access[EC_SDO_ENTRY_ACCESS_COUNT]
Write access.
Definition: sdo_entry.h:53
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:206
int ec_sdo_request_alloc(ec_sdo_request_t *req, size_t size)
Pre-allocates the data memory.
Definition: sdo_request.c:121
Values written by the master.
Definition: ecrt.h:524
Received (dequeued).
Definition: datagram.h:70
EtherCAT master.
Definition: master.h:194
ec_mbox_data_t mbox_coe_data
Received mailbox data for CoE.
Definition: slave.h:238
ec_slave_t * slave
slave the FSM runs on
Definition: fsm_coe.h:46
const ec_code_msg_t sdo_abort_messages[]
SDO abort messages.
Definition: fsm_coe.c:106
uint8_t complete_access
SDO shall be transferred completely.
Definition: sdo_request.h:47
void ec_fsm_mbox_clear(ec_fsm_mbox_t *fsm)
Destructor.
Definition: fsm_mbox.c:64
unsigned int has_general
General category present.
Definition: slave.h:148
void ec_fsm_coe_abort(ec_fsm_coe_t *fsm)
Aborts a running transfer.
Definition: fsm_coe.c:276
Finite state machines for the CANopen over EtherCAT protocol.
Definition: fsm_coe.h:45