69 |
69 |
70 void ec_datagram_init(ec_datagram_t *datagram /**< EtherCAT datagram */) |
70 void ec_datagram_init(ec_datagram_t *datagram /**< EtherCAT datagram */) |
71 { |
71 { |
72 INIT_LIST_HEAD(&datagram->queue); // mark as unqueued |
72 INIT_LIST_HEAD(&datagram->queue); // mark as unqueued |
73 datagram->type = EC_DATAGRAM_NONE; |
73 datagram->type = EC_DATAGRAM_NONE; |
74 datagram->address.logical = 0x00000000; |
74 memset(datagram->address, 0x00, EC_ADDR_LEN); |
75 datagram->data = NULL; |
75 datagram->data = NULL; |
76 datagram->mem_size = 0; |
76 datagram->mem_size = 0; |
77 datagram->data_size = 0; |
77 datagram->data_size = 0; |
78 datagram->index = 0x00; |
78 datagram->index = 0x00; |
79 datagram->working_counter = 0x00; |
79 datagram->working_counter = 0x00; |
80 datagram->state = EC_DATAGRAM_INIT; |
80 datagram->state = EC_DATAGRAM_INIT; |
81 datagram->cycles_sent = 0; |
81 datagram->cycles_sent = 0; |
82 datagram->jiffies_sent = 0; |
82 datagram->jiffies_sent = 0; |
83 datagram->cycles_received = 0; |
83 datagram->cycles_received = 0; |
84 datagram->jiffies_received = 0; |
84 datagram->jiffies_received = 0; |
|
85 datagram->skip_count = 0; |
|
86 datagram->stats_output_jiffies = 0; |
|
87 datagram->name[0] = 0x00; |
85 } |
88 } |
86 |
89 |
87 /*****************************************************************************/ |
90 /*****************************************************************************/ |
88 |
91 |
89 /** |
92 /** |
145 if (unlikely(node_address == 0x0000)) |
148 if (unlikely(node_address == 0x0000)) |
146 EC_WARN("Using node address 0x0000!\n"); |
149 EC_WARN("Using node address 0x0000!\n"); |
147 |
150 |
148 EC_FUNC_HEADER; |
151 EC_FUNC_HEADER; |
149 datagram->type = EC_DATAGRAM_NPRD; |
152 datagram->type = EC_DATAGRAM_NPRD; |
150 datagram->address.physical.slave = node_address; |
153 EC_WRITE_U16(datagram->address, node_address); |
151 datagram->address.physical.mem = offset; |
154 EC_WRITE_U16(datagram->address + 2, offset); |
152 EC_FUNC_FOOTER; |
155 EC_FUNC_FOOTER; |
153 } |
156 } |
154 |
157 |
155 /*****************************************************************************/ |
158 /*****************************************************************************/ |
156 |
159 |
173 if (unlikely(node_address == 0x0000)) |
176 if (unlikely(node_address == 0x0000)) |
174 EC_WARN("Using node address 0x0000!\n"); |
177 EC_WARN("Using node address 0x0000!\n"); |
175 |
178 |
176 EC_FUNC_HEADER; |
179 EC_FUNC_HEADER; |
177 datagram->type = EC_DATAGRAM_NPWR; |
180 datagram->type = EC_DATAGRAM_NPWR; |
178 datagram->address.physical.slave = node_address; |
181 EC_WRITE_U16(datagram->address, node_address); |
179 datagram->address.physical.mem = offset; |
182 EC_WRITE_U16(datagram->address + 2, offset); |
180 EC_FUNC_FOOTER; |
183 EC_FUNC_FOOTER; |
181 } |
184 } |
182 |
185 |
183 /*****************************************************************************/ |
186 /*****************************************************************************/ |
184 |
187 |
198 /**< number of bytes to read */ |
201 /**< number of bytes to read */ |
199 ) |
202 ) |
200 { |
203 { |
201 EC_FUNC_HEADER; |
204 EC_FUNC_HEADER; |
202 datagram->type = EC_DATAGRAM_APRD; |
205 datagram->type = EC_DATAGRAM_APRD; |
203 datagram->address.physical.slave = (int16_t) ring_position * (-1); |
206 EC_WRITE_S16(datagram->address, (int16_t) ring_position * (-1)); |
204 datagram->address.physical.mem = offset; |
207 EC_WRITE_U16(datagram->address + 2, offset); |
205 EC_FUNC_FOOTER; |
208 EC_FUNC_FOOTER; |
206 } |
209 } |
207 |
210 |
208 /*****************************************************************************/ |
211 /*****************************************************************************/ |
209 |
212 |
223 /**< number of bytes to write */ |
226 /**< number of bytes to write */ |
224 ) |
227 ) |
225 { |
228 { |
226 EC_FUNC_HEADER; |
229 EC_FUNC_HEADER; |
227 datagram->type = EC_DATAGRAM_APWR; |
230 datagram->type = EC_DATAGRAM_APWR; |
228 datagram->address.physical.slave = (int16_t) ring_position * (-1); |
231 EC_WRITE_S16(datagram->address, (int16_t) ring_position * (-1)); |
229 datagram->address.physical.mem = offset; |
232 EC_WRITE_U16(datagram->address + 2, offset); |
230 EC_FUNC_FOOTER; |
233 EC_FUNC_FOOTER; |
231 } |
234 } |
232 |
235 |
233 /*****************************************************************************/ |
236 /*****************************************************************************/ |
234 |
237 |
246 /**< number of bytes to read */ |
249 /**< number of bytes to read */ |
247 ) |
250 ) |
248 { |
251 { |
249 EC_FUNC_HEADER; |
252 EC_FUNC_HEADER; |
250 datagram->type = EC_DATAGRAM_BRD; |
253 datagram->type = EC_DATAGRAM_BRD; |
251 datagram->address.physical.slave = 0x0000; |
254 EC_WRITE_U16(datagram->address, 0x0000); |
252 datagram->address.physical.mem = offset; |
255 EC_WRITE_U16(datagram->address + 2, offset); |
253 EC_FUNC_FOOTER; |
256 EC_FUNC_FOOTER; |
254 } |
257 } |
255 |
258 |
256 /*****************************************************************************/ |
259 /*****************************************************************************/ |
257 |
260 |
269 /**< number of bytes to write */ |
272 /**< number of bytes to write */ |
270 ) |
273 ) |
271 { |
274 { |
272 EC_FUNC_HEADER; |
275 EC_FUNC_HEADER; |
273 datagram->type = EC_DATAGRAM_BWR; |
276 datagram->type = EC_DATAGRAM_BWR; |
274 datagram->address.physical.slave = 0x0000; |
277 EC_WRITE_U16(datagram->address, 0x0000); |
275 datagram->address.physical.mem = offset; |
278 EC_WRITE_U16(datagram->address + 2, offset); |
276 EC_FUNC_FOOTER; |
279 EC_FUNC_FOOTER; |
277 } |
280 } |
278 |
281 |
279 /*****************************************************************************/ |
282 /*****************************************************************************/ |
280 |
283 |
292 /**< number of bytes to read/write */ |
295 /**< number of bytes to read/write */ |
293 ) |
296 ) |
294 { |
297 { |
295 EC_FUNC_HEADER; |
298 EC_FUNC_HEADER; |
296 datagram->type = EC_DATAGRAM_LRW; |
299 datagram->type = EC_DATAGRAM_LRW; |
297 datagram->address.logical = offset; |
300 EC_WRITE_U32(datagram->address, offset); |
298 EC_FUNC_FOOTER; |
301 EC_FUNC_FOOTER; |
299 } |
302 } |
300 |
303 |
301 /*****************************************************************************/ |
304 /*****************************************************************************/ |
|
305 |
|
306 /** |
|
307 * Evaluates the working counter of a single-cast datagram. |
|
308 * Outputs an error message. |
|
309 */ |
|
310 |
|
311 void ec_datagram_print_wc_error( |
|
312 const ec_datagram_t *datagram |
|
313 ) |
|
314 { |
|
315 if (datagram->working_counter == 0) |
|
316 printk("No response."); |
|
317 else if (datagram->working_counter > 1) |
|
318 printk("%u slaves responded!", datagram->working_counter); |
|
319 else |
|
320 printk("Success."); |
|
321 printk("\n"); |
|
322 } |
|
323 |
|
324 /*****************************************************************************/ |
|
325 |
|
326 /** |
|
327 * Outputs datagram statistics at most every second. |
|
328 */ |
|
329 |
|
330 void ec_datagram_output_stats( |
|
331 ec_datagram_t *datagram |
|
332 ) |
|
333 { |
|
334 if (jiffies - datagram->stats_output_jiffies < HZ) { |
|
335 datagram->stats_output_jiffies = jiffies; |
|
336 |
|
337 if (unlikely(datagram->skip_count)) { |
|
338 EC_WARN("Datagram %x (%s) was SKIPPED %u time%s.\n", |
|
339 (unsigned int) datagram, datagram->name, |
|
340 datagram->skip_count, |
|
341 datagram->skip_count == 1 ? "" : "s"); |
|
342 datagram->skip_count = 0; |
|
343 } |
|
344 } |
|
345 } |
|
346 |
|
347 /*****************************************************************************/ |