61 const ec_code_msg_t al_status_messages[]; |
61 const ec_code_msg_t al_status_messages[]; |
62 |
62 |
63 /*****************************************************************************/ |
63 /*****************************************************************************/ |
64 |
64 |
65 /** |
65 /** |
66 EtherCAT-Slave-Konstruktor. |
66 Slave constructor. |
67 */ |
67 \return 0 in case of success, else < 0 |
68 |
68 */ |
69 int ec_slave_init(ec_slave_t *slave, /**< EtherCAT-Slave */ |
69 |
70 ec_master_t *master, /**< EtherCAT-Master */ |
70 int ec_slave_init(ec_slave_t *slave, /**< EtherCAT slave */ |
71 uint16_t ring_position, /**< Ringposition */ |
71 ec_master_t *master, /**< EtherCAT master */ |
72 uint16_t station_address /**< Programmierte Adresse */ |
72 uint16_t ring_position, /**< ring position */ |
|
73 uint16_t station_address /**< station address to configure */ |
73 ) |
74 ) |
74 { |
75 { |
75 unsigned int i; |
76 unsigned int i; |
76 |
77 |
77 slave->ring_position = ring_position; |
78 slave->ring_position = ring_position; |
78 slave->station_address = station_address; |
79 slave->station_address = station_address; |
79 |
80 |
80 // Init kobject and add it to the hierarchy |
81 // init kobject and add it to the hierarchy |
81 memset(&slave->kobj, 0x00, sizeof(struct kobject)); |
82 memset(&slave->kobj, 0x00, sizeof(struct kobject)); |
82 kobject_init(&slave->kobj); |
83 kobject_init(&slave->kobj); |
83 slave->kobj.ktype = &ktype_ec_slave; |
84 slave->kobj.ktype = &ktype_ec_slave; |
84 slave->kobj.parent = &master->kobj; |
85 slave->kobj.parent = &master->kobj; |
85 if (kobject_set_name(&slave->kobj, "slave%03i", slave->ring_position)) { |
86 if (kobject_set_name(&slave->kobj, "slave%03i", slave->ring_position)) { |
131 } |
132 } |
132 |
133 |
133 /*****************************************************************************/ |
134 /*****************************************************************************/ |
134 |
135 |
135 /** |
136 /** |
136 EtherCAT-Slave-Destruktor. |
137 Slave destructor. |
137 */ |
138 */ |
138 |
139 |
139 void ec_slave_clear(struct kobject *kobj /**< KObject des Slaves */) |
140 void ec_slave_clear(struct kobject *kobj /**< kobject of the slave */) |
140 { |
141 { |
141 ec_slave_t *slave; |
142 ec_slave_t *slave; |
142 ec_eeprom_string_t *string, *next_str; |
143 ec_eeprom_string_t *string, *next_str; |
143 ec_eeprom_sync_t *sync, *next_sync; |
144 ec_eeprom_sync_t *sync, *next_sync; |
144 ec_eeprom_pdo_t *pdo, *next_pdo; |
145 ec_eeprom_pdo_t *pdo, *next_pdo; |
146 ec_sdo_t *sdo, *next_sdo; |
147 ec_sdo_t *sdo, *next_sdo; |
147 ec_sdo_entry_t *en, *next_en; |
148 ec_sdo_entry_t *en, *next_en; |
148 |
149 |
149 slave = container_of(kobj, ec_slave_t, kobj); |
150 slave = container_of(kobj, ec_slave_t, kobj); |
150 |
151 |
151 // Alle Strings freigeben |
152 // free all string objects |
152 list_for_each_entry_safe(string, next_str, &slave->eeprom_strings, list) { |
153 list_for_each_entry_safe(string, next_str, &slave->eeprom_strings, list) { |
153 list_del(&string->list); |
154 list_del(&string->list); |
154 kfree(string); |
155 kfree(string); |
155 } |
156 } |
156 |
157 |
157 // Alle Sync-Manager freigeben |
158 // free all sync managers |
158 list_for_each_entry_safe(sync, next_sync, &slave->eeprom_syncs, list) { |
159 list_for_each_entry_safe(sync, next_sync, &slave->eeprom_syncs, list) { |
159 list_del(&sync->list); |
160 list_del(&sync->list); |
160 kfree(sync); |
161 kfree(sync); |
161 } |
162 } |
162 |
163 |
163 // Alle PDOs freigeben |
164 // free all PDOs |
164 list_for_each_entry_safe(pdo, next_pdo, &slave->eeprom_pdos, list) { |
165 list_for_each_entry_safe(pdo, next_pdo, &slave->eeprom_pdos, list) { |
165 list_del(&pdo->list); |
166 list_del(&pdo->list); |
166 if (pdo->name) kfree(pdo->name); |
167 if (pdo->name) kfree(pdo->name); |
167 |
168 |
168 // Alle Entries innerhalb eines PDOs freigeben |
169 // free all PDO entries |
169 list_for_each_entry_safe(entry, next_ent, &pdo->entries, list) { |
170 list_for_each_entry_safe(entry, next_ent, &pdo->entries, list) { |
170 list_del(&entry->list); |
171 list_del(&entry->list); |
171 if (entry->name) kfree(entry->name); |
172 if (entry->name) kfree(entry->name); |
172 kfree(entry); |
173 kfree(entry); |
173 } |
174 } |
177 |
178 |
178 if (slave->eeprom_name) kfree(slave->eeprom_name); |
179 if (slave->eeprom_name) kfree(slave->eeprom_name); |
179 if (slave->eeprom_group) kfree(slave->eeprom_group); |
180 if (slave->eeprom_group) kfree(slave->eeprom_group); |
180 if (slave->eeprom_desc) kfree(slave->eeprom_desc); |
181 if (slave->eeprom_desc) kfree(slave->eeprom_desc); |
181 |
182 |
182 // Alle SDOs freigeben |
183 // free all SDOs |
183 list_for_each_entry_safe(sdo, next_sdo, &slave->sdo_dictionary, list) { |
184 list_for_each_entry_safe(sdo, next_sdo, &slave->sdo_dictionary, list) { |
184 list_del(&sdo->list); |
185 list_del(&sdo->list); |
185 if (sdo->name) kfree(sdo->name); |
186 if (sdo->name) kfree(sdo->name); |
186 |
187 |
187 // Alle Entries freigeben |
188 // free all SDO entries |
188 list_for_each_entry_safe(en, next_en, &sdo->entries, list) { |
189 list_for_each_entry_safe(en, next_en, &sdo->entries, list) { |
189 list_del(&en->list); |
190 list_del(&en->list); |
190 kfree(en); |
191 kfree(en); |
191 } |
192 } |
192 kfree(sdo); |
193 kfree(sdo); |
196 } |
197 } |
197 |
198 |
198 /*****************************************************************************/ |
199 /*****************************************************************************/ |
199 |
200 |
200 /** |
201 /** |
201 Liest alle benötigten Informationen aus einem Slave. |
202 Reads all necessary information from a slave. |
202 |
203 \return 0 in case of success, else < 0 |
203 \return 0 wenn alles ok, < 0 bei Fehler. |
204 */ |
204 */ |
205 |
205 |
206 int ec_slave_fetch(ec_slave_t *slave /**< EtherCAT slave */) |
206 int ec_slave_fetch(ec_slave_t *slave /**< EtherCAT-Slave */) |
|
207 { |
207 { |
208 ec_command_t *command; |
208 ec_command_t *command; |
209 unsigned int i; |
209 unsigned int i; |
210 uint16_t dl_status; |
210 uint16_t dl_status; |
211 |
211 |
212 command = &slave->master->simple_command; |
212 command = &slave->master->simple_command; |
213 |
213 |
214 // Read base data |
214 // read base data |
215 if (ec_command_nprd(command, slave->station_address, 0x0000, 6)) return -1; |
215 if (ec_command_nprd(command, slave->station_address, 0x0000, 6)) return -1; |
216 if (unlikely(ec_master_simple_io(slave->master, command))) { |
216 if (unlikely(ec_master_simple_io(slave->master, command))) { |
217 EC_ERR("Reading base data from slave %i failed!\n", |
217 EC_ERR("Reading base data from slave %i failed!\n", |
218 slave->ring_position); |
218 slave->ring_position); |
219 return -1; |
219 return -1; |
226 slave->base_sync_count = EC_READ_U8 (command->data + 5); |
226 slave->base_sync_count = EC_READ_U8 (command->data + 5); |
227 |
227 |
228 if (slave->base_fmmu_count > EC_MAX_FMMUS) |
228 if (slave->base_fmmu_count > EC_MAX_FMMUS) |
229 slave->base_fmmu_count = EC_MAX_FMMUS; |
229 slave->base_fmmu_count = EC_MAX_FMMUS; |
230 |
230 |
231 // Read DL status |
231 // read data link status |
232 if (ec_command_nprd(command, slave->station_address, 0x0110, 2)) return -1; |
232 if (ec_command_nprd(command, slave->station_address, 0x0110, 2)) return -1; |
233 if (unlikely(ec_master_simple_io(slave->master, command))) { |
233 if (unlikely(ec_master_simple_io(slave->master, command))) { |
234 EC_ERR("Reading DL status from slave %i failed!\n", |
234 EC_ERR("Reading DL status from slave %i failed!\n", |
235 slave->ring_position); |
235 slave->ring_position); |
236 return -1; |
236 return -1; |
241 slave->dl_link[i] = dl_status & (1 << (4 + i)) ? 1 : 0; |
241 slave->dl_link[i] = dl_status & (1 << (4 + i)) ? 1 : 0; |
242 slave->dl_loop[i] = dl_status & (1 << (8 + i * 2)) ? 1 : 0; |
242 slave->dl_loop[i] = dl_status & (1 << (8 + i * 2)) ? 1 : 0; |
243 slave->dl_signal[i] = dl_status & (1 << (9 + i * 2)) ? 1 : 0; |
243 slave->dl_signal[i] = dl_status & (1 << (9 + i * 2)) ? 1 : 0; |
244 } |
244 } |
245 |
245 |
246 // Read EEPROM data |
246 // read EEPROM data |
247 if (ec_slave_sii_read16(slave, 0x0004, &slave->sii_alias)) |
247 if (ec_slave_sii_read16(slave, 0x0004, &slave->sii_alias)) |
248 return -1; |
248 return -1; |
249 if (ec_slave_sii_read32(slave, 0x0008, &slave->sii_vendor_id)) |
249 if (ec_slave_sii_read32(slave, 0x0008, &slave->sii_vendor_id)) |
250 return -1; |
250 return -1; |
251 if (ec_slave_sii_read32(slave, 0x000A, &slave->sii_product_code)) |
251 if (ec_slave_sii_read32(slave, 0x000A, &slave->sii_product_code)) |
274 } |
274 } |
275 |
275 |
276 /*****************************************************************************/ |
276 /*****************************************************************************/ |
277 |
277 |
278 /** |
278 /** |
279 Liest 16 Bit aus dem Slave-Information-Interface |
279 Reads 16 bit from the slave information interface (SII). |
280 eines EtherCAT-Slaves. |
280 \return 0 in case of success, else < 0 |
281 |
|
282 \return 0 bei Erfolg, sonst < 0 |
|
283 */ |
281 */ |
284 |
282 |
285 int ec_slave_sii_read16(ec_slave_t *slave, |
283 int ec_slave_sii_read16(ec_slave_t *slave, |
286 /**< EtherCAT-Slave */ |
284 /**< EtherCAT slave */ |
287 uint16_t offset, |
285 uint16_t offset, |
288 /**< Adresse des zu lesenden SII-Registers */ |
286 /**< address of the SII register to read */ |
289 uint16_t *target |
287 uint16_t *target |
290 /**< Speicher für Wert (16-Bit) */ |
288 /**< target memory */ |
291 ) |
289 ) |
292 { |
290 { |
293 ec_command_t *command; |
291 ec_command_t *command; |
294 cycles_t start, end, timeout; |
292 cycles_t start, end, timeout; |
295 |
293 |
296 command = &slave->master->simple_command; |
294 command = &slave->master->simple_command; |
297 |
295 |
298 // Initiate read operation |
296 // initiate read operation |
299 if (ec_command_npwr(command, slave->station_address, 0x502, 6)) return -1; |
297 if (ec_command_npwr(command, slave->station_address, 0x502, 6)) return -1; |
300 EC_WRITE_U8 (command->data, 0x00); // read-only access |
298 EC_WRITE_U8 (command->data, 0x00); // read-only access |
301 EC_WRITE_U8 (command->data + 1, 0x01); // request read operation |
299 EC_WRITE_U8 (command->data + 1, 0x01); // request read operation |
302 EC_WRITE_U32(command->data + 2, offset); |
300 EC_WRITE_U32(command->data + 2, offset); |
303 if (unlikely(ec_master_simple_io(slave->master, command))) { |
301 if (unlikely(ec_master_simple_io(slave->master, command))) { |
304 EC_ERR("SII-read failed on slave %i!\n", slave->ring_position); |
302 EC_ERR("SII-read failed on slave %i!\n", slave->ring_position); |
305 return -1; |
303 return -1; |
306 } |
304 } |
307 |
305 |
308 // Der Slave legt die Informationen des Slave-Information-Interface |
|
309 // in das Datenregister und löscht daraufhin ein Busy-Bit. Solange |
|
310 // den Status auslesen, bis das Bit weg ist. |
|
311 |
|
312 start = get_cycles(); |
306 start = get_cycles(); |
313 timeout = (cycles_t) 100 * cpu_khz; // 100ms |
307 timeout = (cycles_t) 100 * cpu_khz; // 100ms |
314 |
308 |
315 while (1) |
309 while (1) |
316 { |
310 { |
339 } |
334 } |
340 |
335 |
341 /*****************************************************************************/ |
336 /*****************************************************************************/ |
342 |
337 |
343 /** |
338 /** |
344 Liest 32 Bit aus dem Slave-Information-Interface |
339 Reads 32 bit from the slave information interface (SII). |
345 eines EtherCAT-Slaves. |
340 \return 0 in case of success, else < 0 |
346 |
|
347 \return 0 bei Erfolg, sonst < 0 |
|
348 */ |
341 */ |
349 |
342 |
350 int ec_slave_sii_read32(ec_slave_t *slave, |
343 int ec_slave_sii_read32(ec_slave_t *slave, |
351 /**< EtherCAT-Slave */ |
344 /**< EtherCAT slave */ |
352 uint16_t offset, |
345 uint16_t offset, |
353 /**< Adresse des zu lesenden SII-Registers */ |
346 /**< address of the SII register to read */ |
354 uint32_t *target |
347 uint32_t *target |
355 /**< Speicher für Wert (32-Bit) */ |
348 /**< target memory */ |
356 ) |
349 ) |
357 { |
350 { |
358 ec_command_t *command; |
351 ec_command_t *command; |
359 cycles_t start, end, timeout; |
352 cycles_t start, end, timeout; |
360 |
353 |
361 command = &slave->master->simple_command; |
354 command = &slave->master->simple_command; |
362 |
355 |
363 // Initiate read operation |
356 // initiate read operation |
364 if (ec_command_npwr(command, slave->station_address, 0x502, 6)) return -1; |
357 if (ec_command_npwr(command, slave->station_address, 0x502, 6)) return -1; |
365 EC_WRITE_U8 (command->data, 0x00); // read-only access |
358 EC_WRITE_U8 (command->data, 0x00); // read-only access |
366 EC_WRITE_U8 (command->data + 1, 0x01); // request read operation |
359 EC_WRITE_U8 (command->data + 1, 0x01); // request read operation |
367 EC_WRITE_U32(command->data + 2, offset); |
360 EC_WRITE_U32(command->data + 2, offset); |
368 if (unlikely(ec_master_simple_io(slave->master, command))) { |
361 if (unlikely(ec_master_simple_io(slave->master, command))) { |
369 EC_ERR("SII-read failed on slave %i!\n", slave->ring_position); |
362 EC_ERR("SII-read failed on slave %i!\n", slave->ring_position); |
370 return -1; |
363 return -1; |
371 } |
364 } |
372 |
365 |
373 // Der Slave legt die Informationen des Slave-Information-Interface |
|
374 // in das Datenregister und löscht daraufhin ein Busy-Bit. Solange |
|
375 // den Status auslesen, bis das Bit weg ist. |
|
376 |
|
377 start = get_cycles(); |
366 start = get_cycles(); |
378 timeout = (cycles_t) 100 * cpu_khz; // 100ms |
367 timeout = (cycles_t) 100 * cpu_khz; // 100ms |
379 |
368 |
380 while (1) |
369 while (1) |
381 { |
370 { |
404 } |
394 } |
405 |
395 |
406 /*****************************************************************************/ |
396 /*****************************************************************************/ |
407 |
397 |
408 /** |
398 /** |
409 Schreibt 16 Bit Daten in das Slave-Information-Interface |
399 Writes 16 bit of data to the slave information interface (SII). |
410 eines EtherCAT-Slaves. |
400 \return 0 in case of success, else < 0 |
411 |
|
412 \return 0 bei Erfolg, sonst < 0 |
|
413 */ |
401 */ |
414 |
402 |
415 int ec_slave_sii_write16(ec_slave_t *slave, |
403 int ec_slave_sii_write16(ec_slave_t *slave, |
416 /**< EtherCAT-Slave */ |
404 /**< EtherCAT slave */ |
417 uint16_t offset, |
405 uint16_t offset, |
418 /**< Adresse des zu lesenden SII-Registers */ |
406 /**< address of the SII register to write */ |
419 uint16_t value |
407 uint16_t value |
420 /**< Zu schreibender Wert */ |
408 /**< new value */ |
421 ) |
409 ) |
422 { |
410 { |
423 ec_command_t *command; |
411 ec_command_t *command; |
424 cycles_t start, end, timeout; |
412 cycles_t start, end, timeout; |
425 |
413 |
426 command = &slave->master->simple_command; |
414 command = &slave->master->simple_command; |
427 |
415 |
428 EC_INFO("SII-write (slave %i, offset 0x%04X, value 0x%04X)\n", |
416 EC_INFO("SII-write (slave %i, offset 0x%04X, value 0x%04X)\n", |
429 slave->ring_position, offset, value); |
417 slave->ring_position, offset, value); |
430 |
418 |
431 // Initiate write operation |
419 // initiate write operation |
432 if (ec_command_npwr(command, slave->station_address, 0x502, 8)) return -1; |
420 if (ec_command_npwr(command, slave->station_address, 0x502, 8)) return -1; |
433 EC_WRITE_U8 (command->data, 0x01); // enable write access |
421 EC_WRITE_U8 (command->data, 0x01); // enable write access |
434 EC_WRITE_U8 (command->data + 1, 0x02); // request write operation |
422 EC_WRITE_U8 (command->data + 1, 0x02); // request write operation |
435 EC_WRITE_U32(command->data + 2, offset); |
423 EC_WRITE_U32(command->data + 2, offset); |
436 EC_WRITE_U16(command->data + 6, value); |
424 EC_WRITE_U16(command->data + 6, value); |
437 if (unlikely(ec_master_simple_io(slave->master, command))) { |
425 if (unlikely(ec_master_simple_io(slave->master, command))) { |
438 EC_ERR("SII-write failed on slave %i!\n", slave->ring_position); |
426 EC_ERR("SII-write failed on slave %i!\n", slave->ring_position); |
439 return -1; |
427 return -1; |
440 } |
428 } |
441 |
429 |
442 // Der Slave legt die Informationen des Slave-Information-Interface |
|
443 // in das Datenregister und löscht daraufhin ein Busy-Bit. Solange |
|
444 // den Status auslesen, bis das Bit weg ist. |
|
445 |
|
446 start = get_cycles(); |
430 start = get_cycles(); |
447 timeout = (cycles_t) 100 * cpu_khz; // 100ms |
431 timeout = (cycles_t) 100 * cpu_khz; // 100ms |
448 |
432 |
449 while (1) |
433 while (1) |
450 { |
434 { |
479 } |
464 } |
480 |
465 |
481 /*****************************************************************************/ |
466 /*****************************************************************************/ |
482 |
467 |
483 /** |
468 /** |
484 Holt Daten aus dem EEPROM. |
469 Fetches data from slave's EEPROM. |
485 |
470 \return 0 in case of success, else < 0 |
486 \return 0, wenn alles ok, sonst < 0 |
471 */ |
487 */ |
472 |
488 |
473 int ec_slave_fetch_categories(ec_slave_t *slave /**< EtherCAT slave */) |
489 int ec_slave_fetch_categories(ec_slave_t *slave /**< EtherCAT-Slave */) |
|
490 { |
474 { |
491 uint16_t word_offset, cat_type, word_count; |
475 uint16_t word_offset, cat_type, word_count; |
492 uint32_t value; |
476 uint32_t value; |
493 uint8_t *cat_data; |
477 uint8_t *cat_data; |
494 unsigned int i; |
478 unsigned int i; |
505 if (ec_slave_sii_read32(slave, word_offset, &value)) { |
489 if (ec_slave_sii_read32(slave, word_offset, &value)) { |
506 EC_ERR("Unable to read category header.\n"); |
490 EC_ERR("Unable to read category header.\n"); |
507 goto out_free; |
491 goto out_free; |
508 } |
492 } |
509 |
493 |
510 // Last category? |
494 // last category? |
511 if ((value & 0xFFFF) == 0xFFFF) break; |
495 if ((value & 0xFFFF) == 0xFFFF) break; |
512 |
496 |
513 cat_type = value & 0x7FFF; |
497 cat_type = value & 0x7FFF; |
514 word_count = (value >> 16) & 0xFFFF; |
498 word_count = (value >> 16) & 0xFFFF; |
515 |
499 |
516 // Fetch category data |
500 // fetch category data |
517 for (i = 0; i < word_count; i++) { |
501 for (i = 0; i < word_count; i++) { |
518 if (ec_slave_sii_read32(slave, word_offset + 2 + i, &value)) { |
502 if (ec_slave_sii_read32(slave, word_offset + 2 + i, &value)) { |
519 EC_ERR("Unable to read category data word %i.\n", i); |
503 EC_ERR("Unable to read category data word %i.\n", i); |
520 goto out_free; |
504 goto out_free; |
521 } |
505 } |
572 } |
556 } |
573 |
557 |
574 /*****************************************************************************/ |
558 /*****************************************************************************/ |
575 |
559 |
576 /** |
560 /** |
577 Holt die Daten einer String-Kategorie. |
561 Fetches data from a STRING category. |
578 |
562 \return 0 in case of success, else < 0 |
579 \return 0 wenn alles ok, sonst < 0 |
563 */ |
580 */ |
564 |
581 |
565 int ec_slave_fetch_strings(ec_slave_t *slave, /**< EtherCAT slave */ |
582 int ec_slave_fetch_strings(ec_slave_t *slave, /**< EtherCAT-Slave */ |
566 const uint8_t *data /**< category data */ |
583 const uint8_t *data /**< Kategoriedaten */ |
|
584 ) |
567 ) |
585 { |
568 { |
586 unsigned int string_count, i; |
569 unsigned int string_count, i; |
587 size_t size; |
570 size_t size; |
588 off_t offset; |
571 off_t offset; |
590 |
573 |
591 string_count = data[0]; |
574 string_count = data[0]; |
592 offset = 1; |
575 offset = 1; |
593 for (i = 0; i < string_count; i++) { |
576 for (i = 0; i < string_count; i++) { |
594 size = data[offset]; |
577 size = data[offset]; |
595 // Speicher für String-Objekt und Daten in einem Rutsch allozieren |
578 // allocate memory for string structure and data at a single blow |
596 if (!(string = (ec_eeprom_string_t *) |
579 if (!(string = (ec_eeprom_string_t *) |
597 kmalloc(sizeof(ec_eeprom_string_t) + size + 1, GFP_KERNEL))) { |
580 kmalloc(sizeof(ec_eeprom_string_t) + size + 1, GFP_KERNEL))) { |
598 EC_ERR("Failed to allocate string memory.\n"); |
581 EC_ERR("Failed to allocate string memory.\n"); |
599 return -1; |
582 return -1; |
600 } |
583 } |
611 } |
594 } |
612 |
595 |
613 /*****************************************************************************/ |
596 /*****************************************************************************/ |
614 |
597 |
615 /** |
598 /** |
616 Holt die Daten einer General-Kategorie. |
599 Fetches data from a GENERAL category. |
617 */ |
600 \return 0 in case of success, else < 0 |
618 |
601 */ |
619 int ec_slave_fetch_general(ec_slave_t *slave, /**< EtherCAT-Slave */ |
602 |
620 const uint8_t *data /**< Kategorie-Daten */ |
603 int ec_slave_fetch_general(ec_slave_t *slave, /**< EtherCAT slave */ |
|
604 const uint8_t *data /**< category data */ |
621 ) |
605 ) |
622 { |
606 { |
623 unsigned int i; |
607 unsigned int i; |
624 |
608 |
625 if (ec_slave_locate_string(slave, data[0], &slave->eeprom_group)) |
609 if (ec_slave_locate_string(slave, data[0], &slave->eeprom_group)) |
628 return -1; |
612 return -1; |
629 if (ec_slave_locate_string(slave, data[3], &slave->eeprom_desc)) |
613 if (ec_slave_locate_string(slave, data[3], &slave->eeprom_desc)) |
630 return -1; |
614 return -1; |
631 |
615 |
632 for (i = 0; i < 4; i++) |
616 for (i = 0; i < 4; i++) |
633 slave->sii_physical_layer[i] = (data[4] & (0x03 << (i * 2))) >> (i * 2); |
617 slave->sii_physical_layer[i] = |
|
618 (data[4] & (0x03 << (i * 2))) >> (i * 2); |
634 |
619 |
635 return 0; |
620 return 0; |
636 } |
621 } |
637 |
622 |
638 /*****************************************************************************/ |
623 /*****************************************************************************/ |
639 |
624 |
640 /** |
625 /** |
641 Holt die Daten einer Sync-Manager-Kategorie. |
626 Fetches data from a SYNC MANAGER category. |
642 */ |
627 \return 0 in case of success, else < 0 |
643 |
628 */ |
644 int ec_slave_fetch_sync(ec_slave_t *slave, /**< EtherCAT-Slave */ |
629 |
645 const uint8_t *data, /**< Kategorie-Daten */ |
630 int ec_slave_fetch_sync(ec_slave_t *slave, /**< EtherCAT slave */ |
646 size_t word_count /**< Anzahl Words */ |
631 const uint8_t *data, /**< category data */ |
|
632 size_t word_count /**< number of words */ |
647 ) |
633 ) |
648 { |
634 { |
649 unsigned int sync_count, i; |
635 unsigned int sync_count, i; |
650 ec_eeprom_sync_t *sync; |
636 ec_eeprom_sync_t *sync; |
651 |
637 |
652 sync_count = word_count / 4; // Sync-Manager-Strunktur ist 4 Worte lang |
638 sync_count = word_count / 4; // sync manager struct is 4 words long |
653 |
639 |
654 for (i = 0; i < sync_count; i++, data += 8) { |
640 for (i = 0; i < sync_count; i++, data += 8) { |
655 if (!(sync = (ec_eeprom_sync_t *) |
641 if (!(sync = (ec_eeprom_sync_t *) |
656 kmalloc(sizeof(ec_eeprom_sync_t), GFP_KERNEL))) { |
642 kmalloc(sizeof(ec_eeprom_sync_t), GFP_KERNEL))) { |
657 EC_ERR("Failed to allocate Sync-Manager memory.\n"); |
643 EC_ERR("Failed to allocate Sync-Manager memory.\n"); |
671 } |
657 } |
672 |
658 |
673 /*****************************************************************************/ |
659 /*****************************************************************************/ |
674 |
660 |
675 /** |
661 /** |
676 Holt die Daten einer TXPDO-Kategorie. |
662 Fetches data from a [RT]XPDO category. |
677 */ |
663 \return 0 in case of success, else < 0 |
678 |
664 */ |
679 int ec_slave_fetch_pdo(ec_slave_t *slave, /**< EtherCAT-Slave */ |
665 |
680 const uint8_t *data, /**< Kategorie-Daten */ |
666 int ec_slave_fetch_pdo(ec_slave_t *slave, /**< EtherCAT slave */ |
681 size_t word_count, /**< Anzahl Worte */ |
667 const uint8_t *data, /**< category data */ |
682 ec_pdo_type_t pdo_type /**< PDO-Typ */ |
668 size_t word_count, /**< number of words */ |
|
669 ec_pdo_type_t pdo_type /**< PDO type */ |
683 ) |
670 ) |
684 { |
671 { |
685 ec_eeprom_pdo_t *pdo; |
672 ec_eeprom_pdo_t *pdo; |
686 ec_eeprom_pdo_entry_t *entry; |
673 ec_eeprom_pdo_entry_t *entry; |
687 unsigned int entry_count, i; |
674 unsigned int entry_count, i; |
776 } |
764 } |
777 |
765 |
778 /*****************************************************************************/ |
766 /*****************************************************************************/ |
779 |
767 |
780 /** |
768 /** |
781 Bestätigt einen Fehler beim Zustandswechsel. |
769 Acknowledges an error after a state transition. |
782 */ |
770 */ |
783 |
771 |
784 void ec_slave_state_ack(ec_slave_t *slave, |
772 void ec_slave_state_ack(ec_slave_t *slave, /**< EtherCAT slave */ |
785 /**< Slave, dessen Zustand geändert werden soll */ |
773 uint8_t state /**< previous state */ |
786 uint8_t state |
|
787 /**< Alter Zustand */ |
|
788 ) |
774 ) |
789 { |
775 { |
790 ec_command_t *command; |
776 ec_command_t *command; |
791 cycles_t start, end, timeout; |
777 cycles_t start, end, timeout; |
792 |
778 |
803 start = get_cycles(); |
789 start = get_cycles(); |
804 timeout = (cycles_t) 10 * cpu_khz; // 10ms |
790 timeout = (cycles_t) 10 * cpu_khz; // 10ms |
805 |
791 |
806 while (1) |
792 while (1) |
807 { |
793 { |
808 udelay(100); // Dem Slave etwas Zeit lassen... |
794 udelay(100); // wait a little bit... |
809 |
795 |
810 if (ec_command_nprd(command, slave->station_address, 0x0130, 2)) |
796 if (ec_command_nprd(command, slave->station_address, 0x0130, 2)) |
811 return; |
797 return; |
812 if (unlikely(ec_master_simple_io(slave->master, command))) { |
798 if (unlikely(ec_master_simple_io(slave->master, command))) { |
813 EC_WARN("Acknowledge checking failed on slave %i!\n", |
799 EC_WARN("Acknowledge checking failed on slave %i!\n", |
833 |
819 |
834 /*****************************************************************************/ |
820 /*****************************************************************************/ |
835 |
821 |
836 /** |
822 /** |
837 Reads the AL status code of a slave and displays it. |
823 Reads the AL status code of a slave and displays it. |
838 |
|
839 If the AL status code is not supported, or if no error occurred (both |
824 If the AL status code is not supported, or if no error occurred (both |
840 resulting in code=0), nothing is displayed. |
825 resulting in code=0), nothing is displayed. |
841 */ |
826 */ |
842 |
827 |
843 void ec_slave_read_al_status_code(ec_slave_t *slave /**< EtherCAT-Slave */) |
828 void ec_slave_read_al_status_code(ec_slave_t *slave /**< EtherCAT slave */) |
844 { |
829 { |
845 ec_command_t *command; |
830 ec_command_t *command; |
846 uint16_t code; |
831 uint16_t code; |
847 const ec_code_msg_t *al_msg; |
832 const ec_code_msg_t *al_msg; |
848 |
833 |
869 } |
854 } |
870 |
855 |
871 /*****************************************************************************/ |
856 /*****************************************************************************/ |
872 |
857 |
873 /** |
858 /** |
874 Ändert den Zustand eines Slaves. |
859 Does a state transition. |
875 |
860 \return 0 in case of success, else < 0 |
876 \return 0 bei Erfolg, sonst < 0 |
861 */ |
877 */ |
862 |
878 |
863 int ec_slave_state_change(ec_slave_t *slave, /**< EtherCAT slave */ |
879 int ec_slave_state_change(ec_slave_t *slave, |
864 uint8_t state /**< new state */ |
880 /**< Slave, dessen Zustand geändert werden soll */ |
|
881 uint8_t state |
|
882 /**< Neuer Zustand */ |
|
883 ) |
865 ) |
884 { |
866 { |
885 ec_command_t *command; |
867 ec_command_t *command; |
886 cycles_t start, end, timeout; |
868 cycles_t start, end, timeout; |
887 |
869 |
898 start = get_cycles(); |
880 start = get_cycles(); |
899 timeout = (cycles_t) 10 * cpu_khz; // 10ms |
881 timeout = (cycles_t) 10 * cpu_khz; // 10ms |
900 |
882 |
901 while (1) |
883 while (1) |
902 { |
884 { |
903 udelay(100); // Dem Slave etwas Zeit lassen... |
885 udelay(100); // wait a little bit |
904 |
886 |
905 if (ec_command_nprd(command, slave->station_address, 0x0130, 2)) |
887 if (ec_command_nprd(command, slave->station_address, 0x0130, 2)) |
906 return -1; |
888 return -1; |
907 if (unlikely(ec_master_simple_io(slave->master, command))) { |
889 if (unlikely(ec_master_simple_io(slave->master, command))) { |
908 EC_ERR("Failed to check state 0x%02X on slave %i!\n", |
890 EC_ERR("Failed to check state 0x%02X on slave %i!\n", |
910 return -1; |
892 return -1; |
911 } |
893 } |
912 |
894 |
913 end = get_cycles(); |
895 end = get_cycles(); |
914 |
896 |
915 if (unlikely(EC_READ_U8(command->data) & 0x10)) { // State change error |
897 if (unlikely(EC_READ_U8(command->data) & 0x10)) { // state change error |
916 EC_ERR("Failed to set state 0x%02X - Slave %i refused state change" |
898 EC_ERR("Failed to set state 0x%02X - Slave %i refused state change" |
917 " (code 0x%02X)!\n", state, slave->ring_position, |
899 " (code 0x%02X)!\n", state, slave->ring_position, |
918 EC_READ_U8(command->data)); |
900 EC_READ_U8(command->data)); |
919 state = EC_READ_U8(command->data) & 0x0F; |
901 state = EC_READ_U8(command->data) & 0x0F; |
920 ec_slave_read_al_status_code(slave); |
902 ec_slave_read_al_status_code(slave); |
921 ec_slave_state_ack(slave, state); |
903 ec_slave_state_ack(slave, state); |
922 return -1; |
904 return -1; |
923 } |
905 } |
924 |
906 |
925 if (likely(EC_READ_U8(command->data) == (state & 0x0F))) { |
907 if (likely(EC_READ_U8(command->data) == (state & 0x0F))) |
926 // State change successful |
908 return 0; // state change successful |
927 return 0; |
|
928 } |
|
929 |
909 |
930 if (unlikely((end - start) >= timeout)) { |
910 if (unlikely((end - start) >= timeout)) { |
931 EC_ERR("Failed to check state 0x%02X of slave %i - Timeout!\n", |
911 EC_ERR("Failed to check state 0x%02X of slave %i - Timeout!\n", |
932 state, slave->ring_position); |
912 state, slave->ring_position); |
933 return -1; |
913 return -1; |
936 } |
916 } |
937 |
917 |
938 /*****************************************************************************/ |
918 /*****************************************************************************/ |
939 |
919 |
940 /** |
920 /** |
941 Merkt eine FMMU-Konfiguration vor. |
921 Prepares an FMMU configuration. |
942 |
922 Configuration data for the FMMU is saved in the slave structure and is |
943 Die FMMU wird so konfiguriert, dass sie den gesamten Datenbereich des |
923 written to the slave in ecrt_master_activate(). |
944 entsprechenden Sync-Managers abdeckt. Für jede Domäne werden separate |
924 The FMMU configuration is done in a way, that the complete data range |
945 FMMUs konfiguriert. |
925 of the corresponding sync manager is covered. Seperate FMMUs arce configured |
946 |
926 for each domain. |
947 Wenn die entsprechende FMMU bereits konfiguriert ist, wird dies als |
927 If the FMMU configuration is already prepared, the function returns with |
948 Erfolg zurückgegeben. |
928 success. |
949 |
929 \return 0 in case of success, else < 0 |
950 \return 0 bei Erfolg, sonst < 0 |
930 */ |
951 */ |
931 |
952 |
932 int ec_slave_prepare_fmmu(ec_slave_t *slave, /**< EtherCAT slave */ |
953 int ec_slave_prepare_fmmu(ec_slave_t *slave, /**< EtherCAT-Slave */ |
933 const ec_domain_t *domain, /**< domain */ |
954 const ec_domain_t *domain, /**< Domäne */ |
934 const ec_sync_t *sync /**< sync manager */ |
955 const ec_sync_t *sync /**< Sync-Manager */ |
|
956 ) |
935 ) |
957 { |
936 { |
958 unsigned int i; |
937 unsigned int i; |
959 |
938 |
960 // FMMU schon vorgemerkt? |
939 // FMMU configuration already prepared? |
961 for (i = 0; i < slave->fmmu_count; i++) |
940 for (i = 0; i < slave->fmmu_count; i++) |
962 if (slave->fmmus[i].domain == domain && slave->fmmus[i].sync == sync) |
941 if (slave->fmmus[i].domain == domain && slave->fmmus[i].sync == sync) |
963 return 0; |
942 return 0; |
964 |
943 |
965 // Neue FMMU reservieren... |
944 // reserve new FMMU... |
966 |
945 |
967 if (slave->fmmu_count >= slave->base_fmmu_count) { |
946 if (slave->fmmu_count >= slave->base_fmmu_count) { |
968 EC_ERR("Slave %i FMMU limit reached!\n", slave->ring_position); |
947 EC_ERR("Slave %i FMMU limit reached!\n", slave->ring_position); |
969 return -1; |
948 return -1; |
970 } |
949 } |
979 } |
958 } |
980 |
959 |
981 /*****************************************************************************/ |
960 /*****************************************************************************/ |
982 |
961 |
983 /** |
962 /** |
984 Gibt alle Informationen über einen EtherCAT-Slave aus. |
963 Outputs all information about a certain slave. |
985 |
|
986 Verbosity: |
964 Verbosity: |
987 0 - Nur Slavetypen und Adressen |
965 - 0: Only slave types and addresses |
988 1 - mit EEPROM-Informationen |
966 - 1: with EEPROM information |
989 >1 - mit SDO-Dictionaries |
967 - >1: with SDO dictionaries |
990 */ |
968 */ |
991 |
969 |
992 void ec_slave_print(const ec_slave_t *slave, /**< EtherCAT-Slave */ |
970 void ec_slave_print(const ec_slave_t *slave, /**< EtherCAT slave */ |
993 unsigned int verbosity /**< Geschwätzigkeit */ |
971 unsigned int verbosity /**< verbosity level */ |
994 ) |
972 ) |
995 { |
973 { |
996 ec_eeprom_sync_t *sync; |
974 ec_eeprom_sync_t *sync; |
997 ec_eeprom_pdo_t *pdo; |
975 ec_eeprom_pdo_t *pdo; |
998 ec_eeprom_pdo_entry_t *pdo_entry; |
976 ec_eeprom_pdo_entry_t *pdo_entry; |
1162 EC_WARN("Reading CRC fault counters failed on slave %i!\n", |
1139 EC_WARN("Reading CRC fault counters failed on slave %i!\n", |
1163 slave->ring_position); |
1140 slave->ring_position); |
1164 return -1; |
1141 return -1; |
1165 } |
1142 } |
1166 |
1143 |
1167 // No CRC faults. |
1144 if (!EC_READ_U32(command->data)) return 0; // no CRC faults |
1168 if (!EC_READ_U32(command->data)) return 0; |
|
1169 |
1145 |
1170 if (EC_READ_U8(command->data)) |
1146 if (EC_READ_U8(command->data)) |
1171 EC_WARN("%3i RX-error%s on slave %i, channel A.\n", |
1147 EC_WARN("%3i RX-error%s on slave %i, channel A.\n", |
1172 EC_READ_U8(command->data), |
1148 EC_READ_U8(command->data), |
1173 EC_READ_U8(command->data) == 1 ? "" : "s", |
1149 EC_READ_U8(command->data) == 1 ? "" : "s", |
1186 EC_WARN("%3i invalid frame%s on slave %i, channel B.\n", |
1162 EC_WARN("%3i invalid frame%s on slave %i, channel B.\n", |
1187 EC_READ_U8(command->data + 3), |
1163 EC_READ_U8(command->data + 3), |
1188 EC_READ_U8(command->data + 3) == 1 ? "" : "s", |
1164 EC_READ_U8(command->data + 3) == 1 ? "" : "s", |
1189 slave->ring_position); |
1165 slave->ring_position); |
1190 |
1166 |
1191 // Reset CRC counters |
1167 // reset CRC counters |
1192 if (ec_command_npwr(command, slave->station_address, 0x0300, 4)) return -1; |
1168 if (ec_command_npwr(command, slave->station_address, 0x0300, 4)) return -1; |
1193 EC_WRITE_U32(command->data, 0x00000000); |
1169 EC_WRITE_U32(command->data, 0x00000000); |
1194 if (unlikely(ec_master_simple_io(slave->master, command))) { |
1170 if (unlikely(ec_master_simple_io(slave->master, command))) { |
1195 EC_WARN("Resetting CRC fault counters failed on slave %i!\n", |
1171 EC_WARN("Resetting CRC fault counters failed on slave %i!\n", |
1196 slave->ring_position); |
1172 slave->ring_position); |
1201 } |
1177 } |
1202 |
1178 |
1203 /*****************************************************************************/ |
1179 /*****************************************************************************/ |
1204 |
1180 |
1205 /** |
1181 /** |
1206 Schreibt den "Configured station alias". |
1182 Writes the "configured station alias" to the slave's EEPROM. |
1207 \return 0, wenn alles ok, sonst < 0 |
1183 \return 0 in case of success, else < 0 |
1208 */ |
1184 */ |
1209 |
1185 |
1210 int ecrt_slave_write_alias(ec_slave_t *slave, /** EtherCAT-Slave */ |
1186 int ecrt_slave_write_alias(ec_slave_t *slave, /** EtherCAT slave */ |
1211 uint16_t alias /** Neuer Alias */ |
1187 uint16_t alias /** new alias */ |
1212 ) |
1188 ) |
1213 { |
1189 { |
1214 return ec_slave_sii_write16(slave, 0x0004, alias); |
1190 return ec_slave_sii_write16(slave, 0x0004, alias); |
1215 } |
1191 } |
1216 |
1192 |
1217 /*****************************************************************************/ |
1193 /*****************************************************************************/ |
1218 |
1194 |
1219 /** |
1195 /** |
1220 Formatiert Attribut-Daten für lesenden Zugriff im SysFS |
1196 Formats attribute data for SysFS read access. |
1221 |
1197 \return number of bytes to read |
1222 \return Anzahl Bytes im Speicher |
1198 */ |
1223 */ |
1199 |
1224 |
1200 ssize_t ec_show_slave_attribute(struct kobject *kobj, /**< slave's kobject */ |
1225 ssize_t ec_show_slave_attribute(struct kobject *kobj, /**< KObject */ |
1201 struct attribute *attr, /**< attribute */ |
1226 struct attribute *attr, /**< Attribut */ |
1202 char *buffer /**< memory to store data */ |
1227 char *buffer /**< Speicher für die Daten */ |
|
1228 ) |
1203 ) |
1229 { |
1204 { |
1230 ec_slave_t *slave = container_of(kobj, ec_slave_t, kobj); |
1205 ec_slave_t *slave = container_of(kobj, ec_slave_t, kobj); |
1231 |
1206 |
1232 if (attr == &attr_ring_position) { |
1207 if (attr == &attr_ring_position) { |