210 called, to free the slave list, domains etc. |
212 called, to free the slave list, domains etc. |
211 */ |
213 */ |
212 |
214 |
213 void ec_master_reset(ec_master_t *master /**< EtherCAT master */) |
215 void ec_master_reset(ec_master_t *master /**< EtherCAT master */) |
214 { |
216 { |
215 ec_command_t *command, *next_c; |
217 ec_datagram_t *datagram, *next_c; |
216 ec_domain_t *domain, *next_d; |
218 ec_domain_t *domain, *next_d; |
217 |
219 |
218 ec_master_eoe_stop(master); |
220 ec_master_eoe_stop(master); |
219 ec_master_freerun_stop(master); |
221 ec_master_idle_stop(master); |
220 ec_master_clear_slaves(master); |
222 ec_master_clear_slaves(master); |
221 |
223 |
222 // empty command queue |
224 // empty datagram queue |
223 list_for_each_entry_safe(command, next_c, &master->command_queue, queue) { |
225 list_for_each_entry_safe(datagram, next_c, |
224 list_del_init(&command->queue); |
226 &master->datagram_queue, queue) { |
225 command->state = EC_CMD_ERROR; |
227 list_del_init(&datagram->queue); |
|
228 datagram->state = EC_CMD_ERROR; |
226 } |
229 } |
227 |
230 |
228 // clear domains |
231 // clear domains |
229 list_for_each_entry_safe(domain, next_d, &master->domains, list) { |
232 list_for_each_entry_safe(domain, next_d, &master->domains, list) { |
230 list_del(&domain->list); |
233 list_del(&domain->list); |
231 kobject_del(&domain->kobj); |
234 kobject_del(&domain->kobj); |
232 kobject_put(&domain->kobj); |
235 kobject_put(&domain->kobj); |
233 } |
236 } |
234 |
237 |
235 master->command_index = 0; |
238 master->datagram_index = 0; |
236 master->debug_level = 0; |
239 master->debug_level = 0; |
237 master->timeout = 500; // 500us |
240 master->timeout = 500; // 500us |
238 |
241 |
239 master->stats.timeouts = 0; |
242 master->stats.timeouts = 0; |
240 master->stats.delayed = 0; |
243 master->stats.delayed = 0; |
241 master->stats.corrupted = 0; |
244 master->stats.corrupted = 0; |
242 master->stats.unmatched = 0; |
245 master->stats.unmatched = 0; |
243 master->stats.t_last = 0; |
246 master->stats.t_last = 0; |
244 |
247 |
245 master->mode = EC_MASTER_MODE_IDLE; |
248 master->mode = EC_MASTER_MODE_ORPHANED; |
246 |
249 |
247 master->request_cb = NULL; |
250 master->request_cb = NULL; |
248 master->release_cb = NULL; |
251 master->release_cb = NULL; |
249 master->cb_data = NULL; |
252 master->cb_data = NULL; |
250 |
253 |
272 } |
275 } |
273 |
276 |
274 /*****************************************************************************/ |
277 /*****************************************************************************/ |
275 |
278 |
276 /** |
279 /** |
277 Places a command in the command queue. |
280 Places a datagram in the datagram queue. |
278 */ |
281 */ |
279 |
282 |
280 void ec_master_queue_command(ec_master_t *master, /**< EtherCAT master */ |
283 void ec_master_queue_datagram(ec_master_t *master, /**< EtherCAT master */ |
281 ec_command_t *command /**< command */ |
284 ec_datagram_t *datagram /**< datagram */ |
282 ) |
285 ) |
283 { |
286 { |
284 ec_command_t *queued_command; |
287 ec_datagram_t *queued_datagram; |
285 |
288 |
286 // check, if the command is already queued |
289 // check, if the datagram is already queued |
287 list_for_each_entry(queued_command, &master->command_queue, queue) { |
290 list_for_each_entry(queued_datagram, &master->datagram_queue, queue) { |
288 if (queued_command == command) { |
291 if (queued_datagram == datagram) { |
289 command->state = EC_CMD_QUEUED; |
292 datagram->state = EC_CMD_QUEUED; |
290 if (unlikely(master->debug_level)) |
293 if (unlikely(master->debug_level)) |
291 EC_WARN("command already queued.\n"); |
294 EC_WARN("datagram already queued.\n"); |
292 return; |
295 return; |
293 } |
296 } |
294 } |
297 } |
295 |
298 |
296 list_add_tail(&command->queue, &master->command_queue); |
299 list_add_tail(&datagram->queue, &master->datagram_queue); |
297 command->state = EC_CMD_QUEUED; |
300 datagram->state = EC_CMD_QUEUED; |
298 } |
301 } |
299 |
302 |
300 /*****************************************************************************/ |
303 /*****************************************************************************/ |
301 |
304 |
302 /** |
305 /** |
303 Sends the commands in the queue. |
306 Sends the datagrams in the queue. |
304 \return 0 in case of success, else < 0 |
307 \return 0 in case of success, else < 0 |
305 */ |
308 */ |
306 |
309 |
307 void ec_master_send_commands(ec_master_t *master /**< EtherCAT master */) |
310 void ec_master_send_datagrams(ec_master_t *master /**< EtherCAT master */) |
308 { |
311 { |
309 ec_command_t *command; |
312 ec_datagram_t *datagram; |
310 size_t command_size; |
313 size_t datagram_size; |
311 uint8_t *frame_data, *cur_data; |
314 uint8_t *frame_data, *cur_data; |
312 void *follows_word; |
315 void *follows_word; |
313 cycles_t t_start, t_end; |
316 cycles_t t_start, t_end; |
314 unsigned int frame_count, more_commands_waiting; |
317 unsigned int frame_count, more_datagrams_waiting; |
315 |
318 |
316 frame_count = 0; |
319 frame_count = 0; |
317 t_start = get_cycles(); |
320 t_start = get_cycles(); |
318 |
321 |
319 if (unlikely(master->debug_level > 0)) |
322 if (unlikely(master->debug_level > 1)) |
320 EC_DBG("ec_master_send_commands\n"); |
323 EC_DBG("ec_master_send_datagrams\n"); |
321 |
324 |
322 do { |
325 do { |
323 // fetch pointer to transmit socket buffer |
326 // fetch pointer to transmit socket buffer |
324 frame_data = ec_device_tx_data(master->device); |
327 frame_data = ec_device_tx_data(master->device); |
325 cur_data = frame_data + EC_FRAME_HEADER_SIZE; |
328 cur_data = frame_data + EC_FRAME_HEADER_SIZE; |
326 follows_word = NULL; |
329 follows_word = NULL; |
327 more_commands_waiting = 0; |
330 more_datagrams_waiting = 0; |
328 |
331 |
329 // fill current frame with commands |
332 // fill current frame with datagrams |
330 list_for_each_entry(command, &master->command_queue, queue) { |
333 list_for_each_entry(datagram, &master->datagram_queue, queue) { |
331 if (command->state != EC_CMD_QUEUED) continue; |
334 if (datagram->state != EC_CMD_QUEUED) continue; |
332 |
335 |
333 // does the current command fit in the frame? |
336 // does the current datagram fit in the frame? |
334 command_size = EC_COMMAND_HEADER_SIZE + command->data_size |
337 datagram_size = EC_DATAGRAM_HEADER_SIZE + datagram->data_size |
335 + EC_COMMAND_FOOTER_SIZE; |
338 + EC_DATAGRAM_FOOTER_SIZE; |
336 if (cur_data - frame_data + command_size > ETH_DATA_LEN) { |
339 if (cur_data - frame_data + datagram_size > ETH_DATA_LEN) { |
337 more_commands_waiting = 1; |
340 more_datagrams_waiting = 1; |
338 break; |
341 break; |
339 } |
342 } |
340 |
343 |
341 command->state = EC_CMD_SENT; |
344 datagram->state = EC_CMD_SENT; |
342 command->t_sent = t_start; |
345 datagram->t_sent = t_start; |
343 command->index = master->command_index++; |
346 datagram->index = master->datagram_index++; |
344 |
347 |
345 if (unlikely(master->debug_level > 0)) |
348 if (unlikely(master->debug_level > 1)) |
346 EC_DBG("adding command 0x%02X\n", command->index); |
349 EC_DBG("adding datagram 0x%02X\n", datagram->index); |
347 |
350 |
348 // set "command following" flag in previous frame |
351 // set "datagram following" flag in previous frame |
349 if (follows_word) |
352 if (follows_word) |
350 EC_WRITE_U16(follows_word, EC_READ_U16(follows_word) | 0x8000); |
353 EC_WRITE_U16(follows_word, EC_READ_U16(follows_word) | 0x8000); |
351 |
354 |
352 // EtherCAT command header |
355 // EtherCAT datagram header |
353 EC_WRITE_U8 (cur_data, command->type); |
356 EC_WRITE_U8 (cur_data, datagram->type); |
354 EC_WRITE_U8 (cur_data + 1, command->index); |
357 EC_WRITE_U8 (cur_data + 1, datagram->index); |
355 EC_WRITE_U32(cur_data + 2, command->address.logical); |
358 EC_WRITE_U32(cur_data + 2, datagram->address.logical); |
356 EC_WRITE_U16(cur_data + 6, command->data_size & 0x7FF); |
359 EC_WRITE_U16(cur_data + 6, datagram->data_size & 0x7FF); |
357 EC_WRITE_U16(cur_data + 8, 0x0000); |
360 EC_WRITE_U16(cur_data + 8, 0x0000); |
358 follows_word = cur_data + 6; |
361 follows_word = cur_data + 6; |
359 cur_data += EC_COMMAND_HEADER_SIZE; |
362 cur_data += EC_DATAGRAM_HEADER_SIZE; |
360 |
363 |
361 // EtherCAT command data |
364 // EtherCAT datagram data |
362 memcpy(cur_data, command->data, command->data_size); |
365 memcpy(cur_data, datagram->data, datagram->data_size); |
363 cur_data += command->data_size; |
366 cur_data += datagram->data_size; |
364 |
367 |
365 // EtherCAT command footer |
368 // EtherCAT datagram footer |
366 EC_WRITE_U16(cur_data, 0x0000); // reset working counter |
369 EC_WRITE_U16(cur_data, 0x0000); // reset working counter |
367 cur_data += EC_COMMAND_FOOTER_SIZE; |
370 cur_data += EC_DATAGRAM_FOOTER_SIZE; |
368 } |
371 } |
369 |
372 |
370 if (cur_data - frame_data == EC_FRAME_HEADER_SIZE) { |
373 if (cur_data - frame_data == EC_FRAME_HEADER_SIZE) { |
371 if (unlikely(master->debug_level > 0)) |
374 if (unlikely(master->debug_level > 1)) |
372 EC_DBG("nothing to send.\n"); |
375 EC_DBG("nothing to send.\n"); |
373 break; |
376 break; |
374 } |
377 } |
375 |
378 |
376 // EtherCAT frame header |
379 // EtherCAT frame header |
434 return; |
437 return; |
435 } |
438 } |
436 |
439 |
437 cmd_follows = 1; |
440 cmd_follows = 1; |
438 while (cmd_follows) { |
441 while (cmd_follows) { |
439 // process command header |
442 // process datagram header |
440 command_type = EC_READ_U8 (cur_data); |
443 datagram_type = EC_READ_U8 (cur_data); |
441 command_index = EC_READ_U8 (cur_data + 1); |
444 datagram_index = EC_READ_U8 (cur_data + 1); |
442 data_size = EC_READ_U16(cur_data + 6) & 0x07FF; |
445 data_size = EC_READ_U16(cur_data + 6) & 0x07FF; |
443 cmd_follows = EC_READ_U16(cur_data + 6) & 0x8000; |
446 cmd_follows = EC_READ_U16(cur_data + 6) & 0x8000; |
444 cur_data += EC_COMMAND_HEADER_SIZE; |
447 cur_data += EC_DATAGRAM_HEADER_SIZE; |
445 |
448 |
446 if (unlikely(cur_data - frame_data |
449 if (unlikely(cur_data - frame_data |
447 + data_size + EC_COMMAND_FOOTER_SIZE > size)) { |
450 + data_size + EC_DATAGRAM_FOOTER_SIZE > size)) { |
448 master->stats.corrupted++; |
451 master->stats.corrupted++; |
449 ec_master_output_stats(master); |
452 ec_master_output_stats(master); |
450 return; |
453 return; |
451 } |
454 } |
452 |
455 |
453 // search for matching command in the queue |
456 // search for matching datagram in the queue |
454 matched = 0; |
457 matched = 0; |
455 list_for_each_entry(command, &master->command_queue, queue) { |
458 list_for_each_entry(datagram, &master->datagram_queue, queue) { |
456 if (command->state == EC_CMD_SENT |
459 if (datagram->state == EC_CMD_SENT |
457 && command->type == command_type |
460 && datagram->type == datagram_type |
458 && command->index == command_index |
461 && datagram->index == datagram_index |
459 && command->data_size == data_size) { |
462 && datagram->data_size == data_size) { |
460 matched = 1; |
463 matched = 1; |
461 break; |
464 break; |
462 } |
465 } |
463 } |
466 } |
464 |
467 |
465 // no matching command was found |
468 // no matching datagram was found |
466 if (!matched) { |
469 if (!matched) { |
467 master->stats.unmatched++; |
470 master->stats.unmatched++; |
468 ec_master_output_stats(master); |
471 ec_master_output_stats(master); |
469 cur_data += data_size + EC_COMMAND_FOOTER_SIZE; |
472 cur_data += data_size + EC_DATAGRAM_FOOTER_SIZE; |
470 continue; |
473 continue; |
471 } |
474 } |
472 |
475 |
473 // copy received data in the command memory |
476 // copy received data in the datagram memory |
474 memcpy(command->data, cur_data, data_size); |
477 memcpy(datagram->data, cur_data, data_size); |
475 cur_data += data_size; |
478 cur_data += data_size; |
476 |
479 |
477 // set the command's working counter |
480 // set the datagram's working counter |
478 command->working_counter = EC_READ_U16(cur_data); |
481 datagram->working_counter = EC_READ_U16(cur_data); |
479 cur_data += EC_COMMAND_FOOTER_SIZE; |
482 cur_data += EC_DATAGRAM_FOOTER_SIZE; |
480 |
483 |
481 // dequeue the received command |
484 // dequeue the received datagram |
482 command->state = EC_CMD_RECEIVED; |
485 datagram->state = EC_CMD_RECEIVED; |
483 list_del_init(&command->queue); |
486 list_del_init(&datagram->queue); |
484 } |
487 } |
485 } |
488 } |
486 |
489 |
487 /*****************************************************************************/ |
490 /*****************************************************************************/ |
488 |
491 |
489 /** |
492 /** |
490 Sends a single command and waits for its reception. |
493 Sends a single datagram and waits for its reception. |
491 If the slave doesn't respond, the command is sent again. |
494 If the slave doesn't respond, the datagram is sent again. |
492 \return 0 in case of success, else < 0 |
495 \return 0 in case of success, else < 0 |
493 */ |
496 */ |
494 |
497 |
495 int ec_master_simple_io(ec_master_t *master, /**< EtherCAT master */ |
498 int ec_master_simple_io(ec_master_t *master, /**< EtherCAT master */ |
496 ec_command_t *command /**< command */ |
499 ec_datagram_t *datagram /**< datagram */ |
497 ) |
500 ) |
498 { |
501 { |
499 unsigned int response_tries_left; |
502 unsigned int response_tries_left; |
500 |
503 |
501 response_tries_left = 10000; |
504 response_tries_left = 10000; |
502 |
505 |
503 while (1) |
506 while (1) |
504 { |
507 { |
505 ec_master_queue_command(master, command); |
508 ec_master_queue_datagram(master, datagram); |
506 ecrt_master_sync_io(master); |
509 ecrt_master_sync_io(master); |
507 |
510 |
508 if (command->state == EC_CMD_RECEIVED) { |
511 if (datagram->state == EC_CMD_RECEIVED) { |
509 if (likely(command->working_counter)) |
512 if (likely(datagram->working_counter)) |
510 return 0; |
513 return 0; |
511 } |
514 } |
512 else if (command->state == EC_CMD_TIMEOUT) { |
515 else if (datagram->state == EC_CMD_TIMEOUT) { |
513 EC_ERR("Simple-IO TIMEOUT!\n"); |
516 EC_ERR("Simple-IO TIMEOUT!\n"); |
514 return -1; |
517 return -1; |
515 } |
518 } |
516 else if (command->state == EC_CMD_ERROR) { |
519 else if (datagram->state == EC_CMD_ERROR) { |
517 EC_ERR("Simple-IO command error!\n"); |
520 EC_ERR("Simple-IO datagram error!\n"); |
518 return -1; |
521 return -1; |
519 } |
522 } |
520 |
523 |
521 // no direct response, wait a little bit... |
524 // no direct response, wait a little bit... |
522 udelay(100); |
525 udelay(100); |
660 if (master->stats.corrupted) { |
663 if (master->stats.corrupted) { |
661 EC_WARN("%i frame(s) CORRUPTED!\n", master->stats.corrupted); |
664 EC_WARN("%i frame(s) CORRUPTED!\n", master->stats.corrupted); |
662 master->stats.corrupted = 0; |
665 master->stats.corrupted = 0; |
663 } |
666 } |
664 if (master->stats.unmatched) { |
667 if (master->stats.unmatched) { |
665 EC_WARN("%i command(s) UNMATCHED!\n", master->stats.unmatched); |
668 EC_WARN("%i datagram(s) UNMATCHED!\n", master->stats.unmatched); |
666 master->stats.unmatched = 0; |
669 master->stats.unmatched = 0; |
667 } |
670 } |
668 master->stats.t_last = t_now; |
671 master->stats.t_last = t_now; |
669 } |
672 } |
670 } |
673 } |
671 |
674 |
672 /*****************************************************************************/ |
675 /*****************************************************************************/ |
673 |
676 |
674 /** |
677 /** |
675 Starts the Free-Run mode. |
678 Starts the Idle mode. |
676 */ |
679 */ |
677 |
680 |
678 void ec_master_freerun_start(ec_master_t *master /**< EtherCAT master */) |
681 void ec_master_idle_start(ec_master_t *master /**< EtherCAT master */) |
679 { |
682 { |
680 if (master->mode == EC_MASTER_MODE_FREERUN) return; |
683 if (master->mode == EC_MASTER_MODE_IDLE) return; |
681 |
684 |
682 if (master->mode == EC_MASTER_MODE_RUNNING) { |
685 if (master->mode == EC_MASTER_MODE_RUNNING) { |
683 EC_ERR("ec_master_freerun_start: Master already running!\n"); |
686 EC_ERR("ec_master_idle_start: Master already running!\n"); |
684 return; |
687 return; |
685 } |
688 } |
686 |
689 |
687 EC_INFO("Starting Free-Run mode.\n"); |
690 EC_INFO("Starting Idle mode.\n"); |
688 |
691 |
689 master->mode = EC_MASTER_MODE_FREERUN; |
692 master->mode = EC_MASTER_MODE_IDLE; |
690 ec_fsm_reset(&master->fsm); |
693 ec_fsm_reset(&master->fsm); |
691 queue_delayed_work(master->workqueue, &master->freerun_work, 1); |
694 queue_delayed_work(master->workqueue, &master->idle_work, 1); |
692 } |
695 } |
693 |
696 |
694 /*****************************************************************************/ |
697 /*****************************************************************************/ |
695 |
698 |
696 /** |
699 /** |
697 Stops the Free-Run mode. |
700 Stops the Idle mode. |
698 */ |
701 */ |
699 |
702 |
700 void ec_master_freerun_stop(ec_master_t *master /**< EtherCAT master */) |
703 void ec_master_idle_stop(ec_master_t *master /**< EtherCAT master */) |
701 { |
704 { |
702 if (master->mode != EC_MASTER_MODE_FREERUN) return; |
705 if (master->mode != EC_MASTER_MODE_IDLE) return; |
703 |
706 |
704 ec_master_eoe_stop(master); |
707 ec_master_eoe_stop(master); |
705 |
708 |
706 EC_INFO("Stopping Free-Run mode.\n"); |
709 EC_INFO("Stopping Idle mode.\n"); |
707 master->mode = EC_MASTER_MODE_IDLE; |
710 master->mode = EC_MASTER_MODE_ORPHANED; // this is important for the |
708 |
711 // IDLE work function to not |
709 if (!cancel_delayed_work(&master->freerun_work)) { |
712 // queue itself again |
|
713 |
|
714 if (!cancel_delayed_work(&master->idle_work)) { |
710 flush_workqueue(master->workqueue); |
715 flush_workqueue(master->workqueue); |
711 } |
716 } |
712 |
717 |
713 ec_master_clear_slaves(master); |
718 ec_master_clear_slaves(master); |
714 } |
719 } |
715 |
720 |
716 /*****************************************************************************/ |
721 /*****************************************************************************/ |
717 |
722 |
718 /** |
723 /** |
719 Free-Run mode function. |
724 Idle mode function. |
720 */ |
725 */ |
721 |
726 |
722 void ec_master_freerun(void *data /**< master pointer */) |
727 void ec_master_idle_run(void *data /**< master pointer */) |
723 { |
728 { |
724 ec_master_t *master = (ec_master_t *) data; |
729 ec_master_t *master = (ec_master_t *) data; |
725 |
730 |
726 // aquire master lock |
731 // aquire master lock |
727 spin_lock_bh(&master->internal_lock); |
732 spin_lock_bh(&master->internal_lock); |
769 Initializes a sync manager configuration page with EEPROM data. |
774 Initializes a sync manager configuration page with EEPROM data. |
770 The referenced memory (\a data) must be at least EC_SYNC_SIZE bytes. |
775 The referenced memory (\a data) must be at least EC_SYNC_SIZE bytes. |
771 */ |
776 */ |
772 |
777 |
773 void ec_eeprom_sync_config(const ec_eeprom_sync_t *sync, /**< sync manager */ |
778 void ec_eeprom_sync_config(const ec_eeprom_sync_t *sync, /**< sync manager */ |
|
779 const ec_slave_t *slave, /**< EtherCAT slave */ |
774 uint8_t *data /**> configuration memory */ |
780 uint8_t *data /**> configuration memory */ |
775 ) |
781 ) |
776 { |
782 { |
|
783 size_t sync_size; |
|
784 |
|
785 sync_size = ec_slave_calc_eeprom_sync_size(slave, sync); |
|
786 |
|
787 if (slave->master->debug_level) { |
|
788 EC_INFO("Slave %i, sync manager %i:\n", slave->ring_position, |
|
789 sync->index); |
|
790 EC_INFO(" Address: 0x%04X\n", sync->physical_start_address); |
|
791 EC_INFO(" Size: %i\n", sync_size); |
|
792 EC_INFO(" Control: 0x%02X\n", sync->control_register); |
|
793 } |
|
794 |
777 EC_WRITE_U16(data, sync->physical_start_address); |
795 EC_WRITE_U16(data, sync->physical_start_address); |
778 EC_WRITE_U16(data + 2, sync->length); |
796 EC_WRITE_U16(data + 2, sync_size); |
779 EC_WRITE_U8 (data + 4, sync->control_register); |
797 EC_WRITE_U8 (data + 4, sync->control_register); |
780 EC_WRITE_U8 (data + 5, 0x00); // status byte (read only) |
798 EC_WRITE_U8 (data + 5, 0x00); // status byte (read only) |
781 EC_WRITE_U16(data + 6, sync->enable ? 0x0001 : 0x0000); // enable |
799 EC_WRITE_U16(data + 6, sync->enable ? 0x0001 : 0x0000); // enable |
782 } |
800 } |
783 |
801 |
1110 // check and reset CRC fault counters |
1152 // check and reset CRC fault counters |
1111 ec_slave_check_crc(slave); |
1153 ec_slave_check_crc(slave); |
1112 |
1154 |
1113 // reset FMMUs |
1155 // reset FMMUs |
1114 if (slave->base_fmmu_count) { |
1156 if (slave->base_fmmu_count) { |
1115 if (ec_command_npwr(command, slave->station_address, 0x0600, |
1157 if (ec_datagram_npwr(datagram, slave->station_address, 0x0600, |
1116 EC_FMMU_SIZE * slave->base_fmmu_count)) |
1158 EC_FMMU_SIZE * slave->base_fmmu_count)) |
1117 return -1; |
1159 return -1; |
1118 memset(command->data, 0x00, EC_FMMU_SIZE * slave->base_fmmu_count); |
1160 memset(datagram->data, 0x00, |
1119 if (unlikely(ec_master_simple_io(master, command))) { |
1161 EC_FMMU_SIZE * slave->base_fmmu_count); |
|
1162 if (unlikely(ec_master_simple_io(master, datagram))) { |
1120 EC_ERR("Resetting FMMUs failed on slave %i!\n", |
1163 EC_ERR("Resetting FMMUs failed on slave %i!\n", |
1121 slave->ring_position); |
1164 slave->ring_position); |
1122 return -1; |
1165 return -1; |
1123 } |
1166 } |
1124 } |
1167 } |
1125 |
1168 |
1126 // reset sync managers |
1169 // reset sync managers |
1127 if (slave->base_sync_count) { |
1170 if (slave->base_sync_count) { |
1128 if (ec_command_npwr(command, slave->station_address, 0x0800, |
1171 if (ec_datagram_npwr(datagram, slave->station_address, 0x0800, |
1129 EC_SYNC_SIZE * slave->base_sync_count)) |
1172 EC_SYNC_SIZE * slave->base_sync_count)) |
1130 return -1; |
1173 return -1; |
1131 memset(command->data, 0x00, EC_SYNC_SIZE * slave->base_sync_count); |
1174 memset(datagram->data, 0x00, |
1132 if (unlikely(ec_master_simple_io(master, command))) { |
1175 EC_SYNC_SIZE * slave->base_sync_count); |
|
1176 if (unlikely(ec_master_simple_io(master, datagram))) { |
1133 EC_ERR("Resetting sync managers failed on slave %i!\n", |
1177 EC_ERR("Resetting sync managers failed on slave %i!\n", |
1134 slave->ring_position); |
1178 slave->ring_position); |
1135 return -1; |
1179 return -1; |
1136 } |
1180 } |
1137 } |
1181 } |
1138 |
1182 |
1139 // configure sync managers |
1183 // configure sync managers |
1140 if (type) { // known slave type, take type's SM information |
1184 |
|
1185 // does the slave provide sync manager information? |
|
1186 if (!list_empty(&slave->eeprom_syncs)) { |
|
1187 list_for_each_entry(eeprom_sync, &slave->eeprom_syncs, list) { |
|
1188 if (ec_datagram_npwr(datagram, slave->station_address, |
|
1189 0x800 + eeprom_sync->index * |
|
1190 EC_SYNC_SIZE, |
|
1191 EC_SYNC_SIZE)) return -1; |
|
1192 ec_eeprom_sync_config(eeprom_sync, slave, datagram->data); |
|
1193 if (unlikely(ec_master_simple_io(master, datagram))) { |
|
1194 EC_ERR("Setting sync manager %i failed on slave %i!\n", |
|
1195 eeprom_sync->index, slave->ring_position); |
|
1196 return -1; |
|
1197 } |
|
1198 } |
|
1199 } |
|
1200 |
|
1201 else if (type) { // known slave type, take type's SM information |
1141 for (j = 0; type->sync_managers[j] && j < EC_MAX_SYNC; j++) { |
1202 for (j = 0; type->sync_managers[j] && j < EC_MAX_SYNC; j++) { |
1142 sync = type->sync_managers[j]; |
1203 sync = type->sync_managers[j]; |
1143 if (ec_command_npwr(command, slave->station_address, |
1204 if (ec_datagram_npwr(datagram, slave->station_address, |
1144 0x0800 + j * EC_SYNC_SIZE, EC_SYNC_SIZE)) |
1205 0x0800 + j * EC_SYNC_SIZE, EC_SYNC_SIZE)) |
1145 return -1; |
1206 return -1; |
1146 ec_sync_config(sync, slave, command->data); |
1207 ec_sync_config(sync, slave, datagram->data); |
1147 if (unlikely(ec_master_simple_io(master, command))) { |
1208 if (unlikely(ec_master_simple_io(master, datagram))) { |
1148 EC_ERR("Setting sync manager %i failed on slave %i!\n", |
1209 EC_ERR("Setting sync manager %i failed on slave %i!\n", |
1149 j, slave->ring_position); |
1210 j, slave->ring_position); |
1150 return -1; |
1211 return -1; |
1151 } |
1212 } |
1152 } |
1213 } |
1153 } |
1214 } |
1154 else if (slave->sii_mailbox_protocols) { // unknown type, but mailbox |
1215 |
1155 // does the device supply SM configurations in its EEPROM? |
1216 // no sync manager information; guess mailbox settings |
1156 if (!list_empty(&slave->eeprom_syncs)) { |
1217 else if (slave->sii_mailbox_protocols) { |
1157 list_for_each_entry(eeprom_sync, &slave->eeprom_syncs, list) { |
1218 mbox_sync.physical_start_address = |
1158 EC_INFO("Sync manager %i...\n", eeprom_sync->index); |
1219 slave->sii_rx_mailbox_offset; |
1159 if (ec_command_npwr(command, slave->station_address, |
1220 mbox_sync.length = slave->sii_rx_mailbox_size; |
1160 0x800 + eeprom_sync->index * |
1221 mbox_sync.control_register = 0x26; |
1161 EC_SYNC_SIZE, |
1222 mbox_sync.enable = 1; |
1162 EC_SYNC_SIZE)) return -1; |
1223 if (ec_datagram_npwr(datagram, slave->station_address, |
1163 ec_eeprom_sync_config(eeprom_sync, command->data); |
1224 0x800,EC_SYNC_SIZE)) return -1; |
1164 if (unlikely(ec_master_simple_io(master, command))) { |
1225 ec_eeprom_sync_config(&mbox_sync, slave, datagram->data); |
1165 EC_ERR("Setting sync manager %i failed on slave %i!\n", |
1226 if (unlikely(ec_master_simple_io(master, datagram))) { |
1166 eeprom_sync->index, slave->ring_position); |
1227 EC_ERR("Setting sync manager 0 failed on slave %i!\n", |
1167 return -1; |
1228 slave->ring_position); |
1168 } |
1229 return -1; |
1169 } |
|
1170 } |
1230 } |
1171 else { // no sync manager information; guess mailbox settings |
1231 |
1172 mbox_sync.physical_start_address = |
1232 mbox_sync.physical_start_address = |
1173 slave->sii_rx_mailbox_offset; |
1233 slave->sii_tx_mailbox_offset; |
1174 mbox_sync.length = slave->sii_rx_mailbox_size; |
1234 mbox_sync.length = slave->sii_tx_mailbox_size; |
1175 mbox_sync.control_register = 0x26; |
1235 mbox_sync.control_register = 0x22; |
1176 mbox_sync.enable = 1; |
1236 mbox_sync.enable = 1; |
1177 if (ec_command_npwr(command, slave->station_address, |
1237 if (ec_datagram_npwr(datagram, slave->station_address, |
1178 0x800,EC_SYNC_SIZE)) return -1; |
1238 0x808, EC_SYNC_SIZE)) return -1; |
1179 ec_eeprom_sync_config(&mbox_sync, command->data); |
1239 ec_eeprom_sync_config(&mbox_sync, slave, datagram->data); |
1180 if (unlikely(ec_master_simple_io(master, command))) { |
1240 if (unlikely(ec_master_simple_io(master, datagram))) { |
1181 EC_ERR("Setting sync manager 0 failed on slave %i!\n", |
|
1182 slave->ring_position); |
|
1183 return -1; |
|
1184 } |
|
1185 |
|
1186 mbox_sync.physical_start_address = |
|
1187 slave->sii_tx_mailbox_offset; |
|
1188 mbox_sync.length = slave->sii_tx_mailbox_size; |
|
1189 mbox_sync.control_register = 0x22; |
|
1190 mbox_sync.enable = 1; |
|
1191 if (ec_command_npwr(command, slave->station_address, |
|
1192 0x808, EC_SYNC_SIZE)) return -1; |
|
1193 ec_eeprom_sync_config(&mbox_sync, command->data); |
|
1194 if (unlikely(ec_master_simple_io(master, command))) { |
|
1195 EC_ERR("Setting sync manager 1 failed on slave %i!\n", |
1241 EC_ERR("Setting sync manager 1 failed on slave %i!\n", |
1196 slave->ring_position); |
1242 slave->ring_position); |
1197 return -1; |
1243 return -1; |
1198 } |
1244 } |
1199 } |
|
1200 EC_INFO("Mailbox configured for unknown slave %i\n", |
|
1201 slave->ring_position); |
|
1202 } |
1245 } |
1203 |
1246 |
1204 // change state to PREOP |
1247 // change state to PREOP |
1205 if (unlikely(ec_slave_state_change(slave, EC_SLAVE_STATE_PREOP))) |
1248 if (unlikely(ec_slave_state_change(slave, EC_SLAVE_STATE_PREOP))) |
1206 return -1; |
1249 return -1; |
1308 ec_device_call_isr(master->device); |
1351 ec_device_call_isr(master->device); |
1309 |
1352 |
1310 t_end = get_cycles(); // take current time |
1353 t_end = get_cycles(); // take current time |
1311 if (t_end - t_start >= t_timeout) break; // timeout! |
1354 if (t_end - t_start >= t_timeout) break; // timeout! |
1312 |
1355 |
1313 commands_sent = 0; |
1356 datagrams_sent = 0; |
1314 list_for_each_entry_safe(command, n, &master->command_queue, queue) { |
1357 list_for_each_entry_safe(datagram, n, &master->datagram_queue, queue) { |
1315 if (command->state == EC_CMD_RECEIVED) |
1358 if (datagram->state == EC_CMD_RECEIVED) |
1316 list_del_init(&command->queue); |
1359 list_del_init(&datagram->queue); |
1317 else if (command->state == EC_CMD_SENT) |
1360 else if (datagram->state == EC_CMD_SENT) |
1318 commands_sent++; |
1361 datagrams_sent++; |
1319 } |
1362 } |
1320 |
1363 |
1321 if (!commands_sent) break; |
1364 if (!datagrams_sent) break; |
1322 } |
1365 } |
1323 |
1366 |
1324 // timeout; dequeue all commands |
1367 // timeout; dequeue all datagrams |
1325 list_for_each_entry_safe(command, n, &master->command_queue, queue) { |
1368 list_for_each_entry_safe(datagram, n, &master->datagram_queue, queue) { |
1326 switch (command->state) { |
1369 switch (datagram->state) { |
1327 case EC_CMD_SENT: |
1370 case EC_CMD_SENT: |
1328 case EC_CMD_QUEUED: |
1371 case EC_CMD_QUEUED: |
1329 command->state = EC_CMD_TIMEOUT; |
1372 datagram->state = EC_CMD_TIMEOUT; |
1330 master->stats.timeouts++; |
1373 master->stats.timeouts++; |
1331 ec_master_output_stats(master); |
1374 ec_master_output_stats(master); |
1332 break; |
1375 break; |
1333 case EC_CMD_RECEIVED: |
1376 case EC_CMD_RECEIVED: |
1334 master->stats.delayed++; |
1377 master->stats.delayed++; |
1335 ec_master_output_stats(master); |
1378 ec_master_output_stats(master); |
1336 break; |
1379 break; |
1337 default: |
1380 default: |
1338 break; |
1381 break; |
1339 } |
1382 } |
1340 list_del_init(&command->queue); |
1383 list_del_init(&datagram->queue); |
1341 } |
1384 } |
1342 } |
1385 } |
1343 |
1386 |
1344 /*****************************************************************************/ |
1387 /*****************************************************************************/ |
1345 |
1388 |
1346 /** |
1389 /** |
1347 Asynchronous sending of commands. |
1390 Asynchronous sending of datagrams. |
1348 \ingroup RealtimeInterface |
1391 \ingroup RealtimeInterface |
1349 */ |
1392 */ |
1350 |
1393 |
1351 void ecrt_master_async_send(ec_master_t *master /**< EtherCAT master */) |
1394 void ecrt_master_async_send(ec_master_t *master /**< EtherCAT master */) |
1352 { |
1395 { |
1353 ec_command_t *command, *n; |
1396 ec_datagram_t *datagram, *n; |
1354 |
1397 |
1355 if (unlikely(!master->device->link_state)) { |
1398 if (unlikely(!master->device->link_state)) { |
1356 // link is down, no command can be sent |
1399 // link is down, no datagram can be sent |
1357 list_for_each_entry_safe(command, n, &master->command_queue, queue) { |
1400 list_for_each_entry_safe(datagram, n, &master->datagram_queue, queue) { |
1358 command->state = EC_CMD_ERROR; |
1401 datagram->state = EC_CMD_ERROR; |
1359 list_del_init(&command->queue); |
1402 list_del_init(&datagram->queue); |
1360 } |
1403 } |
1361 |
1404 |
1362 // query link state |
1405 // query link state |
1363 ec_device_call_isr(master->device); |
1406 ec_device_call_isr(master->device); |
1364 return; |
1407 return; |
1365 } |
1408 } |
1366 |
1409 |
1367 // send frames |
1410 // send frames |
1368 ec_master_send_commands(master); |
1411 ec_master_send_datagrams(master); |
1369 } |
1412 } |
1370 |
1413 |
1371 /*****************************************************************************/ |
1414 /*****************************************************************************/ |
1372 |
1415 |
1373 /** |
1416 /** |
1374 Asynchronous receiving of commands. |
1417 Asynchronous receiving of datagrams. |
1375 \ingroup RealtimeInterface |
1418 \ingroup RealtimeInterface |
1376 */ |
1419 */ |
1377 |
1420 |
1378 void ecrt_master_async_receive(ec_master_t *master /**< EtherCAT master */) |
1421 void ecrt_master_async_receive(ec_master_t *master /**< EtherCAT master */) |
1379 { |
1422 { |
1380 ec_command_t *command, *next; |
1423 ec_datagram_t *datagram, *next; |
1381 cycles_t t_received, t_timeout; |
1424 cycles_t t_received, t_timeout; |
1382 |
1425 |
1383 ec_device_call_isr(master->device); |
1426 ec_device_call_isr(master->device); |
1384 |
1427 |
1385 t_received = get_cycles(); |
1428 t_received = get_cycles(); |
1386 t_timeout = (cycles_t) master->timeout * (cpu_khz / 1000); |
1429 t_timeout = (cycles_t) master->timeout * (cpu_khz / 1000); |
1387 |
1430 |
1388 // dequeue all received commands |
1431 // dequeue all received datagrams |
1389 list_for_each_entry_safe(command, next, &master->command_queue, queue) |
1432 list_for_each_entry_safe(datagram, next, &master->datagram_queue, queue) |
1390 if (command->state == EC_CMD_RECEIVED) list_del_init(&command->queue); |
1433 if (datagram->state == EC_CMD_RECEIVED) |
1391 |
1434 list_del_init(&datagram->queue); |
1392 // dequeue all commands that timed out |
1435 |
1393 list_for_each_entry_safe(command, next, &master->command_queue, queue) { |
1436 // dequeue all datagrams that timed out |
1394 switch (command->state) { |
1437 list_for_each_entry_safe(datagram, next, &master->datagram_queue, queue) { |
|
1438 switch (datagram->state) { |
1395 case EC_CMD_SENT: |
1439 case EC_CMD_SENT: |
1396 case EC_CMD_QUEUED: |
1440 case EC_CMD_QUEUED: |
1397 if (t_received - command->t_sent > t_timeout) { |
1441 if (t_received - datagram->t_sent > t_timeout) { |
1398 list_del_init(&command->queue); |
1442 list_del_init(&datagram->queue); |
1399 command->state = EC_CMD_TIMEOUT; |
1443 datagram->state = EC_CMD_TIMEOUT; |
1400 master->stats.timeouts++; |
1444 master->stats.timeouts++; |
1401 ec_master_output_stats(master); |
1445 ec_master_output_stats(master); |
1402 } |
1446 } |
1403 break; |
1447 break; |
1404 default: |
1448 default: |