66 uint16_t sdo_index, /**< SDO index */ |
67 uint16_t sdo_index, /**< SDO index */ |
67 uint8_t sdo_subindex, /**< SDO subindex */ |
68 uint8_t sdo_subindex, /**< SDO subindex */ |
68 uint8_t *target /**< 4-byte memory */ |
69 uint8_t *target /**< 4-byte memory */ |
69 ) |
70 ) |
70 { |
71 { |
|
72 ec_command_t command; |
71 size_t rec_size; |
73 size_t rec_size; |
72 uint8_t *data; |
74 uint8_t *data; |
73 |
75 |
74 if (!(data = ec_slave_mbox_prepare_send(slave, 0x03, 6))) return -1; |
76 ec_command_init(&command); |
|
77 |
|
78 if (!(data = ec_slave_mbox_prepare_send(slave, &command, 0x03, 6))) |
|
79 goto err; |
75 |
80 |
76 EC_WRITE_U16(data, 0x2 << 12); // SDO request |
81 EC_WRITE_U16(data, 0x2 << 12); // SDO request |
77 EC_WRITE_U8 (data + 2, (0x1 << 1 // expedited transfer |
82 EC_WRITE_U8 (data + 2, (0x1 << 1 // expedited transfer |
78 | 0x2 << 5)); // initiate upload request |
83 | 0x2 << 5)); // initiate upload request |
79 EC_WRITE_U16(data + 3, sdo_index); |
84 EC_WRITE_U16(data + 3, sdo_index); |
80 EC_WRITE_U8 (data + 5, sdo_subindex); |
85 EC_WRITE_U8 (data + 5, sdo_subindex); |
81 |
86 |
82 if (!(data = ec_slave_mbox_simple_io(slave, &rec_size))) return -1; |
87 if (!(data = ec_slave_mbox_simple_io(slave, &command, &rec_size))) |
|
88 goto err; |
83 |
89 |
84 if (EC_READ_U16(data) >> 12 == 0x2 && // SDO request |
90 if (EC_READ_U16(data) >> 12 == 0x2 && // SDO request |
85 EC_READ_U8 (data + 2) >> 5 == 0x4) { // abort SDO transfer request |
91 EC_READ_U8 (data + 2) >> 5 == 0x4) { // abort SDO transfer request |
86 EC_ERR("SDO upload 0x%04X:%X aborted on slave %i.\n", |
92 EC_ERR("SDO upload 0x%04X:%X aborted on slave %i.\n", |
87 sdo_index, sdo_subindex, slave->ring_position); |
93 sdo_index, sdo_subindex, slave->ring_position); |
88 ec_canopen_abort_msg(EC_READ_U32(data + 6)); |
94 ec_canopen_abort_msg(EC_READ_U32(data + 6)); |
89 return -1; |
95 goto err; |
90 } |
96 } |
91 |
97 |
92 if (EC_READ_U16(data) >> 12 != 0x3 || // SDO response |
98 if (EC_READ_U16(data) >> 12 != 0x3 || // SDO response |
93 EC_READ_U8 (data + 2) >> 5 != 0x2 || // upload response |
99 EC_READ_U8 (data + 2) >> 5 != 0x2 || // upload response |
94 EC_READ_U16(data + 3) != sdo_index || // index |
100 EC_READ_U16(data + 3) != sdo_index || // index |
95 EC_READ_U8 (data + 5) != sdo_subindex) { // subindex |
101 EC_READ_U8 (data + 5) != sdo_subindex) { // subindex |
96 EC_ERR("SDO upload 0x%04X:%X failed:\n", sdo_index, sdo_subindex); |
102 EC_ERR("SDO upload 0x%04X:%X failed:\n", sdo_index, sdo_subindex); |
97 EC_ERR("Invalid SDO upload response at slave %i!\n", |
103 EC_ERR("Invalid SDO upload response at slave %i!\n", |
98 slave->ring_position); |
104 slave->ring_position); |
99 ec_print_data(data, rec_size); |
105 ec_print_data(data, rec_size); |
100 return -1; |
106 goto err; |
101 } |
107 } |
102 |
108 |
103 memcpy(target, data + 6, 4); |
109 memcpy(target, data + 6, 4); |
104 return 0; |
110 |
|
111 ec_command_clear(&command); |
|
112 return 0; |
|
113 err: |
|
114 ec_command_clear(&command); |
|
115 return -1; |
105 } |
116 } |
106 |
117 |
107 /*****************************************************************************/ |
118 /*****************************************************************************/ |
108 |
119 |
109 /** |
120 /** |
118 size_t size /**< Data size in bytes (1 - 4) */ |
129 size_t size /**< Data size in bytes (1 - 4) */ |
119 ) |
130 ) |
120 { |
131 { |
121 uint8_t *data; |
132 uint8_t *data; |
122 size_t rec_size; |
133 size_t rec_size; |
|
134 ec_command_t command; |
|
135 |
|
136 ec_command_init(&command); |
123 |
137 |
124 if (size == 0 || size > 4) { |
138 if (size == 0 || size > 4) { |
125 EC_ERR("Invalid data size!\n"); |
139 EC_ERR("Invalid data size!\n"); |
126 return -1; |
140 goto err; |
127 } |
141 } |
128 |
142 |
129 if (!(data = ec_slave_mbox_prepare_send(slave, 0x03, 0x0A))) return -1; |
143 if (!(data = ec_slave_mbox_prepare_send(slave, &command, 0x03, 0x0A))) |
|
144 goto err; |
130 |
145 |
131 EC_WRITE_U16(data, 0x2 << 12); // SDO request |
146 EC_WRITE_U16(data, 0x2 << 12); // SDO request |
132 EC_WRITE_U8 (data + 2, (0x1 // size specified |
147 EC_WRITE_U8 (data + 2, (0x1 // size specified |
133 | 0x1 << 1 // expedited transfer |
148 | 0x1 << 1 // expedited transfer |
134 | (4 - size) << 2 // data set size |
149 | (4 - size) << 2 // data set size |
136 EC_WRITE_U16(data + 3, sdo_index); |
151 EC_WRITE_U16(data + 3, sdo_index); |
137 EC_WRITE_U8 (data + 5, sdo_subindex); |
152 EC_WRITE_U8 (data + 5, sdo_subindex); |
138 memcpy(data + 6, sdo_data, size); |
153 memcpy(data + 6, sdo_data, size); |
139 if (size < 4) memset(data + 6 + size, 0x00, 4 - size); |
154 if (size < 4) memset(data + 6 + size, 0x00, 4 - size); |
140 |
155 |
141 if (!(data = ec_slave_mbox_simple_io(slave, &rec_size))) return -1; |
156 if (!(data = ec_slave_mbox_simple_io(slave, &command, &rec_size))) |
|
157 goto err; |
142 |
158 |
143 if (EC_READ_U16(data) >> 12 == 0x2 && // SDO request |
159 if (EC_READ_U16(data) >> 12 == 0x2 && // SDO request |
144 EC_READ_U8 (data + 2) >> 5 == 0x4) { // abort SDO transfer request |
160 EC_READ_U8 (data + 2) >> 5 == 0x4) { // abort SDO transfer request |
145 EC_ERR("SDO download 0x%04X:%X (%i bytes) aborted on slave %i.\n", |
161 EC_ERR("SDO download 0x%04X:%X (%i bytes) aborted on slave %i.\n", |
146 sdo_index, sdo_subindex, size, slave->ring_position); |
162 sdo_index, sdo_subindex, size, slave->ring_position); |
180 ) |
200 ) |
181 { |
201 { |
182 uint8_t *data; |
202 uint8_t *data; |
183 size_t rec_size, data_size; |
203 size_t rec_size, data_size; |
184 uint32_t complete_size; |
204 uint32_t complete_size; |
185 |
205 ec_command_t command; |
186 if (!(data = ec_slave_mbox_prepare_send(slave, 0x03, 6))) return -1; |
206 |
|
207 ec_command_init(&command); |
|
208 |
|
209 if (!(data = ec_slave_mbox_prepare_send(slave, &command, 0x03, 6))) |
|
210 goto err; |
187 |
211 |
188 EC_WRITE_U16(data, 0x2 << 12); // SDO request |
212 EC_WRITE_U16(data, 0x2 << 12); // SDO request |
189 EC_WRITE_U8 (data + 2, 0x2 << 5); // initiate upload request |
213 EC_WRITE_U8 (data + 2, 0x2 << 5); // initiate upload request |
190 EC_WRITE_U16(data + 3, sdo_index); |
214 EC_WRITE_U16(data + 3, sdo_index); |
191 EC_WRITE_U8 (data + 5, sdo_subindex); |
215 EC_WRITE_U8 (data + 5, sdo_subindex); |
192 |
216 |
193 if (!(data = ec_slave_mbox_simple_io(slave, &rec_size))) return -1; |
217 if (!(data = ec_slave_mbox_simple_io(slave, &command, &rec_size))) |
|
218 goto err; |
194 |
219 |
195 if (EC_READ_U16(data) >> 12 == 0x2 && // SDO request |
220 if (EC_READ_U16(data) >> 12 == 0x2 && // SDO request |
196 EC_READ_U8 (data + 2) >> 5 == 0x4) { // abort SDO transfer request |
221 EC_READ_U8 (data + 2) >> 5 == 0x4) { // abort SDO transfer request |
197 EC_ERR("SDO upload 0x%04X:%X aborted on slave %i.\n", |
222 EC_ERR("SDO upload 0x%04X:%X aborted on slave %i.\n", |
198 sdo_index, sdo_subindex, slave->ring_position); |
223 sdo_index, sdo_subindex, slave->ring_position); |
199 ec_canopen_abort_msg(EC_READ_U32(data + 6)); |
224 ec_canopen_abort_msg(EC_READ_U32(data + 6)); |
200 return -1; |
225 goto err; |
201 } |
226 } |
202 |
227 |
203 if (EC_READ_U16(data) >> 12 != 0x3 || // SDO response |
228 if (EC_READ_U16(data) >> 12 != 0x3 || // SDO response |
204 EC_READ_U8 (data + 2) >> 5 != 0x2 || // initiate upload response |
229 EC_READ_U8 (data + 2) >> 5 != 0x2 || // initiate upload response |
205 EC_READ_U16(data + 3) != sdo_index || // index |
230 EC_READ_U16(data + 3) != sdo_index || // index |
206 EC_READ_U8 (data + 5) != sdo_subindex) { // subindex |
231 EC_READ_U8 (data + 5) != sdo_subindex) { // subindex |
207 EC_ERR("SDO upload 0x%04X:%X failed:\n", sdo_index, sdo_subindex); |
232 EC_ERR("SDO upload 0x%04X:%X failed:\n", sdo_index, sdo_subindex); |
208 EC_ERR("Invalid SDO upload response at slave %i!\n", |
233 EC_ERR("Invalid SDO upload response at slave %i!\n", |
209 slave->ring_position); |
234 slave->ring_position); |
210 ec_print_data(data, rec_size); |
235 ec_print_data(data, rec_size); |
211 return -1; |
236 goto err; |
212 } |
237 } |
213 |
238 |
214 if (rec_size < 10) { |
239 if (rec_size < 10) { |
215 EC_ERR("Received currupted SDO upload response!\n"); |
240 EC_ERR("Received currupted SDO upload response!\n"); |
216 ec_print_data(data, rec_size); |
241 ec_print_data(data, rec_size); |
217 return -1; |
242 goto err; |
218 } |
243 } |
219 |
244 |
220 if ((complete_size = EC_READ_U32(data + 6)) > *size) { |
245 if ((complete_size = EC_READ_U32(data + 6)) > *size) { |
221 EC_ERR("SDO data does not fit into buffer (%i / %i)!\n", |
246 EC_ERR("SDO data does not fit into buffer (%i / %i)!\n", |
222 complete_size, *size); |
247 complete_size, *size); |
223 return -1; |
248 goto err; |
224 } |
249 } |
225 |
250 |
226 data_size = rec_size - 10; |
251 data_size = rec_size - 10; |
227 |
252 |
228 if (data_size != complete_size) { |
253 if (data_size != complete_size) { |
229 EC_ERR("SDO data incomplete - Fragmenting not implemented.\n"); |
254 EC_ERR("SDO data incomplete - Fragmenting not implemented.\n"); |
230 return -1; |
255 goto err; |
231 } |
256 } |
232 |
257 |
233 memcpy(target, data + 10, data_size); |
258 memcpy(target, data + 10, data_size); |
234 return 0; |
259 |
|
260 ec_command_clear(&command); |
|
261 return 0; |
|
262 err: |
|
263 ec_command_clear(&command); |
|
264 return -1; |
235 } |
265 } |
236 |
266 |
237 /*****************************************************************************/ |
267 /*****************************************************************************/ |
238 |
268 |
239 /** |
269 /** |
246 uint8_t *data; |
276 uint8_t *data; |
247 size_t rec_size; |
277 size_t rec_size; |
248 unsigned int i, sdo_count; |
278 unsigned int i, sdo_count; |
249 ec_sdo_t *sdo; |
279 ec_sdo_t *sdo; |
250 uint16_t sdo_index; |
280 uint16_t sdo_index; |
251 |
281 ec_command_t command; |
252 if (!(data = ec_slave_mbox_prepare_send(slave, 0x03, 8))) return -1; |
282 |
|
283 ec_command_init(&command); |
|
284 |
|
285 if (!(data = ec_slave_mbox_prepare_send(slave, &command, 0x03, 8))) |
|
286 goto err; |
253 |
287 |
254 EC_WRITE_U16(data, 0x8 << 12); // SDO information |
288 EC_WRITE_U16(data, 0x8 << 12); // SDO information |
255 EC_WRITE_U8 (data + 2, 0x01); // Get OD List Request |
289 EC_WRITE_U8 (data + 2, 0x01); // Get OD List Request |
256 EC_WRITE_U8 (data + 3, 0x00); |
290 EC_WRITE_U8 (data + 3, 0x00); |
257 EC_WRITE_U16(data + 4, 0x0000); |
291 EC_WRITE_U16(data + 4, 0x0000); |
258 EC_WRITE_U16(data + 6, 0x0001); // deliver all SDOs! |
292 EC_WRITE_U16(data + 6, 0x0001); // deliver all SDOs! |
259 |
293 |
260 if (unlikely(ec_master_simple_io(slave->master, &slave->mbox_command))) { |
294 if (unlikely(ec_master_simple_io(slave->master, &command))) { |
261 EC_ERR("Mailbox checking failed on slave %i!\n", slave->ring_position); |
295 EC_ERR("Mailbox checking failed on slave %i!\n", slave->ring_position); |
262 return -1; |
296 goto err; |
263 } |
297 } |
264 |
298 |
265 do { |
299 do { |
266 if (!(data = ec_slave_mbox_simple_receive(slave, 0x03, &rec_size))) |
300 if (!(data = ec_slave_mbox_simple_receive(slave, &command, |
267 return -1; |
301 0x03, &rec_size))) |
|
302 goto err; |
268 |
303 |
269 if (EC_READ_U16(data) >> 12 == 0x8 && // SDO information |
304 if (EC_READ_U16(data) >> 12 == 0x8 && // SDO information |
270 (EC_READ_U8(data + 2) & 0x7F) == 0x07) { // error response |
305 (EC_READ_U8(data + 2) & 0x7F) == 0x07) { // error response |
271 EC_ERR("SDO information error response at slave %i!\n", |
306 EC_ERR("SDO information error response at slave %i!\n", |
272 slave->ring_position); |
307 slave->ring_position); |
273 ec_canopen_abort_msg(EC_READ_U32(data + 6)); |
308 ec_canopen_abort_msg(EC_READ_U32(data + 6)); |
274 return -1; |
309 goto err; |
275 } |
310 } |
276 |
311 |
277 if (EC_READ_U16(data) >> 12 != 0x8 || // SDO information |
312 if (EC_READ_U16(data) >> 12 != 0x8 || // SDO information |
278 (EC_READ_U8 (data + 2) & 0x7F) != 0x02) { // Get OD List response |
313 (EC_READ_U8 (data + 2) & 0x7F) != 0x02) { // Get OD List response |
279 EC_ERR("Invalid SDO list response at slave %i!\n", |
314 EC_ERR("Invalid SDO list response at slave %i!\n", |
280 slave->ring_position); |
315 slave->ring_position); |
281 ec_print_data(data, rec_size); |
316 ec_print_data(data, rec_size); |
282 return -1; |
317 goto err; |
283 } |
318 } |
284 |
319 |
285 if (rec_size < 8) { |
320 if (rec_size < 8) { |
286 EC_ERR("Invalid data size!\n"); |
321 EC_ERR("Invalid data size!\n"); |
287 ec_print_data(data, rec_size); |
322 ec_print_data(data, rec_size); |
288 return -1; |
323 goto err; |
289 } |
324 } |
290 |
325 |
291 sdo_count = (rec_size - 8) / 2; |
326 sdo_count = (rec_size - 8) / 2; |
292 for (i = 0; i < sdo_count; i++) { |
327 for (i = 0; i < sdo_count; i++) { |
293 sdo_index = EC_READ_U16(data + 8 + i * 2); |
328 sdo_index = EC_READ_U16(data + 8 + i * 2); |
294 if (!sdo_index) continue; // sometimes index is 0... ??? |
329 if (!sdo_index) continue; // sometimes index is 0... ??? |
295 |
330 |
296 if (!(sdo = (ec_sdo_t *) kmalloc(sizeof(ec_sdo_t), GFP_KERNEL))) { |
331 if (!(sdo = (ec_sdo_t *) kmalloc(sizeof(ec_sdo_t), GFP_KERNEL))) { |
297 EC_ERR("Failed to allocate memory for SDO!\n"); |
332 EC_ERR("Failed to allocate memory for SDO!\n"); |
298 return -1; |
333 goto err; |
299 } |
334 } |
300 |
335 |
301 // Initialize SDO object |
336 // Initialize SDO object |
302 sdo->index = sdo_index; |
337 sdo->index = sdo_index; |
303 //sdo->unkown = 0x0000; |
338 //sdo->unkown = 0x0000; |
309 } |
344 } |
310 } |
345 } |
311 while (EC_READ_U8(data + 2) & 0x80); |
346 while (EC_READ_U8(data + 2) & 0x80); |
312 |
347 |
313 // Fetch all SDO descriptions |
348 // Fetch all SDO descriptions |
314 if (ec_slave_fetch_sdo_descriptions(slave)) return -1; |
349 if (ec_slave_fetch_sdo_descriptions(slave, &command)) goto err; |
315 |
350 |
316 return 0; |
351 ec_command_clear(&command); |
|
352 return 0; |
|
353 err: |
|
354 ec_command_clear(&command); |
|
355 return -1; |
317 } |
356 } |
318 |
357 |
319 /*****************************************************************************/ |
358 /*****************************************************************************/ |
320 |
359 |
321 /** |
360 /** |
322 Fetches the SDO descriptions for the known SDOs. |
361 Fetches the SDO descriptions for the known SDOs. |
323 \return 0 in case of success, else < 0 |
362 \return 0 in case of success, else < 0 |
324 */ |
363 */ |
325 |
364 |
326 int ec_slave_fetch_sdo_descriptions(ec_slave_t *slave /**< EtherCAT slave */) |
365 int ec_slave_fetch_sdo_descriptions(ec_slave_t *slave, /**< EtherCAT slave */ |
|
366 ec_command_t *command /**< command */ |
|
367 ) |
327 { |
368 { |
328 uint8_t *data; |
369 uint8_t *data; |
329 size_t rec_size, name_size; |
370 size_t rec_size, name_size; |
330 ec_sdo_t *sdo; |
371 ec_sdo_t *sdo; |
331 |
372 |
332 list_for_each_entry(sdo, &slave->sdo_dictionary, list) { |
373 list_for_each_entry(sdo, &slave->sdo_dictionary, list) { |
333 if (!(data = ec_slave_mbox_prepare_send(slave, 0x03, 8))) return -1; |
374 if (!(data = ec_slave_mbox_prepare_send(slave, command, 0x03, 8))) |
|
375 return -1; |
334 EC_WRITE_U16(data, 0x8 << 12); // SDO information |
376 EC_WRITE_U16(data, 0x8 << 12); // SDO information |
335 EC_WRITE_U8 (data + 2, 0x03); // Get object description request |
377 EC_WRITE_U8 (data + 2, 0x03); // Get object description request |
336 EC_WRITE_U8 (data + 3, 0x00); |
378 EC_WRITE_U8 (data + 3, 0x00); |
337 EC_WRITE_U16(data + 4, 0x0000); |
379 EC_WRITE_U16(data + 4, 0x0000); |
338 EC_WRITE_U16(data + 6, sdo->index); // SDO index |
380 EC_WRITE_U16(data + 6, sdo->index); // SDO index |
339 |
381 |
340 if (!(data = ec_slave_mbox_simple_io(slave, &rec_size))) return -1; |
382 if (!(data = ec_slave_mbox_simple_io(slave, command, &rec_size))) |
|
383 return -1; |
341 |
384 |
342 if (EC_READ_U16(data) >> 12 == 0x8 && // SDO information |
385 if (EC_READ_U16(data) >> 12 == 0x8 && // SDO information |
343 (EC_READ_U8 (data + 2) & 0x7F) == 0x07) { // error response |
386 (EC_READ_U8 (data + 2) & 0x7F) == 0x07) { // error response |
344 EC_ERR("SDO information error response at slave %i while" |
387 EC_ERR("SDO information error response at slave %i while" |
345 " fetching SDO 0x%04X!\n", slave->ring_position, |
388 " fetching SDO 0x%04X!\n", slave->ring_position, |
400 Fetches all entries (subindices) to an SDO. |
446 Fetches all entries (subindices) to an SDO. |
401 \return 0 in case of success, else < 0 |
447 \return 0 in case of success, else < 0 |
402 */ |
448 */ |
403 |
449 |
404 int ec_slave_fetch_sdo_entries(ec_slave_t *slave, /**< EtherCAT slave */ |
450 int ec_slave_fetch_sdo_entries(ec_slave_t *slave, /**< EtherCAT slave */ |
|
451 ec_command_t *command, /**< command */ |
405 ec_sdo_t *sdo, /**< SDO */ |
452 ec_sdo_t *sdo, /**< SDO */ |
406 uint8_t subindices /**< number of subindices */ |
453 uint8_t subindices /**< number of subindices */ |
407 ) |
454 ) |
408 { |
455 { |
409 uint8_t *data; |
456 uint8_t *data; |
410 size_t rec_size, data_size; |
457 size_t rec_size, data_size; |
411 uint8_t i; |
458 uint8_t i; |
412 ec_sdo_entry_t *entry; |
459 ec_sdo_entry_t *entry; |
413 |
460 |
414 for (i = 1; i <= subindices; i++) { |
461 for (i = 1; i <= subindices; i++) { |
415 if (!(data = ec_slave_mbox_prepare_send(slave, 0x03, 10))) |
462 if (!(data = ec_slave_mbox_prepare_send(slave, command, 0x03, 10))) |
416 return -1; |
463 return -1; |
417 |
464 |
418 EC_WRITE_U16(data, 0x8 << 12); // SDO information |
465 EC_WRITE_U16(data, 0x8 << 12); // SDO information |
419 EC_WRITE_U8 (data + 2, 0x05); // Get entry description request |
466 EC_WRITE_U8 (data + 2, 0x05); // Get entry description request |
420 EC_WRITE_U8 (data + 3, 0x00); |
467 EC_WRITE_U8 (data + 3, 0x00); |
421 EC_WRITE_U16(data + 4, 0x0000); |
468 EC_WRITE_U16(data + 4, 0x0000); |
422 EC_WRITE_U16(data + 6, sdo->index); // SDO index |
469 EC_WRITE_U16(data + 6, sdo->index); // SDO index |
423 EC_WRITE_U8 (data + 8, i); // SDO subindex |
470 EC_WRITE_U8 (data + 8, i); // SDO subindex |
424 EC_WRITE_U8 (data + 9, 0x00); // value info (no values) |
471 EC_WRITE_U8 (data + 9, 0x00); // value info (no values) |
425 |
472 |
426 if (!(data = ec_slave_mbox_simple_io(slave, &rec_size))) return -1; |
473 if (!(data = ec_slave_mbox_simple_io(slave, command, &rec_size))) |
|
474 return -1; |
427 |
475 |
428 if (EC_READ_U16(data) >> 12 == 0x8 && // SDO information |
476 if (EC_READ_U16(data) >> 12 == 0x8 && // SDO information |
429 (EC_READ_U8 (data + 2) & 0x7F) == 0x07) { // error response |
477 (EC_READ_U8 (data + 2) & 0x7F) == 0x07) { // error response |
430 EC_ERR("SDO information error response at slave %i while" |
478 EC_ERR("SDO information error response at slave %i while" |
431 " fetching SDO entry 0x%04X:%i!\n", slave->ring_position, |
479 " fetching SDO entry 0x%04X:%i!\n", slave->ring_position, |