133 { |
133 { |
134 return fsm->state != ec_fsm_master_state_end |
134 return fsm->state != ec_fsm_master_state_end |
135 && fsm->state != ec_fsm_master_state_error; |
135 && fsm->state != ec_fsm_master_state_error; |
136 } |
136 } |
137 |
137 |
138 /*****************************************************************************/ |
|
139 |
|
140 /** |
|
141 \return true, if the master state machine terminated gracefully |
|
142 */ |
|
143 |
|
144 int ec_fsm_master_success(ec_fsm_master_t *fsm /**< master state machine */) |
|
145 { |
|
146 return fsm->state == ec_fsm_master_state_end; |
|
147 } |
|
148 |
|
149 /****************************************************************************** |
138 /****************************************************************************** |
150 * operation/idle state machine |
139 * master state machine |
151 *****************************************************************************/ |
140 *****************************************************************************/ |
152 |
141 |
153 /** |
142 /** |
154 Master state: START. |
143 Master state: START. |
155 Starts with getting slave count and slave states. |
144 Starts with getting slave count and slave states. |
156 */ |
145 */ |
157 |
146 |
158 void ec_fsm_master_state_start(ec_fsm_master_t *fsm) |
147 void ec_fsm_master_state_start(ec_fsm_master_t *fsm) |
159 { |
148 { |
160 ec_datagram_brd(fsm->datagram, 0x0130, 2); |
149 ec_datagram_brd(fsm->datagram, 0x0130, 2); |
161 ec_master_queue_datagram(fsm->master, fsm->datagram); |
|
162 fsm->state = ec_fsm_master_state_broadcast; |
150 fsm->state = ec_fsm_master_state_broadcast; |
163 } |
151 } |
164 |
152 |
165 /*****************************************************************************/ |
153 /*****************************************************************************/ |
166 |
154 |
174 ec_datagram_t *datagram = fsm->datagram; |
162 ec_datagram_t *datagram = fsm->datagram; |
175 unsigned int i; |
163 unsigned int i; |
176 ec_slave_t *slave; |
164 ec_slave_t *slave; |
177 ec_master_t *master = fsm->master; |
165 ec_master_t *master = fsm->master; |
178 |
166 |
179 if (datagram->state == EC_DATAGRAM_TIMED_OUT) { |
167 if (datagram->state == EC_DATAGRAM_TIMED_OUT) |
180 // always retry |
168 return; // always retry |
181 ec_master_queue_datagram(fsm->master, fsm->datagram); |
|
182 return; |
|
183 } |
|
184 |
169 |
185 if (datagram->state != EC_DATAGRAM_RECEIVED) { // EC_DATAGRAM_ERROR |
170 if (datagram->state != EC_DATAGRAM_RECEIVED) { // EC_DATAGRAM_ERROR |
186 // link is down |
171 // link is down |
187 fsm->slaves_responding = 0; |
172 fsm->slaves_responding = 0; |
188 list_for_each_entry(slave, &master->slaves, list) { |
173 list_for_each_entry(slave, &master->slaves, list) { |
258 |
243 |
259 EC_INFO("Scanning bus.\n"); |
244 EC_INFO("Scanning bus.\n"); |
260 |
245 |
261 // begin scanning of slaves |
246 // begin scanning of slaves |
262 fsm->slave = list_entry(master->slaves.next, ec_slave_t, list); |
247 fsm->slave = list_entry(master->slaves.next, ec_slave_t, list); |
|
248 fsm->state = ec_fsm_master_state_scan_slaves; |
263 ec_fsm_slave_start_scan(&fsm->fsm_slave, fsm->slave); |
249 ec_fsm_slave_start_scan(&fsm->fsm_slave, fsm->slave); |
264 ec_fsm_slave_exec(&fsm->fsm_slave); // execute immediately |
250 ec_fsm_slave_exec(&fsm->fsm_slave); // execute immediately |
265 fsm->state = ec_fsm_master_state_scan_slaves; |
|
266 return; |
251 return; |
267 } |
252 } |
268 |
253 |
269 // fetch state from each slave |
254 // fetch state from each slave |
270 fsm->slave = list_entry(master->slaves.next, ec_slave_t, list); |
255 fsm->slave = list_entry(master->slaves.next, ec_slave_t, list); |
271 ec_datagram_nprd(fsm->datagram, fsm->slave->station_address, 0x0130, 2); |
256 ec_datagram_nprd(fsm->datagram, fsm->slave->station_address, 0x0130, 2); |
272 ec_master_queue_datagram(master, fsm->datagram); |
|
273 fsm->retries = EC_FSM_RETRIES; |
257 fsm->retries = EC_FSM_RETRIES; |
274 fsm->state = ec_fsm_master_state_read_states; |
258 fsm->state = ec_fsm_master_state_read_states; |
275 } |
259 } |
276 |
260 |
277 /*****************************************************************************/ |
261 /*****************************************************************************/ |
363 slave->ring_position, old_state); |
347 slave->ring_position, old_state); |
364 } |
348 } |
365 } |
349 } |
366 |
350 |
367 fsm->slave = slave; |
351 fsm->slave = slave; |
|
352 fsm->state = ec_fsm_master_state_configure_slave; |
368 ec_fsm_slave_start_conf(&fsm->fsm_slave, slave); |
353 ec_fsm_slave_start_conf(&fsm->fsm_slave, slave); |
369 ec_fsm_slave_exec(&fsm->fsm_slave); // execute immediately |
354 ec_fsm_slave_exec(&fsm->fsm_slave); // execute immediately |
370 fsm->state = ec_fsm_master_state_configure_slave; |
|
371 return; |
355 return; |
372 } |
356 } |
373 |
357 |
374 // Check, if EoE processing has to be started |
358 // Check, if EoE processing has to be started |
375 ec_master_eoe_start(master); |
359 ec_master_eoe_start(master); |
389 master->sdo_seq_master++; |
373 master->sdo_seq_master++; |
390 } |
374 } |
391 else { |
375 else { |
392 // start uploading SDO |
376 // start uploading SDO |
393 fsm->slave = slave; |
377 fsm->slave = slave; |
|
378 fsm->sdo_request = master->sdo_request; |
394 fsm->state = ec_fsm_master_state_sdo_request; |
379 fsm->state = ec_fsm_master_state_sdo_request; |
395 fsm->sdo_request = master->sdo_request; |
|
396 ec_fsm_coe_upload(&fsm->fsm_coe, slave, fsm->sdo_request); |
380 ec_fsm_coe_upload(&fsm->fsm_coe, slave, fsm->sdo_request); |
397 ec_fsm_coe_exec(&fsm->fsm_coe); // execute immediately |
381 ec_fsm_coe_exec(&fsm->fsm_coe); // execute immediately |
398 return; |
382 return; |
399 } |
383 } |
400 } |
384 } |
444 ec_slave_t *slave = fsm->slave; |
428 ec_slave_t *slave = fsm->slave; |
445 |
429 |
446 // is there another slave to query? |
430 // is there another slave to query? |
447 if (slave->list.next != &master->slaves) { |
431 if (slave->list.next != &master->slaves) { |
448 // process next slave |
432 // process next slave |
449 fsm->slave = list_entry(fsm->slave->list.next, ec_slave_t, list); |
433 fsm->slave = list_entry(slave->list.next, ec_slave_t, list); |
450 ec_datagram_nprd(fsm->datagram, fsm->slave->station_address, |
434 ec_datagram_nprd(fsm->datagram, fsm->slave->station_address, |
451 0x0130, 2); |
435 0x0130, 2); |
452 ec_master_queue_datagram(master, fsm->datagram); |
|
453 fsm->retries = EC_FSM_RETRIES; |
436 fsm->retries = EC_FSM_RETRIES; |
454 fsm->state = ec_fsm_master_state_read_states; |
437 fsm->state = ec_fsm_master_state_read_states; |
455 return; |
438 return; |
456 } |
439 } |
457 |
440 |
486 void ec_fsm_master_state_read_states(ec_fsm_master_t *fsm /**< master state machine */) |
469 void ec_fsm_master_state_read_states(ec_fsm_master_t *fsm /**< master state machine */) |
487 { |
470 { |
488 ec_slave_t *slave = fsm->slave; |
471 ec_slave_t *slave = fsm->slave; |
489 ec_datagram_t *datagram = fsm->datagram; |
472 ec_datagram_t *datagram = fsm->datagram; |
490 |
473 |
491 if (datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--) { |
474 if (datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--) |
492 ec_master_queue_datagram(fsm->master, fsm->datagram); |
475 return; |
493 return; |
|
494 } |
|
495 |
476 |
496 if (datagram->state != EC_DATAGRAM_RECEIVED) { |
477 if (datagram->state != EC_DATAGRAM_RECEIVED) { |
497 EC_ERR("Failed to receive AL state datagram for slave %i" |
478 EC_ERR("Failed to receive AL state datagram for slave %i" |
498 " (datagram state %i)\n", slave->ring_position, datagram->state); |
479 " (datagram state %i)\n", slave->ring_position, datagram->state); |
499 fsm->state = ec_fsm_master_state_error; |
480 fsm->state = ec_fsm_master_state_error; |
511 ec_slave_set_state(slave, EC_READ_U8(datagram->data)); // set app state first |
492 ec_slave_set_state(slave, EC_READ_U8(datagram->data)); // set app state first |
512 ec_slave_set_online_state(slave, EC_SLAVE_ONLINE); |
493 ec_slave_set_online_state(slave, EC_SLAVE_ONLINE); |
513 |
494 |
514 // check, if new slave state has to be acknowledged |
495 // check, if new slave state has to be acknowledged |
515 if (slave->current_state & EC_SLAVE_STATE_ACK_ERR && !slave->error_flag) { |
496 if (slave->current_state & EC_SLAVE_STATE_ACK_ERR && !slave->error_flag) { |
|
497 fsm->state = ec_fsm_master_state_acknowledge; |
516 ec_fsm_change_ack(&fsm->fsm_change, slave); |
498 ec_fsm_change_ack(&fsm->fsm_change, slave); |
517 ec_fsm_change_exec(&fsm->fsm_change); |
499 ec_fsm_change_exec(&fsm->fsm_change); |
518 fsm->state = ec_fsm_master_state_acknowledge; |
|
519 return; |
500 return; |
520 } |
501 } |
521 |
502 |
522 ec_fsm_master_action_next_slave_state(fsm); |
503 ec_fsm_master_action_next_slave_state(fsm); |
523 } |
504 } |
590 { |
571 { |
591 ec_datagram_t *datagram = fsm->datagram; |
572 ec_datagram_t *datagram = fsm->datagram; |
592 |
573 |
593 while (fsm->slave->online_state == EC_SLAVE_ONLINE) { |
574 while (fsm->slave->online_state == EC_SLAVE_ONLINE) { |
594 if (fsm->slave->list.next == &fsm->master->slaves) { // last slave? |
575 if (fsm->slave->list.next == &fsm->master->slaves) { // last slave? |
595 fsm->state = ec_fsm_master_state_start; |
576 fsm->state = ec_fsm_master_state_end; |
596 fsm->state(fsm); // execute immediately |
|
597 return; |
577 return; |
598 } |
578 } |
599 // check next slave |
579 // check next slave |
600 fsm->slave = list_entry(fsm->slave->list.next, ec_slave_t, list); |
580 fsm->slave = list_entry(fsm->slave->list.next, ec_slave_t, list); |
601 } |
581 } |
604 EC_DBG("Reinitializing slave %i.\n", fsm->slave->ring_position); |
584 EC_DBG("Reinitializing slave %i.\n", fsm->slave->ring_position); |
605 |
585 |
606 // write station address |
586 // write station address |
607 ec_datagram_apwr(datagram, fsm->slave->ring_position, 0x0010, 2); |
587 ec_datagram_apwr(datagram, fsm->slave->ring_position, 0x0010, 2); |
608 EC_WRITE_U16(datagram->data, fsm->slave->station_address); |
588 EC_WRITE_U16(datagram->data, fsm->slave->station_address); |
609 ec_master_queue_datagram(fsm->master, datagram); |
|
610 fsm->retries = EC_FSM_RETRIES; |
589 fsm->retries = EC_FSM_RETRIES; |
611 fsm->state = ec_fsm_master_state_rewrite_addresses; |
590 fsm->state = ec_fsm_master_state_rewrite_addresses; |
612 } |
591 } |
613 |
592 |
614 /*****************************************************************************/ |
593 /*****************************************************************************/ |
668 ) |
647 ) |
669 { |
648 { |
670 ec_slave_t *slave = fsm->slave; |
649 ec_slave_t *slave = fsm->slave; |
671 ec_datagram_t *datagram = fsm->datagram; |
650 ec_datagram_t *datagram = fsm->datagram; |
672 |
651 |
673 if (datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--) { |
652 if (datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--) |
674 ec_master_queue_datagram(fsm->master, fsm->datagram); |
653 return; |
675 return; |
|
676 } |
|
677 |
654 |
678 if (datagram->state != EC_DATAGRAM_RECEIVED) { |
655 if (datagram->state != EC_DATAGRAM_RECEIVED) { |
679 EC_ERR("Failed to receive address datagram for slave %i" |
656 EC_ERR("Failed to receive address datagram for slave %i" |
680 " (datagram state %i).\n", |
657 " (datagram state %i).\n", |
681 slave->ring_position, datagram->state); |
658 slave->ring_position, datagram->state); |
689 fsm->state = ec_fsm_master_state_error; |
666 fsm->state = ec_fsm_master_state_error; |
690 return; |
667 return; |
691 } |
668 } |
692 |
669 |
693 if (fsm->slave->list.next == &fsm->master->slaves) { // last slave? |
670 if (fsm->slave->list.next == &fsm->master->slaves) { // last slave? |
694 fsm->state = ec_fsm_master_state_start; |
671 fsm->state = ec_fsm_master_state_end; |
695 fsm->state(fsm); // execute immediately |
|
696 return; |
672 return; |
697 } |
673 } |
698 |
674 |
699 // check next slave |
675 // check next slave |
700 fsm->slave = list_entry(fsm->slave->list.next, ec_slave_t, list); |
676 fsm->slave = list_entry(fsm->slave->list.next, ec_slave_t, list); |
710 */ |
686 */ |
711 |
687 |
712 void ec_fsm_master_state_scan_slaves(ec_fsm_master_t *fsm /**< master state machine */) |
688 void ec_fsm_master_state_scan_slaves(ec_fsm_master_t *fsm /**< master state machine */) |
713 { |
689 { |
714 ec_master_t *master = fsm->master; |
690 ec_master_t *master = fsm->master; |
715 ec_slave_t *slave; |
691 ec_slave_t *slave = fsm->slave; |
716 |
692 |
717 if (ec_fsm_slave_exec(&fsm->fsm_slave)) // execute slave state machine |
693 if (ec_fsm_slave_exec(&fsm->fsm_slave)) // execute slave state machine |
718 return; |
694 return; |
719 |
695 |
720 // another slave to fetch? |
696 // another slave to fetch? |
721 if (fsm->slave->list.next != &master->slaves) { |
697 if (slave->list.next != &master->slaves) { |
722 fsm->slave = list_entry(fsm->slave->list.next, ec_slave_t, list); |
698 fsm->slave = list_entry(slave->list.next, ec_slave_t, list); |
723 ec_fsm_slave_start_scan(&fsm->fsm_slave, fsm->slave); |
699 ec_fsm_slave_start_scan(&fsm->fsm_slave, fsm->slave); |
724 ec_fsm_slave_exec(&fsm->fsm_slave); // execute immediately |
700 ec_fsm_slave_exec(&fsm->fsm_slave); // execute immediately |
725 return; |
701 return; |
726 } |
702 } |
727 |
703 |
801 |
777 |
802 // check for another EEPROM write request |
778 // check for another EEPROM write request |
803 if (ec_fsm_master_action_process_eeprom(fsm)) |
779 if (ec_fsm_master_action_process_eeprom(fsm)) |
804 return; // processing another request |
780 return; // processing another request |
805 |
781 |
806 // restart master state machine. |
782 fsm->state = ec_fsm_master_state_end; |
807 fsm->state = ec_fsm_master_state_start; |
|
808 fsm->state(fsm); // execute immediately |
|
809 } |
783 } |
810 |
784 |
811 /*****************************************************************************/ |
785 /*****************************************************************************/ |
812 |
786 |
813 /** |
787 /** |
833 ec_slave_sdo_dict_info(slave, &sdo_count, &entry_count); |
807 ec_slave_sdo_dict_info(slave, &sdo_count, &entry_count); |
834 EC_DBG("Fetched %i SDOs and %i entries from slave %i.\n", |
808 EC_DBG("Fetched %i SDOs and %i entries from slave %i.\n", |
835 sdo_count, entry_count, slave->ring_position); |
809 sdo_count, entry_count, slave->ring_position); |
836 } |
810 } |
837 |
811 |
838 // restart master state machine. |
812 fsm->state = ec_fsm_master_state_end; |
839 fsm->state = ec_fsm_master_state_start; |
|
840 fsm->state(fsm); // execute immediately |
|
841 } |
813 } |
842 |
814 |
843 /*****************************************************************************/ |
815 /*****************************************************************************/ |
844 |
816 |
845 /** |
817 /** |
863 // SDO dictionary fetching finished |
835 // SDO dictionary fetching finished |
864 |
836 |
865 request->return_code = 1; |
837 request->return_code = 1; |
866 master->sdo_seq_master++; |
838 master->sdo_seq_master++; |
867 |
839 |
868 // restart master state machine. |
840 fsm->state = ec_fsm_master_state_end; |
869 fsm->state = ec_fsm_master_state_start; |
|
870 fsm->state(fsm); // execute immediately |
|
871 } |
841 } |
872 |
842 |
873 /*****************************************************************************/ |
843 /*****************************************************************************/ |
874 |
844 |
875 /** |
845 /** |