IgH EtherCAT Master  1.5.2
slave.c
Go to the documentation of this file.
1 /******************************************************************************
2  *
3  * $Id$
4  *
5  * Copyright (C) 2006-2012 Florian Pose, Ingenieurgemeinschaft IgH
6  *
7  * This file is part of the IgH EtherCAT Master.
8  *
9  * The IgH EtherCAT Master is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU General Public License version 2, as
11  * published by the Free Software Foundation.
12  *
13  * The IgH EtherCAT Master is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
16  * Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License along
19  * with the IgH EtherCAT Master; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
21  *
22  * ---
23  *
24  * The license mentioned above concerns the source code only. Using the
25  * EtherCAT technology and brand is only permitted in compliance with the
26  * industrial property and similar rights of Beckhoff Automation GmbH.
27  *
28  *****************************************************************************/
29 
35 /*****************************************************************************/
36 
37 #include <linux/module.h>
38 #include <linux/delay.h>
39 
40 #include "globals.h"
41 #include "datagram.h"
42 #include "master.h"
43 #include "slave_config.h"
44 
45 #include "slave.h"
46 
47 /*****************************************************************************/
48 
49 extern const ec_code_msg_t al_status_messages[];
50 
51 /*****************************************************************************/
52 
53 char *ec_slave_sii_string(ec_slave_t *, unsigned int);
54 
55 /*****************************************************************************/
56 
63  ec_slave_t *slave,
64  ec_master_t *master,
65  ec_device_index_t dev_idx,
66  uint16_t ring_position,
67  uint16_t station_address
68  )
69 {
70  unsigned int i;
71 
72  slave->master = master;
73  slave->device_index = dev_idx;
74 
75  slave->ring_position = ring_position;
76  slave->station_address = station_address;
77  slave->effective_alias = 0x0000;
78 #ifdef EC_SII_CACHE
79  slave->effective_vendor_id = 0x00000000;
80  slave->effective_product_code = 0x00000000;
81  slave->effective_revision_number = 0x00000000;
82  slave->effective_serial_number = 0x00000000;
83 #endif
84  slave->config = NULL;
87  slave->last_al_error = 0;
88  slave->error_flag = 0;
89  slave->force_config = 0;
90  slave->reboot = 0;
91  slave->configured_rx_mailbox_offset = 0x0000;
92  slave->configured_rx_mailbox_size = 0x0000;
93  slave->configured_tx_mailbox_offset = 0x0000;
94  slave->configured_tx_mailbox_size = 0x0000;
95 
96  slave->base_type = 0;
97  slave->base_revision = 0;
98  slave->base_build = 0;
99  slave->base_fmmu_count = 0;
100  slave->base_sync_count = 0;
101 
102  for (i = 0; i < EC_MAX_PORTS; i++) {
103  slave->ports[i].desc = EC_PORT_NOT_IMPLEMENTED;
104 
105  slave->ports[i].link.link_up = 0;
106  slave->ports[i].link.loop_closed = 1;
107  slave->ports[i].link.signal_detected = 0;
108  slave->ports[i].link.bypassed = 0;
109 
110  slave->ports[i].receive_time = 0U;
111 
112  slave->ports[i].next_slave = NULL;
113  slave->ports[i].delay_to_next_dc = 0U;
114 
115 #ifdef EC_LOOP_CONTROL
116  slave->ports[i].state = EC_SLAVE_PORT_DOWN;
117  slave->ports[i].link_detection_jiffies = 0;
118 #endif
119  }
120  slave->upstream_port = 0;
121 
122  slave->base_fmmu_bit_operation = 0;
123  slave->base_dc_supported = 0;
124  slave->base_dc_range = EC_DC_32;
125  slave->has_dc_system_time = 0;
126  slave->transmission_delay = 0U;
127 
128  slave->vendor_words = NULL;
129  slave->sii_image = NULL;
130 
131 
132  INIT_LIST_HEAD(&slave->sdo_dictionary);
133 
134  slave->scan_required = 1;
135  slave->sdo_dictionary_fetched = 0;
136  slave->jiffies_preop = 0;
137 
138  INIT_LIST_HEAD(&slave->sdo_requests);
139  INIT_LIST_HEAD(&slave->reg_requests);
140  INIT_LIST_HEAD(&slave->foe_requests);
141  INIT_LIST_HEAD(&slave->soe_requests);
142  INIT_LIST_HEAD(&slave->eoe_requests);
143  INIT_LIST_HEAD(&slave->mbg_requests);
144  INIT_LIST_HEAD(&slave->dict_requests);
145 
146  // create state machine object
147  ec_fsm_slave_init(&slave->fsm, slave);
148 
149  slave->read_mbox_busy = 0;
150  rt_mutex_init(&slave->mbox_sem);
151 
152 #ifdef EC_EOE
155 #endif
161 
162  slave->valid_mbox_data = 0;
163 }
164 
165 
167  ec_sii_image_t *sii_image
168  )
169 {
170  unsigned int i;
171 
172  sii_image->words = NULL;
173  sii_image->nwords = 0;
174 
175  sii_image->sii.alias = 0x0000;
176  sii_image->sii.vendor_id = 0x00000000;
177  sii_image->sii.product_code = 0x00000000;
178  sii_image->sii.revision_number = 0x00000000;
179  sii_image->sii.serial_number = 0x00000000;
180  sii_image->sii.boot_rx_mailbox_offset = 0x0000;
181  sii_image->sii.boot_rx_mailbox_size = 0x0000;
182  sii_image->sii.boot_tx_mailbox_offset = 0x0000;
183  sii_image->sii.boot_tx_mailbox_size = 0x0000;
184  sii_image->sii.std_rx_mailbox_offset = 0x0000;
185  sii_image->sii.std_rx_mailbox_size = 0x0000;
186  sii_image->sii.std_tx_mailbox_offset = 0x0000;
187  sii_image->sii.std_tx_mailbox_size = 0x0000;
188  sii_image->sii.mailbox_protocols = 0;
189  sii_image->sii.strings = NULL;
190  sii_image->sii.string_count = 0;
191 
192  sii_image->sii.has_general = 0;
193  sii_image->sii.group = NULL;
194  sii_image->sii.image = NULL;
195  sii_image->sii.order = NULL;
196  sii_image->sii.name = NULL;
197  memset(&sii_image->sii.coe_details, 0x00, sizeof(ec_sii_coe_details_t));
198  memset(&sii_image->sii.general_flags, 0x00, sizeof(ec_sii_general_flags_t));
199  sii_image->sii.current_on_ebus = 0;
200 
201  sii_image->sii.syncs = NULL;
202  sii_image->sii.sync_count = 0;
203 
204  INIT_LIST_HEAD(&sii_image->sii.pdos);
205 
206  for (i = 0; i < EC_MAX_PORTS; i++) {
207  sii_image->sii.physical_layer[i] = 0xFF;
208  }
209 }
210 
211 /*****************************************************************************/
212 
217 {
218  rt_mutex_lock(&slave->mbox_sem);
219  slave->read_mbox_busy = 0;
220  rt_mutex_unlock(&slave->mbox_sem);
221 }
222 
223 
224 /*****************************************************************************/
225 
230 {
231  int rc;
232 
233  rt_mutex_lock(&slave->mbox_sem);
234  rc = slave->read_mbox_busy;
235  if (!slave->read_mbox_busy) {
236  slave->read_mbox_busy = 1;
237  }
238  rt_mutex_unlock(&slave->mbox_sem);
239  return rc;
240 }
241 
242 
243 /*****************************************************************************/
244 
251 {
252  ec_sdo_t *sdo, *next_sdo;
253 
254  // abort all pending requests
255 
256  while (!list_empty(&slave->sdo_requests)) {
257  ec_sdo_request_t *request =
258  list_entry(slave->sdo_requests.next, ec_sdo_request_t, list);
259  list_del_init(&request->list); // dequeue
260  EC_SLAVE_WARN(slave, "Discarding SDO request,"
261  " slave about to be deleted.\n");
262  request->state = EC_INT_REQUEST_FAILURE;
263  }
264 
265  while (!list_empty(&slave->reg_requests)) {
266  ec_reg_request_t *reg =
267  list_entry(slave->reg_requests.next, ec_reg_request_t, list);
268  list_del_init(&reg->list); // dequeue
269  EC_SLAVE_WARN(slave, "Discarding register request,"
270  " slave about to be deleted.\n");
271  reg->state = EC_INT_REQUEST_FAILURE;
272  }
273 
274  while (!list_empty(&slave->foe_requests)) {
275  ec_foe_request_t *request =
276  list_entry(slave->foe_requests.next, ec_foe_request_t, list);
277  list_del_init(&request->list); // dequeue
278  EC_SLAVE_WARN(slave, "Discarding FoE request,"
279  " slave about to be deleted.\n");
280  request->state = EC_INT_REQUEST_FAILURE;
281  }
282 
283  while (!list_empty(&slave->soe_requests)) {
284  ec_soe_request_t *request =
285  list_entry(slave->soe_requests.next, ec_soe_request_t, list);
286  list_del_init(&request->list); // dequeue
287  EC_SLAVE_WARN(slave, "Discarding SoE request,"
288  " slave about to be deleted.\n");
289  request->state = EC_INT_REQUEST_FAILURE;
290  }
291 
292  while (!list_empty(&slave->eoe_requests)) {
293  ec_eoe_request_t *request =
294  list_entry(slave->eoe_requests.next, ec_eoe_request_t, list);
295  list_del_init(&request->list); // dequeue
296  EC_SLAVE_WARN(slave, "Discarding EoE request,"
297  " slave about to be deleted.\n");
298  request->state = EC_INT_REQUEST_FAILURE;
299  }
300 
301  while (!list_empty(&slave->mbg_requests)) {
302  ec_mbg_request_t *request =
303  list_entry(slave->mbg_requests.next, ec_mbg_request_t, list);
304  list_del_init(&request->list); // dequeue
305  EC_SLAVE_WARN(slave, "Discarding MBox Gateway request,"
306  " slave about to be deleted.\n");
307  request->state = EC_INT_REQUEST_FAILURE;
308  }
309 
310  while (!list_empty(&slave->dict_requests)) {
311  ec_dict_request_t *request =
312  list_entry(slave->dict_requests.next, ec_dict_request_t, list);
313  list_del_init(&request->list); // dequeue
314  EC_SLAVE_WARN(slave, "Discarding dictionary request,"
315  " slave about to be deleted.\n");
316  request->state = EC_INT_REQUEST_FAILURE;
317  }
318 
319  wake_up_all(&slave->master->request_queue);
320 
321  if (slave->config) {
323  }
324 
325  // free all SDOs
326  list_for_each_entry_safe(sdo, next_sdo, &slave->sdo_dictionary, list) {
327  list_del(&sdo->list);
328  ec_sdo_clear(sdo);
329  kfree(sdo);
330  }
331 
332  if (slave->vendor_words) {
333  kfree(slave->vendor_words);
334  slave->vendor_words = NULL;
335  }
336 
337  // free mailbox response data
338 #ifdef EC_EOE
341 #endif
347 
348  ec_fsm_slave_clear(&slave->fsm);
349 }
350 
351 /*****************************************************************************/
352 
356 {
357  unsigned int i;
358 
359  if (slave->sii_image && slave->sii_image->sii.syncs) {
360  for (i = 0; i < slave->sii_image->sii.sync_count; i++) {
361  ec_sync_clear(&slave->sii_image->sii.syncs[i]);
362  }
363  kfree(slave->sii_image->sii.syncs);
364  slave->sii_image->sii.syncs = NULL;
365  }
366 }
367 
368 /*****************************************************************************/
369 
375  uint16_t new_state
376  )
377 {
378  unsigned int i;
379  uint8_t state;
380 
381  for (i = 0; i < EC_MAX_PORTS; i++) {
382  // link status
383  state = new_state & (1 << (4 + i)) ? 1 : 0;
384  if (slave->ports[i].link.link_up != state) {
385  EC_SLAVE_DBG(slave, 1, "Port %u link status changed to %s.\n",
386  i, state ? "up" : "down");
387  slave->ports[i].link.link_up = state;
388  }
389 
390  // loop status
391  state = new_state & (1 << (8 + i * 2)) ? 1 : 0;
392  if (slave->ports[i].link.loop_closed != state) {
393  EC_SLAVE_DBG(slave, 1, "Port %u loop status changed to %s.\n",
394  i, state ? "closed" : "open");
395  slave->ports[i].link.loop_closed = state;
396  }
397 
398  // signal detection
399  state = new_state & (1 << (9 + i * 2)) ? 1 : 0;
400  if (slave->ports[i].link.signal_detected != state) {
401  EC_SLAVE_DBG(slave, 1, "Port %u signal status changed to %s.\n",
402  i, state ? "yes" : "no");
403  slave->ports[i].link.signal_detected = state;
404  }
405  }
406 }
407 
408 /*****************************************************************************/
409 
415  ec_slave_state_t new_state
416  )
417 {
418  if (new_state != slave->current_state) {
419  if (slave->master->debug_level) {
420  char old_state[EC_STATE_STRING_SIZE],
421  cur_state[EC_STATE_STRING_SIZE];
422  ec_state_string(slave->current_state, old_state, 0);
423  ec_state_string(new_state, cur_state, 0);
424  EC_SLAVE_DBG(slave, 0, "%s -> %s.\n", old_state, cur_state);
425  }
426  slave->current_state = new_state;
427  }
428 }
429 
430 /*****************************************************************************/
431 
437  ec_slave_state_t state
438  )
439 {
440  slave->requested_state = state;
441  slave->error_flag = 0;
442 }
443 
444 /*****************************************************************************/
445 
451  )
452 {
453  slave->reboot = 1;
454 }
455 
456 /*****************************************************************************/
457 
465  ec_slave_t *slave,
466  const uint8_t *data,
467  size_t data_size
468  )
469 {
470  int i, err;
471  size_t size;
472  off_t offset;
473 
474  if (!slave->sii_image) {
475  EC_SLAVE_ERR(slave, "SII data not attached!\n");
476  return -EINVAL;
477  }
478 
479  slave->sii_image->sii.string_count = data[0];
480 
481  if (slave->sii_image->sii.string_count) {
482  if (!(slave->sii_image->sii.strings =
483  kmalloc(sizeof(char *) * slave->sii_image->sii.string_count,
484  GFP_KERNEL))) {
485  EC_SLAVE_ERR(slave, "Failed to allocate string array memory.\n");
486  err = -ENOMEM;
487  goto out_zero;
488  }
489 
490  offset = 1;
491  for (i = 0; i < slave->sii_image->sii.string_count; i++) {
492  size = data[offset];
493  // allocate memory for string structure and data at a single blow
494  if (!(slave->sii_image->sii.strings[i] =
495  kmalloc(sizeof(char) * size + 1, GFP_KERNEL))) {
496  EC_SLAVE_ERR(slave, "Failed to allocate string memory.\n");
497  err = -ENOMEM;
498  goto out_free;
499  }
500  memcpy(slave->sii_image->sii.strings[i], data + offset + 1, size);
501  slave->sii_image->sii.strings[i][size] = 0x00; // append binary zero
502  offset += 1 + size;
503  }
504  }
505 
506  return 0;
507 
508 out_free:
509  for (i--; i >= 0; i--)
510  kfree(slave->sii_image->sii.strings[i]);
511  kfree(slave->sii_image->sii.strings);
512  slave->sii_image->sii.strings = NULL;
513 out_zero:
514  slave->sii_image->sii.string_count = 0;
515  return err;
516 }
517 
518 /*****************************************************************************/
519 
526  ec_slave_t *slave,
527  const uint8_t *data,
528  size_t data_size
529  )
530 {
531  unsigned int i;
532  uint8_t flags;
533 
534  if (data_size != 32) {
535  EC_SLAVE_ERR(slave, "Wrong size of general category (%zu/32).\n",
536  data_size);
537  return -EINVAL;
538  }
539 
540  if (!slave->sii_image) {
541  EC_SLAVE_ERR(slave, "SII data not attached!\n");
542  return -EINVAL;
543  }
544 
545  slave->sii_image->sii.group = ec_slave_sii_string(slave, data[0]);
546  slave->sii_image->sii.image = ec_slave_sii_string(slave, data[1]);
547  slave->sii_image->sii.order = ec_slave_sii_string(slave, data[2]);
548  slave->sii_image->sii.name = ec_slave_sii_string(slave, data[3]);
549 
550  for (i = 0; i < 4; i++)
551  slave->sii_image->sii.physical_layer[i] =
552  (data[4] & (0x03 << (i * 2))) >> (i * 2);
553 
554  // read CoE details
555  flags = EC_READ_U8(data + 5);
556  slave->sii_image->sii.coe_details.enable_sdo = (flags >> 0) & 0x01;
557  slave->sii_image->sii.coe_details.enable_sdo_info = (flags >> 1) & 0x01;
558  slave->sii_image->sii.coe_details.enable_pdo_assign = (flags >> 2) & 0x01;
559  slave->sii_image->sii.coe_details.enable_pdo_configuration = (flags >> 3) & 0x01;
560  slave->sii_image->sii.coe_details.enable_upload_at_startup = (flags >> 4) & 0x01;
561  slave->sii_image->sii.coe_details.enable_sdo_complete_access = (flags >> 5) & 0x01;
562 
563  // read general flags
564  flags = EC_READ_U8(data + 0x000B);
565  slave->sii_image->sii.general_flags.enable_safeop = (flags >> 0) & 0x01;
566  slave->sii_image->sii.general_flags.enable_not_lrw = (flags >> 1) & 0x01;
567 
568  slave->sii_image->sii.current_on_ebus = EC_READ_S16(data + 0x0C);
569  slave->sii_image->sii.has_general = 1;
570  return 0;
571 }
572 
573 /*****************************************************************************/
574 
582  ec_slave_t *slave,
583  const uint8_t *data,
584  size_t data_size
585  )
586 {
587  unsigned int i, count, total_count;
588  ec_sync_t *sync;
589  size_t memsize;
590  ec_sync_t *syncs;
591  uint8_t index;
592 
593  // one sync manager struct is 4 words long
594  if (data_size % 8) {
595  EC_SLAVE_ERR(slave, "Invalid SII sync manager category size %zu.\n",
596  data_size);
597  return -EINVAL;
598  }
599 
600  if (!slave->sii_image) {
601  EC_SLAVE_ERR(slave, "SII data not attached!\n");
602  return -EINVAL;
603  }
604 
605  count = data_size / 8;
606 
607  if (count) {
608  total_count = count + slave->sii_image->sii.sync_count;
609  if (total_count > EC_MAX_SYNC_MANAGERS) {
610  EC_SLAVE_ERR(slave, "Exceeded maximum number of"
611  " sync managers!\n");
612  return -EOVERFLOW;
613  }
614  memsize = sizeof(ec_sync_t) * total_count;
615  if (!(syncs = kmalloc(memsize, GFP_KERNEL))) {
616  EC_SLAVE_ERR(slave, "Failed to allocate %zu bytes"
617  " for sync managers.\n", memsize);
618  return -ENOMEM;
619  }
620 
621  for (i = 0; i < slave->sii_image->sii.sync_count; i++)
622  ec_sync_init_copy(syncs + i, slave->sii_image->sii.syncs + i);
623 
624  // initialize new sync managers
625  for (i = 0; i < count; i++, data += 8) {
626  index = i + slave->sii_image->sii.sync_count;
627  sync = &syncs[index];
628 
629  ec_sync_init(sync, slave);
630  sync->physical_start_address = EC_READ_U16(data);
631  sync->default_length = EC_READ_U16(data + 2);
632  sync->control_register = EC_READ_U8(data + 4);
633  sync->enable = EC_READ_U8(data + 6);
634  }
635 
636  if (slave->sii_image->sii.syncs)
637  kfree(slave->sii_image->sii.syncs);
638  slave->sii_image->sii.syncs = syncs;
639  slave->sii_image->sii.sync_count = total_count;
640  }
641 
642  return 0;
643 }
644 
645 /*****************************************************************************/
646 
653  ec_slave_t *slave,
654  const uint8_t *data,
655  size_t data_size,
656  ec_direction_t dir
657  )
658 {
659  int ret;
660  ec_pdo_t *pdo;
661  ec_pdo_entry_t *entry;
662  unsigned int entry_count, i;
663 
664  if (!slave->sii_image) {
665  EC_SLAVE_ERR(slave, "SII data not attached!\n");
666  return -EINVAL;
667  }
668 
669  while (data_size >= 8) {
670  if (!(pdo = kmalloc(sizeof(ec_pdo_t), GFP_KERNEL))) {
671  EC_SLAVE_ERR(slave, "Failed to allocate PDO memory.\n");
672  return -ENOMEM;
673  }
674 
675  ec_pdo_init(pdo);
676  pdo->index = EC_READ_U16(data);
677  entry_count = EC_READ_U8(data + 2);
678  pdo->sync_index = EC_READ_U8(data + 3);
679  ret = ec_pdo_set_name(pdo,
680  ec_slave_sii_string(slave, EC_READ_U8(data + 5)));
681  if (ret) {
682  ec_pdo_clear(pdo);
683  kfree(pdo);
684  return ret;
685  }
686  list_add_tail(&pdo->list, &slave->sii_image->sii.pdos);
687 
688  data_size -= 8;
689  data += 8;
690 
691  for (i = 0; i < entry_count; i++) {
692  if (!(entry = kmalloc(sizeof(ec_pdo_entry_t), GFP_KERNEL))) {
693  EC_SLAVE_ERR(slave, "Failed to allocate PDO entry memory.\n");
694  return -ENOMEM;
695  }
696 
697  ec_pdo_entry_init(entry);
698  entry->index = EC_READ_U16(data);
699  entry->subindex = EC_READ_U8(data + 2);
700  ret = ec_pdo_entry_set_name(entry,
701  ec_slave_sii_string(slave, EC_READ_U8(data + 3)));
702  if (ret) {
703  ec_pdo_entry_clear(entry);
704  kfree(entry);
705  return ret;
706  }
707  entry->bit_length = EC_READ_U8(data + 5);
708  list_add_tail(&entry->list, &pdo->entries);
709 
710  data_size -= 8;
711  data += 8;
712  }
713 
714  // if sync manager index is positive, the PDO is mapped by default
715  if (pdo->sync_index >= 0) {
716  ec_sync_t *sync;
717 
718  if (!(sync = ec_slave_get_sync(slave, pdo->sync_index))) {
719  EC_SLAVE_ERR(slave, "Invalid SM index %i for PDO 0x%04X.",
720  pdo->sync_index, pdo->index);
721  return -ENOENT;
722  }
723 
724  ret = ec_pdo_list_add_pdo_copy(&sync->pdos, pdo);
725  if (ret)
726  return ret;
727  }
728  }
729 
730  return 0;
731 }
732 
733 /*****************************************************************************/
734 
741  ec_slave_t *slave,
742  unsigned int index
743  )
744 {
745  if (!index--)
746  return NULL;
747 
748  if (!slave->sii_image) {
749  EC_SLAVE_ERR(slave, "SII data not attached!\n");
750  return NULL;
751  }
752 
753  if (index >= slave->sii_image->sii.string_count) {
754  EC_SLAVE_DBG(slave, 1, "String %u not found.\n", index);
755  return NULL;
756  }
757 
758  return slave->sii_image->sii.strings[index];
759 }
760 
761 /*****************************************************************************/
762 
768  ec_slave_t *slave,
769  uint8_t sync_index
770  )
771 {
772 
773  if (!slave->sii_image) {
774  EC_SLAVE_ERR(slave, "SII data not attached!\n");
775  return NULL;
776  }
777 
778  if (sync_index < slave->sii_image->sii.sync_count) {
779  return &slave->sii_image->sii.syncs[sync_index];
780  } else {
781  return NULL;
782  }
783 }
784 
785 /*****************************************************************************/
786 
792  unsigned int *sdo_count,
793  unsigned int *entry_count
795  )
796 {
797  unsigned int sdos = 0, entries = 0;
798  ec_sdo_t *sdo;
799  ec_sdo_entry_t *entry;
800 
801  list_for_each_entry(sdo, &slave->sdo_dictionary, list) {
802  sdos++;
803  list_for_each_entry(entry, &sdo->entries, list) {
804  entries++;
805  }
806  }
807 
808  *sdo_count = sdos;
809  *entry_count = entries;
810 }
811 
812 /*****************************************************************************/
813 
820  ec_slave_t *slave,
821  uint16_t index
822  )
823 {
824  ec_sdo_t *sdo;
825 
826  list_for_each_entry(sdo, &slave->sdo_dictionary, list) {
827  if (sdo->index != index)
828  continue;
829  return sdo;
830  }
831 
832  return NULL;
833 }
834 
835 /*****************************************************************************/
836 
846  const ec_slave_t *slave,
847  uint16_t index
848  )
849 {
850  const ec_sdo_t *sdo;
851 
852  list_for_each_entry(sdo, &slave->sdo_dictionary, list) {
853  if (sdo->index != index)
854  continue;
855  return sdo;
856  }
857 
858  return NULL;
859 }
860 
861 /*****************************************************************************/
862 
868  const ec_slave_t *slave,
869  uint16_t sdo_position
870  )
871 {
872  const ec_sdo_t *sdo;
873 
874  list_for_each_entry(sdo, &slave->sdo_dictionary, list) {
875  if (sdo_position--)
876  continue;
877  return sdo;
878  }
879 
880  return NULL;
881 }
882 
883 /*****************************************************************************/
884 
890  const ec_slave_t *slave
891  )
892 {
893  const ec_sdo_t *sdo;
894  uint16_t count = 0;
895 
896  list_for_each_entry(sdo, &slave->sdo_dictionary, list) {
897  count++;
898  }
899 
900  return count;
901 }
902 
903 /*****************************************************************************/
904 
909  const ec_slave_t *slave,
910  uint16_t index
911  )
912 {
913  unsigned int i;
914  const ec_sync_t *sync;
915  const ec_pdo_t *pdo;
916 
917  if (!slave->sii_image) {
918  EC_SLAVE_ERR(slave, "SII data not attached!\n");
919  return NULL;
920  }
921 
922  for (i = 0; i < slave->sii_image->sii.sync_count; i++) {
923  sync = &slave->sii_image->sii.syncs[i];
924 
925  if (!(pdo = ec_pdo_list_find_pdo_const(&sync->pdos, index)))
926  continue;
927 
928  return pdo;
929  }
930 
931  return NULL;
932 }
933 
934 /*****************************************************************************/
935 
939  ec_slave_t *slave,
940  ec_pdo_t *pdo
941  )
942 {
943  const ec_sdo_t *sdo;
944  ec_pdo_entry_t *pdo_entry;
945  const ec_sdo_entry_t *sdo_entry;
946 
947  list_for_each_entry(sdo, &slave->sdo_dictionary, list) {
948  if (sdo->index == pdo->index) {
949  ec_pdo_set_name(pdo, sdo->name);
950  } else {
951  list_for_each_entry(pdo_entry, &pdo->entries, list) {
952  if (sdo->index == pdo_entry->index) {
953  sdo_entry = ec_sdo_get_entry_const(
954  sdo, pdo_entry->subindex);
955  if (sdo_entry) {
956  ec_pdo_entry_set_name(pdo_entry,
957  sdo_entry->description);
958  }
959  }
960  }
961  }
962  }
963 }
964 
965 /*****************************************************************************/
966 
970  ec_slave_t *slave
971  )
972 {
973  unsigned int i;
974  ec_sync_t *sync;
975  ec_pdo_t *pdo;
976 
977  if (!slave->sii_image) {
978  EC_SLAVE_ERR(slave, "SII data not attached!\n");
979  return;
980  }
981 
982  for (i = 0; i < slave->sii_image->sii.sync_count; i++) {
983  sync = slave->sii_image->sii.syncs + i;
984  list_for_each_entry(pdo, &sync->pdos.list, list) {
985  ec_slave_find_names_for_pdo(slave, pdo);
986  }
987  }
988 }
989 
990 /*****************************************************************************/
991 
997  ec_slave_t *slave,
998  unsigned int port_index
999  )
1000 {
1001  static const unsigned int prev_table[EC_MAX_PORTS] = {
1002  2, 3, 1, 0
1003  };
1004 
1005  if (port_index >= EC_MAX_PORTS) {
1006  EC_SLAVE_WARN(slave, "%s(port_index=%u): Invalid port index!\n",
1007  __func__, port_index);
1008  }
1009 
1010  do {
1011  port_index = prev_table[port_index];
1012  if (slave->ports[port_index].next_slave) {
1013  return port_index;
1014  }
1015  } while (port_index != slave->upstream_port);
1016 
1017  return slave->upstream_port;
1018 }
1019 
1020 /*****************************************************************************/
1021 
1027  ec_slave_t *slave,
1028  unsigned int port_index
1029  )
1030 {
1031  static const unsigned int prev_table[EC_MAX_PORTS] = {
1032  2, 3, 1, 0
1033  };
1034 
1035  if (port_index >= EC_MAX_PORTS) {
1036  EC_SLAVE_WARN(slave, "%s(port_index=%u): Invalid port index!\n",
1037  __func__, port_index);
1038  }
1039 
1040  do {
1041  port_index = prev_table[port_index];
1042  if (!slave->ports[port_index].link.bypassed &&
1043  slave->ports[port_index].next_slave) {
1044  return port_index;
1045  }
1046  } while (port_index != slave->upstream_port);
1047 
1048  return slave->upstream_port;
1049 }
1050 
1051 /*****************************************************************************/
1052 
1058  ec_slave_t *slave,
1059  unsigned int port_index
1060  )
1061 {
1062  static const unsigned int next_table[EC_MAX_PORTS] = {
1063  3, 2, 0, 1
1064  };
1065 
1066  if (port_index >= EC_MAX_PORTS) {
1067  EC_SLAVE_WARN(slave, "%s(port_index=%u): Invalid port index!\n",
1068  __func__, port_index);
1069  }
1070 
1071  do {
1072  port_index = next_table[port_index];
1073  if (slave->ports[port_index].next_slave) {
1074  return port_index;
1075  }
1076  } while (port_index != slave->upstream_port);
1077 
1078  return slave->upstream_port;
1079 }
1080 
1081 /*****************************************************************************/
1082 
1086  ec_slave_t *slave
1087  )
1088 {
1089  int i, replace;
1090 
1091  // initially assume it's port 0 (normal connection order)
1092  slave->upstream_port = 0;
1093  replace = slave->ports[0].link.loop_closed || slave->ports[0].link.bypassed;
1094 
1095  if (!slave->base_dc_supported) {
1096  // we can't tell any better for non-DC slaves; assume we're right
1097  EC_SLAVE_DBG(slave, 1, "DC not supported; assuming upstream port 0.\n");
1098  return;
1099  }
1100 
1101  // any open & non-bypassed port with a lower receive time
1102  // is a better candidate for the upstream port
1103  for (i = 1; i < EC_MAX_PORTS; ++i) {
1104  if (!slave->ports[i].link.loop_closed &&
1105  !slave->ports[i].link.bypassed) {
1106  int32_t diff = slave->ports[i].receive_time -
1107  slave->ports[slave->upstream_port].receive_time;
1108  if (diff < 0 || replace) {
1109  slave->upstream_port = i;
1110  replace = 0;
1111  }
1112  }
1113  }
1114  EC_SLAVE_DBG(slave, 1, "upstream port = %u\n", slave->upstream_port);
1115 }
1116 
1117 /*****************************************************************************/
1118 
1124  ec_slave_t *slave
1125  )
1126 {
1127  uint32_t rtt_sum = 0, rtt;
1128  unsigned int port_index = ec_slave_get_next_port(slave, slave->upstream_port);
1129 
1130  while (port_index != slave->upstream_port) {
1131  unsigned int prev_index =
1132  ec_slave_get_previous_normal_port(slave, port_index);
1133 
1134  if (!slave->ports[port_index].link.bypassed) {
1135  rtt = slave->ports[port_index].receive_time -
1136  slave->ports[prev_index].receive_time;
1137  rtt_sum += rtt;
1138  }
1139  port_index = ec_slave_get_next_port(slave, port_index);
1140  }
1141 
1142  return rtt_sum;
1143 }
1144 
1145 /*****************************************************************************/
1146 
1152  ec_slave_t *slave
1153  )
1154 {
1155  unsigned int port_index;
1156  ec_slave_t *dc_slave = NULL;
1157 
1158  if (slave->base_dc_supported) {
1159  dc_slave = slave;
1160  } else {
1161  port_index = ec_slave_get_next_port(slave, slave->upstream_port);
1162 
1163  while (port_index != slave->upstream_port) {
1164  ec_slave_t *next = slave->ports[port_index].next_slave;
1165 
1166  if (next) {
1167  dc_slave = ec_slave_find_next_dc_slave(next);
1168 
1169  if (dc_slave) {
1170  break;
1171  }
1172  }
1173  port_index = ec_slave_get_next_port(slave, port_index);
1174  }
1175  }
1176 
1177  return dc_slave;
1178 }
1179 
1180 /*****************************************************************************/
1181 
1185  ec_slave_t *slave
1186  )
1187 {
1188  unsigned int port_index;
1189  ec_slave_t *next_slave, *next_dc;
1190  uint32_t rtt, next_rtt_sum;
1191 
1192  if (!slave->base_dc_supported)
1193  return;
1194 
1195  port_index = ec_slave_get_next_port(slave, slave->upstream_port);
1196 
1197  while (port_index != slave->upstream_port) {
1198  next_slave = slave->ports[port_index].next_slave;
1199  next_dc = ec_slave_find_next_dc_slave(next_slave);
1200 
1201  if (next_dc) {
1202  unsigned int prev_port =
1203  ec_slave_get_previous_normal_port(slave, port_index);
1204 
1205  if (!slave->ports[port_index].link.bypassed) {
1206  rtt = slave->ports[port_index].receive_time -
1207  slave->ports[prev_port].receive_time;
1208  } else {
1209  rtt = 0; // FIXME
1210  }
1211  next_rtt_sum = ec_slave_calc_rtt_sum(next_dc);
1212 
1213  slave->ports[port_index].delay_to_next_dc =
1214  (rtt - next_rtt_sum) / 2; // FIXME
1215  next_dc->ports[next_dc->upstream_port].delay_to_next_dc =
1216  (rtt - next_rtt_sum) / 2;
1217 
1218 #if 0
1219  EC_SLAVE_DBG(slave, 1, "delay %u:%u rtt=%u"
1220  " next_rtt_sum=%u delay=%u\n",
1221  slave->ring_position, port_index, rtt, next_rtt_sum,
1222  slave->ports[port_index].delay_to_next_dc);
1223 #endif
1224  }
1225 
1226  port_index = ec_slave_get_next_port(slave, port_index);
1227  }
1228 }
1229 
1230 /*****************************************************************************/
1231 
1235  ec_slave_t *slave,
1236  uint32_t *delay
1237  )
1238 {
1239  unsigned int i;
1240  ec_slave_t *next_dc;
1241 
1242  EC_SLAVE_DBG(slave, 1, "%s(delay = %u ns)\n", __func__, *delay);
1243 
1244  slave->transmission_delay = *delay;
1245 
1246  i = ec_slave_get_next_port(slave, slave->upstream_port);
1247 
1248  while (i != slave->upstream_port) {
1249  ec_slave_port_t *port = &slave->ports[i];
1250  next_dc = ec_slave_find_next_dc_slave(port->next_slave);
1251  if (next_dc) {
1252  *delay = *delay + port->delay_to_next_dc;
1253 #if 0
1254  EC_SLAVE_DBG(slave, 1, "%u:%u %u\n",
1255  slave->ring_position, i, *delay);
1256 #endif
1257  ec_slave_calc_transmission_delays_rec(next_dc, delay);
1258  }
1259 
1260  i = ec_slave_get_next_port(slave, i);
1261  }
1262 
1263  *delay = *delay + slave->ports[slave->upstream_port].delay_to_next_dc;
1264 }
1265 
1266 /*****************************************************************************/
ec_sii_general_flags_t general_flags
General flags.
Definition: slave.h:186
ec_mbox_data_t mbox_eoe_frag_data
Received mailbox data for EoE, type frame fragment.
Definition: slave.h:288
struct list_head mbg_requests
EoE set IP parameter requests.
Definition: slave.h:279
Slave information interface general flags.
Definition: globals.h:203
ec_internal_request_state_t state
Request state.
Definition: reg_request.h:56
uint16_t ring_position
Ring position.
Definition: slave.h:221
uint32_t revision_number
Revision number.
Definition: slave.h:162
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:116
uint8_t upstream_port
Index of master-facing port.
Definition: slave.h:232
void ec_slave_calc_upstream_port(ec_slave_t *slave)
Calculates which of ports 0-3 appears to be the upstream one.
Definition: slave.c:1085
uint16_t ec_slave_sdo_count(const ec_slave_t *slave)
Get the number of SDOs in the dictionary.
Definition: slave.c:889
struct rt_mutex mbox_sem
Semaphore protecting the check_mbox variable.
Definition: slave.h:285
uint16_t boot_rx_mailbox_offset
Bootstrap receive mailbox address.
Definition: slave.h:164
ec_internal_request_state_t state
Request state.
void ec_fsm_slave_clear(ec_fsm_slave_t *fsm)
Destructor.
Definition: fsm_slave.c:116
uint16_t configured_tx_mailbox_size
Configured send mailbox size.
Definition: slave.h:248
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:996
void ec_mbox_data_init(ec_mbox_data_t *mbox_data)
Initialize mailbox response data.
Definition: datagram.c:679
uint8_t enable_upload_at_startup
?.
Definition: globals.h:197
void ec_slave_attach_pdo_names(ec_slave_t *slave)
Attach PDO names.
Definition: slave.c:969
uint16_t base_build
Build number.
Definition: slave.h:253
EtherCAT Mailbox Gateway request.
struct list_head list
List item.
Definition: soe_request.h:49
#define EC_SLAVE_DBG(slave, level, fmt, args...)
Convenience macro for printing slave-specific debug messages to syslog.
Definition: slave.h:108
CANopen SDO entry.
Definition: sdo_entry.h:54
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:265
unsigned int reboot
Request reboot.
Definition: slave.h:241
ec_mbox_data_t mbox_eoe_init_data
Received mailbox data for EoE, type eoe init reponse.
Definition: slave.h:289
uint8_t enable_not_lrw
Slave does not support LRW.
Definition: globals.h:205
uint16_t configured_tx_mailbox_offset
Configured send mailbox offset.
Definition: slave.h:246
size_t ec_state_string(uint8_t, char *, uint8_t)
Prints slave states in clear text.
Definition: module.c:408
ec_slave_port_t ports[EC_MAX_PORTS]
Ports.
Definition: slave.h:231
CANopen SDO request.
Definition: sdo_request.h:48
ec_slave_state_t current_state
Current application state.
Definition: slave.h:237
Complete slave information interface data image.
Definition: slave.h:201
const ec_code_msg_t al_status_messages[]
Application layer status messages.
Definition: fsm_change.c:399
EtherCAT slave structure.
ec_internal_request_state_t state
SDO request state.
Definition: sdo_request.h:63
ec_mbox_data_t mbox_mbg_data
Received mailbox data for MBox Gateway.
Definition: slave.h:295
Register request.
Definition: reg_request.h:48
ec_mbox_data_t mbox_foe_data
Received mailbox data for FoE.
Definition: slave.h:292
ec_sdo_t * ec_slave_get_sdo(ec_slave_t *slave, uint16_t index)
Get an SDO from the dictionary.
Definition: slave.c:819
ec_slave_port_link_t link
Port link status.
Definition: slave.h:141
#define EC_SLAVE_WARN(slave, fmt, args...)
Convenience macro for printing slave-specific warnings to syslog.
Definition: slave.h:91
uint8_t enable_sdo
Enable SDO access.
Definition: globals.h:193
struct list_head list
List of PDOs.
Definition: pdo_list.h:50
uint32_t serial_number
Serial number.
Definition: slave.h:163
ec_sii_coe_details_t coe_details
CoE detail flags.
Definition: slave.h:185
char * order
Order number.
Definition: slave.h:182
int ec_pdo_set_name(ec_pdo_t *pdo, const char *name)
Set PDO name.
Definition: pdo.c:125
ec_internal_request_state_t state
Request state.
Definition: soe_request.h:58
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:938
ec_fsm_slave_t fsm
Slave state machine.
Definition: slave.h:282
struct list_head reg_requests
Register access requests.
Definition: slave.h:275
struct list_head list
List item.
Definition: sdo.h:50
void ec_pdo_init(ec_pdo_t *pdo)
PDO constructor.
Definition: pdo.c:46
const ec_pdo_t * ec_slave_find_pdo(const ec_slave_t *slave, uint16_t index)
Finds a mapped PDO.
Definition: slave.c:908
CANopen SDO.
Definition: sdo.h:49
uint16_t index
SDO index.
Definition: sdo.h:52
int16_t current_on_ebus
Power consumption in mA.
Definition: slave.h:187
uint16_t boot_tx_mailbox_size
Bootstrap transmit mailbox size.
Definition: slave.h:167
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:464
void ec_slave_set_dl_status(ec_slave_t *slave, uint16_t new_state)
Sets the data-link state of a slave.
Definition: slave.c:374
wait_queue_head_t request_queue
Wait queue for external requests from user space.
Definition: master.h:338
uint16_t station_address
Configured station address.
Definition: slave.h:222
unsigned int sync_count
Number of sync managers.
Definition: slave.h:191
void ec_slave_clear(ec_slave_t *slave)
Slave destructor.
Definition: slave.c:250
struct list_head sdo_dictionary
SDO dictionary list.
Definition: slave.h:269
uint16_t std_rx_mailbox_size
Standard receive mailbox size.
Definition: slave.h:169
uint8_t base_type
Slave type.
Definition: slave.h:251
Global definitions and macros.
uint16_t std_tx_mailbox_offset
Standard transmit mailbox address.
Definition: slave.h:170
PDO entry description.
Definition: pdo_entry.h:48
EtherCAT master structure.
void ec_pdo_clear(ec_pdo_t *pdo)
PDO destructor.
Definition: pdo.c:94
uint16_t index
PDO index.
Definition: pdo.h:51
int8_t sync_index
Assigned sync manager.
Definition: pdo.h:52
uint16_t boot_tx_mailbox_offset
Bootstrap transmit mailbox address.
Definition: slave.h:166
uint16_t index
PDO entry index.
Definition: pdo_entry.h:50
void ec_slave_sdo_dict_info(const ec_slave_t *slave, unsigned int *sdo_count, unsigned int *entry_count)
Counts the total number of SDOs and entries in the dictionary.
Definition: slave.c:791
EtherCAT slave.
Definition: slave.h:214
struct list_head sdo_requests
SDO access requests.
Definition: slave.h:274
char * description
Description.
Definition: sdo_entry.h:62
ec_sii_image_t * sii_image
Current complete SII image.
Definition: slave.h:267
Code/Message pair.
Definition: globals.h:313
struct list_head soe_requests
SoE requests.
Definition: slave.h:277
Slave information interface CANopen over EtherCAT details flags.
Definition: globals.h:192
uint8_t enable_safeop
?.
Definition: globals.h:204
ec_slave_config_t * config
Current configuration.
Definition: slave.h:235
void ec_slave_sii_image_init(ec_sii_image_t *sii_image)
Definition: slave.c:166
void ec_pdo_entry_clear(ec_pdo_entry_t *entry)
PDO entry destructor.
Definition: pdo_entry.c:76
void ec_slave_clear_sync_managers(ec_slave_t *slave)
Clear the sync manager array.
Definition: slave.c:355
uint8_t enable_sdo_info
SDO information service available.
Definition: globals.h:194
uint8_t enable_sdo_complete_access
Complete access possible.
Definition: globals.h:198
void ec_slave_calc_port_delays(ec_slave_t *slave)
Calculates the port transmission delays.
Definition: slave.c:1184
PDO description.
Definition: pdo.h:49
uint8_t sdo_dictionary_fetched
Dictionary has been fetched.
Definition: slave.h:271
uint16_t mailbox_protocols
Supported mailbox protocols.
Definition: slave.h:172
unsigned int ec_slave_get_previous_normal_port(ec_slave_t *slave, unsigned int port_index)
Returns the previous connected & unbypassed port of a given port.
Definition: slave.c:1026
unsigned int debug_level
Master debug level.
Definition: master.h:310
#define EC_SLAVE_ERR(slave, fmt, args...)
Convenience macro for printing slave-specific errors to syslog.
Definition: slave.h:77
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:141
struct list_head list
List item.
ec_slave_dc_range_t base_dc_range
DC range.
Definition: slave.h:258
uint8_t bit_length
entry length in bit
Definition: pdo_entry.h:53
Sync manager.
Definition: sync.h:47
uint16_t std_rx_mailbox_offset
Standard receive mailbox address.
Definition: slave.h:168
uint8_t base_fmmu_bit_operation
FMMU bit operation is supported.
Definition: slave.h:256
uint32_t transmission_delay
DC system time transmission delay (offset from reference clock).
Definition: slave.h:262
ec_device_index_t
Master devices.
Definition: globals.h:236
char * name
SDO name.
Definition: sdo.h:54
uint16_t alias
Configured station alias.
Definition: slave.h:159
ec_direction_t
Direction type for PDO assignment functions.
Definition: ecrt.h:436
uint8_t base_fmmu_count
Number of supported FMMUs.
Definition: slave.h:254
void ec_slave_calc_transmission_delays_rec(ec_slave_t *slave, uint32_t *delay)
Recursively calculates transmission delays.
Definition: slave.c:1234
uint16_t configured_rx_mailbox_offset
Configured receive mailbox offset.
Definition: slave.h:242
void ec_slave_request_reboot(ec_slave_t *slave)
Request a slave reboot (some slaves will ignore this).
Definition: slave.c:450
struct list_head entries
List of PDO entries.
Definition: pdo.h:54
uint32_t effective_product_code
Effective product code.
Definition: slave.h:227
ec_slave_port_desc_t desc
Port descriptors.
Definition: slave.h:140
unsigned int string_count
Number of SII strings.
Definition: slave.h:176
ec_master_t * master
Master owning the slave.
Definition: slave.h:216
void ec_pdo_entry_init(ec_pdo_entry_t *entry)
PDO entry constructor.
Definition: pdo_entry.c:45
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:867
uint8_t has_dc_system_time
The slave supports the DC system time register.
Definition: slave.h:259
char ** strings
Strings in SII categories.
Definition: slave.h:175
ec_slave_state_t
State of an EtherCAT slave.
Definition: globals.h:159
uint8_t subindex
PDO entry subindex.
Definition: pdo_entry.h:51
struct list_head list
List item.
Definition: foe_request.h:51
EtherCAT datagram structure.
uint8_t control_register
Control register value.
Definition: sync.h:51
int ec_read_mbox_locked(ec_slave_t *slave)
Return the current mailbox lock status and lock it if not locked.
Definition: slave.c:229
CANopen dictionary request.
Definition: dict_request.h:48
void ec_sync_clear(ec_sync_t *sync)
Destructor.
Definition: sync.c:81
Port is not implemented.
Definition: ecrt.h:355
uint8_t base_revision
Revision.
Definition: slave.h:252
32 bit.
Definition: globals.h:211
uint32_t effective_vendor_id
Effective vendor ID.
Definition: slave.h:226
struct list_head list
List item.
Definition: dict_request.h:49
Ethernet-over-EtherCAT set IP parameter request.
Definition: eoe_request.h:49
uint16_t * vendor_words
First 16 words of SII image.
Definition: slave.h:266
void ec_read_mbox_lock_clear(ec_slave_t *slave)
Clears the mailbox lock.
Definition: slave.c:216
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:845
uint8_t valid_mbox_data
Received mailbox data is valid.
Definition: slave.h:297
ec_slave_t * ec_slave_find_next_dc_slave(ec_slave_t *slave)
Finds the next slave supporting DC delay measurement.
Definition: slave.c:1151
uint16_t effective_alias
Effective alias address.
Definition: slave.h:223
struct list_head entries
List of entries.
Definition: sdo.h:56
ec_internal_request_state_t state
Request state.
Definition: eoe_request.h:51
#define EC_READ_U16(DATA)
Read a 16-bit unsigned value from EtherCAT data.
Definition: ecrt.h:2554
struct list_head foe_requests
FoE requests.
Definition: slave.h:276
void ec_mbox_data_clear(ec_mbox_data_t *mbox_data)
Free internal memory for mailbox response data.
Definition: datagram.c:694
uint8_t enable
Enable bit.
Definition: sync.h:52
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:581
#define EC_STATE_STRING_SIZE
Minimum size of a buffer used with ec_state_string().
Definition: globals.h:65
uint16_t boot_rx_mailbox_size
Bootstrap receive mailbox size.
Definition: slave.h:165
#define EC_MAX_PORTS
Maximum number of slave ports.
Definition: ecrt.h:217
uint32_t effective_serial_number
Effective serial number.
Definition: slave.h:229
struct list_head list
List item.
Definition: sdo_request.h:49
void ec_fsm_slave_init(ec_fsm_slave_t *fsm, ec_slave_t *slave)
Constructor.
Definition: fsm_slave.c:74
uint8_t read_mbox_busy
Flag set during a mailbox read request.
Definition: slave.h:284
void ec_slave_init(ec_slave_t *slave, ec_master_t *master, ec_device_index_t dev_idx, uint16_t ring_position, uint16_t station_address)
Slave constructor.
Definition: slave.c:62
ec_slave_t * next_slave
Connected slaves.
Definition: slave.h:142
uint32_t receive_time
Port receive times for delay measurement.
Definition: slave.h:143
Slave port.
Definition: slave.h:139
char * image
Image name.
Definition: slave.h:181
ec_pdo_list_t pdos
Current PDO assignment.
Definition: sync.h:53
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:436
uint16_t physical_start_address
Physical start address.
Definition: sync.h:49
ec_mbox_data_t mbox_voe_data
Received mailbox data for VoE.
Definition: slave.h:294
unsigned long jiffies_preop
Time, the slave went to PREOP.
Definition: slave.h:272
uint16_t configured_rx_mailbox_size
Configured receive mailbox size.
Definition: slave.h:244
uint8_t base_dc_supported
Distributed clocks are supported.
Definition: slave.h:257
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:1123
char * ec_slave_sii_string(ec_slave_t *, unsigned int)
Searches the string list for an index.
Definition: slave.c:740
void ec_sync_init_copy(ec_sync_t *sync, const ec_sync_t *other)
Copy constructor.
Definition: sync.c:63
char * group
Group name.
Definition: slave.h:180
uint8_t physical_layer[EC_MAX_PORTS]
Port media.
Definition: slave.h:184
struct list_head list
list item
Definition: pdo_entry.h:49
void ec_sdo_clear(ec_sdo_t *sdo)
SDO destructor.
Definition: sdo.c:67
uint8_t base_sync_count
Number of supported sync managers.
Definition: slave.h:255
#define EC_READ_U8(DATA)
Read an 8-bit unsigned value from EtherCAT data.
Definition: ecrt.h:2538
struct list_head dict_requests
Dictionary read requests.
Definition: slave.h:280
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:1057
EtherCAT slave configuration structure.
ec_sii_t sii
Extracted SII data.
Definition: slave.h:207
#define EC_READ_S16(DATA)
Read a 16-bit signed value from EtherCAT data.
Definition: ecrt.h:2562
FoE request.
Definition: foe_request.h:50
ec_device_index_t device_index
Index of device the slave responds on.
Definition: slave.h:217
void ec_slave_config_detach(ec_slave_config_t *sc)
Detaches the configuration from a slave object.
Definition: slave_config.c:315
uint16_t default_length
Data length in bytes.
Definition: sync.h:50
uint32_t product_code
Vendor-specific product code.
Definition: slave.h:161
PREOP state (mailbox communication, no IO)
Definition: globals.h:164
struct list_head list
List item.
Definition: pdo.h:50
size_t nwords
Size of the SII contents in words.
Definition: slave.h:205
uint8_t scan_required
Scan required.
Definition: slave.h:270
unsigned int error_flag
Stop processing after an error.
Definition: slave.h:239
ec_sync_t * syncs
SYNC MANAGER categories.
Definition: slave.h:190
uint16_t std_tx_mailbox_size
Standard transmit mailbox size.
Definition: slave.h:171
EtherCAT master.
Definition: master.h:202
uint8_t enable_pdo_configuration
PDO configuration possible.
Definition: globals.h:196
struct list_head list
List item.
Definition: reg_request.h:49
ec_slave_state_t requested_state
Requested application state.
Definition: slave.h:236
struct list_head eoe_requests
EoE set IP parameter requests.
Definition: slave.h:278
uint32_t effective_revision_number
Effective revision number.
Definition: slave.h:228
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:652
uint16_t last_al_error
Last AL state error code.
Definition: slave.h:238
#define EC_MAX_SYNC_MANAGERS
Maximum number of sync managers per slave.
Definition: ecrt.h:208
void ec_sync_init(ec_sync_t *sync, ec_slave_t *slave)
Constructor.
Definition: sync.c:46
struct list_head list
List item.
Definition: eoe_request.h:50
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:525
void ec_slave_set_al_status(ec_slave_t *slave, ec_slave_state_t new_state)
Sets the application state of a slave.
Definition: slave.c:414
char * name
Slave name.
Definition: slave.h:183
ec_mbox_data_t mbox_coe_data
Received mailbox data for CoE.
Definition: slave.h:291
int ec_pdo_entry_set_name(ec_pdo_entry_t *entry, const char *name)
Set PDO entry name.
Definition: pdo_entry.c:89
unknown state
Definition: globals.h:160
ec_mbox_data_t mbox_soe_data
Received mailbox data for SoE.
Definition: slave.h:293
uint32_t vendor_id
Vendor ID.
Definition: slave.h:160
uint32_t delay_to_next_dc
Delay to next slave with DC support behind this port [ns].
Definition: slave.h:145
struct list_head pdos
SII [RT]XPDO categories.
Definition: slave.h:194
unsigned int force_config
Force (re-)configuration.
Definition: slave.h:240
ec_internal_request_state_t state
FoE request state.
Definition: foe_request.h:64
unsigned int has_general
General category present.
Definition: slave.h:179
Sercos-over-EtherCAT request.
Definition: soe_request.h:48
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:767
uint8_t enable_pdo_assign
PDO mapping configurable.
Definition: globals.h:195
ec_internal_request_state_t state
SDO request state.
Definition: dict_request.h:50