25 |
25 |
26 /*****************************************************************************/ |
26 /*****************************************************************************/ |
27 |
27 |
28 void ec_master_freerun(unsigned long); |
28 void ec_master_freerun(unsigned long); |
29 ssize_t ec_show_master_attribute(struct kobject *, struct attribute *, char *); |
29 ssize_t ec_show_master_attribute(struct kobject *, struct attribute *, char *); |
|
30 void ec_master_process_watch_command(ec_master_t *); |
30 |
31 |
31 /*****************************************************************************/ |
32 /*****************************************************************************/ |
32 |
33 |
33 EC_SYSFS_READ_ATTR(slave_count); |
34 EC_SYSFS_READ_ATTR(slave_count); |
34 EC_SYSFS_READ_ATTR(mode); |
35 EC_SYSFS_READ_ATTR(mode); |
69 INIT_LIST_HEAD(&master->slaves); |
71 INIT_LIST_HEAD(&master->slaves); |
70 INIT_LIST_HEAD(&master->command_queue); |
72 INIT_LIST_HEAD(&master->command_queue); |
71 INIT_LIST_HEAD(&master->domains); |
73 INIT_LIST_HEAD(&master->domains); |
72 INIT_LIST_HEAD(&master->eoe_slaves); |
74 INIT_LIST_HEAD(&master->eoe_slaves); |
73 |
75 |
74 // Init kobject and add it to the hierarchy |
76 // init kobject and add it to the hierarchy |
75 memset(&master->kobj, 0x00, sizeof(struct kobject)); |
77 memset(&master->kobj, 0x00, sizeof(struct kobject)); |
76 kobject_init(&master->kobj); |
78 kobject_init(&master->kobj); |
77 master->kobj.ktype = &ktype_ec_master; |
79 master->kobj.ktype = &ktype_ec_master; |
78 if (kobject_set_name(&master->kobj, "ethercat%i", index)) { |
80 if (kobject_set_name(&master->kobj, "ethercat%i", index)) { |
79 EC_ERR("Failed to set kobj name.\n"); |
81 EC_ERR("Failed to set kobj name.\n"); |
80 kobject_put(&master->kobj); |
82 kobject_put(&master->kobj); |
81 return -1; |
83 return -1; |
82 } |
84 } |
83 |
85 |
84 // Init freerun timer |
86 // init freerun timer |
85 init_timer(&master->freerun_timer); |
87 init_timer(&master->freerun_timer); |
86 master->freerun_timer.function = ec_master_freerun; |
88 master->freerun_timer.function = ec_master_freerun; |
87 master->freerun_timer.data = (unsigned long) master; |
89 master->freerun_timer.data = (unsigned long) master; |
88 |
90 |
89 ec_command_init(&master->simple_command); |
91 ec_command_init(&master->simple_command); |
94 } |
96 } |
95 |
97 |
96 /*****************************************************************************/ |
98 /*****************************************************************************/ |
97 |
99 |
98 /** |
100 /** |
99 Destruktor eines EtherCAT-Masters. |
101 Master destructor. |
100 |
102 Removes all pending commands, clears the slave list, clears all domains |
101 Entfernt alle Kommandos aus der Liste, löscht den Zeiger |
103 and frees the device. |
102 auf das Slave-Array und gibt die Prozessdaten frei. |
104 */ |
103 */ |
105 |
104 |
106 void ec_master_clear(struct kobject *kobj /**< kobject of the master */) |
105 void ec_master_clear(struct kobject *kobj /**< KObject des Masters */) |
|
106 { |
107 { |
107 ec_master_t *master = container_of(kobj, ec_master_t, kobj); |
108 ec_master_t *master = container_of(kobj, ec_master_t, kobj); |
108 |
109 |
109 EC_INFO("Clearing master %i...\n", master->index); |
110 EC_INFO("Clearing master %i...\n", master->index); |
110 |
111 |
124 } |
125 } |
125 |
126 |
126 /*****************************************************************************/ |
127 /*****************************************************************************/ |
127 |
128 |
128 /** |
129 /** |
129 Setzt den Master zurück in den Ausgangszustand. |
130 Resets the master. |
130 |
131 Note: This function has to be called, everytime ec_master_release() is |
131 Bei einem "release" sollte immer diese Funktion aufgerufen werden, |
132 called, to free the slave list, domains etc. |
132 da sonst Slave-Liste, Domains, etc. weiter existieren. |
133 */ |
133 */ |
134 |
134 |
135 void ec_master_reset(ec_master_t *master /**< EtherCAT master */) |
135 void ec_master_reset(ec_master_t *master |
|
136 /**< Zeiger auf den zurückzusetzenden Master */ |
|
137 ) |
|
138 { |
136 { |
139 ec_slave_t *slave, *next_s; |
137 ec_slave_t *slave, *next_s; |
140 ec_command_t *command, *next_c; |
138 ec_command_t *command, *next_c; |
141 ec_domain_t *domain, *next_d; |
139 ec_domain_t *domain, *next_d; |
142 ec_eoe_t *eoe, *next_eoe; |
140 ec_eoe_t *eoe, *next_eoe; |
143 |
141 |
144 ec_master_freerun_stop(master); |
142 ec_master_freerun_stop(master); |
145 |
143 |
146 // Alle Slaves entfernen |
144 // remove all slaves |
147 list_for_each_entry_safe(slave, next_s, &master->slaves, list) { |
145 list_for_each_entry_safe(slave, next_s, &master->slaves, list) { |
148 list_del(&slave->list); |
146 list_del(&slave->list); |
149 kobject_del(&slave->kobj); |
147 kobject_del(&slave->kobj); |
150 kobject_put(&slave->kobj); |
148 kobject_put(&slave->kobj); |
151 } |
149 } |
152 master->slave_count = 0; |
150 master->slave_count = 0; |
153 |
151 |
154 // Kommando-Warteschlange leeren |
152 // empty command queue |
155 list_for_each_entry_safe(command, next_c, &master->command_queue, queue) { |
153 list_for_each_entry_safe(command, next_c, &master->command_queue, queue) { |
156 list_del_init(&command->queue); |
154 list_del_init(&command->queue); |
157 command->state = EC_CMD_ERROR; |
155 command->state = EC_CMD_ERROR; |
158 } |
156 } |
159 |
157 |
160 // Domain-Liste leeren |
158 // clear domains |
161 list_for_each_entry_safe(domain, next_d, &master->domains, list) { |
159 list_for_each_entry_safe(domain, next_d, &master->domains, list) { |
162 list_del(&domain->list); |
160 list_del(&domain->list); |
163 kobject_del(&domain->kobj); |
161 kobject_del(&domain->kobj); |
164 kobject_put(&domain->kobj); |
162 kobject_put(&domain->kobj); |
165 } |
163 } |
166 |
164 |
167 // EOE-Liste leeren |
165 // clear EoE objects |
168 list_for_each_entry_safe(eoe, next_eoe, &master->eoe_slaves, list) { |
166 list_for_each_entry_safe(eoe, next_eoe, &master->eoe_slaves, list) { |
169 list_del(&eoe->list); |
167 list_del(&eoe->list); |
170 ec_eoe_clear(eoe); |
168 ec_eoe_clear(eoe); |
171 kfree(eoe); |
169 kfree(eoe); |
172 } |
170 } |
189 } |
187 } |
190 |
188 |
191 /*****************************************************************************/ |
189 /*****************************************************************************/ |
192 |
190 |
193 /** |
191 /** |
194 Stellt ein Kommando in die Warteschlange. |
192 Places a command in the command queue. |
195 */ |
193 */ |
196 |
194 |
197 void ec_master_queue_command(ec_master_t *master, /**< EtherCAT-Master */ |
195 void ec_master_queue_command(ec_master_t *master, /**< EtherCAT master */ |
198 ec_command_t *command /**< Kommando */ |
196 ec_command_t *command /**< command */ |
199 ) |
197 ) |
200 { |
198 { |
201 ec_command_t *queued_command; |
199 ec_command_t *queued_command; |
202 |
200 |
203 // Ist das Kommando schon in der Warteschlange? |
201 // check, if the command is already queued |
204 list_for_each_entry(queued_command, &master->command_queue, queue) { |
202 list_for_each_entry(queued_command, &master->command_queue, queue) { |
205 if (queued_command == command) { |
203 if (queued_command == command) { |
206 command->state = EC_CMD_QUEUED; |
204 command->state = EC_CMD_QUEUED; |
207 if (unlikely(master->debug_level)) |
205 if (unlikely(master->debug_level)) |
208 EC_WARN("command already queued.\n"); |
206 EC_WARN("command already queued.\n"); |
237 EC_DBG("ec_master_send_commands\n"); |
234 EC_DBG("ec_master_send_commands\n"); |
238 start = get_cycles(); |
235 start = get_cycles(); |
239 } |
236 } |
240 |
237 |
241 do { |
238 do { |
242 // Zeiger auf Socket-Buffer holen |
239 // fetch pointer to transmit socket buffer |
243 frame_data = ec_device_tx_data(master->device); |
240 frame_data = ec_device_tx_data(master->device); |
244 cur_data = frame_data + EC_FRAME_HEADER_SIZE; |
241 cur_data = frame_data + EC_FRAME_HEADER_SIZE; |
245 follows_word = NULL; |
242 follows_word = NULL; |
246 more_commands_waiting = 0; |
243 more_commands_waiting = 0; |
247 |
244 |
248 // Aktuellen Frame mit Kommandos füllen |
245 // fill current frame with commands |
249 list_for_each_entry(command, &master->command_queue, queue) { |
246 list_for_each_entry(command, &master->command_queue, queue) { |
250 if (command->state != EC_CMD_QUEUED) continue; |
247 if (command->state != EC_CMD_QUEUED) continue; |
251 |
248 |
252 // Passt das aktuelle Kommando noch in den aktuellen Rahmen? |
249 // does the current command fit in the frame? |
253 command_size = EC_COMMAND_HEADER_SIZE + command->data_size |
250 command_size = EC_COMMAND_HEADER_SIZE + command->data_size |
254 + EC_COMMAND_FOOTER_SIZE; |
251 + EC_COMMAND_FOOTER_SIZE; |
255 if (cur_data - frame_data + command_size > EC_MAX_FRAME_SIZE) { |
252 if (cur_data - frame_data + command_size > EC_MAX_FRAME_SIZE) { |
256 more_commands_waiting = 1; |
253 more_commands_waiting = 1; |
257 break; |
254 break; |
261 command->index = master->command_index++; |
258 command->index = master->command_index++; |
262 |
259 |
263 if (unlikely(master->debug_level > 0)) |
260 if (unlikely(master->debug_level > 0)) |
264 EC_DBG("adding command 0x%02X\n", command->index); |
261 EC_DBG("adding command 0x%02X\n", command->index); |
265 |
262 |
266 // Command-Following-Flag im letzten Kommando setzen |
263 // set "command following" flag in previous frame |
267 if (follows_word) |
264 if (follows_word) |
268 EC_WRITE_U16(follows_word, EC_READ_U16(follows_word) | 0x8000); |
265 EC_WRITE_U16(follows_word, EC_READ_U16(follows_word) | 0x8000); |
269 |
266 |
270 // EtherCAT command header |
267 // EtherCAT command header |
271 EC_WRITE_U8 (cur_data, command->type); |
268 EC_WRITE_U8 (cur_data, command->type); |
279 // EtherCAT command data |
276 // EtherCAT command data |
280 memcpy(cur_data, command->data, command->data_size); |
277 memcpy(cur_data, command->data, command->data_size); |
281 cur_data += command->data_size; |
278 cur_data += command->data_size; |
282 |
279 |
283 // EtherCAT command footer |
280 // EtherCAT command footer |
284 EC_WRITE_U16(cur_data, 0x0000); // Working counter |
281 EC_WRITE_U16(cur_data, 0x0000); // reset working counter |
285 cur_data += EC_COMMAND_FOOTER_SIZE; |
282 cur_data += EC_COMMAND_FOOTER_SIZE; |
286 } |
283 } |
287 |
284 |
288 if (cur_data - frame_data == EC_FRAME_HEADER_SIZE) { |
285 if (cur_data - frame_data == EC_FRAME_HEADER_SIZE) { |
289 if (unlikely(master->debug_level > 0)) |
286 if (unlikely(master->debug_level > 0)) |
293 |
290 |
294 // EtherCAT frame header |
291 // EtherCAT frame header |
295 EC_WRITE_U16(frame_data, ((cur_data - frame_data |
292 EC_WRITE_U16(frame_data, ((cur_data - frame_data |
296 - EC_FRAME_HEADER_SIZE) & 0x7FF) | 0x1000); |
293 - EC_FRAME_HEADER_SIZE) & 0x7FF) | 0x1000); |
297 |
294 |
298 // Rahmen auffüllen |
295 // pad frame |
299 while (cur_data - frame_data < EC_MIN_FRAME_SIZE) |
296 while (cur_data - frame_data < EC_MIN_FRAME_SIZE) |
300 EC_WRITE_U8(cur_data++, 0x00); |
297 EC_WRITE_U8(cur_data++, 0x00); |
301 |
298 |
302 if (unlikely(master->debug_level > 0)) |
299 if (unlikely(master->debug_level > 0)) |
303 EC_DBG("frame size: %i\n", cur_data - frame_data); |
300 EC_DBG("frame size: %i\n", cur_data - frame_data); |
304 |
301 |
305 // Send frame |
302 // send frame |
306 ec_device_send(master->device, cur_data - frame_data); |
303 ec_device_send(master->device, cur_data - frame_data); |
307 frame_count++; |
304 frame_count++; |
308 } |
305 } |
309 while (more_commands_waiting); |
306 while (more_commands_waiting); |
310 |
307 |
317 |
314 |
318 /*****************************************************************************/ |
315 /*****************************************************************************/ |
319 |
316 |
320 /** |
317 /** |
321 Processes a received frame. |
318 Processes a received frame. |
322 |
|
323 This function is called by the network driver for every received frame. |
319 This function is called by the network driver for every received frame. |
324 |
320 \return 0 in case of success, else < 0 |
325 \return 0 bei Erfolg, sonst < 0 |
321 */ |
326 */ |
322 |
327 |
323 void ec_master_receive(ec_master_t *master, /**< EtherCAT master */ |
328 void ec_master_receive(ec_master_t *master, /**< EtherCAT-Master */ |
324 const uint8_t *frame_data, /**< received data */ |
329 const uint8_t *frame_data, /**< Empfangene Daten */ |
325 size_t size /**< size of the received data */ |
330 size_t size /**< Anzahl empfangene Datenbytes */ |
326 ) |
331 ) |
|
332 { |
327 { |
333 size_t frame_size, data_size; |
328 size_t frame_size, data_size; |
334 uint8_t command_type, command_index; |
329 uint8_t command_type, command_index; |
335 unsigned int cmd_follows, matched; |
330 unsigned int cmd_follows, matched; |
336 const uint8_t *cur_data; |
331 const uint8_t *cur_data; |
368 master->stats.corrupted++; |
363 master->stats.corrupted++; |
369 ec_master_output_stats(master); |
364 ec_master_output_stats(master); |
370 return; |
365 return; |
371 } |
366 } |
372 |
367 |
373 // Suche passendes Kommando in der Liste |
368 // search for matching command in the queue |
374 matched = 0; |
369 matched = 0; |
375 list_for_each_entry(command, &master->command_queue, queue) { |
370 list_for_each_entry(command, &master->command_queue, queue) { |
376 if (command->state == EC_CMD_SENT |
371 if (command->state == EC_CMD_SENT |
377 && command->type == command_type |
372 && command->type == command_type |
378 && command->index == command_index |
373 && command->index == command_index |
380 matched = 1; |
375 matched = 1; |
381 break; |
376 break; |
382 } |
377 } |
383 } |
378 } |
384 |
379 |
385 // Kein passendes Kommando in der Liste gefunden |
380 // no matching command was found |
386 if (!matched) { |
381 if (!matched) { |
387 master->stats.unmatched++; |
382 master->stats.unmatched++; |
388 ec_master_output_stats(master); |
383 ec_master_output_stats(master); |
389 cur_data += data_size + EC_COMMAND_FOOTER_SIZE; |
384 cur_data += data_size + EC_COMMAND_FOOTER_SIZE; |
390 continue; |
385 continue; |
391 } |
386 } |
392 |
387 |
393 // Empfangene Daten in Kommando-Datenspeicher kopieren |
388 // copy received data in the command memory |
394 memcpy(command->data, cur_data, data_size); |
389 memcpy(command->data, cur_data, data_size); |
395 cur_data += data_size; |
390 cur_data += data_size; |
396 |
391 |
397 // Working-Counter setzen |
392 // set the command's working counter |
398 command->working_counter = EC_READ_U16(cur_data); |
393 command->working_counter = EC_READ_U16(cur_data); |
399 cur_data += EC_COMMAND_FOOTER_SIZE; |
394 cur_data += EC_COMMAND_FOOTER_SIZE; |
400 |
395 |
401 // Kommando aus der Warteschlange entfernen |
396 // dequeue the received command |
402 command->state = EC_CMD_RECEIVED; |
397 command->state = EC_CMD_RECEIVED; |
403 list_del_init(&command->queue); |
398 list_del_init(&command->queue); |
404 } |
399 } |
405 } |
400 } |
406 |
401 |
407 /*****************************************************************************/ |
402 /*****************************************************************************/ |
408 |
403 |
409 /** |
404 /** |
410 Sendet ein einzelnes Kommando und wartet auf den Empfang. |
405 Sends a single command and waits for its reception. |
411 |
406 If the slave doesn't respond, the command is sent again. |
412 Wenn der Slave nicht antwortet, wird das Kommando |
407 \return 0 in case of success, else < 0 |
413 nochmals gesendet. |
408 */ |
414 |
409 |
415 \return 0 bei Erfolg, sonst < 0 |
410 int ec_master_simple_io(ec_master_t *master, /**< EtherCAT master */ |
416 */ |
411 ec_command_t *command /**< command */ |
417 |
|
418 int ec_master_simple_io(ec_master_t *master, /**< EtherCAT-Master */ |
|
419 ec_command_t *command /**< Kommando */ |
|
420 ) |
412 ) |
421 { |
413 { |
422 unsigned int response_tries_left; |
414 unsigned int response_tries_left; |
423 |
415 |
424 response_tries_left = 10; |
416 response_tries_left = 10; |
452 } |
444 } |
453 |
445 |
454 /*****************************************************************************/ |
446 /*****************************************************************************/ |
455 |
447 |
456 /** |
448 /** |
457 Durchsucht den EtherCAT-Bus nach Slaves. |
449 Scans the EtherCAT bus for slaves. |
458 |
450 Creates a list of slave structures for further processing. |
459 Erstellt ein Array mit allen Slave-Informationen die für den |
451 \return 0 in case of success, else < 0 |
460 weiteren Betrieb notwendig sind. |
452 */ |
461 |
453 |
462 \return 0 bei Erfolg, sonst < 0 |
454 int ec_master_bus_scan(ec_master_t *master /**< EtherCAT master */) |
463 */ |
|
464 |
|
465 int ec_master_bus_scan(ec_master_t *master /**< EtherCAT-Master */) |
|
466 { |
455 { |
467 ec_slave_t *slave, *next; |
456 ec_slave_t *slave, *next; |
468 ec_slave_ident_t *ident; |
457 ec_slave_ident_t *ident; |
469 unsigned int i; |
458 unsigned int i; |
470 ec_command_t *command; |
459 ec_command_t *command; |
477 return -1; |
466 return -1; |
478 } |
467 } |
479 |
468 |
480 command = &master->simple_command; |
469 command = &master->simple_command; |
481 |
470 |
482 // Determine number of slaves on bus |
471 // determine number of slaves on bus |
483 if (ec_command_brd(command, 0x0000, 4)) return -1; |
472 if (ec_command_brd(command, 0x0000, 4)) return -1; |
484 if (unlikely(ec_master_simple_io(master, command))) return -1; |
473 if (unlikely(ec_master_simple_io(master, command))) return -1; |
485 master->slave_count = command->working_counter; |
474 master->slave_count = command->working_counter; |
486 EC_INFO("Found %i slaves on bus.\n", master->slave_count); |
475 EC_INFO("Found %i slaves on bus.\n", master->slave_count); |
487 |
476 |
488 if (!master->slave_count) return 0; |
477 if (!master->slave_count) return 0; |
489 |
478 |
490 // Init slaves |
479 // init slaves |
491 for (i = 0; i < master->slave_count; i++) { |
480 for (i = 0; i < master->slave_count; i++) { |
492 if (!(slave = (ec_slave_t *) kmalloc(sizeof(ec_slave_t), GFP_KERNEL))) { |
481 if (!(slave = (ec_slave_t *) kmalloc(sizeof(ec_slave_t), GFP_KERNEL))) { |
493 EC_ERR("Failed to allocate slave %i!\n", i); |
482 EC_ERR("Failed to allocate slave %i!\n", i); |
494 goto out_free; |
483 goto out_free; |
495 } |
484 } |
508 coupler_index = 0; |
497 coupler_index = 0; |
509 reverse_coupler_index = 0xFFFF; |
498 reverse_coupler_index = 0xFFFF; |
510 current_coupler_index = 0x3FFF; |
499 current_coupler_index = 0x3FFF; |
511 coupler_subindex = 0; |
500 coupler_subindex = 0; |
512 |
501 |
513 // For every slave on the bus |
502 // for every slave on the bus |
514 list_for_each_entry(slave, &master->slaves, list) { |
503 list_for_each_entry(slave, &master->slaves, list) { |
515 |
504 |
516 // Write station address |
505 // write station address |
517 if (ec_command_apwr(command, slave->ring_position, 0x0010, |
506 if (ec_command_apwr(command, slave->ring_position, 0x0010, |
518 sizeof(uint16_t))) goto out_free; |
507 sizeof(uint16_t))) goto out_free; |
519 EC_WRITE_U16(command->data, slave->station_address); |
508 EC_WRITE_U16(command->data, slave->station_address); |
520 if (unlikely(ec_master_simple_io(master, command))) { |
509 if (unlikely(ec_master_simple_io(master, command))) { |
521 EC_ERR("Writing station address failed on slave %i!\n", |
510 EC_ERR("Writing station address failed on slave %i!\n", |
522 slave->ring_position); |
511 slave->ring_position); |
523 goto out_free; |
512 goto out_free; |
524 } |
513 } |
525 |
514 |
526 // Fetch all slave information |
515 // fetch all slave information |
527 if (ec_slave_fetch(slave)) goto out_free; |
516 if (ec_slave_fetch(slave)) goto out_free; |
528 |
517 |
529 // Search for identification in "database" |
518 // search for identification in "database" |
530 ident = slave_idents; |
519 ident = slave_idents; |
531 while (ident->type) { |
520 while (ident->type) { |
532 if (unlikely(ident->vendor_id == slave->sii_vendor_id |
521 if (unlikely(ident->vendor_id == slave->sii_vendor_id |
533 && ident->product_code == slave->sii_product_code)) { |
522 && ident->product_code == slave->sii_product_code)) { |
534 slave->type = ident->type; |
523 slave->type = ident->type; |
578 } |
567 } |
579 |
568 |
580 /*****************************************************************************/ |
569 /*****************************************************************************/ |
581 |
570 |
582 /** |
571 /** |
583 Statistik-Ausgaben während des zyklischen Betriebs. |
572 Output statistics in cyclic mode. |
584 |
573 This function outputs statistical data on demand, but not more often than |
585 Diese Funktion sorgt dafür, dass Statistiken während des zyklischen |
574 necessary. The output happens at most once a second. |
586 Betriebs bei Bedarf, aber nicht zu oft ausgegeben werden. |
575 */ |
587 |
576 |
588 Die Ausgabe erfolgt gesammelt höchstens einmal pro Sekunde. |
577 void ec_master_output_stats(ec_master_t *master /**< EtherCAT master */) |
589 */ |
|
590 |
|
591 void ec_master_output_stats(ec_master_t *master /**< EtherCAT-Master */) |
|
592 { |
578 { |
593 cycles_t t_now = get_cycles(); |
579 cycles_t t_now = get_cycles(); |
594 |
580 |
595 if (unlikely((u32) (t_now - master->stats.t_last) / cpu_khz > 1000)) { |
581 if (unlikely((u32) (t_now - master->stats.t_last) / cpu_khz > 1000)) { |
596 if (master->stats.timeouts) { |
582 if (master->stats.timeouts) { |
634 |
620 |
635 EC_INFO("Starting Free-Run mode.\n"); |
621 EC_INFO("Starting Free-Run mode.\n"); |
636 |
622 |
637 master->mode = EC_MASTER_MODE_FREERUN; |
623 master->mode = EC_MASTER_MODE_FREERUN; |
638 |
624 |
|
625 if (master->watch_command.state == EC_CMD_INIT) { |
|
626 if (ec_command_brd(&master->watch_command, 0x130, 2)) { |
|
627 EC_ERR("Failed to allocate watchdog command!\n"); |
|
628 return; |
|
629 } |
|
630 } |
|
631 |
|
632 ecrt_master_prepare_async_io(master); |
|
633 |
639 master->freerun_timer.expires = jiffies + 10; |
634 master->freerun_timer.expires = jiffies + 10; |
640 add_timer(&master->freerun_timer); |
635 add_timer(&master->freerun_timer); |
641 } |
636 } |
642 |
637 |
643 /*****************************************************************************/ |
638 /*****************************************************************************/ |
644 |
639 |
645 /** |
640 /** |
646 Stops Free-Run mode. |
641 Stops the Free-Run mode. |
647 */ |
642 */ |
648 |
643 |
649 void ec_master_freerun_stop(ec_master_t *master /**< EtherCAT master */) |
644 void ec_master_freerun_stop(ec_master_t *master /**< EtherCAT master */) |
650 { |
645 { |
651 if (master->mode != EC_MASTER_MODE_FREERUN) return; |
646 if (master->mode != EC_MASTER_MODE_FREERUN) return; |
660 |
655 |
661 /** |
656 /** |
662 Free-Run mode function. |
657 Free-Run mode function. |
663 */ |
658 */ |
664 |
659 |
665 void ec_master_freerun(unsigned long data) |
660 void ec_master_freerun(unsigned long data /**< private timer data = master */) |
666 { |
661 { |
667 ec_master_t *master = (ec_master_t *) data; |
662 ec_master_t *master = (ec_master_t *) data; |
668 |
663 |
669 // nop |
664 ecrt_master_async_receive(master); |
|
665 |
|
666 // watchdog command |
|
667 ec_master_process_watch_command(master); |
|
668 ec_master_queue_command(master, &master->watch_command); |
|
669 |
|
670 master->slave_count = master->watch_command.working_counter; |
|
671 |
|
672 ecrt_master_async_send(master); |
670 |
673 |
671 master->freerun_timer.expires += HZ; |
674 master->freerun_timer.expires += HZ; |
672 add_timer(&master->freerun_timer); |
675 add_timer(&master->freerun_timer); |
673 } |
676 } |
674 |
677 |
675 /*****************************************************************************/ |
678 /*****************************************************************************/ |
676 |
679 |
677 /** |
680 /** |
678 Wandelt eine ASCII-kodierte Bus-Adresse in einen Slave-Zeiger. |
681 Translates an ASCII coded bus-address to a slave pointer. |
679 |
682 These are the valid addressing schemes: |
680 Gültige Adress-Strings sind Folgende: |
683 - \a "X" = the X. slave on the bus, |
681 - \a "X" = der X. Slave im Bus, |
684 - \a "X:Y" = the Y. slave after the X. branch (bus coupler), |
682 - \a "X:Y" = der Y. Slave hinter dem X. Buskoppler, |
685 - \a "#X" = the slave with alias X, |
683 - \a "#X" = der Slave mit dem Alias X, |
686 - \a "#X:Y" = the Y. slave after the branch (bus coupler) with alias X. |
684 - \a "#X:Y" = der Y. Slave hinter dem Buskoppler mit dem Alias X. |
687 X and Y are zero-based indices and may be provided in hexadecimal or octal |
685 |
688 notation (with respective prefix). |
686 X und Y fangen immer bei 0 an und können auch hexadezimal oder oktal |
689 \return pointer to the slave on success, else NULL |
687 angegeben werden (mit entsprechendem Prefix). |
|
688 |
|
689 \return Zeiger auf Slave bei Erfolg, sonst NULL |
|
690 */ |
690 */ |
691 |
691 |
692 ec_slave_t *ecrt_master_get_slave(const ec_master_t *master, /**< Master */ |
692 ec_slave_t *ecrt_master_get_slave(const ec_master_t *master, /**< Master */ |
693 const char *address /**< Address-String */ |
693 const char *address /**< address string */ |
694 ) |
694 ) |
695 { |
695 { |
696 unsigned long first, second; |
696 unsigned long first, second; |
697 char *remainder, *remainder2; |
697 char *remainder, *remainder2; |
698 unsigned int alias_requested, alias_found; |
698 unsigned int alias_requested, alias_found; |
783 } |
783 } |
784 |
784 |
785 /*****************************************************************************/ |
785 /*****************************************************************************/ |
786 |
786 |
787 /** |
787 /** |
788 Initialisiert eine Sync-Manager-Konfigurationsseite. |
788 Initializes a sync manager configuration page. |
789 |
789 The referenced memory (\a data) must be at least EC_SYNC_SIZE bytes. |
790 Der mit \a data referenzierte Speicher muss mindestens EC_SYNC_SIZE Bytes |
790 */ |
791 groß sein. |
791 |
792 */ |
792 void ec_sync_config(const ec_sync_t *sync, /**< sync manager */ |
793 |
793 uint8_t *data /**> configuration memory */ |
794 void ec_sync_config(const ec_sync_t *sync, /**< Sync-Manager */ |
|
795 uint8_t *data /**> Zeiger auf Konfigurationsspeicher */ |
|
796 ) |
794 ) |
797 { |
795 { |
798 EC_WRITE_U16(data, sync->physical_start_address); |
796 EC_WRITE_U16(data, sync->physical_start_address); |
799 EC_WRITE_U16(data + 2, sync->size); |
797 EC_WRITE_U16(data + 2, sync->size); |
800 EC_WRITE_U8 (data + 4, sync->control_byte); |
798 EC_WRITE_U8 (data + 4, sync->control_byte); |
803 } |
801 } |
804 |
802 |
805 /*****************************************************************************/ |
803 /*****************************************************************************/ |
806 |
804 |
807 /** |
805 /** |
808 Initialisiert eine Sync-Manager-Konfigurationsseite mit EEPROM-Daten. |
806 Initializes a sync manager configuration page with EEPROM data. |
809 |
807 The referenced memory (\a data) must be at least EC_SYNC_SIZE bytes. |
810 Der mit \a data referenzierte Speicher muss mindestens EC_SYNC_SIZE Bytes |
808 */ |
811 groß sein. |
809 |
812 */ |
810 void ec_eeprom_sync_config(const ec_eeprom_sync_t *sync, /**< sync manager */ |
813 |
811 uint8_t *data /**> configuration memory */ |
814 void ec_eeprom_sync_config(const ec_eeprom_sync_t *sync, /**< Sync-Manager */ |
|
815 uint8_t *data /**> Zeiger auf Konfig.-Speicher */ |
|
816 ) |
812 ) |
817 { |
813 { |
818 EC_WRITE_U16(data, sync->physical_start_address); |
814 EC_WRITE_U16(data, sync->physical_start_address); |
819 EC_WRITE_U16(data + 2, sync->length); |
815 EC_WRITE_U16(data + 2, sync->length); |
820 EC_WRITE_U8 (data + 4, sync->control_register); |
816 EC_WRITE_U8 (data + 4, sync->control_register); |
823 } |
819 } |
824 |
820 |
825 /*****************************************************************************/ |
821 /*****************************************************************************/ |
826 |
822 |
827 /** |
823 /** |
828 Initialisiert eine FMMU-Konfigurationsseite. |
824 Initializes an FMMU configuration page. |
829 |
825 The referenced memory (\a data) must be at least EC_FMMU_SIZE bytes. |
830 Der mit \a data referenzierte Speicher muss mindestens EC_FMMU_SIZE Bytes |
826 */ |
831 groß sein. |
827 |
832 */ |
828 void ec_fmmu_config(const ec_fmmu_t *fmmu, /**< FMMU */ |
833 |
829 uint8_t *data /**> configuration memory */ |
834 void ec_fmmu_config(const ec_fmmu_t *fmmu, /**< Sync-Manager */ |
|
835 uint8_t *data /**> Zeiger auf Konfigurationsspeicher */ |
|
836 ) |
830 ) |
837 { |
831 { |
838 EC_WRITE_U32(data, fmmu->logical_start_address); |
832 EC_WRITE_U32(data, fmmu->logical_start_address); |
839 EC_WRITE_U16(data + 4, fmmu->sync->size); |
833 EC_WRITE_U16(data + 4, fmmu->sync->size); |
840 EC_WRITE_U8 (data + 6, 0x00); // Logical start bit |
834 EC_WRITE_U8 (data + 6, 0x00); // logical start bit |
841 EC_WRITE_U8 (data + 7, 0x07); // Logical end bit |
835 EC_WRITE_U8 (data + 7, 0x07); // logical end bit |
842 EC_WRITE_U16(data + 8, fmmu->sync->physical_start_address); |
836 EC_WRITE_U16(data + 8, fmmu->sync->physical_start_address); |
843 EC_WRITE_U8 (data + 10, 0x00); // Physical start bit |
837 EC_WRITE_U8 (data + 10, 0x00); // physical start bit |
844 EC_WRITE_U8 (data + 11, (fmmu->sync->control_byte & 0x04) ? 0x02 : 0x01); |
838 EC_WRITE_U8 (data + 11, (fmmu->sync->control_byte & 0x04) ? 0x02 : 0x01); |
845 EC_WRITE_U16(data + 12, 0x0001); // Enable |
839 EC_WRITE_U16(data + 12, 0x0001); // enable |
846 EC_WRITE_U16(data + 14, 0x0000); // res. |
840 EC_WRITE_U16(data + 14, 0x0000); // reserved |
847 } |
841 } |
848 |
842 |
849 /*****************************************************************************/ |
843 /*****************************************************************************/ |
850 |
844 |
851 /** |
845 /** |
852 Formatiert Attribut-Daten für lesenden Zugriff im SysFS |
846 Formats attribute data for SysFS read access. |
853 |
847 \return number of bytes to read |
854 \return Anzahl Bytes im Speicher |
848 */ |
855 */ |
849 |
856 |
850 ssize_t ec_show_master_attribute(struct kobject *kobj, /**< kobject */ |
857 ssize_t ec_show_master_attribute(struct kobject *kobj, /**< KObject */ |
851 struct attribute *attr, /**< attribute */ |
858 struct attribute *attr, /**< Attribut */ |
852 char *buffer /**< memory to store data */ |
859 char *buffer /**< Speicher für die Daten */ |
|
860 ) |
853 ) |
861 { |
854 { |
862 ec_master_t *master = container_of(kobj, ec_master_t, kobj); |
855 ec_master_t *master = container_of(kobj, ec_master_t, kobj); |
863 |
856 |
864 if (attr == &attr_slave_count) { |
857 if (attr == &attr_slave_count) { |
924 printk(")\n"); |
917 printk(")\n"); |
925 } |
918 } |
926 } |
919 } |
927 |
920 |
928 /****************************************************************************** |
921 /****************************************************************************** |
929 * |
922 * Realtime interface |
930 * Echtzeitschnittstelle |
|
931 * |
|
932 *****************************************************************************/ |
923 *****************************************************************************/ |
933 |
924 |
934 /** |
925 /** |
935 Erstellt eine neue Domäne. |
926 Creates a domain. |
936 |
927 \return pointer to new domain on success, else NULL |
937 \return Zeiger auf die Domäne bei Erfolg, sonst NULL. |
928 */ |
938 */ |
929 |
939 |
930 ec_domain_t *ecrt_master_create_domain(ec_master_t *master /**< master */) |
940 ec_domain_t *ecrt_master_create_domain(ec_master_t *master /**< Master */) |
|
941 { |
931 { |
942 ec_domain_t *domain, *last_domain; |
932 ec_domain_t *domain, *last_domain; |
943 unsigned int index; |
933 unsigned int index; |
944 |
934 |
945 if (!(domain = (ec_domain_t *) kmalloc(sizeof(ec_domain_t), GFP_KERNEL))) { |
935 if (!(domain = (ec_domain_t *) kmalloc(sizeof(ec_domain_t), GFP_KERNEL))) { |
973 } |
963 } |
974 |
964 |
975 /*****************************************************************************/ |
965 /*****************************************************************************/ |
976 |
966 |
977 /** |
967 /** |
978 Konfiguriert alle Slaves und setzt den Operational-Zustand. |
968 Configures all slaves and leads them to the OP state. |
979 |
969 Does the complete configuration and activation for all slaves. Sets sync |
980 Führt die komplette Konfiguration und Aktivierunge aller registrierten |
970 managers and FMMUs, and does the appropriate transitions, until the slave |
981 Slaves durch. Setzt Sync-Manager und FMMUs, führt die entsprechenden |
971 is operational. |
982 Zustandsübergänge durch, bis der Slave betriebsbereit ist. |
972 \return 0 in case of success, else < 0 |
983 |
973 */ |
984 \return 0 bei Erfolg, sonst < 0 |
974 |
985 */ |
975 int ecrt_master_activate(ec_master_t *master /**< EtherCAT master */) |
986 |
|
987 int ecrt_master_activate(ec_master_t *master /**< EtherCAT-Master */) |
|
988 { |
976 { |
989 unsigned int j; |
977 unsigned int j; |
990 ec_slave_t *slave; |
978 ec_slave_t *slave; |
991 ec_command_t *command; |
979 ec_command_t *command; |
992 const ec_sync_t *sync; |
980 const ec_sync_t *sync; |
996 ec_domain_t *domain; |
984 ec_domain_t *domain; |
997 ec_eeprom_sync_t *eeprom_sync, mbox_sync; |
985 ec_eeprom_sync_t *eeprom_sync, mbox_sync; |
998 |
986 |
999 command = &master->simple_command; |
987 command = &master->simple_command; |
1000 |
988 |
1001 if (ec_command_brd(&master->watch_command, 0x130, 2)) { |
989 if (master->watch_command.state == EC_CMD_INIT) { |
1002 EC_ERR("Failed to allocate watchdog command!\n"); |
990 if (ec_command_brd(&master->watch_command, 0x130, 2)) { |
1003 return -1; |
991 EC_ERR("Failed to allocate watchdog command!\n"); |
1004 } |
992 return -1; |
1005 |
993 } |
1006 // Domains erstellen |
994 } |
|
995 |
|
996 // allocate all domains |
1007 domain_offset = 0; |
997 domain_offset = 0; |
1008 list_for_each_entry(domain, &master->domains, list) { |
998 list_for_each_entry(domain, &master->domains, list) { |
1009 if (ec_domain_alloc(domain, domain_offset)) { |
999 if (ec_domain_alloc(domain, domain_offset)) { |
1010 EC_ERR("Failed to allocate domain %X!\n", (u32) domain); |
1000 EC_ERR("Failed to allocate domain %X!\n", (u32) domain); |
1011 return -1; |
1001 return -1; |
1012 } |
1002 } |
1013 domain_offset += domain->data_size; |
1003 domain_offset += domain->data_size; |
1014 } |
1004 } |
1015 |
1005 |
1016 // Slaves aktivieren |
1006 // configure and activate slaves |
1017 list_for_each_entry(slave, &master->slaves, list) { |
1007 list_for_each_entry(slave, &master->slaves, list) { |
1018 |
1008 |
1019 // Change state to INIT |
1009 // change state to INIT |
1020 if (unlikely(ec_slave_state_change(slave, EC_SLAVE_STATE_INIT))) |
1010 if (unlikely(ec_slave_state_change(slave, EC_SLAVE_STATE_INIT))) |
1021 return -1; |
1011 return -1; |
1022 |
1012 |
1023 // Check if slave was registered... |
1013 // check for slave registration |
1024 type = slave->type; |
1014 type = slave->type; |
1025 if (!type) |
1015 if (!type) |
1026 EC_WARN("Slave %i has unknown type!\n", slave->ring_position); |
1016 EC_WARN("Slave %i has unknown type!\n", slave->ring_position); |
1027 |
1017 |
1028 // Check and reset CRC fault counters |
1018 // check and reset CRC fault counters |
1029 ec_slave_check_crc(slave); |
1019 ec_slave_check_crc(slave); |
1030 |
1020 |
1031 // Resetting FMMUs |
1021 // reset FMMUs |
1032 if (slave->base_fmmu_count) { |
1022 if (slave->base_fmmu_count) { |
1033 if (ec_command_npwr(command, slave->station_address, 0x0600, |
1023 if (ec_command_npwr(command, slave->station_address, 0x0600, |
1034 EC_FMMU_SIZE * slave->base_fmmu_count)) |
1024 EC_FMMU_SIZE * slave->base_fmmu_count)) |
1035 return -1; |
1025 return -1; |
1036 memset(command->data, 0x00, EC_FMMU_SIZE * slave->base_fmmu_count); |
1026 memset(command->data, 0x00, EC_FMMU_SIZE * slave->base_fmmu_count); |
1039 slave->ring_position); |
1029 slave->ring_position); |
1040 return -1; |
1030 return -1; |
1041 } |
1031 } |
1042 } |
1032 } |
1043 |
1033 |
1044 // Resetting Sync Manager channels |
1034 // reset sync managers |
1045 if (slave->base_sync_count) { |
1035 if (slave->base_sync_count) { |
1046 if (ec_command_npwr(command, slave->station_address, 0x0800, |
1036 if (ec_command_npwr(command, slave->station_address, 0x0800, |
1047 EC_SYNC_SIZE * slave->base_sync_count)) |
1037 EC_SYNC_SIZE * slave->base_sync_count)) |
1048 return -1; |
1038 return -1; |
1049 memset(command->data, 0x00, EC_SYNC_SIZE * slave->base_sync_count); |
1039 memset(command->data, 0x00, EC_SYNC_SIZE * slave->base_sync_count); |
1052 slave->ring_position); |
1042 slave->ring_position); |
1053 return -1; |
1043 return -1; |
1054 } |
1044 } |
1055 } |
1045 } |
1056 |
1046 |
1057 // Set Sync Managers |
1047 // configure sync managers |
1058 |
1048 if (type) { // known slave type, take type's SM information |
1059 // Known slave type, take type's SM information |
|
1060 if (type) { |
|
1061 for (j = 0; type->sync_managers[j] && j < EC_MAX_SYNC; j++) { |
1049 for (j = 0; type->sync_managers[j] && j < EC_MAX_SYNC; j++) { |
1062 sync = type->sync_managers[j]; |
1050 sync = type->sync_managers[j]; |
1063 if (ec_command_npwr(command, slave->station_address, |
1051 if (ec_command_npwr(command, slave->station_address, |
1064 0x0800 + j * EC_SYNC_SIZE, EC_SYNC_SIZE)) |
1052 0x0800 + j * EC_SYNC_SIZE, EC_SYNC_SIZE)) |
1065 return -1; |
1053 return -1; |
1069 j, slave->ring_position); |
1057 j, slave->ring_position); |
1070 return -1; |
1058 return -1; |
1071 } |
1059 } |
1072 } |
1060 } |
1073 } |
1061 } |
1074 |
1062 else if (slave->sii_mailbox_protocols) { // unknown type, but mailbox |
1075 // Unknown slave type, but has mailbox |
1063 // does the device supply SM configurations in its EEPROM? |
1076 else if (slave->sii_mailbox_protocols) { |
|
1077 |
|
1078 // Does the device supply SM configurations in its EEPROM? |
|
1079 if (!list_empty(&slave->eeprom_syncs)) { |
1064 if (!list_empty(&slave->eeprom_syncs)) { |
1080 list_for_each_entry(eeprom_sync, &slave->eeprom_syncs, list) { |
1065 list_for_each_entry(eeprom_sync, &slave->eeprom_syncs, list) { |
1081 EC_INFO("Sync manager %i...\n", eeprom_sync->index); |
1066 EC_INFO("Sync manager %i...\n", eeprom_sync->index); |
1082 if (ec_command_npwr(command, slave->station_address, |
1067 if (ec_command_npwr(command, slave->station_address, |
1083 0x800 + eeprom_sync->index * |
1068 0x800 + eeprom_sync->index * |
1124 } |
1107 } |
1125 EC_INFO("Mailbox configured for unknown slave %i\n", |
1108 EC_INFO("Mailbox configured for unknown slave %i\n", |
1126 slave->ring_position); |
1109 slave->ring_position); |
1127 } |
1110 } |
1128 |
1111 |
1129 // Change state to PREOP |
1112 // change state to PREOP |
1130 if (unlikely(ec_slave_state_change(slave, EC_SLAVE_STATE_PREOP))) |
1113 if (unlikely(ec_slave_state_change(slave, EC_SLAVE_STATE_PREOP))) |
1131 return -1; |
1114 return -1; |
1132 |
1115 |
1133 // Stop activation here for slaves without type |
1116 // stop activation here for slaves without type |
1134 if (!type) continue; |
1117 if (!type) continue; |
1135 |
1118 |
1136 // Slaves that are not registered are only brought into PREOP |
1119 // slaves that are not registered are only brought into PREOP |
1137 // state -> nice blinking and mailbox communication possible |
1120 // state -> nice blinking and mailbox communication possible |
1138 if (!slave->registered && !slave->type->special) { |
1121 if (!slave->registered && !slave->type->special) { |
1139 EC_WARN("Slave %i was not registered!\n", slave->ring_position); |
1122 EC_WARN("Slave %i was not registered!\n", slave->ring_position); |
1140 continue; |
1123 continue; |
1141 } |
1124 } |
1142 |
1125 |
1143 // Set FMMUs |
1126 // configure FMMUs |
1144 for (j = 0; j < slave->fmmu_count; j++) { |
1127 for (j = 0; j < slave->fmmu_count; j++) { |
1145 fmmu = &slave->fmmus[j]; |
1128 fmmu = &slave->fmmus[j]; |
1146 if (ec_command_npwr(command, slave->station_address, |
1129 if (ec_command_npwr(command, slave->station_address, |
1147 0x0600 + j * EC_FMMU_SIZE, EC_FMMU_SIZE)) |
1130 0x0600 + j * EC_FMMU_SIZE, EC_FMMU_SIZE)) |
1148 return -1; |
1131 return -1; |
1187 |
1170 |
1188 |
1171 |
1189 /*****************************************************************************/ |
1172 /*****************************************************************************/ |
1190 |
1173 |
1191 /** |
1174 /** |
1192 Lädt die SDO-Dictionaries aller Slaves. |
1175 Fetches the SDO dictionaries of all slaves. |
1193 |
1176 Slaves that do not support the CoE protocol are left out. |
1194 Slaves, die kein CoE unterstützen, werden ausgelassen. |
1177 \return 0 in case of success, else < 0 |
1195 |
1178 */ |
1196 \return 0 wenn alles ok, sonst < 0 |
1179 |
1197 */ |
1180 int ecrt_master_fetch_sdo_lists(ec_master_t *master /**< EtherCAT master */) |
1198 |
|
1199 int ecrt_master_fetch_sdo_lists(ec_master_t *master /**< EtherCAT-Master */) |
|
1200 { |
1181 { |
1201 ec_slave_t *slave; |
1182 ec_slave_t *slave; |
1202 |
1183 |
1203 list_for_each_entry(slave, &master->slaves, list) { |
1184 list_for_each_entry(slave, &master->slaves, list) { |
1204 if (slave->sii_mailbox_protocols & EC_MBOX_COE) { |
1185 if (slave->sii_mailbox_protocols & EC_MBOX_COE) { |
1214 } |
1195 } |
1215 |
1196 |
1216 /*****************************************************************************/ |
1197 /*****************************************************************************/ |
1217 |
1198 |
1218 /** |
1199 /** |
1219 Sendet und empfängt Kommandos synchron. |
1200 Sends queued commands and waits for their reception. |
1220 */ |
1201 */ |
1221 |
1202 |
1222 void ecrt_master_sync_io(ec_master_t *master) |
1203 void ecrt_master_sync_io(ec_master_t *master /**< EtherCAT master */) |
1223 { |
1204 { |
1224 ec_command_t *command, *n; |
1205 ec_command_t *command, *n; |
1225 unsigned int commands_sent; |
1206 unsigned int commands_sent; |
1226 cycles_t t_start, t_end, t_timeout; |
1207 cycles_t t_start, t_end, t_timeout; |
1227 |
1208 |
1228 // Kommandos senden |
1209 // send commands |
1229 ecrt_master_async_send(master); |
1210 ecrt_master_async_send(master); |
1230 |
1211 |
1231 t_start = get_cycles(); // Sendezeit nehmen |
1212 t_start = get_cycles(); // measure io time |
1232 t_timeout = (cycles_t) master->timeout * (cpu_khz / 1000); |
1213 t_timeout = (cycles_t) master->timeout * (cpu_khz / 1000); |
1233 |
1214 |
1234 while (1) // Aktiv auf Empfang warten |
1215 while (1) { // active waiting |
1235 { |
|
1236 ec_device_call_isr(master->device); |
1216 ec_device_call_isr(master->device); |
1237 |
1217 |
1238 t_end = get_cycles(); // Aktuelle Zeit nehmen |
1218 t_end = get_cycles(); // take current time |
1239 if (t_end - t_start >= t_timeout) break; // Timeout |
1219 if (t_end - t_start >= t_timeout) break; // timeout! |
1240 |
1220 |
1241 commands_sent = 0; |
1221 commands_sent = 0; |
1242 list_for_each_entry_safe(command, n, &master->command_queue, queue) { |
1222 list_for_each_entry_safe(command, n, &master->command_queue, queue) { |
1243 if (command->state == EC_CMD_RECEIVED) |
1223 if (command->state == EC_CMD_RECEIVED) |
1244 list_del_init(&command->queue); |
1224 list_del_init(&command->queue); |
1270 } |
1250 } |
1271 |
1251 |
1272 /*****************************************************************************/ |
1252 /*****************************************************************************/ |
1273 |
1253 |
1274 /** |
1254 /** |
1275 Sendet Kommandos asynchron. |
1255 Asynchronous sending of commands. |
1276 */ |
1256 */ |
1277 |
1257 |
1278 void ecrt_master_async_send(ec_master_t *master) |
1258 void ecrt_master_async_send(ec_master_t *master /**< EtherCAT master */) |
1279 { |
1259 { |
1280 ec_command_t *command, *n; |
1260 ec_command_t *command, *n; |
1281 |
1261 |
1282 if (unlikely(!master->device->link_state)) { |
1262 if (unlikely(!master->device->link_state)) { |
1283 // Link DOWN, keines der Kommandos kann gesendet werden. |
1263 // link is down, no command can be sent |
1284 list_for_each_entry_safe(command, n, &master->command_queue, queue) { |
1264 list_for_each_entry_safe(command, n, &master->command_queue, queue) { |
1285 command->state = EC_CMD_ERROR; |
1265 command->state = EC_CMD_ERROR; |
1286 list_del_init(&command->queue); |
1266 list_del_init(&command->queue); |
1287 } |
1267 } |
1288 |
1268 |
1289 // Device-Zustand abfragen |
1269 // query link state |
1290 ec_device_call_isr(master->device); |
1270 ec_device_call_isr(master->device); |
1291 return; |
1271 return; |
1292 } |
1272 } |
1293 |
1273 |
1294 // Rahmen senden |
1274 // send frames |
1295 ec_master_send_commands(master); |
1275 ec_master_send_commands(master); |
1296 } |
1276 } |
1297 |
1277 |
1298 /*****************************************************************************/ |
1278 /*****************************************************************************/ |
1299 |
1279 |
1300 /** |
1280 /** |
1301 Empfängt Kommandos asynchron. |
1281 Asynchronous receiving of commands. |
1302 */ |
1282 */ |
1303 |
1283 |
1304 void ecrt_master_async_receive(ec_master_t *master) |
1284 void ecrt_master_async_receive(ec_master_t *master /**< EtherCAT master */) |
1305 { |
1285 { |
1306 ec_command_t *command, *next; |
1286 ec_command_t *command, *next; |
1307 |
1287 |
1308 ec_device_call_isr(master->device); |
1288 ec_device_call_isr(master->device); |
1309 |
1289 |
1310 // Alle empfangenen Kommandos aus der Liste entfernen |
1290 // dequeue all received commands |
1311 list_for_each_entry_safe(command, next, &master->command_queue, queue) |
1291 list_for_each_entry_safe(command, next, &master->command_queue, queue) |
1312 if (command->state == EC_CMD_RECEIVED) list_del_init(&command->queue); |
1292 if (command->state == EC_CMD_RECEIVED) list_del_init(&command->queue); |
1313 |
1293 |
1314 // Alle verbleibenden Kommandos entfernen. |
1294 // dequeue all remaining commands |
1315 list_for_each_entry_safe(command, next, &master->command_queue, queue) { |
1295 list_for_each_entry_safe(command, next, &master->command_queue, queue) { |
1316 switch (command->state) { |
1296 switch (command->state) { |
1317 case EC_CMD_SENT: |
1297 case EC_CMD_SENT: |
1318 case EC_CMD_QUEUED: |
1298 case EC_CMD_QUEUED: |
1319 command->state = EC_CMD_TIMEOUT; |
1299 command->state = EC_CMD_TIMEOUT; |
1328 } |
1308 } |
1329 |
1309 |
1330 /*****************************************************************************/ |
1310 /*****************************************************************************/ |
1331 |
1311 |
1332 /** |
1312 /** |
1333 Bereitet Synchronen Datenverkehr vor. |
1313 Prepares synchronous IO. |
1334 |
1314 Queues all domain commands and sends them. Then waits a certain time, so |
1335 Fürgt einmal die Kommandos aller Domains zur Warteschlange hinzu, sendet |
1315 that ecrt_master_sasync_receive() can be called securely. |
1336 diese ab und wartet so lange, bis diese anschließend problemlos empfangen |
1316 */ |
1337 werden können. |
1317 |
1338 */ |
1318 void ecrt_master_prepare_async_io(ec_master_t *master /**< EtherCAT master */) |
1339 |
|
1340 void ecrt_master_prepare_async_io(ec_master_t *master) |
|
1341 { |
1319 { |
1342 ec_domain_t *domain; |
1320 ec_domain_t *domain; |
1343 cycles_t t_start, t_end, t_timeout; |
1321 cycles_t t_start, t_end, t_timeout; |
1344 |
1322 |
1345 // Kommandos aller Domains in die Warteschlange setzen |
1323 // queue commands of all domains |
1346 list_for_each_entry(domain, &master->domains, list) |
1324 list_for_each_entry(domain, &master->domains, list) |
1347 ecrt_domain_queue(domain); |
1325 ecrt_domain_queue(domain); |
1348 |
1326 |
1349 ecrt_master_async_send(master); |
1327 ecrt_master_async_send(master); |
1350 |
1328 |
1351 t_start = get_cycles(); // Sendezeit nehmen |
1329 t_start = get_cycles(); // take sending time |
1352 t_timeout = (cycles_t) master->timeout * (cpu_khz / 1000); |
1330 t_timeout = (cycles_t) master->timeout * (cpu_khz / 1000); |
1353 |
1331 |
1354 // Aktiv warten! |
1332 // active waiting |
1355 while (1) { |
1333 while (1) { |
1356 t_end = get_cycles(); |
1334 t_end = get_cycles(); |
1357 if (t_end - t_start >= t_timeout) break; |
1335 if (t_end - t_start >= t_timeout) break; |
1358 } |
1336 } |
1359 } |
1337 } |
1360 |
1338 |
1361 /*****************************************************************************/ |
1339 /*****************************************************************************/ |
1362 |
1340 |
1363 /** |
1341 /** |
1364 Führt Routinen im zyklischen Betrieb aus. |
1342 Does all cyclic master work. |
1365 */ |
1343 */ |
1366 |
1344 |
1367 void ecrt_master_run(ec_master_t *master /**< EtherCAT-Master */) |
1345 void ecrt_master_run(ec_master_t *master /**< EtherCAT master */) |
1368 { |
1346 { |
1369 // Statistiken ausgeben |
1347 // output statistics |
1370 ec_master_output_stats(master); |
1348 ec_master_output_stats(master); |
1371 |
1349 |
1372 // Watchdog-Kommando |
1350 // watchdog command |
1373 ec_master_process_watch_command(master); |
1351 ec_master_process_watch_command(master); |
1374 ec_master_queue_command(master, &master->watch_command); |
1352 ec_master_queue_command(master, &master->watch_command); |
1375 |
1353 |
1376 // Ethernet-over-EtherCAT |
1354 // Ethernet-over-EtherCAT |
1377 ec_master_run_eoe(master); |
1355 ec_master_run_eoe(master); |
1378 } |
1356 } |
1379 |
1357 |
1380 /*****************************************************************************/ |
1358 /*****************************************************************************/ |
1381 |
1359 |
1382 /** |
1360 /** |
1383 Setzt die Debug-Ebene des Masters. |
1361 Sets the debug level of the master. |
1384 |
1362 The following levels are valid: |
1385 Folgende Debug-Level sind definiert: |
1363 - 1: only output positions marks and basic data |
1386 |
1364 - 2: additional frame data output |
1387 - 1: Nur Positionsmarken in bestimmten Funktionen |
1365 */ |
1388 - 2: Komplette Frame-Inhalte |
1366 |
1389 */ |
1367 void ecrt_master_debug(ec_master_t *master, /**< EtherCAT master */ |
1390 |
1368 int level /**< debug level */ |
1391 void ecrt_master_debug(ec_master_t *master, /**< EtherCAT-Master */ |
|
1392 int level /**< Debug-Level */ |
|
1393 ) |
1369 ) |
1394 { |
1370 { |
1395 if (level != master->debug_level) { |
1371 if (level != master->debug_level) { |
1396 master->debug_level = level; |
1372 master->debug_level = level; |
1397 EC_INFO("Master debug level set to %i.\n", level); |
1373 EC_INFO("Master debug level set to %i.\n", level); |