IgH EtherCAT Master  1.6.9
datagram_pair.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
26
27/****************************************************************************/
28
29#include <linux/slab.h>
30
31#include "master.h"
32#include "datagram_pair.h"
33
34/****************************************************************************/
35
41 ec_datagram_pair_t *pair,
42 ec_domain_t *domain,
43 uint32_t logical_offset,
44 uint8_t *data,
45 size_t data_size,
46 const unsigned int used[]
47 )
48{
49 ec_device_index_t dev_idx;
50 int ret;
51
52 INIT_LIST_HEAD(&pair->list);
53 pair->domain = domain;
54
55 for (dev_idx = EC_DEVICE_MAIN;
56 dev_idx < ec_master_num_devices(domain->master); dev_idx++) {
57 ec_datagram_init(&pair->datagrams[dev_idx]);
58 snprintf(pair->datagrams[dev_idx].name,
59 EC_DATAGRAM_NAME_SIZE, "domain%u-%u-%s", domain->index,
60 logical_offset, ec_device_names[dev_idx != 0]);
61 pair->datagrams[dev_idx].device_index = dev_idx;
62 }
63
64 pair->expected_working_counter = 0U;
65
66 for (dev_idx = EC_DEVICE_BACKUP;
67 dev_idx < ec_master_num_devices(domain->master); dev_idx++) {
68 /* backup datagrams have their own memory */
69 ret = ec_datagram_prealloc(&pair->datagrams[dev_idx], data_size);
70 if (ret) {
71 goto out_datagrams;
72 }
73 }
74
75#if EC_MAX_NUM_DEVICES > 1
76 if (!(pair->send_buffer = kmalloc(data_size, GFP_KERNEL))) {
77 EC_MASTER_ERR(domain->master,
78 "Failed to allocate domain send buffer!\n");
79 ret = -ENOMEM;
80 goto out_datagrams;
81 }
82#endif
83
84 /* The ec_datagram_lxx() calls below can not fail, because either the
85 * datagram has external memory or it is preallocated. */
86
87 if (used[EC_DIR_OUTPUT] && used[EC_DIR_INPUT]) { // inputs and outputs
89 logical_offset, data_size, data);
90
91 for (dev_idx = EC_DEVICE_BACKUP;
92 dev_idx < ec_master_num_devices(domain->master); dev_idx++) {
93 ec_datagram_lrw(&pair->datagrams[dev_idx],
94 logical_offset, data_size);
95 }
96
97 // If LRW is used, output FMMUs increment the working counter by 2,
98 // while input FMMUs increment it by 1.
100 used[EC_DIR_OUTPUT] * 2 + used[EC_DIR_INPUT];
101 } else if (used[EC_DIR_OUTPUT]) { // outputs only
103 logical_offset, data_size, data);
104 for (dev_idx = EC_DEVICE_BACKUP;
105 dev_idx < ec_master_num_devices(domain->master); dev_idx++) {
106 ec_datagram_lwr(&pair->datagrams[dev_idx],
107 logical_offset, data_size);
108 }
109
111 } else { // inputs only (or nothing)
113 logical_offset, data_size, data);
114 for (dev_idx = EC_DEVICE_BACKUP;
115 dev_idx < ec_master_num_devices(domain->master); dev_idx++) {
116 ec_datagram_lrd(&pair->datagrams[dev_idx], logical_offset,
117 data_size);
118 }
119
121 }
122
123 for (dev_idx = EC_DEVICE_MAIN;
124 dev_idx < ec_master_num_devices(domain->master); dev_idx++) {
125 ec_datagram_zero(&pair->datagrams[dev_idx]);
126 }
127
128 return 0;
129
130out_datagrams:
131 for (dev_idx = EC_DEVICE_MAIN;
132 dev_idx < ec_master_num_devices(domain->master); dev_idx++) {
133 ec_datagram_clear(&pair->datagrams[dev_idx]);
134 }
135
136 return ret;
137}
138
139/****************************************************************************/
140
144 ec_datagram_pair_t *pair
145 )
146{
147 unsigned int dev_idx;
148
149 for (dev_idx = EC_DEVICE_MAIN;
150 dev_idx < ec_master_num_devices(pair->domain->master);
151 dev_idx++) {
152 ec_datagram_clear(&pair->datagrams[dev_idx]);
153 }
154
155#if EC_MAX_NUM_DEVICES > 1
156 if (pair->send_buffer) {
157 kfree(pair->send_buffer);
158 }
159#endif
160}
161
162/****************************************************************************/
163
169 ec_datagram_pair_t *pair,
170 uint16_t wc_sum[]
171 )
172{
173 unsigned int dev_idx;
174 uint16_t pair_wc = 0;
175
176 for (dev_idx = 0; dev_idx < ec_master_num_devices(pair->domain->master);
177 dev_idx++) {
178 ec_datagram_t *datagram = &pair->datagrams[dev_idx];
179
180#ifdef EC_RT_SYSLOG
181 ec_datagram_output_stats(datagram);
182#endif
183
184 if (datagram->state == EC_DATAGRAM_RECEIVED) {
185 pair_wc += datagram->working_counter;
186 wc_sum[dev_idx] += datagram->working_counter;
187 }
188 }
189
190 return pair_wc;
191}
192
193/****************************************************************************/
int ec_datagram_lrw_ext(ec_datagram_t *datagram, uint32_t offset, size_t data_size, uint8_t *external_memory)
Initializes an EtherCAT LRW datagram with external memory.
Definition datagram.c:535
int ec_datagram_prealloc(ec_datagram_t *datagram, size_t size)
Allocates internal payload memory.
Definition datagram.c:142
int ec_datagram_lrd_ext(ec_datagram_t *datagram, uint32_t offset, size_t data_size, uint8_t *external_memory)
Initializes an EtherCAT LRD datagram with external memory.
Definition datagram.c:485
void ec_datagram_zero(ec_datagram_t *datagram)
Fills the datagram payload memory with zeros.
Definition datagram.c:170
int ec_datagram_lwr_ext(ec_datagram_t *datagram, uint32_t offset, size_t data_size, uint8_t *external_memory)
Initializes an EtherCAT LWR datagram with external memory.
Definition datagram.c:510
void ec_datagram_output_stats(ec_datagram_t *datagram)
Outputs datagram statistics at most every second.
Definition datagram.c:614
int ec_datagram_lwr(ec_datagram_t *datagram, uint32_t offset, size_t data_size)
Initializes an EtherCAT LWR datagram.
Definition datagram.c:444
int ec_datagram_lrd(ec_datagram_t *datagram, uint32_t offset, size_t data_size)
Initializes an EtherCAT LRD datagram.
Definition datagram.c:425
void ec_datagram_clear(ec_datagram_t *datagram)
Destructor.
Definition datagram.c:110
int ec_datagram_lrw(ec_datagram_t *datagram, uint32_t offset, size_t data_size)
Initializes an EtherCAT LRW datagram.
Definition datagram.c:463
void ec_datagram_init(ec_datagram_t *datagram)
Constructor.
Definition datagram.c:80
@ EC_DATAGRAM_RECEIVED
Received (dequeued).
Definition datagram.h:70
uint16_t ec_datagram_pair_process(ec_datagram_pair_t *pair, uint16_t wc_sum[])
Process received data.
int ec_datagram_pair_init(ec_datagram_pair_t *pair, ec_domain_t *domain, uint32_t logical_offset, uint8_t *data, size_t data_size, const unsigned int used[])
Datagram pair constructor.
void ec_datagram_pair_clear(ec_datagram_pair_t *pair)
Datagram pair destructor.
EtherCAT datagram pair structure.
const char * ec_device_names[2]
Device names.
Definition module.c:465
#define EC_DATAGRAM_NAME_SIZE
Size of the datagram description string.
Definition globals.h:104
ec_device_index_t
Master devices.
Definition globals.h:198
@ EC_DEVICE_MAIN
Main device.
Definition globals.h:199
@ EC_DEVICE_BACKUP
Backup device.
Definition globals.h:200
struct ec_domain ec_domain_t
Definition ecrt.h:306
@ EC_DIR_INPUT
Values read by the master.
Definition ecrt.h:507
@ EC_DIR_OUTPUT
Values written by the master.
Definition ecrt.h:506
EtherCAT master structure.
#define ec_master_num_devices(MASTER)
Number of Ethernet devices.
Definition master.h:323
#define EC_MASTER_ERR(master, fmt, args...)
Convenience macro for printing master-specific errors to syslog.
Definition master.h:74
Domain datagram pair.
ec_datagram_t datagrams[EC_MAX_NUM_DEVICES]
Datagrams.
struct list_head list
List header.
unsigned int expected_working_counter
Expectord working conter.
ec_domain_t * domain
Parent domain.
EtherCAT datagram.
Definition datagram.h:79
uint16_t working_counter
Working counter.
Definition datagram.h:93
ec_datagram_state_t state
State.
Definition datagram.h:94
ec_device_index_t device_index
Device via which the datagram shall be / was sent.
Definition datagram.h:84
char name[EC_DATAGRAM_NAME_SIZE]
Description of the datagram.
Definition datagram.h:106
ec_master_t * master
EtherCAT master owning the domain.
Definition domain.h:49
unsigned int index
Index (just a number).
Definition domain.h:50