IgH EtherCAT Master  1.6.0
slave.c
Go to the documentation of this file.
1 /*****************************************************************************
2  *
3  * Copyright (C) 2006-2012 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 
27 /****************************************************************************/
28 
29 #include <linux/module.h>
30 #include <linux/delay.h>
31 
32 #include "globals.h"
33 #include "datagram.h"
34 #include "master.h"
35 #include "slave_config.h"
36 
37 #include "slave.h"
38 
39 /****************************************************************************/
40 
41 extern const ec_code_msg_t al_status_messages[];
42 
43 /****************************************************************************/
44 
45 char *ec_slave_sii_string(ec_slave_t *, unsigned int);
46 
47 /****************************************************************************/
48 
55  ec_slave_t *slave,
56  ec_master_t *master,
57  ec_device_index_t dev_idx,
58  uint16_t ring_position,
59  uint16_t station_address
60  )
61 {
62  unsigned int i;
63 
64  slave->master = master;
65  slave->device_index = dev_idx;
66  slave->ring_position = ring_position;
67  slave->station_address = station_address;
68  slave->effective_alias = 0x0000;
69 
70  slave->config = NULL;
73  slave->error_flag = 0;
74  slave->force_config = 0;
75  slave->configured_rx_mailbox_offset = 0x0000;
76  slave->configured_rx_mailbox_size = 0x0000;
77  slave->configured_tx_mailbox_offset = 0x0000;
78  slave->configured_tx_mailbox_size = 0x0000;
79 
80  slave->base_type = 0;
81  slave->base_revision = 0;
82  slave->base_build = 0;
83  slave->base_fmmu_count = 0;
84  slave->base_sync_count = 0;
85 
86  for (i = 0; i < EC_MAX_PORTS; i++) {
88 
89  slave->ports[i].link.link_up = 0;
90  slave->ports[i].link.loop_closed = 0;
91  slave->ports[i].link.signal_detected = 0;
92  slave->sii.physical_layer[i] = 0xFF;
93 
94  slave->ports[i].receive_time = 0U;
95 
96  slave->ports[i].next_slave = NULL;
97  slave->ports[i].delay_to_next_dc = 0U;
98  }
99 
100  slave->base_fmmu_bit_operation = 0;
101  slave->base_dc_supported = 0;
102  slave->base_dc_range = EC_DC_32;
103  slave->has_dc_system_time = 0;
104  slave->transmission_delay = 0U;
105 
106  slave->sii_words = NULL;
107  slave->sii_nwords = 0;
108 
109  slave->sii.alias = 0x0000;
110  slave->sii.vendor_id = 0x00000000;
111  slave->sii.product_code = 0x00000000;
112  slave->sii.revision_number = 0x00000000;
113  slave->sii.serial_number = 0x00000000;
114  slave->sii.boot_rx_mailbox_offset = 0x0000;
115  slave->sii.boot_rx_mailbox_size = 0x0000;
116  slave->sii.boot_tx_mailbox_offset = 0x0000;
117  slave->sii.boot_tx_mailbox_size = 0x0000;
118  slave->sii.std_rx_mailbox_offset = 0x0000;
119  slave->sii.std_rx_mailbox_size = 0x0000;
120  slave->sii.std_tx_mailbox_offset = 0x0000;
121  slave->sii.std_tx_mailbox_size = 0x0000;
122  slave->sii.mailbox_protocols = 0;
123 
124  slave->sii.strings = NULL;
125  slave->sii.string_count = 0;
126 
127  slave->sii.has_general = 0;
128  slave->sii.group = NULL;
129  slave->sii.image = NULL;
130  slave->sii.order = NULL;
131  slave->sii.name = NULL;
132  memset(&slave->sii.coe_details, 0x00, sizeof(ec_sii_coe_details_t));
133  memset(&slave->sii.general_flags, 0x00, sizeof(ec_sii_general_flags_t));
134  slave->sii.current_on_ebus = 0;
135 
136  slave->sii.syncs = NULL;
137  slave->sii.sync_count = 0;
138 
139  INIT_LIST_HEAD(&slave->sii.pdos);
140 
141  INIT_LIST_HEAD(&slave->sdo_dictionary);
142 
143  slave->sdo_dictionary_fetched = 0;
144  slave->jiffies_preop = 0;
145 
146  INIT_LIST_HEAD(&slave->sdo_requests);
147  INIT_LIST_HEAD(&slave->reg_requests);
148  INIT_LIST_HEAD(&slave->foe_requests);
149  INIT_LIST_HEAD(&slave->soe_requests);
150  INIT_LIST_HEAD(&slave->eoe_requests);
151 
152  // create state machine object
153  ec_fsm_slave_init(&slave->fsm, slave);
154 }
155 
156 /****************************************************************************/
157 
164 {
165  ec_sdo_t *sdo, *next_sdo;
166  unsigned int i;
167  ec_pdo_t *pdo, *next_pdo;
168 
169  // abort all pending requests
170 
171  while (!list_empty(&slave->sdo_requests)) {
172  ec_sdo_request_t *request =
173  list_entry(slave->sdo_requests.next, ec_sdo_request_t, list);
174  list_del_init(&request->list); // dequeue
175  EC_SLAVE_WARN(slave, "Discarding SDO request,"
176  " slave about to be deleted.\n");
177  request->state = EC_INT_REQUEST_FAILURE;
178  }
179 
180  while (!list_empty(&slave->reg_requests)) {
181  ec_reg_request_t *reg =
182  list_entry(slave->reg_requests.next, ec_reg_request_t, list);
183  list_del_init(&reg->list); // dequeue
184  EC_SLAVE_WARN(slave, "Discarding register request,"
185  " slave about to be deleted.\n");
186  reg->state = EC_INT_REQUEST_FAILURE;
187  }
188 
189  while (!list_empty(&slave->foe_requests)) {
190  ec_foe_request_t *request =
191  list_entry(slave->foe_requests.next, ec_foe_request_t, list);
192  list_del_init(&request->list); // dequeue
193  EC_SLAVE_WARN(slave, "Discarding FoE request,"
194  " slave about to be deleted.\n");
195  request->state = EC_INT_REQUEST_FAILURE;
196  }
197 
198  while (!list_empty(&slave->soe_requests)) {
199  ec_soe_request_t *request =
200  list_entry(slave->soe_requests.next, ec_soe_request_t, list);
201  list_del_init(&request->list); // dequeue
202  EC_SLAVE_WARN(slave, "Discarding SoE request,"
203  " slave about to be deleted.\n");
204  request->state = EC_INT_REQUEST_FAILURE;
205  }
206 
207 #ifdef EC_EOE
208  while (!list_empty(&slave->eoe_requests)) {
209  ec_eoe_request_t *request =
210  list_entry(slave->eoe_requests.next, ec_eoe_request_t, list);
211  list_del_init(&request->list); // dequeue
212  EC_SLAVE_WARN(slave, "Discarding EoE request,"
213  " slave about to be deleted.\n");
214  request->state = EC_INT_REQUEST_FAILURE;
215  }
216 #endif
217 
218  wake_up_all(&slave->master->request_queue);
219 
220  if (slave->config) {
222  }
223 
224  // free all SDOs
225  list_for_each_entry_safe(sdo, next_sdo, &slave->sdo_dictionary, list) {
226  list_del(&sdo->list);
227  ec_sdo_clear(sdo);
228  kfree(sdo);
229  }
230 
231  // free all strings
232  if (slave->sii.strings) {
233  for (i = 0; i < slave->sii.string_count; i++)
234  kfree(slave->sii.strings[i]);
235  kfree(slave->sii.strings);
236  }
237 
238  // free all sync managers
240 
241  // free all SII PDOs
242  list_for_each_entry_safe(pdo, next_pdo, &slave->sii.pdos, list) {
243  list_del(&pdo->list);
244  ec_pdo_clear(pdo);
245  kfree(pdo);
246  }
247 
248  if (slave->sii_words) {
249  kfree(slave->sii_words);
250  }
251 
252  ec_fsm_slave_clear(&slave->fsm);
253 }
254 
255 /****************************************************************************/
256 
260 {
261  unsigned int i;
262 
263  if (slave->sii.syncs) {
264  for (i = 0; i < slave->sii.sync_count; i++) {
265  ec_sync_clear(&slave->sii.syncs[i]);
266  }
267  kfree(slave->sii.syncs);
268  slave->sii.syncs = NULL;
269  }
270 }
271 
272 /****************************************************************************/
273 
279  ec_slave_state_t new_state
280  )
281 {
282  if (new_state != slave->current_state) {
283  if (slave->master->debug_level) {
284  char old_state[EC_STATE_STRING_SIZE],
285  cur_state[EC_STATE_STRING_SIZE];
286  ec_state_string(slave->current_state, old_state, 0);
287  ec_state_string(new_state, cur_state, 0);
288  EC_SLAVE_DBG(slave, 0, "%s -> %s.\n", old_state, cur_state);
289  }
290  slave->current_state = new_state;
291  }
292 }
293 
294 /****************************************************************************/
295 
301  ec_slave_state_t state
302  )
303 {
304  slave->requested_state = state;
305  slave->error_flag = 0;
306 }
307 
308 /****************************************************************************/
309 
317  ec_slave_t *slave,
318  const uint8_t *data,
319  size_t data_size
320  )
321 {
322  int i, err;
323  size_t size;
324  off_t offset;
325 
326  slave->sii.string_count = data[0];
327 
328  if (slave->sii.string_count) {
329  if (!(slave->sii.strings =
330  kmalloc(sizeof(char *) * slave->sii.string_count,
331  GFP_KERNEL))) {
332  EC_SLAVE_ERR(slave, "Failed to allocate string array memory.\n");
333  err = -ENOMEM;
334  goto out_zero;
335  }
336 
337  offset = 1;
338  for (i = 0; i < slave->sii.string_count; i++) {
339  size = data[offset];
340  // allocate memory for string structure and data at a single blow
341  if (!(slave->sii.strings[i] =
342  kmalloc(sizeof(char) * size + 1, GFP_KERNEL))) {
343  EC_SLAVE_ERR(slave, "Failed to allocate string memory.\n");
344  err = -ENOMEM;
345  goto out_free;
346  }
347  memcpy(slave->sii.strings[i], data + offset + 1, size);
348  slave->sii.strings[i][size] = 0x00; // append binary zero
349  offset += 1 + size;
350  }
351  }
352 
353  return 0;
354 
355 out_free:
356  for (i--; i >= 0; i--)
357  kfree(slave->sii.strings[i]);
358  kfree(slave->sii.strings);
359  slave->sii.strings = NULL;
360 out_zero:
361  slave->sii.string_count = 0;
362  return err;
363 }
364 
365 /****************************************************************************/
366 
373  ec_slave_t *slave,
374  const uint8_t *data,
375  size_t data_size
376  )
377 {
378  unsigned int i;
379  uint8_t flags;
380 
381  if (data_size != 32) {
382  EC_SLAVE_ERR(slave, "Wrong size of general category (%zu/32).\n",
383  data_size);
384  return -EINVAL;
385  }
386 
387  slave->sii.group = ec_slave_sii_string(slave, data[0]);
388  slave->sii.image = ec_slave_sii_string(slave, data[1]);
389  slave->sii.order = ec_slave_sii_string(slave, data[2]);
390  slave->sii.name = ec_slave_sii_string(slave, data[3]);
391 
392  for (i = 0; i < 4; i++)
393  slave->sii.physical_layer[i] =
394  (data[4] & (0x03 << (i * 2))) >> (i * 2);
395 
396  // read CoE details
397  flags = EC_READ_U8(data + 5);
398  slave->sii.coe_details.enable_sdo = (flags >> 0) & 0x01;
399  slave->sii.coe_details.enable_sdo_info = (flags >> 1) & 0x01;
400  slave->sii.coe_details.enable_pdo_assign = (flags >> 2) & 0x01;
401  slave->sii.coe_details.enable_pdo_configuration = (flags >> 3) & 0x01;
402  slave->sii.coe_details.enable_upload_at_startup = (flags >> 4) & 0x01;
403  slave->sii.coe_details.enable_sdo_complete_access = (flags >> 5) & 0x01;
404 
405  // read general flags
406  flags = EC_READ_U8(data + 0x000B);
407  slave->sii.general_flags.enable_safeop = (flags >> 0) & 0x01;
408  slave->sii.general_flags.enable_not_lrw = (flags >> 1) & 0x01;
409 
410  slave->sii.current_on_ebus = EC_READ_S16(data + 0x0C);
411  slave->sii.has_general = 1;
412  return 0;
413 }
414 
415 /****************************************************************************/
416 
424  ec_slave_t *slave,
425  const uint8_t *data,
426  size_t data_size
427  )
428 {
429  unsigned int i, count, total_count;
430  ec_sync_t *sync;
431  size_t memsize;
432  ec_sync_t *syncs;
433  uint8_t index;
434 
435  // one sync manager struct is 4 words long
436  if (data_size % 8) {
437  EC_SLAVE_ERR(slave, "Invalid SII sync manager category size %zu.\n",
438  data_size);
439  return -EINVAL;
440  }
441 
442  count = data_size / 8;
443 
444  if (count) {
445  total_count = count + slave->sii.sync_count;
446  if (total_count > EC_MAX_SYNC_MANAGERS) {
447  EC_SLAVE_ERR(slave, "Exceeded maximum number of"
448  " sync managers!\n");
449  return -EOVERFLOW;
450  }
451  memsize = sizeof(ec_sync_t) * total_count;
452  if (!(syncs = kmalloc(memsize, GFP_KERNEL))) {
453  EC_SLAVE_ERR(slave, "Failed to allocate %zu bytes"
454  " for sync managers.\n", memsize);
455  return -ENOMEM;
456  }
457 
458  for (i = 0; i < slave->sii.sync_count; i++)
459  ec_sync_init_copy(syncs + i, slave->sii.syncs + i);
460 
461  // initialize new sync managers
462  for (i = 0; i < count; i++, data += 8) {
463  index = i + slave->sii.sync_count;
464  sync = &syncs[index];
465 
466  ec_sync_init(sync, slave);
467  sync->physical_start_address = EC_READ_U16(data);
468  sync->default_length = EC_READ_U16(data + 2);
469  sync->control_register = EC_READ_U8(data + 4);
470  sync->enable = EC_READ_U8(data + 6);
471  }
472 
473  if (slave->sii.syncs)
474  kfree(slave->sii.syncs);
475  slave->sii.syncs = syncs;
476  slave->sii.sync_count = total_count;
477  }
478 
479  return 0;
480 }
481 
482 /****************************************************************************/
483 
490  ec_slave_t *slave,
491  const uint8_t *data,
492  size_t data_size,
493  ec_direction_t dir
494  )
495 {
496  int ret;
497  ec_pdo_t *pdo;
498  ec_pdo_entry_t *entry;
499  unsigned int entry_count, i;
500 
501  while (data_size >= 8) {
502  if (!(pdo = kmalloc(sizeof(ec_pdo_t), GFP_KERNEL))) {
503  EC_SLAVE_ERR(slave, "Failed to allocate PDO memory.\n");
504  return -ENOMEM;
505  }
506 
507  ec_pdo_init(pdo);
508  pdo->index = EC_READ_U16(data);
509  entry_count = EC_READ_U8(data + 2);
510  pdo->sync_index = EC_READ_U8(data + 3);
511  ret = ec_pdo_set_name(pdo,
512  ec_slave_sii_string(slave, EC_READ_U8(data + 5)));
513  if (ret) {
514  ec_pdo_clear(pdo);
515  kfree(pdo);
516  return ret;
517  }
518  list_add_tail(&pdo->list, &slave->sii.pdos);
519 
520  data_size -= 8;
521  data += 8;
522 
523  for (i = 0; i < entry_count; i++) {
524  if (!(entry = kmalloc(sizeof(ec_pdo_entry_t), GFP_KERNEL))) {
525  EC_SLAVE_ERR(slave, "Failed to allocate PDO entry memory.\n");
526  return -ENOMEM;
527  }
528 
529  ec_pdo_entry_init(entry);
530  entry->index = EC_READ_U16(data);
531  entry->subindex = EC_READ_U8(data + 2);
532  ret = ec_pdo_entry_set_name(entry,
533  ec_slave_sii_string(slave, EC_READ_U8(data + 3)));
534  if (ret) {
535  ec_pdo_entry_clear(entry);
536  kfree(entry);
537  return ret;
538  }
539  entry->bit_length = EC_READ_U8(data + 5);
540  list_add_tail(&entry->list, &pdo->entries);
541 
542  data_size -= 8;
543  data += 8;
544  }
545 
546  // if sync manager index is positive, the PDO is mapped by default
547  if (pdo->sync_index >= 0) {
548  ec_sync_t *sync;
549 
550  if (!(sync = ec_slave_get_sync(slave, pdo->sync_index))) {
551  EC_SLAVE_ERR(slave, "Invalid SM index %i for PDO 0x%04X.",
552  pdo->sync_index, pdo->index);
553  return -ENOENT;
554  }
555 
556  ret = ec_pdo_list_add_pdo_copy(&sync->pdos, pdo);
557  if (ret)
558  return ret;
559  }
560  }
561 
562  return 0;
563 }
564 
565 /****************************************************************************/
566 
573  ec_slave_t *slave,
574  unsigned int index
575  )
576 {
577  if (!index--)
578  return NULL;
579 
580  if (index >= slave->sii.string_count) {
581  EC_SLAVE_DBG(slave, 1, "String %u not found.\n", index);
582  return NULL;
583  }
584 
585  return slave->sii.strings[index];
586 }
587 
588 /****************************************************************************/
589 
595  ec_slave_t *slave,
596  uint8_t sync_index
597  )
598 {
599  if (sync_index < slave->sii.sync_count) {
600  return &slave->sii.syncs[sync_index];
601  } else {
602  return NULL;
603  }
604 }
605 
606 /****************************************************************************/
607 
613  unsigned int *sdo_count,
614  unsigned int *entry_count
616  )
617 {
618  unsigned int sdos = 0, entries = 0;
619  ec_sdo_t *sdo;
620  ec_sdo_entry_t *entry;
621 
622  list_for_each_entry(sdo, &slave->sdo_dictionary, list) {
623  sdos++;
624  list_for_each_entry(entry, &sdo->entries, list) {
625  entries++;
626  }
627  }
628 
629  *sdo_count = sdos;
630  *entry_count = entries;
631 }
632 
633 /****************************************************************************/
634 
641  ec_slave_t *slave,
642  uint16_t index
643  )
644 {
645  ec_sdo_t *sdo;
646 
647  list_for_each_entry(sdo, &slave->sdo_dictionary, list) {
648  if (sdo->index != index)
649  continue;
650  return sdo;
651  }
652 
653  return NULL;
654 }
655 
656 /****************************************************************************/
657 
667  const ec_slave_t *slave,
668  uint16_t index
669  )
670 {
671  const ec_sdo_t *sdo;
672 
673  list_for_each_entry(sdo, &slave->sdo_dictionary, list) {
674  if (sdo->index != index)
675  continue;
676  return sdo;
677  }
678 
679  return NULL;
680 }
681 
682 /****************************************************************************/
683 
689  const ec_slave_t *slave,
690  uint16_t sdo_position
691  )
692 {
693  const ec_sdo_t *sdo;
694 
695  list_for_each_entry(sdo, &slave->sdo_dictionary, list) {
696  if (sdo_position--)
697  continue;
698  return sdo;
699  }
700 
701  return NULL;
702 }
703 
704 /****************************************************************************/
705 
711  const ec_slave_t *slave
712  )
713 {
714  const ec_sdo_t *sdo;
715  uint16_t count = 0;
716 
717  list_for_each_entry(sdo, &slave->sdo_dictionary, list) {
718  count++;
719  }
720 
721  return count;
722 }
723 
724 /****************************************************************************/
725 
730  const ec_slave_t *slave,
731  uint16_t index
732  )
733 {
734  unsigned int i;
735  const ec_sync_t *sync;
736  const ec_pdo_t *pdo;
737 
738  for (i = 0; i < slave->sii.sync_count; i++) {
739  sync = &slave->sii.syncs[i];
740 
741  if (!(pdo = ec_pdo_list_find_pdo_const(&sync->pdos, index)))
742  continue;
743 
744  return pdo;
745  }
746 
747  return NULL;
748 }
749 
750 /****************************************************************************/
751 
755  ec_slave_t *slave,
756  ec_pdo_t *pdo
757  )
758 {
759  const ec_sdo_t *sdo;
760  ec_pdo_entry_t *pdo_entry;
761  const ec_sdo_entry_t *sdo_entry;
762 
763  list_for_each_entry(sdo, &slave->sdo_dictionary, list) {
764  if (sdo->index == pdo->index) {
765  ec_pdo_set_name(pdo, sdo->name);
766  } else {
767  list_for_each_entry(pdo_entry, &pdo->entries, list) {
768  if (sdo->index == pdo_entry->index) {
769  sdo_entry = ec_sdo_get_entry_const(
770  sdo, pdo_entry->subindex);
771  if (sdo_entry) {
772  ec_pdo_entry_set_name(pdo_entry,
773  sdo_entry->description);
774  }
775  }
776  }
777  }
778  }
779 }
780 
781 /****************************************************************************/
782 
786  ec_slave_t *slave
787  )
788 {
789  unsigned int i;
790  ec_sync_t *sync;
791  ec_pdo_t *pdo;
792 
793  for (i = 0; i < slave->sii.sync_count; i++) {
794  sync = slave->sii.syncs + i;
795  list_for_each_entry(pdo, &sync->pdos.list, list) {
796  ec_slave_find_names_for_pdo(slave, pdo);
797  }
798  }
799 }
800 
801 /****************************************************************************/
802 
808  ec_slave_t *slave,
809  unsigned int port_index
810  )
811 {
812  static const unsigned int prev_table[EC_MAX_PORTS] = {
813  2, 3, 1, 0
814  };
815 
816  if (port_index >= EC_MAX_PORTS) {
817  EC_SLAVE_WARN(slave, "%s(port_index=%u): Invalid port index!\n",
818  __func__, port_index);
819  }
820 
821  do {
822  port_index = prev_table[port_index];
823  if (slave->ports[port_index].next_slave) {
824  return port_index;
825  }
826  } while (port_index);
827 
828  return 0;
829 }
830 
831 /****************************************************************************/
832 
838  ec_slave_t *slave,
839  unsigned int port_index
840  )
841 {
842  static const unsigned int next_table[EC_MAX_PORTS] = {
843  3, 2, 0, 1
844  };
845 
846  if (port_index >= EC_MAX_PORTS) {
847  EC_SLAVE_WARN(slave, "%s(port_index=%u): Invalid port index!\n",
848  __func__, port_index);
849  }
850 
851  do {
852  port_index = next_table[port_index];
853  if (slave->ports[port_index].next_slave) {
854  return port_index;
855  }
856  } while (port_index);
857 
858  return 0;
859 }
860 
861 /****************************************************************************/
862 
868  ec_slave_t *slave
869  )
870 {
871  uint32_t rtt_sum = 0, rtt;
872  unsigned int port_index = ec_slave_get_next_port(slave, 0);
873 
874  while (port_index != 0) {
875  unsigned int prev_index =
876  ec_slave_get_previous_port(slave, port_index);
877 
878  rtt = slave->ports[port_index].receive_time -
879  slave->ports[prev_index].receive_time;
880  rtt_sum += rtt;
881  port_index = ec_slave_get_next_port(slave, port_index);
882  }
883 
884  return rtt_sum;
885 }
886 
887 /****************************************************************************/
888 
894  ec_slave_t *slave
895  )
896 {
897  unsigned int port_index;
898  ec_slave_t *dc_slave = NULL;
899 
900  if (slave->base_dc_supported) {
901  dc_slave = slave;
902  } else {
903  port_index = ec_slave_get_next_port(slave, 0);
904 
905  while (port_index != 0) {
906  ec_slave_t *next = slave->ports[port_index].next_slave;
907 
908  if (next) {
909  dc_slave = ec_slave_find_next_dc_slave(next);
910 
911  if (dc_slave) {
912  break;
913  }
914  }
915  port_index = ec_slave_get_next_port(slave, port_index);
916  }
917  }
918 
919  return dc_slave;
920 }
921 
922 /****************************************************************************/
923 
927  ec_slave_t *slave
928  )
929 {
930  unsigned int port_index;
931  ec_slave_t *next_slave, *next_dc;
932  uint32_t rtt, next_rtt_sum;
933 
934  if (!slave->base_dc_supported)
935  return;
936 
937  port_index = ec_slave_get_next_port(slave, 0);
938 
939  while (port_index != 0) {
940  next_slave = slave->ports[port_index].next_slave;
941  next_dc = ec_slave_find_next_dc_slave(next_slave);
942 
943  if (next_dc) {
944  unsigned int prev_port =
945  ec_slave_get_previous_port(slave, port_index);
946 
947  rtt = slave->ports[port_index].receive_time -
948  slave->ports[prev_port].receive_time;
949  next_rtt_sum = ec_slave_calc_rtt_sum(next_dc);
950 
951  slave->ports[port_index].delay_to_next_dc =
952  (rtt - next_rtt_sum) / 2; // FIXME
953  next_dc->ports[0].delay_to_next_dc =
954  (rtt - next_rtt_sum) / 2;
955 
956 #if 0
957  EC_SLAVE_DBG(slave, 1, "delay %u:%u rtt=%u"
958  " next_rtt_sum=%u delay=%u\n",
959  slave->ring_position, port_index, rtt, next_rtt_sum,
960  slave->ports[port_index].delay_to_next_dc);
961 #endif
962  }
963 
964  port_index = ec_slave_get_next_port(slave, port_index);
965  }
966 }
967 
968 /****************************************************************************/
969 
973  ec_slave_t *slave,
974  uint32_t *delay
975  )
976 {
977  unsigned int i;
978  ec_slave_t *next_dc;
979 
980  EC_SLAVE_DBG(slave, 1, "%s(delay = %u ns)\n", __func__, *delay);
981 
982  slave->transmission_delay = *delay;
983 
984  i = ec_slave_get_next_port(slave, 0);
985 
986  while (i != 0) {
987  ec_slave_port_t *port = &slave->ports[i];
988  next_dc = ec_slave_find_next_dc_slave(port->next_slave);
989  if (next_dc) {
990  *delay = *delay + port->delay_to_next_dc;
991 #if 0
992  EC_SLAVE_DBG(slave, 1, "%u:%u %u\n",
993  slave->ring_position, i, *delay);
994 #endif
996  }
997 
998  i = ec_slave_get_next_port(slave, i);
999  }
1000 
1001  *delay = *delay + slave->ports[0].delay_to_next_dc;
1002 }
1003 
1004 /****************************************************************************/
ec_sii_general_flags_t general_flags
General flags.
Definition: slave.h:153
Slave information interface general flags.
Definition: globals.h:165
ec_internal_request_state_t state
Request state.
Definition: reg_request.h:48
uint16_t ring_position
Ring position.
Definition: slave.h:175
uint32_t revision_number
Revision number.
Definition: slave.h:129
const ec_sdo_entry_t * ec_sdo_get_entry_const(const ec_sdo_t *sdo, uint8_t subindex)
Get an SDO entry from an SDO via its subindex.
Definition: sdo.c:108
uint16_t ec_slave_sdo_count(const ec_slave_t *slave)
Get the number of SDOs in the dictionary.
Definition: slave.c:710
uint16_t boot_rx_mailbox_offset
Bootstrap receive mailbox address.
Definition: slave.h:131
void ec_fsm_slave_clear(ec_fsm_slave_t *fsm)
Destructor.
Definition: fsm_slave.c:87
ec_sii_t sii
Extracted SII data.
Definition: slave.h:215
uint16_t configured_tx_mailbox_size
Configured send mailbox size.
Definition: slave.h:193
unsigned int ec_slave_get_previous_port(ec_slave_t *slave, unsigned int port_index)
Returns the previous connected port of a given port.
Definition: slave.c:807
uint8_t enable_upload_at_startup
?.
Definition: globals.h:159
void ec_slave_attach_pdo_names(ec_slave_t *slave)
Attach PDO names.
Definition: slave.c:785
uint16_t base_build
Build number.
Definition: slave.h:198
#define EC_SLAVE_DBG(slave, level, fmt, args...)
Convenience macro for printing slave-specific debug messages to syslog.
Definition: slave.h:98
CANopen SDO entry.
Definition: sdo_entry.h:46
const ec_pdo_t * ec_pdo_list_find_pdo_const(const ec_pdo_list_t *pl, uint16_t index)
Finds a PDO with the given index and returns a const pointer.
Definition: pdo_list.c:257
uint8_t enable_not_lrw
Slave does not support LRW.
Definition: globals.h:167
uint16_t configured_tx_mailbox_offset
Configured send mailbox offset.
Definition: slave.h:191
size_t ec_state_string(uint8_t, char *, uint8_t)
Prints slave states in clear text.
Definition: module.c:399
ec_slave_port_t ports[EC_MAX_PORTS]
Ports.
Definition: slave.h:179
CANopen SDO request.
Definition: sdo_request.h:40
ec_slave_state_t current_state
Current application state.
Definition: slave.h:184
const ec_code_msg_t al_status_messages[]
Application layer status messages.
Definition: fsm_change.c:341
EtherCAT slave structure.
ec_internal_request_state_t state
SDO request state.
Definition: sdo_request.h:55
Register request.
Definition: reg_request.h:40
ec_sdo_t * ec_slave_get_sdo(ec_slave_t *slave, uint16_t index)
Get an SDO from the dictionary.
Definition: slave.c:640
ec_slave_port_link_t link
Port link status.
Definition: slave.h:112
#define EC_SLAVE_WARN(slave, fmt, args...)
Convenience macro for printing slave-specific warnings to syslog.
Definition: slave.h:82
uint8_t enable_sdo
Enable SDO access.
Definition: globals.h:155
struct list_head list
List of PDOs.
Definition: pdo_list.h:42
uint32_t serial_number
Serial number.
Definition: slave.h:130
ec_sii_coe_details_t coe_details
CoE detail flags.
Definition: slave.h:152
char * order
Order number.
Definition: slave.h:149
int ec_pdo_set_name(ec_pdo_t *pdo, const char *name)
Set PDO name.
Definition: pdo.c:117
void ec_slave_find_names_for_pdo(ec_slave_t *slave, ec_pdo_t *pdo)
Find name for a PDO and its entries.
Definition: slave.c:754
ec_fsm_slave_t fsm
Slave state machine.
Definition: slave.h:227
void ec_slave_set_state(ec_slave_t *slave, ec_slave_state_t new_state)
Sets the application state of a slave.
Definition: slave.c:278
struct list_head reg_requests
Register access requests.
Definition: slave.h:222
struct list_head list
List item.
Definition: sdo.h:42
void ec_pdo_init(ec_pdo_t *pdo)
PDO constructor.
Definition: pdo.c:38
const ec_pdo_t * ec_slave_find_pdo(const ec_slave_t *slave, uint16_t index)
Finds a mapped PDO.
Definition: slave.c:729
CANopen SDO.
Definition: sdo.h:41
uint16_t index
SDO index.
Definition: sdo.h:44
int16_t current_on_ebus
Power consumption in mA.
Definition: slave.h:154
uint16_t boot_tx_mailbox_size
Bootstrap transmit mailbox size.
Definition: slave.h:134
int ec_slave_fetch_sii_strings(ec_slave_t *slave, const uint8_t *data, size_t data_size)
Fetches data from a STRING category.
Definition: slave.c:316
wait_queue_head_t request_queue
Wait queue for external requests from user space.
Definition: master.h:297
uint16_t station_address
Configured station address.
Definition: slave.h:176
unsigned int sync_count
Number of sync managers.
Definition: slave.h:158
void ec_slave_clear(ec_slave_t *slave)
Slave destructor.
Definition: slave.c:163
struct list_head sdo_dictionary
SDO dictionary list.
Definition: slave.h:217
uint16_t std_rx_mailbox_size
Standard receive mailbox size.
Definition: slave.h:136
uint8_t base_type
Slave type.
Definition: slave.h:196
Global definitions and macros.
uint16_t std_tx_mailbox_offset
Standard transmit mailbox address.
Definition: slave.h:137
PDO entry description.
Definition: pdo_entry.h:40
EtherCAT master structure.
void ec_pdo_clear(ec_pdo_t *pdo)
PDO destructor.
Definition: pdo.c:86
uint16_t index
PDO index.
Definition: pdo.h:43
int8_t sync_index
Assigned sync manager.
Definition: pdo.h:44
uint16_t boot_tx_mailbox_offset
Bootstrap transmit mailbox address.
Definition: slave.h:133
uint16_t index
PDO entry index.
Definition: pdo_entry.h:42
void ec_slave_sdo_dict_info(const ec_slave_t *slave, unsigned int *sdo_count, unsigned int *entry_count)
Counts the total number of SDOs and entries in the dictionary.
Definition: slave.c:612
EtherCAT slave.
Definition: slave.h:168
struct list_head sdo_requests
SDO access requests.
Definition: slave.h:221
char * description
Description.
Definition: sdo_entry.h:54
Code/Message pair.
Definition: globals.h:275
struct list_head soe_requests
SoE requests.
Definition: slave.h:224
Slave information interface CANopen over EtherCAT details flags.
Definition: globals.h:154
uint8_t enable_safeop
?.
Definition: globals.h:166
ec_slave_config_t * config
Current configuration.
Definition: slave.h:182
void ec_pdo_entry_clear(ec_pdo_entry_t *entry)
PDO entry destructor.
Definition: pdo_entry.c:68
void ec_slave_clear_sync_managers(ec_slave_t *slave)
Clear the sync manager array.
Definition: slave.c:259
uint8_t enable_sdo_info
SDO information service available.
Definition: globals.h:156
uint8_t enable_sdo_complete_access
Complete access possible.
Definition: globals.h:160
void ec_slave_calc_port_delays(ec_slave_t *slave)
Calculates the port transmission delays.
Definition: slave.c:926
PDO description.
Definition: pdo.h:41
uint8_t sdo_dictionary_fetched
Dictionary has been fetched.
Definition: slave.h:218
uint16_t * sii_words
Complete SII image.
Definition: slave.h:211
uint16_t mailbox_protocols
Supported mailbox protocols.
Definition: slave.h:139
unsigned int debug_level
Master debug level.
Definition: master.h:271
#define EC_SLAVE_ERR(slave, fmt, args...)
Convenience macro for printing slave-specific errors to syslog.
Definition: slave.h:68
int ec_pdo_list_add_pdo_copy(ec_pdo_list_t *pl, const ec_pdo_t *pdo)
Add the copy of an existing PDO to the list.
Definition: pdo_list.c:133
ec_slave_dc_range_t base_dc_range
DC range.
Definition: slave.h:203
uint8_t bit_length
entry length in bit
Definition: pdo_entry.h:45
Sync manager.
Definition: sync.h:39
uint16_t std_rx_mailbox_offset
Standard receive mailbox address.
Definition: slave.h:135
uint8_t base_fmmu_bit_operation
FMMU bit operation is supported.
Definition: slave.h:201
struct list_head list
List item.
Definition: soe_request.h:41
uint32_t transmission_delay
DC system time transmission delay (offset from reference clock).
Definition: slave.h:207
ec_device_index_t
Master devices.
Definition: globals.h:198
char * name
SDO name.
Definition: sdo.h:46
uint16_t alias
Configured station alias.
Definition: slave.h:126
ec_direction_t
Direction type for PDO assignment functions.
Definition: ecrt.h:501
uint8_t base_fmmu_count
Number of supported FMMUs.
Definition: slave.h:199
void ec_slave_calc_transmission_delays_rec(ec_slave_t *slave, uint32_t *delay)
Recursively calculates transmission delays.
Definition: slave.c:972
uint16_t configured_rx_mailbox_offset
Configured receive mailbox offset.
Definition: slave.h:187
struct list_head entries
List of PDO entries.
Definition: pdo.h:46
ec_slave_port_desc_t desc
Port descriptors.
Definition: slave.h:111
unsigned int string_count
Number of SII strings.
Definition: slave.h:143
ec_master_t * master
Master owning the slave.
Definition: slave.h:170
void ec_pdo_entry_init(ec_pdo_entry_t *entry)
PDO entry constructor.
Definition: pdo_entry.c:37
const ec_sdo_t * ec_slave_get_sdo_by_pos_const(const ec_slave_t *slave, uint16_t sdo_position)
Get an SDO from the dictionary, given its position in the list.
Definition: slave.c:688
uint8_t has_dc_system_time
The slave supports the DC system time register.
Definition: slave.h:204
char ** strings
Strings in SII categories.
Definition: slave.h:142
ec_slave_state_t
State of an EtherCAT slave.
Definition: globals.h:121
uint8_t subindex
PDO entry subindex.
Definition: pdo_entry.h:43
EtherCAT datagram structure.
uint8_t control_register
Control register value.
Definition: sync.h:43
void ec_sync_clear(ec_sync_t *sync)
Destructor.
Definition: sync.c:73
Port is not implemented.
Definition: ecrt.h:424
uint8_t base_revision
Revision.
Definition: slave.h:197
32 bit.
Definition: globals.h:173
Ethernet-over-EtherCAT set IP parameter request.
Definition: eoe_request.h:41
const ec_sdo_t * ec_slave_get_sdo_const(const ec_slave_t *slave, uint16_t index)
Get an SDO from the dictionary.
Definition: slave.c:666
FoE request.
Definition: foe_request.h:42
ec_slave_t * ec_slave_find_next_dc_slave(ec_slave_t *slave)
Finds the next slave supporting DC delay measurement.
Definition: slave.c:893
uint16_t effective_alias
Effective alias address.
Definition: slave.h:177
struct list_head entries
List of entries.
Definition: sdo.h:48
ec_internal_request_state_t state
Request state.
Definition: eoe_request.h:43
#define EC_READ_U16(DATA)
Read a 16-bit unsigned value from EtherCAT data.
Definition: ecrt.h:2611
struct list_head foe_requests
FoE requests.
Definition: slave.h:223
uint8_t enable
Enable bit.
Definition: sync.h:44
int ec_slave_fetch_sii_syncs(ec_slave_t *slave, const uint8_t *data, size_t data_size)
Fetches data from a SYNC MANAGER category.
Definition: slave.c:423
#define EC_STATE_STRING_SIZE
Minimum size of a buffer used with ec_state_string().
Definition: globals.h:54
uint16_t boot_rx_mailbox_size
Bootstrap receive mailbox size.
Definition: slave.h:132
#define EC_MAX_PORTS
Maximum number of slave ports.
Definition: ecrt.h:273
struct list_head list
List item.
Definition: sdo_request.h:41
void ec_fsm_slave_init(ec_fsm_slave_t *fsm, ec_slave_t *slave)
Constructor.
Definition: fsm_slave.c:56
void ec_slave_init(ec_slave_t *slave, ec_master_t *master, ec_device_index_t dev_idx, uint16_t ring_position, uint16_t station_address)
Slave constructor.
Definition: slave.c:54
ec_slave_t * next_slave
Connected slaves.
Definition: slave.h:113
uint32_t receive_time
Port receive times for delay measurement.
Definition: slave.h:114
Slave port.
Definition: slave.h:110
char * image
Image name.
Definition: slave.h:148
ec_pdo_list_t pdos
Current PDO assignment.
Definition: sync.h:45
void ec_slave_request_state(ec_slave_t *slave, ec_slave_state_t state)
Request a slave state and resets the error flag.
Definition: slave.c:300
uint16_t physical_start_address
Physical start address.
Definition: sync.h:41
unsigned long jiffies_preop
Time, the slave went to PREOP.
Definition: slave.h:219
uint16_t configured_rx_mailbox_size
Configured receive mailbox size.
Definition: slave.h:189
uint8_t base_dc_supported
Distributed clocks are supported.
Definition: slave.h:202
uint32_t ec_slave_calc_rtt_sum(ec_slave_t *slave)
Calculates the sum of round-trip-times of connected ports 1-3.
Definition: slave.c:867
char * ec_slave_sii_string(ec_slave_t *, unsigned int)
Searches the string list for an index.
Definition: slave.c:572
size_t sii_nwords
Size of the SII contents in words.
Definition: slave.h:212
void ec_sync_init_copy(ec_sync_t *sync, const ec_sync_t *other)
Copy constructor.
Definition: sync.c:55
char * group
Group name.
Definition: slave.h:147
uint8_t physical_layer[EC_MAX_PORTS]
Port media.
Definition: slave.h:151
struct list_head list
list item
Definition: pdo_entry.h:41
void ec_sdo_clear(ec_sdo_t *sdo)
SDO destructor.
Definition: sdo.c:59
uint8_t base_sync_count
Number of supported sync managers.
Definition: slave.h:200
#define EC_READ_U8(DATA)
Read an 8-bit unsigned value from EtherCAT data.
Definition: ecrt.h:2595
unsigned int ec_slave_get_next_port(ec_slave_t *slave, unsigned int port_index)
Returns the next connected port of a given port.
Definition: slave.c:837
EtherCAT slave configuration structure.
ec_internal_request_state_t state
FoE request state.
Definition: foe_request.h:55
#define EC_READ_S16(DATA)
Read a 16-bit signed value from EtherCAT data.
Definition: ecrt.h:2619
ec_device_index_t device_index
Index of device the slave responds on.
Definition: slave.h:171
void ec_slave_config_detach(ec_slave_config_t *sc)
Detaches the configuration from a slave object.
Definition: slave_config.c:276
uint16_t default_length
Data length in bytes.
Definition: sync.h:42
uint32_t product_code
Vendor-specific product code.
Definition: slave.h:128
PREOP state (mailbox communication, no IO)
Definition: globals.h:126
struct list_head list
List item.
Definition: pdo.h:42
unsigned int error_flag
Stop processing after an error.
Definition: slave.h:185
ec_sync_t * syncs
SYNC MANAGER categories.
Definition: slave.h:157
uint16_t std_tx_mailbox_size
Standard transmit mailbox size.
Definition: slave.h:138
EtherCAT master.
Definition: master.h:183
uint8_t enable_pdo_configuration
PDO configuration possible.
Definition: globals.h:158
struct list_head list
List item.
Definition: reg_request.h:41
ec_slave_state_t requested_state
Requested application state.
Definition: slave.h:183
struct list_head eoe_requests
EoE set IP parameter requests.
Definition: slave.h:225
int ec_slave_fetch_sii_pdos(ec_slave_t *slave, const uint8_t *data, size_t data_size, ec_direction_t dir)
Fetches data from a [RT]xPDO category.
Definition: slave.c:489
#define EC_MAX_SYNC_MANAGERS
Maximum number of sync managers per slave.
Definition: ecrt.h:264
ec_internal_request_state_t state
Request state.
Definition: soe_request.h:52
void ec_sync_init(ec_sync_t *sync, ec_slave_t *slave)
Constructor.
Definition: sync.c:38
struct list_head list
List item.
Definition: eoe_request.h:42
int ec_slave_fetch_sii_general(ec_slave_t *slave, const uint8_t *data, size_t data_size)
Fetches data from a GENERAL category.
Definition: slave.c:372
Sercos-over-EtherCAT request.
Definition: soe_request.h:40
char * name
Slave name.
Definition: slave.h:150
int ec_pdo_entry_set_name(ec_pdo_entry_t *entry, const char *name)
Set PDO entry name.
Definition: pdo_entry.c:81
unknown state
Definition: globals.h:122
uint32_t vendor_id
Vendor ID.
Definition: slave.h:127
uint32_t delay_to_next_dc
Delay to next slave with DC support behind this port [ns].
Definition: slave.h:116
struct list_head pdos
SII [RT]XPDO categories.
Definition: slave.h:161
unsigned int force_config
Force (re-)configuration.
Definition: slave.h:186
struct list_head list
List item.
Definition: foe_request.h:43
unsigned int has_general
General category present.
Definition: slave.h:146
ec_sync_t * ec_slave_get_sync(ec_slave_t *slave, uint8_t sync_index)
Get the sync manager given an index.
Definition: slave.c:594
uint8_t enable_pdo_assign
PDO mapping configurable.
Definition: globals.h:157