27 } |
32 } |
28 ec_sdo_abort_message_t; |
33 ec_sdo_abort_message_t; |
29 |
34 |
30 const ec_sdo_abort_message_t sdo_abort_messages[]; |
35 const ec_sdo_abort_message_t sdo_abort_messages[]; |
31 |
36 |
32 void ec_canopen_abort_msg(uint32_t); |
37 /*****************************************************************************/ |
33 int ec_slave_fetch_sdo_descriptions(ec_slave_t *); |
38 |
34 |
39 /** |
35 /*****************************************************************************/ |
40 Beschreibt ein CANopen-SDO eines Slaves im Expedited-Modus. |
36 |
41 \return 0 wenn alles ok, < 0 bei Fehler |
37 /** |
42 */ |
38 Schreibt ein CANopen-SDO (service data object), expedited. |
43 |
39 */ |
44 int ec_slave_sdo_write_exp(ec_slave_t *slave, /**< EtherCAT-Slave */ |
40 |
45 uint16_t sdo_index, /**< SDO-Index */ |
41 int ecrt_slave_sdo_exp_write(ec_slave_t *slave, /**< EtherCAT-Slave */ |
46 uint8_t sdo_subindex, /**< SDO-Subindex */ |
42 uint16_t sdo_index, /**< SDO-Index */ |
47 const uint8_t *sdo_data, /**< Neuer Wert */ |
43 uint8_t sdo_subindex, /**< SDO-Subindex */ |
48 size_t size |
44 uint32_t value, /**< Neuer Wert */ |
49 ) |
45 size_t size /**< Größe des Datenfeldes */ |
|
46 ) |
|
47 { |
50 { |
48 uint8_t data[0x0A]; |
51 uint8_t data[0x0A]; |
49 unsigned int i; |
|
50 size_t rec_size; |
52 size_t rec_size; |
51 |
53 |
52 if (size == 0 || size > 4) { |
54 if (size == 0 || size > 4) { |
53 EC_ERR("Invalid SDO data size: %i!\n", size); |
55 EC_ERR("Invalid data size!\n"); |
54 return -1; |
56 return -1; |
55 } |
57 } |
56 |
58 |
57 EC_WRITE_U16(data, 0x02 << 12); // Number (0), Service (SDO request) |
59 EC_WRITE_U16(data, 0x2000); // SDO request |
58 EC_WRITE_U8 (data + 2, 0x23 | ((4 - size) << 2)); // Spec., exp., init. |
60 EC_WRITE_U8 (data + 2, 0x23 | (4 - size) << 2); // expedited, size specif. |
59 EC_WRITE_U16(data + 3, sdo_index); |
61 EC_WRITE_U16(data + 3, sdo_index); |
60 EC_WRITE_U8 (data + 5, sdo_subindex); |
62 EC_WRITE_U8 (data + 5, sdo_subindex); |
61 |
63 |
62 for (i = 0; i < size; i++) { |
64 memcpy(data + 6, sdo_data, size); |
63 EC_WRITE_U8(data + 6 + i, value & 0xFF); |
65 if (size < 4) memset(data + 6 + size, 0x00, 4 - size); |
64 value >>= 8; |
|
65 } |
|
66 |
66 |
67 // Mailox senden und empfangen |
67 // Mailox senden und empfangen |
68 if (ec_slave_mailbox_send(slave, 0x03, data, 0x0A)) return -1; |
68 if (ec_slave_mailbox_send(slave, 0x03, data, 0x0A)) return -1; |
69 |
69 |
70 rec_size = 0x0A; |
70 rec_size = 0x0A; |
71 if (ec_slave_mailbox_receive(slave, 0x03, data, &rec_size)) return -1; |
71 if (ec_slave_mailbox_receive(slave, 0x03, data, &rec_size)) return -1; |
72 |
72 |
73 if (EC_READ_U16(data) >> 12 == 0x02 && // SDO request |
73 if (EC_READ_U16(data) >> 12 == 0x02 && // SDO request |
74 EC_READ_U8 (data + 2) >> 5 == 0x04) { // Abort SDO transf. req. |
74 EC_READ_U8 (data + 2) >> 5 == 0x04) { // Abort SDO transfer request |
75 EC_ERR("SDO download of 0x%04X:%X (value %X, size %X) aborted on slave" |
75 EC_ERR("SDO download of 0x%04X:%X (%i bytes) aborted on!" |
76 " %i.\n", sdo_index, sdo_subindex, value, size, |
76 " slave %i.\n", sdo_index, sdo_subindex, size, |
77 slave->ring_position); |
77 slave->ring_position); |
78 ec_canopen_abort_msg(EC_READ_U32(data + 6)); |
78 ec_canopen_abort_msg(EC_READ_U32(data + 6)); |
79 return -1; |
79 return -1; |
80 } |
80 } |
81 |
81 |
93 } |
93 } |
94 |
94 |
95 /*****************************************************************************/ |
95 /*****************************************************************************/ |
96 |
96 |
97 /** |
97 /** |
98 Liest ein CANopen-SDO (service data object), expedited. |
98 Liest 32-Bit eines CANopen-SDOs im Expedited-Modus aus einem Slave. |
99 */ |
99 \return 0 wenn alles ok, < 0 bei Fehler |
100 |
100 */ |
101 int ecrt_slave_sdo_exp_read(ec_slave_t *slave, /**< EtherCAT-Slave */ |
101 |
102 uint16_t sdo_index, /**< SDO-Index */ |
102 int ec_slave_sdo_read_exp(ec_slave_t *slave, /**< EtherCAT-Slave */ |
103 uint8_t sdo_subindex, /**< SDO-Subindex */ |
103 uint16_t sdo_index, /**< SDO-Index */ |
104 uint32_t *value /**< Speicher für gel. Wert */ |
104 uint8_t sdo_subindex, /**< SDO-Subindex */ |
105 ) |
105 uint8_t *target /**< Speicher für 4 Bytes */ |
|
106 ) |
106 { |
107 { |
107 uint8_t data[0x20]; |
108 uint8_t data[0x20]; |
108 size_t rec_size; |
109 size_t rec_size; |
109 |
110 |
110 EC_WRITE_U16(data, 0x2000); // Number (0), Service = SDO request |
111 EC_WRITE_U16(data, 0x2000); // SDO request |
111 EC_WRITE_U8 (data + 2, 0x1 << 1 | 0x2 << 5); // Expedited upload request |
112 EC_WRITE_U8 (data + 2, 0x42); // Upload request, expedited |
112 EC_WRITE_U16(data + 3, sdo_index); |
113 EC_WRITE_U16(data + 3, sdo_index); |
113 EC_WRITE_U8 (data + 5, sdo_subindex); |
114 EC_WRITE_U8 (data + 5, sdo_subindex); |
114 |
115 |
115 if (ec_slave_mailbox_send(slave, 0x03, data, 6)) return -1; |
116 if (ec_slave_mailbox_send(slave, 0x03, data, 6)) return -1; |
116 |
117 |
132 EC_ERR("Invalid SDO upload response at slave %i!\n", |
133 EC_ERR("Invalid SDO upload response at slave %i!\n", |
133 slave->ring_position); |
134 slave->ring_position); |
134 return -1; |
135 return -1; |
135 } |
136 } |
136 |
137 |
137 *value = EC_READ_U32(data + 6); |
138 memcpy(target, data + 6, 4); |
138 return 0; |
139 return 0; |
139 } |
140 } |
140 |
141 |
141 /*****************************************************************************/ |
142 /*****************************************************************************/ |
142 |
143 |
143 /** |
144 /** |
144 Liest ein CANopen-SDO (service data object). |
145 Liest ein CANopen-SDO aus einem Slave. |
|
146 \return 0 wenn alles ok, < 0 bei Fehler |
145 */ |
147 */ |
146 |
148 |
147 int ecrt_slave_sdo_read(ec_slave_t *slave, /**< EtherCAT-Slave */ |
149 int ecrt_slave_sdo_read(ec_slave_t *slave, /**< EtherCAT-Slave */ |
148 uint16_t sdo_index, /**< SDO-Index */ |
150 uint16_t sdo_index, /**< SDO-Index */ |
149 uint8_t sdo_subindex, /**< SDO-Subindex */ |
151 uint8_t sdo_subindex, /**< SDO-Subindex */ |
153 { |
155 { |
154 uint8_t data[0x20]; |
156 uint8_t data[0x20]; |
155 size_t rec_size, data_size; |
157 size_t rec_size, data_size; |
156 uint32_t complete_size; |
158 uint32_t complete_size; |
157 |
159 |
158 EC_WRITE_U16(data, 0x2000); // Number (0), Service = SDO request |
160 EC_WRITE_U16(data, 0x2000); // SDO request |
159 EC_WRITE_U8 (data + 2, 0x2 << 5); // Initiate upload request |
161 EC_WRITE_U8 (data + 2, 0x2 << 5); // Initiate upload request |
160 EC_WRITE_U16(data + 3, sdo_index); |
162 EC_WRITE_U16(data + 3, sdo_index); |
161 EC_WRITE_U8 (data + 5, sdo_subindex); |
163 EC_WRITE_U8 (data + 5, sdo_subindex); |
162 |
164 |
163 if (ec_slave_mailbox_send(slave, 0x03, data, 6)) return -1; |
165 if (ec_slave_mailbox_send(slave, 0x03, data, 6)) return -1; |
207 } |
209 } |
208 |
210 |
209 /*****************************************************************************/ |
211 /*****************************************************************************/ |
210 |
212 |
211 /** |
213 /** |
212 Schreibt ein CANopen-SDO (Angabe des Masters und der Adresse), expedited. |
|
213 |
|
214 Siehe ecrt_slave_sdo_exp_write() |
|
215 |
|
216 \return 0 wenn alles ok, < 0 bei Fehler |
|
217 */ |
|
218 |
|
219 int ecrt_master_sdo_exp_write(ec_master_t *master, |
|
220 /**< EtherCAT-Master */ |
|
221 const char *addr, |
|
222 /**< Addresse, siehe ec_master_slave_address() */ |
|
223 uint16_t index, |
|
224 /**< SDO-Index */ |
|
225 uint8_t subindex, |
|
226 /**< SDO-Subindex */ |
|
227 uint32_t value, |
|
228 /**< Neuer Wert */ |
|
229 size_t size |
|
230 /**< Größe des Datenfeldes */ |
|
231 ) |
|
232 { |
|
233 ec_slave_t *slave; |
|
234 if (!(slave = ec_master_slave_address(master, addr))) return -1; |
|
235 return ecrt_slave_sdo_exp_write(slave, index, subindex, value, size); |
|
236 } |
|
237 |
|
238 /*****************************************************************************/ |
|
239 |
|
240 /** |
|
241 Liest ein CANopen-SDO (Angabe des Masters und der Adresse), expedited. |
|
242 |
|
243 Siehe ecrt_slave_sdo_exp_read() |
|
244 |
|
245 \return 0 wenn alles ok, < 0 bei Fehler |
|
246 */ |
|
247 |
|
248 int ecrt_master_sdo_exp_read(ec_master_t *master, |
|
249 /**< EtherCAT-Slave */ |
|
250 const char *addr, |
|
251 /**< Addresse, siehe ec_master_slave_address() */ |
|
252 uint16_t index, |
|
253 /**< SDO-Index */ |
|
254 uint8_t subindex, |
|
255 /**< SDO-Subindex */ |
|
256 uint32_t *value |
|
257 /**< Speicher für gel. Wert */ |
|
258 ) |
|
259 { |
|
260 ec_slave_t *slave; |
|
261 if (!(slave = ec_master_slave_address(master, addr))) return -1; |
|
262 return ecrt_slave_sdo_exp_read(slave, index, subindex, value); |
|
263 } |
|
264 |
|
265 /*****************************************************************************/ |
|
266 |
|
267 /** |
|
268 Liest ein CANopen-SDO (Angabe des Masters und der Adresse), expedited. |
|
269 |
|
270 Siehe ecrt_slave_sdo_exp_read() |
|
271 |
|
272 \return 0 wenn alles ok, < 0 bei Fehler |
|
273 */ |
|
274 |
|
275 int ecrt_master_sdo_read(ec_master_t *master, /**< EtherCAT-Master */ |
|
276 const char *addr, /**< Addresse, siehe |
|
277 ec_master_slave_address() */ |
|
278 uint16_t sdo_index, /**< SDO-Index */ |
|
279 uint8_t sdo_subindex, /**< SDO-Subindex */ |
|
280 uint8_t *target, /**< Speicher für gel. Wert */ |
|
281 size_t *size /**< Größe des Speichers */ |
|
282 ) |
|
283 { |
|
284 ec_slave_t *slave; |
|
285 if (!(slave = ec_master_slave_address(master, addr))) return -1; |
|
286 return ecrt_slave_sdo_read(slave, sdo_index, sdo_subindex, target, size); |
|
287 } |
|
288 |
|
289 /*****************************************************************************/ |
|
290 |
|
291 /** |
|
292 Holt das Object-Dictionary aus dem Slave. |
214 Holt das Object-Dictionary aus dem Slave. |
293 |
|
294 \return 0, wenn alles ok, sonst < 0 |
215 \return 0, wenn alles ok, sonst < 0 |
295 */ |
216 */ |
296 |
217 |
297 int ec_slave_fetch_sdo_list(ec_slave_t *slave /**< EtherCAT-Slave */) |
218 int ec_slave_fetch_sdo_list(ec_slave_t *slave /**< EtherCAT-Slave */) |
298 { |
219 { |
300 size_t rec_size; |
221 size_t rec_size; |
301 unsigned int i, sdo_count; |
222 unsigned int i, sdo_count; |
302 ec_sdo_t *sdo; |
223 ec_sdo_t *sdo; |
303 uint16_t sdo_index; |
224 uint16_t sdo_index; |
304 |
225 |
305 EC_WRITE_U16(data, 0x8000); // Number (0), Service = SDO information |
226 EC_WRITE_U16(data, 0x8000); // SDO information |
306 EC_WRITE_U8 (data + 2, 0x01); // Get OD List Request |
227 EC_WRITE_U8 (data + 2, 0x01); // Get OD List Request |
307 EC_WRITE_U8 (data + 3, 0x00); // res. |
228 EC_WRITE_U8 (data + 3, 0x00); |
308 EC_WRITE_U16(data + 4, 0x0000); // fragments left |
229 EC_WRITE_U16(data + 4, 0x0000); |
309 EC_WRITE_U16(data + 6, 0x0001); // Deliver all SDOs! |
230 EC_WRITE_U16(data + 6, 0x0001); // Deliver all SDOs! |
310 |
231 |
311 if (ec_slave_mailbox_send(slave, 0x03, data, 8)) return -1; |
232 if (ec_slave_mailbox_send(slave, 0x03, data, 8)) return -1; |
312 |
233 |
313 do { |
234 do { |
368 uint8_t data[0xF0]; |
289 uint8_t data[0xF0]; |
369 size_t rec_size, name_size; |
290 size_t rec_size, name_size; |
370 ec_sdo_t *sdo; |
291 ec_sdo_t *sdo; |
371 |
292 |
372 list_for_each_entry(sdo, &slave->sdo_dictionary, list) { |
293 list_for_each_entry(sdo, &slave->sdo_dictionary, list) { |
373 EC_WRITE_U16(data, 0x8000); // Number (0), Service = SDO inform. |
294 EC_WRITE_U16(data, 0x8000); // SDO information |
374 EC_WRITE_U8 (data + 2, 0x03); // Get object description request |
295 EC_WRITE_U8 (data + 2, 0x03); // Get object description request |
375 EC_WRITE_U8 (data + 3, 0x00); // res. |
296 EC_WRITE_U8 (data + 3, 0x00); |
376 EC_WRITE_U16(data + 4, 0x0000); // fragments left |
297 EC_WRITE_U16(data + 4, 0x0000); |
377 EC_WRITE_U16(data + 6, sdo->index); // SDO index |
298 EC_WRITE_U16(data + 6, sdo->index); // SDO index |
|
299 |
378 if (ec_slave_mailbox_send(slave, 0x03, data, 8)) return -1; |
300 if (ec_slave_mailbox_send(slave, 0x03, data, 8)) return -1; |
379 |
301 |
380 rec_size = 0xF0; |
302 rec_size = 0xF0; |
381 if (ec_slave_mailbox_receive(slave, 0x03, data, &rec_size)) |
303 if (ec_slave_mailbox_receive(slave, 0x03, data, &rec_size)) |
382 return -1; |
304 return -1; |
487 " dictionary is present"}, |
409 " dictionary is present"}, |
488 {} |
410 {} |
489 }; |
411 }; |
490 |
412 |
491 /*****************************************************************************/ |
413 /*****************************************************************************/ |
492 |
414 // Echtzeitschnittstelle |
493 EXPORT_SYMBOL(ecrt_slave_sdo_exp_write); |
415 |
494 EXPORT_SYMBOL(ecrt_slave_sdo_exp_read); |
416 /*****************************************************************************/ |
|
417 |
|
418 /** |
|
419 Liest ein 8-Bit CANopen-SDO im Expedited-Modus aus einem Slave. |
|
420 Siehe ec_slave_sdo_read_exp() |
|
421 \return 0 wenn alles ok, < 0 bei Fehler |
|
422 */ |
|
423 |
|
424 int ecrt_slave_sdo_read_exp8(ec_slave_t *slave, /**< EtherCAT-Slave */ |
|
425 uint16_t sdo_index, /**< SDO-Index */ |
|
426 uint8_t sdo_subindex, /**< SDO-Subindex */ |
|
427 uint8_t *target /**< Speicher für gel. Wert */ |
|
428 ) |
|
429 { |
|
430 uint8_t data[4]; |
|
431 if (ec_slave_sdo_read_exp(slave, sdo_index, sdo_subindex, data)) return -1; |
|
432 *target = EC_READ_U8(data); |
|
433 return 0; |
|
434 } |
|
435 |
|
436 /*****************************************************************************/ |
|
437 |
|
438 /** |
|
439 Liest ein 16-Bit CANopen-SDO im Expedited-Modus aus einem Slave. |
|
440 Siehe ec_slave_sdo_read_exp() |
|
441 \return 0 wenn alles ok, < 0 bei Fehler |
|
442 */ |
|
443 |
|
444 int ecrt_slave_sdo_read_exp16(ec_slave_t *slave, /**< EtherCAT-Slave */ |
|
445 uint16_t sdo_index, /**< SDO-Index */ |
|
446 uint8_t sdo_subindex, /**< SDO-Subindex */ |
|
447 uint16_t *target /**< Speicher für gel. Wert */ |
|
448 ) |
|
449 { |
|
450 uint8_t data[4]; |
|
451 if (ec_slave_sdo_read_exp(slave, sdo_index, sdo_subindex, data)) return -1; |
|
452 *target = EC_READ_U16(data); |
|
453 return 0; |
|
454 } |
|
455 |
|
456 /*****************************************************************************/ |
|
457 |
|
458 /** |
|
459 Liest ein 32-Bit CANopen-SDO im Expedited-Modus aus einem Slave. |
|
460 Siehe ec_slave_sdo_read_exp() |
|
461 \return 0 wenn alles ok, < 0 bei Fehler |
|
462 */ |
|
463 |
|
464 int ecrt_slave_sdo_read_exp32(ec_slave_t *slave, /**< EtherCAT-Slave */ |
|
465 uint16_t sdo_index, /**< SDO-Index */ |
|
466 uint8_t sdo_subindex, /**< SDO-Subindex */ |
|
467 uint32_t *target /**< Speicher für gel. Wert */ |
|
468 ) |
|
469 { |
|
470 uint8_t data[4]; |
|
471 if (ec_slave_sdo_read_exp(slave, sdo_index, sdo_subindex, data)) return -1; |
|
472 *target = EC_READ_U32(data); |
|
473 return 0; |
|
474 } |
|
475 |
|
476 /*****************************************************************************/ |
|
477 |
|
478 /** |
|
479 Beschreibt ein 8-Bit CANopen-SDO eines Slaves im Expedited-Modus. |
|
480 \return 0 wenn alles ok, < 0 bei Fehler |
|
481 */ |
|
482 |
|
483 int ecrt_slave_sdo_write_exp8(ec_slave_t *slave, /**< EtherCAT-Slave */ |
|
484 uint16_t sdo_index, /**< SDO-Index */ |
|
485 uint8_t sdo_subindex, /**< SDO-Subindex */ |
|
486 uint8_t value /**< Neuer Wert */ |
|
487 ) |
|
488 { |
|
489 return ec_slave_sdo_write_exp(slave, sdo_index, sdo_subindex, &value, 1); |
|
490 } |
|
491 |
|
492 /*****************************************************************************/ |
|
493 |
|
494 /** |
|
495 Beschreibt ein 16-Bit CANopen-SDO eines Slaves im Expedited-Modus. |
|
496 \return 0 wenn alles ok, < 0 bei Fehler |
|
497 */ |
|
498 |
|
499 int ecrt_slave_sdo_write_exp16(ec_slave_t *slave, /**< EtherCAT-Slave */ |
|
500 uint16_t sdo_index, /**< SDO-Index */ |
|
501 uint8_t sdo_subindex, /**< SDO-Subindex */ |
|
502 uint16_t value /**< Neuer Wert */ |
|
503 ) |
|
504 { |
|
505 uint8_t data[2]; |
|
506 EC_WRITE_U16(data, value); |
|
507 return ec_slave_sdo_write_exp(slave, sdo_index, sdo_subindex, data, 2); |
|
508 } |
|
509 |
|
510 /*****************************************************************************/ |
|
511 |
|
512 /** |
|
513 Beschreibt ein 32-Bit CANopen-SDO eines Slaves im Expedited-Modus. |
|
514 \return 0 wenn alles ok, < 0 bei Fehler |
|
515 */ |
|
516 |
|
517 int ecrt_slave_sdo_write_exp32(ec_slave_t *slave, /**< EtherCAT-Slave */ |
|
518 uint16_t sdo_index, /**< SDO-Index */ |
|
519 uint8_t sdo_subindex, /**< SDO-Subindex */ |
|
520 uint32_t value /**< Neuer Wert */ |
|
521 ) |
|
522 { |
|
523 uint8_t data[4]; |
|
524 EC_WRITE_U32(data, value); |
|
525 return ec_slave_sdo_write_exp(slave, sdo_index, sdo_subindex, data, 4); |
|
526 } |
|
527 |
|
528 /*****************************************************************************/ |
|
529 |
|
530 EXPORT_SYMBOL(ecrt_slave_sdo_read_exp8); |
|
531 EXPORT_SYMBOL(ecrt_slave_sdo_read_exp16); |
|
532 EXPORT_SYMBOL(ecrt_slave_sdo_read_exp32); |
|
533 EXPORT_SYMBOL(ecrt_slave_sdo_write_exp8); |
|
534 EXPORT_SYMBOL(ecrt_slave_sdo_write_exp16); |
|
535 EXPORT_SYMBOL(ecrt_slave_sdo_write_exp32); |
495 EXPORT_SYMBOL(ecrt_slave_sdo_read); |
536 EXPORT_SYMBOL(ecrt_slave_sdo_read); |
496 EXPORT_SYMBOL(ecrt_master_sdo_exp_write); |
|
497 EXPORT_SYMBOL(ecrt_master_sdo_exp_read); |
|
498 EXPORT_SYMBOL(ecrt_master_sdo_read); |
|
499 |
537 |
500 /*****************************************************************************/ |
538 /*****************************************************************************/ |
501 |
539 |
502 /* Emacs-Konfiguration |
540 /* Emacs-Konfiguration |
503 ;;; Local Variables: *** |
541 ;;; Local Variables: *** |