changeset 293 | 14aeb79aa992 |
parent 292 | 2cf6ae0a2419 |
child 297 | ac2a057a8ef2 |
child 1715 | e675450f2174 |
292:2cf6ae0a2419 | 293:14aeb79aa992 |
---|---|
105 fsm->master_state = ec_fsm_master_start; |
105 fsm->master_state = ec_fsm_master_start; |
106 fsm->master_slaves_responding = 0; |
106 fsm->master_slaves_responding = 0; |
107 fsm->master_slave_states = EC_SLAVE_STATE_UNKNOWN; |
107 fsm->master_slave_states = EC_SLAVE_STATE_UNKNOWN; |
108 fsm->master_validation = 0; |
108 fsm->master_validation = 0; |
109 |
109 |
110 ec_command_init(&fsm->command); |
110 ec_datagram_init(&fsm->datagram); |
111 if (ec_command_prealloc(&fsm->command, EC_MAX_DATA_SIZE)) { |
111 if (ec_datagram_prealloc(&fsm->datagram, EC_MAX_DATA_SIZE)) { |
112 EC_ERR("Failed to allocate FSM command.\n"); |
112 EC_ERR("Failed to allocate FSM datagram.\n"); |
113 return -1; |
113 return -1; |
114 } |
114 } |
115 |
115 |
116 return 0; |
116 return 0; |
117 } |
117 } |
122 Destructor. |
122 Destructor. |
123 */ |
123 */ |
124 |
124 |
125 void ec_fsm_clear(ec_fsm_t *fsm /**< finite state machine */) |
125 void ec_fsm_clear(ec_fsm_t *fsm /**< finite state machine */) |
126 { |
126 { |
127 ec_command_clear(&fsm->command); |
127 ec_datagram_clear(&fsm->datagram); |
128 } |
128 } |
129 |
129 |
130 /*****************************************************************************/ |
130 /*****************************************************************************/ |
131 |
131 |
132 /** |
132 /** |
160 Starts with getting slave count and slave states. |
160 Starts with getting slave count and slave states. |
161 */ |
161 */ |
162 |
162 |
163 void ec_fsm_master_start(ec_fsm_t *fsm) |
163 void ec_fsm_master_start(ec_fsm_t *fsm) |
164 { |
164 { |
165 ec_command_brd(&fsm->command, 0x0130, 2); |
165 ec_datagram_brd(&fsm->datagram, 0x0130, 2); |
166 ec_master_queue_command(fsm->master, &fsm->command); |
166 ec_master_queue_datagram(fsm->master, &fsm->datagram); |
167 fsm->master_state = ec_fsm_master_broadcast; |
167 fsm->master_state = ec_fsm_master_broadcast; |
168 } |
168 } |
169 |
169 |
170 /*****************************************************************************/ |
170 /*****************************************************************************/ |
171 |
171 |
174 Processes the broadcast read slave count and slaves states. |
174 Processes the broadcast read slave count and slaves states. |
175 */ |
175 */ |
176 |
176 |
177 void ec_fsm_master_broadcast(ec_fsm_t *fsm /**< finite state machine */) |
177 void ec_fsm_master_broadcast(ec_fsm_t *fsm /**< finite state machine */) |
178 { |
178 { |
179 ec_command_t *command = &fsm->command; |
179 ec_datagram_t *datagram = &fsm->datagram; |
180 unsigned int topology_change, states_change, i; |
180 unsigned int topology_change, states_change, i; |
181 ec_slave_t *slave; |
181 ec_slave_t *slave; |
182 ec_master_t *master = fsm->master; |
182 ec_master_t *master = fsm->master; |
183 |
183 |
184 if (command->state != EC_CMD_RECEIVED) { |
184 if (datagram->state != EC_CMD_RECEIVED) { |
185 if (!master->device->link_state) { |
185 if (!master->device->link_state) { |
186 fsm->master_slaves_responding = 0; |
186 fsm->master_slaves_responding = 0; |
187 list_for_each_entry(slave, &master->slaves, list) { |
187 list_for_each_entry(slave, &master->slaves, list) { |
188 slave->online = 0; |
188 slave->online = 0; |
189 } |
189 } |
191 fsm->master_state = ec_fsm_master_start; |
191 fsm->master_state = ec_fsm_master_start; |
192 fsm->master_state(fsm); // execute immediately |
192 fsm->master_state(fsm); // execute immediately |
193 return; |
193 return; |
194 } |
194 } |
195 |
195 |
196 topology_change = (command->working_counter != |
196 topology_change = (datagram->working_counter != |
197 fsm->master_slaves_responding); |
197 fsm->master_slaves_responding); |
198 states_change = (EC_READ_U8(command->data) != fsm->master_slave_states); |
198 states_change = (EC_READ_U8(datagram->data) != fsm->master_slave_states); |
199 |
199 |
200 fsm->master_slave_states = EC_READ_U8(command->data); |
200 fsm->master_slave_states = EC_READ_U8(datagram->data); |
201 fsm->master_slaves_responding = command->working_counter; |
201 fsm->master_slaves_responding = datagram->working_counter; |
202 |
202 |
203 if (topology_change) { |
203 if (topology_change) { |
204 EC_INFO("%i slave%s responding.\n", |
204 EC_INFO("%i slave%s responding.\n", |
205 fsm->master_slaves_responding, |
205 fsm->master_slaves_responding, |
206 fsm->master_slaves_responding == 1 ? "" : "s"); |
206 fsm->master_slaves_responding == 1 ? "" : "s"); |
270 return; |
270 return; |
271 } |
271 } |
272 |
272 |
273 // fetch state from each slave |
273 // fetch state from each slave |
274 fsm->slave = list_entry(master->slaves.next, ec_slave_t, list); |
274 fsm->slave = list_entry(master->slaves.next, ec_slave_t, list); |
275 ec_command_nprd(&fsm->command, fsm->slave->station_address, 0x0130, 2); |
275 ec_datagram_nprd(&fsm->datagram, fsm->slave->station_address, 0x0130, 2); |
276 ec_master_queue_command(master, &fsm->command); |
276 ec_master_queue_datagram(master, &fsm->datagram); |
277 fsm->master_state = ec_fsm_master_states; |
277 fsm->master_state = ec_fsm_master_states; |
278 } |
278 } |
279 |
279 |
280 /*****************************************************************************/ |
280 /*****************************************************************************/ |
281 |
281 |
291 |
291 |
292 // have all states been read? |
292 // have all states been read? |
293 if (slave->list.next != &master->slaves) { |
293 if (slave->list.next != &master->slaves) { |
294 // process next slave |
294 // process next slave |
295 fsm->slave = list_entry(fsm->slave->list.next, ec_slave_t, list); |
295 fsm->slave = list_entry(fsm->slave->list.next, ec_slave_t, list); |
296 ec_command_nprd(&fsm->command, fsm->slave->station_address, 0x0130, 2); |
296 ec_datagram_nprd(&fsm->datagram, fsm->slave->station_address, |
297 ec_master_queue_command(master, &fsm->command); |
297 0x0130, 2); |
298 ec_master_queue_datagram(master, &fsm->datagram); |
|
298 fsm->master_state = ec_fsm_master_states; |
299 fsm->master_state = ec_fsm_master_states; |
299 return; |
300 return; |
300 } |
301 } |
301 |
302 |
302 // all slave stated read; check, if a bus validation has to be done |
303 // all slave stated read; check, if a bus validation has to be done |
329 */ |
330 */ |
330 |
331 |
331 void ec_fsm_master_states(ec_fsm_t *fsm /**< finite state machine */) |
332 void ec_fsm_master_states(ec_fsm_t *fsm /**< finite state machine */) |
332 { |
333 { |
333 ec_slave_t *slave = fsm->slave; |
334 ec_slave_t *slave = fsm->slave; |
334 ec_command_t *command = &fsm->command; |
335 ec_datagram_t *datagram = &fsm->datagram; |
335 uint8_t new_state; |
336 uint8_t new_state; |
336 |
337 |
337 if (command->state != EC_CMD_RECEIVED) { |
338 if (datagram->state != EC_CMD_RECEIVED) { |
338 fsm->master_state = ec_fsm_master_start; |
339 fsm->master_state = ec_fsm_master_start; |
339 fsm->master_state(fsm); // execute immediately |
340 fsm->master_state(fsm); // execute immediately |
340 return; |
341 return; |
341 } |
342 } |
342 |
343 |
343 // did the slave not respond to its station address? |
344 // did the slave not respond to its station address? |
344 if (command->working_counter != 1) { |
345 if (datagram->working_counter != 1) { |
345 if (slave->online) { |
346 if (slave->online) { |
346 slave->online = 0; |
347 slave->online = 0; |
347 EC_INFO("Slave %i: offline.\n", slave->ring_position); |
348 EC_INFO("Slave %i: offline.\n", slave->ring_position); |
348 } |
349 } |
349 ec_fsm_master_action_next_slave_state(fsm); |
350 ec_fsm_master_action_next_slave_state(fsm); |
350 return; |
351 return; |
351 } |
352 } |
352 |
353 |
353 // slave responded |
354 // slave responded |
354 new_state = EC_READ_U8(command->data); |
355 new_state = EC_READ_U8(datagram->data); |
355 if (!slave->online) { // slave was offline before |
356 if (!slave->online) { // slave was offline before |
356 slave->online = 1; |
357 slave->online = 1; |
357 slave->error_flag = 0; // clear error flag |
358 slave->error_flag = 0; // clear error flag |
358 slave->current_state = new_state; |
359 slave->current_state = new_state; |
359 EC_INFO("Slave %i: online (", slave->ring_position); |
360 EC_INFO("Slave %i: online (", slave->ring_position); |
533 their station address, so that they can be reconfigured later. |
534 their station address, so that they can be reconfigured later. |
534 */ |
535 */ |
535 |
536 |
536 void ec_fsm_master_reconfigure(ec_fsm_t *fsm /**< finite state machine */) |
537 void ec_fsm_master_reconfigure(ec_fsm_t *fsm /**< finite state machine */) |
537 { |
538 { |
538 ec_command_t *command = &fsm->command; |
539 ec_datagram_t *datagram = &fsm->datagram; |
539 |
540 |
540 while (fsm->slave->online) { |
541 while (fsm->slave->online) { |
541 if (fsm->slave->list.next == &fsm->master->slaves) { // last slave? |
542 if (fsm->slave->list.next == &fsm->master->slaves) { // last slave? |
542 fsm->master_state = ec_fsm_master_start; |
543 fsm->master_state = ec_fsm_master_start; |
543 fsm->master_state(fsm); // execute immediately |
544 fsm->master_state(fsm); // execute immediately |
548 } |
549 } |
549 |
550 |
550 EC_INFO("Reinitializing slave %i.\n", fsm->slave->ring_position); |
551 EC_INFO("Reinitializing slave %i.\n", fsm->slave->ring_position); |
551 |
552 |
552 // write station address |
553 // write station address |
553 ec_command_apwr(command, fsm->slave->ring_position, 0x0010, 2); |
554 ec_datagram_apwr(datagram, fsm->slave->ring_position, 0x0010, 2); |
554 EC_WRITE_U16(command->data, fsm->slave->station_address); |
555 EC_WRITE_U16(datagram->data, fsm->slave->station_address); |
555 ec_master_queue_command(fsm->master, command); |
556 ec_master_queue_datagram(fsm->master, datagram); |
556 fsm->master_state = ec_fsm_master_address; |
557 fsm->master_state = ec_fsm_master_address; |
557 } |
558 } |
558 |
559 |
559 /*****************************************************************************/ |
560 /*****************************************************************************/ |
560 |
561 |
564 */ |
565 */ |
565 |
566 |
566 void ec_fsm_master_address(ec_fsm_t *fsm /**< finite state machine */) |
567 void ec_fsm_master_address(ec_fsm_t *fsm /**< finite state machine */) |
567 { |
568 { |
568 ec_slave_t *slave = fsm->slave; |
569 ec_slave_t *slave = fsm->slave; |
569 ec_command_t *command = &fsm->command; |
570 ec_datagram_t *datagram = &fsm->datagram; |
570 |
571 |
571 if (command->state != EC_CMD_RECEIVED || command->working_counter != 1) { |
572 if (datagram->state != EC_CMD_RECEIVED || datagram->working_counter != 1) { |
572 EC_ERR("Failed to write station address on slave %i.\n", |
573 EC_ERR("Failed to write station address on slave %i.\n", |
573 slave->ring_position); |
574 slave->ring_position); |
574 } |
575 } |
575 |
576 |
576 if (fsm->slave->list.next == &fsm->master->slaves) { // last slave? |
577 if (fsm->slave->list.next == &fsm->master->slaves) { // last slave? |
750 slave, according to its ring position. |
751 slave, according to its ring position. |
751 */ |
752 */ |
752 |
753 |
753 void ec_fsm_slave_start_reading(ec_fsm_t *fsm /**< finite state machine */) |
754 void ec_fsm_slave_start_reading(ec_fsm_t *fsm /**< finite state machine */) |
754 { |
755 { |
755 ec_command_t *command = &fsm->command; |
756 ec_datagram_t *datagram = &fsm->datagram; |
756 |
757 |
757 // write station address |
758 // write station address |
758 ec_command_apwr(command, fsm->slave->ring_position, 0x0010, 2); |
759 ec_datagram_apwr(datagram, fsm->slave->ring_position, 0x0010, 2); |
759 EC_WRITE_U16(command->data, fsm->slave->station_address); |
760 EC_WRITE_U16(datagram->data, fsm->slave->station_address); |
760 ec_master_queue_command(fsm->master, command); |
761 ec_master_queue_datagram(fsm->master, datagram); |
761 fsm->slave_state = ec_fsm_slave_read_state; |
762 fsm->slave_state = ec_fsm_slave_read_state; |
762 } |
763 } |
763 |
764 |
764 /*****************************************************************************/ |
765 /*****************************************************************************/ |
765 |
766 |
767 Slave state: READ_STATUS. |
768 Slave state: READ_STATUS. |
768 */ |
769 */ |
769 |
770 |
770 void ec_fsm_slave_read_state(ec_fsm_t *fsm /**< finite state machine */) |
771 void ec_fsm_slave_read_state(ec_fsm_t *fsm /**< finite state machine */) |
771 { |
772 { |
772 ec_command_t *command = &fsm->command; |
773 ec_datagram_t *datagram = &fsm->datagram; |
773 |
774 |
774 if (command->state != EC_CMD_RECEIVED || command->working_counter != 1) { |
775 if (datagram->state != EC_CMD_RECEIVED || datagram->working_counter != 1) { |
775 fsm->slave->error_flag = 1; |
776 fsm->slave->error_flag = 1; |
776 fsm->slave_state = ec_fsm_slave_end; |
777 fsm->slave_state = ec_fsm_slave_end; |
777 EC_ERR("Failed to write station address of slave %i.\n", |
778 EC_ERR("Failed to write station address of slave %i.\n", |
778 fsm->slave->ring_position); |
779 fsm->slave->ring_position); |
779 return; |
780 return; |
780 } |
781 } |
781 |
782 |
782 // Read AL state |
783 // Read AL state |
783 ec_command_nprd(command, fsm->slave->station_address, 0x0130, 2); |
784 ec_datagram_nprd(datagram, fsm->slave->station_address, 0x0130, 2); |
784 ec_master_queue_command(fsm->master, command); |
785 ec_master_queue_datagram(fsm->master, datagram); |
785 fsm->slave_state = ec_fsm_slave_read_base; |
786 fsm->slave_state = ec_fsm_slave_read_base; |
786 } |
787 } |
787 |
788 |
788 /*****************************************************************************/ |
789 /*****************************************************************************/ |
789 |
790 |
791 Slave state: READ_BASE. |
792 Slave state: READ_BASE. |
792 */ |
793 */ |
793 |
794 |
794 void ec_fsm_slave_read_base(ec_fsm_t *fsm /**< finite state machine */) |
795 void ec_fsm_slave_read_base(ec_fsm_t *fsm /**< finite state machine */) |
795 { |
796 { |
796 ec_command_t *command = &fsm->command; |
797 ec_datagram_t *datagram = &fsm->datagram; |
797 ec_slave_t *slave = fsm->slave; |
798 ec_slave_t *slave = fsm->slave; |
798 |
799 |
799 if (command->state != EC_CMD_RECEIVED || command->working_counter != 1) { |
800 if (datagram->state != EC_CMD_RECEIVED || datagram->working_counter != 1) { |
800 fsm->slave->error_flag = 1; |
801 fsm->slave->error_flag = 1; |
801 fsm->slave_state = ec_fsm_slave_end; |
802 fsm->slave_state = ec_fsm_slave_end; |
802 EC_ERR("Failed to read AL state of slave %i.\n", |
803 EC_ERR("Failed to read AL state of slave %i.\n", |
803 fsm->slave->ring_position); |
804 fsm->slave->ring_position); |
804 return; |
805 return; |
805 } |
806 } |
806 |
807 |
807 slave->current_state = EC_READ_U8(command->data); |
808 slave->current_state = EC_READ_U8(datagram->data); |
808 if (slave->current_state & EC_ACK) { |
809 if (slave->current_state & EC_ACK) { |
809 EC_WARN("Slave %i has state error bit set (0x%02X)!\n", |
810 EC_WARN("Slave %i has state error bit set (0x%02X)!\n", |
810 slave->ring_position, slave->current_state); |
811 slave->ring_position, slave->current_state); |
811 slave->current_state &= 0x0F; |
812 slave->current_state &= 0x0F; |
812 } |
813 } |
813 |
814 |
814 // read base data |
815 // read base data |
815 ec_command_nprd(command, fsm->slave->station_address, 0x0000, 6); |
816 ec_datagram_nprd(datagram, fsm->slave->station_address, 0x0000, 6); |
816 ec_master_queue_command(fsm->master, command); |
817 ec_master_queue_datagram(fsm->master, datagram); |
817 fsm->slave_state = ec_fsm_slave_read_dl; |
818 fsm->slave_state = ec_fsm_slave_read_dl; |
818 } |
819 } |
819 |
820 |
820 /*****************************************************************************/ |
821 /*****************************************************************************/ |
821 |
822 |
823 Slave state: READ_DL. |
824 Slave state: READ_DL. |
824 */ |
825 */ |
825 |
826 |
826 void ec_fsm_slave_read_dl(ec_fsm_t *fsm /**< finite state machine */) |
827 void ec_fsm_slave_read_dl(ec_fsm_t *fsm /**< finite state machine */) |
827 { |
828 { |
828 ec_command_t *command = &fsm->command; |
829 ec_datagram_t *datagram = &fsm->datagram; |
829 ec_slave_t *slave = fsm->slave; |
830 ec_slave_t *slave = fsm->slave; |
830 |
831 |
831 if (command->state != EC_CMD_RECEIVED || command->working_counter != 1) { |
832 if (datagram->state != EC_CMD_RECEIVED || datagram->working_counter != 1) { |
832 fsm->slave->error_flag = 1; |
833 fsm->slave->error_flag = 1; |
833 fsm->slave_state = ec_fsm_slave_end; |
834 fsm->slave_state = ec_fsm_slave_end; |
834 EC_ERR("Failed to read base data of slave %i.\n", |
835 EC_ERR("Failed to read base data of slave %i.\n", |
835 slave->ring_position); |
836 slave->ring_position); |
836 return; |
837 return; |
837 } |
838 } |
838 |
839 |
839 slave->base_type = EC_READ_U8 (command->data); |
840 slave->base_type = EC_READ_U8 (datagram->data); |
840 slave->base_revision = EC_READ_U8 (command->data + 1); |
841 slave->base_revision = EC_READ_U8 (datagram->data + 1); |
841 slave->base_build = EC_READ_U16(command->data + 2); |
842 slave->base_build = EC_READ_U16(datagram->data + 2); |
842 slave->base_fmmu_count = EC_READ_U8 (command->data + 4); |
843 slave->base_fmmu_count = EC_READ_U8 (datagram->data + 4); |
843 slave->base_sync_count = EC_READ_U8 (command->data + 5); |
844 slave->base_sync_count = EC_READ_U8 (datagram->data + 5); |
844 |
845 |
845 if (slave->base_fmmu_count > EC_MAX_FMMUS) |
846 if (slave->base_fmmu_count > EC_MAX_FMMUS) |
846 slave->base_fmmu_count = EC_MAX_FMMUS; |
847 slave->base_fmmu_count = EC_MAX_FMMUS; |
847 |
848 |
848 // read data link status |
849 // read data link status |
849 ec_command_nprd(command, slave->station_address, 0x0110, 2); |
850 ec_datagram_nprd(datagram, slave->station_address, 0x0110, 2); |
850 ec_master_queue_command(slave->master, command); |
851 ec_master_queue_datagram(slave->master, datagram); |
851 fsm->slave_state = ec_fsm_slave_eeprom_size; |
852 fsm->slave_state = ec_fsm_slave_eeprom_size; |
852 } |
853 } |
853 |
854 |
854 /*****************************************************************************/ |
855 /*****************************************************************************/ |
855 |
856 |
858 Read the actual size of the EEPROM to allocate the EEPROM image. |
859 Read the actual size of the EEPROM to allocate the EEPROM image. |
859 */ |
860 */ |
860 |
861 |
861 void ec_fsm_slave_eeprom_size(ec_fsm_t *fsm /**< finite state machine */) |
862 void ec_fsm_slave_eeprom_size(ec_fsm_t *fsm /**< finite state machine */) |
862 { |
863 { |
863 ec_command_t *command = &fsm->command; |
864 ec_datagram_t *datagram = &fsm->datagram; |
864 ec_slave_t *slave = fsm->slave; |
865 ec_slave_t *slave = fsm->slave; |
865 uint16_t dl_status; |
866 uint16_t dl_status; |
866 unsigned int i; |
867 unsigned int i; |
867 |
868 |
868 if (command->state != EC_CMD_RECEIVED || command->working_counter != 1) { |
869 if (datagram->state != EC_CMD_RECEIVED || datagram->working_counter != 1) { |
869 fsm->slave->error_flag = 1; |
870 fsm->slave->error_flag = 1; |
870 fsm->slave_state = ec_fsm_slave_end; |
871 fsm->slave_state = ec_fsm_slave_end; |
871 EC_ERR("Failed to read DL status of slave %i.\n", |
872 EC_ERR("Failed to read DL status of slave %i.\n", |
872 slave->ring_position); |
873 slave->ring_position); |
873 return; |
874 return; |
874 } |
875 } |
875 |
876 |
876 dl_status = EC_READ_U16(command->data); |
877 dl_status = EC_READ_U16(datagram->data); |
877 for (i = 0; i < 4; i++) { |
878 for (i = 0; i < 4; i++) { |
878 slave->dl_link[i] = dl_status & (1 << (4 + i)) ? 1 : 0; |
879 slave->dl_link[i] = dl_status & (1 << (4 + i)) ? 1 : 0; |
879 slave->dl_loop[i] = dl_status & (1 << (8 + i * 2)) ? 1 : 0; |
880 slave->dl_loop[i] = dl_status & (1 << (8 + i * 2)) ? 1 : 0; |
880 slave->dl_signal[i] = dl_status & (1 << (9 + i * 2)) ? 1 : 0; |
881 slave->dl_signal[i] = dl_status & (1 << (9 + i * 2)) ? 1 : 0; |
881 } |
882 } |
1066 |
1067 |
1067 void ec_fsm_slave_conf(ec_fsm_t *fsm /**< finite state machine */) |
1068 void ec_fsm_slave_conf(ec_fsm_t *fsm /**< finite state machine */) |
1068 { |
1069 { |
1069 ec_slave_t *slave = fsm->slave; |
1070 ec_slave_t *slave = fsm->slave; |
1070 ec_master_t *master = fsm->master; |
1071 ec_master_t *master = fsm->master; |
1071 ec_command_t *command = &fsm->command; |
1072 ec_datagram_t *datagram = &fsm->datagram; |
1072 |
1073 |
1073 fsm->change_state(fsm); // execute state change state machine |
1074 fsm->change_state(fsm); // execute state change state machine |
1074 |
1075 |
1075 if (fsm->change_state == ec_fsm_change_error) { |
1076 if (fsm->change_state == ec_fsm_change_error) { |
1076 slave->error_flag = 1; |
1077 slave->error_flag = 1; |
1099 fsm->slave_state(fsm); // execute immediately |
1100 fsm->slave_state(fsm); // execute immediately |
1100 return; |
1101 return; |
1101 } |
1102 } |
1102 |
1103 |
1103 // reset FMMUs |
1104 // reset FMMUs |
1104 ec_command_npwr(command, slave->station_address, 0x0600, |
1105 ec_datagram_npwr(datagram, slave->station_address, 0x0600, |
1105 EC_FMMU_SIZE * slave->base_fmmu_count); |
1106 EC_FMMU_SIZE * slave->base_fmmu_count); |
1106 memset(command->data, 0x00, EC_FMMU_SIZE * slave->base_fmmu_count); |
1107 memset(datagram->data, 0x00, EC_FMMU_SIZE * slave->base_fmmu_count); |
1107 ec_master_queue_command(master, command); |
1108 ec_master_queue_datagram(master, datagram); |
1108 fsm->slave_state = ec_fsm_slave_sync; |
1109 fsm->slave_state = ec_fsm_slave_sync; |
1109 } |
1110 } |
1110 |
1111 |
1111 /*****************************************************************************/ |
1112 /*****************************************************************************/ |
1112 |
1113 |
1115 Configure sync managers. |
1116 Configure sync managers. |
1116 */ |
1117 */ |
1117 |
1118 |
1118 void ec_fsm_slave_sync(ec_fsm_t *fsm /**< finite state machine */) |
1119 void ec_fsm_slave_sync(ec_fsm_t *fsm /**< finite state machine */) |
1119 { |
1120 { |
1120 ec_command_t *command = &fsm->command; |
1121 ec_datagram_t *datagram = &fsm->datagram; |
1121 ec_slave_t *slave = fsm->slave; |
1122 ec_slave_t *slave = fsm->slave; |
1122 unsigned int j; |
1123 unsigned int j; |
1123 const ec_sync_t *sync; |
1124 const ec_sync_t *sync; |
1124 ec_eeprom_sync_t *eeprom_sync, mbox_sync; |
1125 ec_eeprom_sync_t *eeprom_sync, mbox_sync; |
1125 |
1126 |
1126 if (command->state != EC_CMD_RECEIVED || command->working_counter != 1) { |
1127 if (datagram->state != EC_CMD_RECEIVED || datagram->working_counter != 1) { |
1127 slave->error_flag = 1; |
1128 slave->error_flag = 1; |
1128 fsm->slave_state = ec_fsm_slave_end; |
1129 fsm->slave_state = ec_fsm_slave_end; |
1129 EC_ERR("Failed to reset FMMUs of slave %i.\n", |
1130 EC_ERR("Failed to reset FMMUs of slave %i.\n", |
1130 slave->ring_position); |
1131 slave->ring_position); |
1131 return; |
1132 return; |
1136 fsm->slave_state(fsm); // execute immediately |
1137 fsm->slave_state(fsm); // execute immediately |
1137 return; |
1138 return; |
1138 } |
1139 } |
1139 |
1140 |
1140 // configure sync managers |
1141 // configure sync managers |
1141 ec_command_npwr(command, slave->station_address, 0x0800, |
1142 ec_datagram_npwr(datagram, slave->station_address, 0x0800, |
1142 EC_SYNC_SIZE * slave->base_sync_count); |
1143 EC_SYNC_SIZE * slave->base_sync_count); |
1143 memset(command->data, 0x00, EC_SYNC_SIZE * slave->base_sync_count); |
1144 memset(datagram->data, 0x00, EC_SYNC_SIZE * slave->base_sync_count); |
1144 |
1145 |
1145 // known slave type, take type's SM information |
1146 // known slave type, take type's SM information |
1146 if (slave->type) { |
1147 if (slave->type) { |
1147 for (j = 0; slave->type->sync_managers[j] && j < EC_MAX_SYNC; j++) { |
1148 for (j = 0; slave->type->sync_managers[j] && j < EC_MAX_SYNC; j++) { |
1148 sync = slave->type->sync_managers[j]; |
1149 sync = slave->type->sync_managers[j]; |
1149 ec_sync_config(sync, slave, command->data + EC_SYNC_SIZE * j); |
1150 ec_sync_config(sync, slave, datagram->data + EC_SYNC_SIZE * j); |
1150 } |
1151 } |
1151 } |
1152 } |
1152 |
1153 |
1153 // unknown type, but slave has mailbox |
1154 // unknown type, but slave has mailbox |
1154 else if (slave->sii_mailbox_protocols) |
1155 else if (slave->sii_mailbox_protocols) |
1161 fsm->slave_state = ec_fsm_slave_end; |
1162 fsm->slave_state = ec_fsm_slave_end; |
1162 EC_ERR("Invalid sync manager configuration found!"); |
1163 EC_ERR("Invalid sync manager configuration found!"); |
1163 return; |
1164 return; |
1164 } |
1165 } |
1165 ec_eeprom_sync_config(eeprom_sync, |
1166 ec_eeprom_sync_config(eeprom_sync, |
1166 command->data + EC_SYNC_SIZE |
1167 datagram->data + EC_SYNC_SIZE |
1167 * eeprom_sync->index); |
1168 * eeprom_sync->index); |
1168 } |
1169 } |
1169 } |
1170 } |
1170 |
1171 |
1171 // no sync manager information; guess mailbox settings |
1172 // no sync manager information; guess mailbox settings |
1173 mbox_sync.physical_start_address = |
1174 mbox_sync.physical_start_address = |
1174 slave->sii_rx_mailbox_offset; |
1175 slave->sii_rx_mailbox_offset; |
1175 mbox_sync.length = slave->sii_rx_mailbox_size; |
1176 mbox_sync.length = slave->sii_rx_mailbox_size; |
1176 mbox_sync.control_register = 0x26; |
1177 mbox_sync.control_register = 0x26; |
1177 mbox_sync.enable = 1; |
1178 mbox_sync.enable = 1; |
1178 ec_eeprom_sync_config(&mbox_sync, command->data); |
1179 ec_eeprom_sync_config(&mbox_sync, datagram->data); |
1179 |
1180 |
1180 mbox_sync.physical_start_address = |
1181 mbox_sync.physical_start_address = |
1181 slave->sii_tx_mailbox_offset; |
1182 slave->sii_tx_mailbox_offset; |
1182 mbox_sync.length = slave->sii_tx_mailbox_size; |
1183 mbox_sync.length = slave->sii_tx_mailbox_size; |
1183 mbox_sync.control_register = 0x22; |
1184 mbox_sync.control_register = 0x22; |
1184 mbox_sync.enable = 1; |
1185 mbox_sync.enable = 1; |
1185 ec_eeprom_sync_config(&mbox_sync, |
1186 ec_eeprom_sync_config(&mbox_sync, |
1186 command->data + EC_SYNC_SIZE); |
1187 datagram->data + EC_SYNC_SIZE); |
1187 } |
1188 } |
1188 |
1189 |
1189 EC_INFO("Mailbox configured for unknown slave %i\n", |
1190 EC_INFO("Mailbox configured for unknown slave %i\n", |
1190 slave->ring_position); |
1191 slave->ring_position); |
1191 } |
1192 } |
1192 |
1193 |
1193 ec_master_queue_command(fsm->master, command); |
1194 ec_master_queue_datagram(fsm->master, datagram); |
1194 fsm->slave_state = ec_fsm_slave_preop; |
1195 fsm->slave_state = ec_fsm_slave_preop; |
1195 } |
1196 } |
1196 |
1197 |
1197 /*****************************************************************************/ |
1198 /*****************************************************************************/ |
1198 |
1199 |
1201 Change slave state to PREOP. |
1202 Change slave state to PREOP. |
1202 */ |
1203 */ |
1203 |
1204 |
1204 void ec_fsm_slave_preop(ec_fsm_t *fsm /**< finite state machine */) |
1205 void ec_fsm_slave_preop(ec_fsm_t *fsm /**< finite state machine */) |
1205 { |
1206 { |
1206 ec_command_t *command = &fsm->command; |
1207 ec_datagram_t *datagram = &fsm->datagram; |
1207 ec_slave_t *slave = fsm->slave; |
1208 ec_slave_t *slave = fsm->slave; |
1208 |
1209 |
1209 if (command->state != EC_CMD_RECEIVED || command->working_counter != 1) { |
1210 if (datagram->state != EC_CMD_RECEIVED || datagram->working_counter != 1) { |
1210 slave->error_flag = 1; |
1211 slave->error_flag = 1; |
1211 fsm->slave_state = ec_fsm_slave_end; |
1212 fsm->slave_state = ec_fsm_slave_end; |
1212 EC_ERR("Failed to set sync managers on slave %i.\n", |
1213 EC_ERR("Failed to set sync managers on slave %i.\n", |
1213 slave->ring_position); |
1214 slave->ring_position); |
1214 return; |
1215 return; |
1229 |
1230 |
1230 void ec_fsm_slave_fmmu(ec_fsm_t *fsm /**< finite state machine */) |
1231 void ec_fsm_slave_fmmu(ec_fsm_t *fsm /**< finite state machine */) |
1231 { |
1232 { |
1232 ec_slave_t *slave = fsm->slave; |
1233 ec_slave_t *slave = fsm->slave; |
1233 ec_master_t *master = fsm->master; |
1234 ec_master_t *master = fsm->master; |
1234 ec_command_t *command = &fsm->command; |
1235 ec_datagram_t *datagram = &fsm->datagram; |
1235 unsigned int j; |
1236 unsigned int j; |
1236 |
1237 |
1237 fsm->change_state(fsm); // execute state change state machine |
1238 fsm->change_state(fsm); // execute state change state machine |
1238 |
1239 |
1239 if (fsm->change_state == ec_fsm_change_error) { |
1240 if (fsm->change_state == ec_fsm_change_error) { |
1261 fsm->slave_state(fsm); // execute immediately |
1262 fsm->slave_state(fsm); // execute immediately |
1262 return; |
1263 return; |
1263 } |
1264 } |
1264 |
1265 |
1265 // configure FMMUs |
1266 // configure FMMUs |
1266 ec_command_npwr(command, slave->station_address, |
1267 ec_datagram_npwr(datagram, slave->station_address, |
1267 0x0600, EC_FMMU_SIZE * slave->base_fmmu_count); |
1268 0x0600, EC_FMMU_SIZE * slave->base_fmmu_count); |
1268 memset(command->data, 0x00, EC_FMMU_SIZE * slave->base_fmmu_count); |
1269 memset(datagram->data, 0x00, EC_FMMU_SIZE * slave->base_fmmu_count); |
1269 for (j = 0; j < slave->fmmu_count; j++) { |
1270 for (j = 0; j < slave->fmmu_count; j++) { |
1270 ec_fmmu_config(&slave->fmmus[j], slave, |
1271 ec_fmmu_config(&slave->fmmus[j], slave, |
1271 command->data + EC_FMMU_SIZE * j); |
1272 datagram->data + EC_FMMU_SIZE * j); |
1272 } |
1273 } |
1273 |
1274 |
1274 ec_master_queue_command(master, command); |
1275 ec_master_queue_datagram(master, datagram); |
1275 fsm->slave_state = ec_fsm_slave_saveop; |
1276 fsm->slave_state = ec_fsm_slave_saveop; |
1276 } |
1277 } |
1277 |
1278 |
1278 /*****************************************************************************/ |
1279 /*****************************************************************************/ |
1279 |
1280 |
1282 Set slave state to SAVEOP. |
1283 Set slave state to SAVEOP. |
1283 */ |
1284 */ |
1284 |
1285 |
1285 void ec_fsm_slave_saveop(ec_fsm_t *fsm /**< finite state machine */) |
1286 void ec_fsm_slave_saveop(ec_fsm_t *fsm /**< finite state machine */) |
1286 { |
1287 { |
1287 ec_command_t *command = &fsm->command; |
1288 ec_datagram_t *datagram = &fsm->datagram; |
1288 |
1289 |
1289 if (fsm->slave->base_fmmu_count && (command->state != EC_CMD_RECEIVED || |
1290 if (fsm->slave->base_fmmu_count && (datagram->state != EC_CMD_RECEIVED || |
1290 command->working_counter != 1)) { |
1291 datagram->working_counter != 1)) { |
1291 fsm->slave->error_flag = 1; |
1292 fsm->slave->error_flag = 1; |
1292 fsm->slave_state = ec_fsm_slave_end; |
1293 fsm->slave_state = ec_fsm_slave_end; |
1293 EC_ERR("Failed to set FMMUs on slave %i.\n", |
1294 EC_ERR("Failed to set FMMUs on slave %i.\n", |
1294 fsm->slave->ring_position); |
1295 fsm->slave->ring_position); |
1295 return; |
1296 return; |
1377 Starts reading the slave information interface. |
1378 Starts reading the slave information interface. |
1378 */ |
1379 */ |
1379 |
1380 |
1380 void ec_fsm_sii_start_reading(ec_fsm_t *fsm /**< finite state machine */) |
1381 void ec_fsm_sii_start_reading(ec_fsm_t *fsm /**< finite state machine */) |
1381 { |
1382 { |
1382 ec_command_t *command = &fsm->command; |
1383 ec_datagram_t *datagram = &fsm->datagram; |
1383 |
1384 |
1384 // initiate read operation |
1385 // initiate read operation |
1385 if (fsm->sii_mode) { |
1386 if (fsm->sii_mode) { |
1386 ec_command_npwr(command, fsm->slave->station_address, 0x502, 4); |
1387 ec_datagram_npwr(datagram, fsm->slave->station_address, 0x502, 4); |
1387 } |
1388 } |
1388 else { |
1389 else { |
1389 ec_command_apwr(command, fsm->slave->ring_position, 0x502, 4); |
1390 ec_datagram_apwr(datagram, fsm->slave->ring_position, 0x502, 4); |
1390 } |
1391 } |
1391 |
1392 |
1392 EC_WRITE_U8 (command->data, 0x00); // read-only access |
1393 EC_WRITE_U8 (datagram->data, 0x00); // read-only access |
1393 EC_WRITE_U8 (command->data + 1, 0x01); // request read operation |
1394 EC_WRITE_U8 (datagram->data + 1, 0x01); // request read operation |
1394 EC_WRITE_U16(command->data + 2, fsm->sii_offset); |
1395 EC_WRITE_U16(datagram->data + 2, fsm->sii_offset); |
1395 ec_master_queue_command(fsm->master, command); |
1396 ec_master_queue_datagram(fsm->master, datagram); |
1396 fsm->sii_state = ec_fsm_sii_read_check; |
1397 fsm->sii_state = ec_fsm_sii_read_check; |
1397 } |
1398 } |
1398 |
1399 |
1399 /*****************************************************************************/ |
1400 /*****************************************************************************/ |
1400 |
1401 |
1401 /** |
1402 /** |
1402 SII state: READ_CHECK. |
1403 SII state: READ_CHECK. |
1403 Checks, if the SII-read-command has been sent and issues a fetch command. |
1404 Checks, if the SII-read-datagram has been sent and issues a fetch datagram. |
1404 */ |
1405 */ |
1405 |
1406 |
1406 void ec_fsm_sii_read_check(ec_fsm_t *fsm /**< finite state machine */) |
1407 void ec_fsm_sii_read_check(ec_fsm_t *fsm /**< finite state machine */) |
1407 { |
1408 { |
1408 ec_command_t *command = &fsm->command; |
1409 ec_datagram_t *datagram = &fsm->datagram; |
1409 |
1410 |
1410 if (command->state != EC_CMD_RECEIVED || command->working_counter != 1) { |
1411 if (datagram->state != EC_CMD_RECEIVED || datagram->working_counter != 1) { |
1411 EC_ERR("SII: Reception of read command failed.\n"); |
1412 EC_ERR("SII: Reception of read datagram failed.\n"); |
1412 fsm->sii_state = ec_fsm_sii_error; |
1413 fsm->sii_state = ec_fsm_sii_error; |
1413 return; |
1414 return; |
1414 } |
1415 } |
1415 |
1416 |
1416 fsm->sii_start = get_cycles(); |
1417 fsm->sii_start = get_cycles(); |
1417 |
1418 |
1418 // issue check/fetch command |
1419 // issue check/fetch datagram |
1419 if (fsm->sii_mode) { |
1420 if (fsm->sii_mode) { |
1420 ec_command_nprd(command, fsm->slave->station_address, 0x502, 10); |
1421 ec_datagram_nprd(datagram, fsm->slave->station_address, 0x502, 10); |
1421 } |
1422 } |
1422 else { |
1423 else { |
1423 ec_command_aprd(command, fsm->slave->ring_position, 0x502, 10); |
1424 ec_datagram_aprd(datagram, fsm->slave->ring_position, 0x502, 10); |
1424 } |
1425 } |
1425 |
1426 |
1426 ec_master_queue_command(fsm->master, command); |
1427 ec_master_queue_datagram(fsm->master, datagram); |
1427 fsm->sii_state = ec_fsm_sii_read_fetch; |
1428 fsm->sii_state = ec_fsm_sii_read_fetch; |
1428 } |
1429 } |
1429 |
1430 |
1430 /*****************************************************************************/ |
1431 /*****************************************************************************/ |
1431 |
1432 |
1432 /** |
1433 /** |
1433 SII state: READ_FETCH. |
1434 SII state: READ_FETCH. |
1434 Fetches the result of an SII-read command. |
1435 Fetches the result of an SII-read datagram. |
1435 */ |
1436 */ |
1436 |
1437 |
1437 void ec_fsm_sii_read_fetch(ec_fsm_t *fsm /**< finite state machine */) |
1438 void ec_fsm_sii_read_fetch(ec_fsm_t *fsm /**< finite state machine */) |
1438 { |
1439 { |
1439 ec_command_t *command = &fsm->command; |
1440 ec_datagram_t *datagram = &fsm->datagram; |
1440 |
1441 |
1441 if (command->state != EC_CMD_RECEIVED || command->working_counter != 1) { |
1442 if (datagram->state != EC_CMD_RECEIVED || datagram->working_counter != 1) { |
1442 EC_ERR("SII: Reception of check/fetch command failed.\n"); |
1443 EC_ERR("SII: Reception of check/fetch datagram failed.\n"); |
1443 fsm->sii_state = ec_fsm_sii_error; |
1444 fsm->sii_state = ec_fsm_sii_error; |
1444 return; |
1445 return; |
1445 } |
1446 } |
1446 |
1447 |
1447 // check "busy bit" |
1448 // check "busy bit" |
1448 if (EC_READ_U8(command->data + 1) & 0x81) { |
1449 if (EC_READ_U8(datagram->data + 1) & 0x81) { |
1449 // still busy... timeout? |
1450 // still busy... timeout? |
1450 if (get_cycles() - fsm->sii_start >= (cycles_t) 10 * cpu_khz) { |
1451 if (get_cycles() - fsm->sii_start >= (cycles_t) 10 * cpu_khz) { |
1451 EC_ERR("SII: Timeout.\n"); |
1452 EC_ERR("SII: Timeout.\n"); |
1452 fsm->sii_state = ec_fsm_sii_error; |
1453 fsm->sii_state = ec_fsm_sii_error; |
1453 #if 0 |
1454 #if 0 |
1454 EC_DBG("SII busy: %02X %02X %02X %02X\n", |
1455 EC_DBG("SII busy: %02X %02X %02X %02X\n", |
1455 EC_READ_U8(command->data + 0), |
1456 EC_READ_U8(datagram->data + 0), |
1456 EC_READ_U8(command->data + 1), |
1457 EC_READ_U8(datagram->data + 1), |
1457 EC_READ_U8(command->data + 2), |
1458 EC_READ_U8(datagram->data + 2), |
1458 EC_READ_U8(command->data + 3)); |
1459 EC_READ_U8(datagram->data + 3)); |
1459 #endif |
1460 #endif |
1460 } |
1461 } |
1461 |
1462 |
1462 // issue check/fetch command again |
1463 // issue check/fetch datagram again |
1463 if (fsm->sii_mode) { |
1464 if (fsm->sii_mode) { |
1464 ec_command_nprd(command, fsm->slave->station_address, 0x502, 10); |
1465 ec_datagram_nprd(datagram, fsm->slave->station_address, 0x502, 10); |
1465 } |
1466 } |
1466 else { |
1467 else { |
1467 ec_command_aprd(command, fsm->slave->ring_position, 0x502, 10); |
1468 ec_datagram_aprd(datagram, fsm->slave->ring_position, 0x502, 10); |
1468 } |
1469 } |
1469 ec_master_queue_command(fsm->master, command); |
1470 ec_master_queue_datagram(fsm->master, datagram); |
1470 return; |
1471 return; |
1471 } |
1472 } |
1472 |
1473 |
1473 #if 0 |
1474 #if 0 |
1474 EC_DBG("SII rec: %02X %02X %02X %02X - %02X %02X %02X %02X\n", |
1475 EC_DBG("SII rec: %02X %02X %02X %02X - %02X %02X %02X %02X\n", |
1475 EC_READ_U8(command->data + 0), EC_READ_U8(command->data + 1), |
1476 EC_READ_U8(datagram->data + 0), EC_READ_U8(datagram->data + 1), |
1476 EC_READ_U8(command->data + 2), EC_READ_U8(command->data + 3), |
1477 EC_READ_U8(datagram->data + 2), EC_READ_U8(datagram->data + 3), |
1477 EC_READ_U8(command->data + 6), EC_READ_U8(command->data + 7), |
1478 EC_READ_U8(datagram->data + 6), EC_READ_U8(datagram->data + 7), |
1478 EC_READ_U8(command->data + 8), EC_READ_U8(command->data + 9)); |
1479 EC_READ_U8(datagram->data + 8), EC_READ_U8(datagram->data + 9)); |
1479 #endif |
1480 #endif |
1480 |
1481 |
1481 // SII value received. |
1482 // SII value received. |
1482 memcpy(fsm->sii_value, command->data + 6, 4); |
1483 memcpy(fsm->sii_value, datagram->data + 6, 4); |
1483 fsm->sii_state = ec_fsm_sii_end; |
1484 fsm->sii_state = ec_fsm_sii_end; |
1484 } |
1485 } |
1485 |
1486 |
1486 /*****************************************************************************/ |
1487 /*****************************************************************************/ |
1487 |
1488 |
1490 Starts reading the slave information interface. |
1491 Starts reading the slave information interface. |
1491 */ |
1492 */ |
1492 |
1493 |
1493 void ec_fsm_sii_start_writing(ec_fsm_t *fsm /**< finite state machine */) |
1494 void ec_fsm_sii_start_writing(ec_fsm_t *fsm /**< finite state machine */) |
1494 { |
1495 { |
1495 ec_command_t *command = &fsm->command; |
1496 ec_datagram_t *datagram = &fsm->datagram; |
1496 |
1497 |
1497 // initiate write operation |
1498 // initiate write operation |
1498 ec_command_npwr(command, fsm->slave->station_address, 0x502, 8); |
1499 ec_datagram_npwr(datagram, fsm->slave->station_address, 0x502, 8); |
1499 EC_WRITE_U8 (command->data, 0x01); // enable write access |
1500 EC_WRITE_U8 (datagram->data, 0x01); // enable write access |
1500 EC_WRITE_U8 (command->data + 1, 0x02); // request write operation |
1501 EC_WRITE_U8 (datagram->data + 1, 0x02); // request write operation |
1501 EC_WRITE_U32(command->data + 2, fsm->sii_offset); |
1502 EC_WRITE_U32(datagram->data + 2, fsm->sii_offset); |
1502 memcpy(command->data + 6, fsm->sii_value, 2); |
1503 memcpy(datagram->data + 6, fsm->sii_value, 2); |
1503 ec_master_queue_command(fsm->master, command); |
1504 ec_master_queue_datagram(fsm->master, datagram); |
1504 fsm->sii_state = ec_fsm_sii_write_check; |
1505 fsm->sii_state = ec_fsm_sii_write_check; |
1505 } |
1506 } |
1506 |
1507 |
1507 /*****************************************************************************/ |
1508 /*****************************************************************************/ |
1508 |
1509 |
1510 SII state: WRITE_CHECK. |
1511 SII state: WRITE_CHECK. |
1511 */ |
1512 */ |
1512 |
1513 |
1513 void ec_fsm_sii_write_check(ec_fsm_t *fsm /**< finite state machine */) |
1514 void ec_fsm_sii_write_check(ec_fsm_t *fsm /**< finite state machine */) |
1514 { |
1515 { |
1515 ec_command_t *command = &fsm->command; |
1516 ec_datagram_t *datagram = &fsm->datagram; |
1516 |
1517 |
1517 if (command->state != EC_CMD_RECEIVED || command->working_counter != 1) { |
1518 if (datagram->state != EC_CMD_RECEIVED || datagram->working_counter != 1) { |
1518 EC_ERR("SII: Reception of write command failed.\n"); |
1519 EC_ERR("SII: Reception of write datagram failed.\n"); |
1519 fsm->sii_state = ec_fsm_sii_error; |
1520 fsm->sii_state = ec_fsm_sii_error; |
1520 return; |
1521 return; |
1521 } |
1522 } |
1522 |
1523 |
1523 fsm->sii_start = get_cycles(); |
1524 fsm->sii_start = get_cycles(); |
1524 |
1525 |
1525 // issue check/fetch command |
1526 // issue check/fetch datagram |
1526 ec_command_nprd(command, fsm->slave->station_address, 0x502, 2); |
1527 ec_datagram_nprd(datagram, fsm->slave->station_address, 0x502, 2); |
1527 ec_master_queue_command(fsm->master, command); |
1528 ec_master_queue_datagram(fsm->master, datagram); |
1528 fsm->sii_state = ec_fsm_sii_write_check2; |
1529 fsm->sii_state = ec_fsm_sii_write_check2; |
1529 } |
1530 } |
1530 |
1531 |
1531 /*****************************************************************************/ |
1532 /*****************************************************************************/ |
1532 |
1533 |
1534 SII state: WRITE_CHECK2. |
1535 SII state: WRITE_CHECK2. |
1535 */ |
1536 */ |
1536 |
1537 |
1537 void ec_fsm_sii_write_check2(ec_fsm_t *fsm /**< finite state machine */) |
1538 void ec_fsm_sii_write_check2(ec_fsm_t *fsm /**< finite state machine */) |
1538 { |
1539 { |
1539 ec_command_t *command = &fsm->command; |
1540 ec_datagram_t *datagram = &fsm->datagram; |
1540 |
1541 |
1541 if (command->state != EC_CMD_RECEIVED || command->working_counter != 1) { |
1542 if (datagram->state != EC_CMD_RECEIVED || datagram->working_counter != 1) { |
1542 EC_ERR("SII: Reception of write check command failed.\n"); |
1543 EC_ERR("SII: Reception of write check datagram failed.\n"); |
1543 fsm->sii_state = ec_fsm_sii_error; |
1544 fsm->sii_state = ec_fsm_sii_error; |
1544 return; |
1545 return; |
1545 } |
1546 } |
1546 |
1547 |
1547 if (EC_READ_U8(command->data + 1) & 0x82) { |
1548 if (EC_READ_U8(datagram->data + 1) & 0x82) { |
1548 // still busy... timeout? |
1549 // still busy... timeout? |
1549 if (get_cycles() - fsm->sii_start >= (cycles_t) 10 * cpu_khz) { |
1550 if (get_cycles() - fsm->sii_start >= (cycles_t) 10 * cpu_khz) { |
1550 EC_ERR("SII: Write timeout.\n"); |
1551 EC_ERR("SII: Write timeout.\n"); |
1551 fsm->sii_state = ec_fsm_sii_error; |
1552 fsm->sii_state = ec_fsm_sii_error; |
1552 } |
1553 } |
1553 |
1554 |
1554 // issue check/fetch command again |
1555 // issue check/fetch datagram again |
1555 ec_master_queue_command(fsm->master, command); |
1556 ec_master_queue_datagram(fsm->master, datagram); |
1556 } |
1557 } |
1557 else if (EC_READ_U8(command->data + 1) & 0x40) { |
1558 else if (EC_READ_U8(datagram->data + 1) & 0x40) { |
1558 EC_ERR("SII: Write operation failed!\n"); |
1559 EC_ERR("SII: Write operation failed!\n"); |
1559 fsm->sii_state = ec_fsm_sii_error; |
1560 fsm->sii_state = ec_fsm_sii_error; |
1560 } |
1561 } |
1561 else { // success |
1562 else { // success |
1562 fsm->sii_state = ec_fsm_sii_end; |
1563 fsm->sii_state = ec_fsm_sii_end; |
1593 Change state: START. |
1594 Change state: START. |
1594 */ |
1595 */ |
1595 |
1596 |
1596 void ec_fsm_change_start(ec_fsm_t *fsm /**< finite state machine */) |
1597 void ec_fsm_change_start(ec_fsm_t *fsm /**< finite state machine */) |
1597 { |
1598 { |
1598 ec_command_t *command = &fsm->command; |
1599 ec_datagram_t *datagram = &fsm->datagram; |
1599 ec_slave_t *slave = fsm->slave; |
1600 ec_slave_t *slave = fsm->slave; |
1600 |
1601 |
1601 // write new state to slave |
1602 // write new state to slave |
1602 ec_command_npwr(command, slave->station_address, 0x0120, 2); |
1603 ec_datagram_npwr(datagram, slave->station_address, 0x0120, 2); |
1603 EC_WRITE_U16(command->data, fsm->change_new); |
1604 EC_WRITE_U16(datagram->data, fsm->change_new); |
1604 ec_master_queue_command(fsm->master, command); |
1605 ec_master_queue_datagram(fsm->master, datagram); |
1605 fsm->change_state = ec_fsm_change_check; |
1606 fsm->change_state = ec_fsm_change_check; |
1606 } |
1607 } |
1607 |
1608 |
1608 /*****************************************************************************/ |
1609 /*****************************************************************************/ |
1609 |
1610 |
1611 Change state: CHECK. |
1612 Change state: CHECK. |
1612 */ |
1613 */ |
1613 |
1614 |
1614 void ec_fsm_change_check(ec_fsm_t *fsm /**< finite state machine */) |
1615 void ec_fsm_change_check(ec_fsm_t *fsm /**< finite state machine */) |
1615 { |
1616 { |
1616 ec_command_t *command = &fsm->command; |
1617 ec_datagram_t *datagram = &fsm->datagram; |
1617 ec_slave_t *slave = fsm->slave; |
1618 ec_slave_t *slave = fsm->slave; |
1618 |
1619 |
1619 if (command->state != EC_CMD_RECEIVED) { |
1620 if (datagram->state != EC_CMD_RECEIVED) { |
1620 fsm->change_state = ec_fsm_change_error; |
1621 fsm->change_state = ec_fsm_change_error; |
1621 EC_ERR("Failed to send state command to slave %i!\n", |
1622 EC_ERR("Failed to send state datagram to slave %i!\n", |
1622 fsm->slave->ring_position); |
1623 fsm->slave->ring_position); |
1623 return; |
1624 return; |
1624 } |
1625 } |
1625 |
1626 |
1626 if (command->working_counter != 1) { |
1627 if (datagram->working_counter != 1) { |
1627 fsm->change_state = ec_fsm_change_error; |
1628 fsm->change_state = ec_fsm_change_error; |
1628 EC_ERR("Failed to set state 0x%02X on slave %i: Slave did not" |
1629 EC_ERR("Failed to set state 0x%02X on slave %i: Slave did not" |
1629 " respond.\n", fsm->change_new, fsm->slave->ring_position); |
1630 " respond.\n", fsm->change_new, fsm->slave->ring_position); |
1630 return; |
1631 return; |
1631 } |
1632 } |
1632 |
1633 |
1633 fsm->change_start = get_cycles(); |
1634 fsm->change_start = get_cycles(); |
1634 |
1635 |
1635 // read AL status from slave |
1636 // read AL status from slave |
1636 ec_command_nprd(command, slave->station_address, 0x0130, 2); |
1637 ec_datagram_nprd(datagram, slave->station_address, 0x0130, 2); |
1637 ec_master_queue_command(fsm->master, command); |
1638 ec_master_queue_datagram(fsm->master, datagram); |
1638 fsm->change_state = ec_fsm_change_status; |
1639 fsm->change_state = ec_fsm_change_status; |
1639 } |
1640 } |
1640 |
1641 |
1641 /*****************************************************************************/ |
1642 /*****************************************************************************/ |
1642 |
1643 |
1644 Change state: STATUS. |
1645 Change state: STATUS. |
1645 */ |
1646 */ |
1646 |
1647 |
1647 void ec_fsm_change_status(ec_fsm_t *fsm /**< finite state machine */) |
1648 void ec_fsm_change_status(ec_fsm_t *fsm /**< finite state machine */) |
1648 { |
1649 { |
1649 ec_command_t *command = &fsm->command; |
1650 ec_datagram_t *datagram = &fsm->datagram; |
1650 ec_slave_t *slave = fsm->slave; |
1651 ec_slave_t *slave = fsm->slave; |
1651 |
1652 |
1652 if (command->state != EC_CMD_RECEIVED || command->working_counter != 1) { |
1653 if (datagram->state != EC_CMD_RECEIVED || datagram->working_counter != 1) { |
1653 fsm->change_state = ec_fsm_change_error; |
1654 fsm->change_state = ec_fsm_change_error; |
1654 EC_ERR("Failed to check state 0x%02X on slave %i.\n", |
1655 EC_ERR("Failed to check state 0x%02X on slave %i.\n", |
1655 fsm->change_new, slave->ring_position); |
1656 fsm->change_new, slave->ring_position); |
1656 return; |
1657 return; |
1657 } |
1658 } |
1658 |
1659 |
1659 slave->current_state = EC_READ_U8(command->data); |
1660 slave->current_state = EC_READ_U8(datagram->data); |
1660 |
1661 |
1661 if (slave->current_state == fsm->change_new) { |
1662 if (slave->current_state == fsm->change_new) { |
1662 // state has been set successfully |
1663 // state has been set successfully |
1663 fsm->change_state = ec_fsm_change_end; |
1664 fsm->change_state = ec_fsm_change_end; |
1664 return; |
1665 return; |
1669 fsm->change_new = slave->current_state & 0x0F; |
1670 fsm->change_new = slave->current_state & 0x0F; |
1670 EC_ERR("Failed to set state 0x%02X - Slave %i refused state change" |
1671 EC_ERR("Failed to set state 0x%02X - Slave %i refused state change" |
1671 " (code 0x%02X)!\n", fsm->change_new, slave->ring_position, |
1672 " (code 0x%02X)!\n", fsm->change_new, slave->ring_position, |
1672 slave->current_state); |
1673 slave->current_state); |
1673 // fetch AL status error code |
1674 // fetch AL status error code |
1674 ec_command_nprd(command, slave->station_address, 0x0134, 2); |
1675 ec_datagram_nprd(datagram, slave->station_address, 0x0134, 2); |
1675 ec_master_queue_command(fsm->master, command); |
1676 ec_master_queue_datagram(fsm->master, datagram); |
1676 fsm->change_state = ec_fsm_change_code; |
1677 fsm->change_state = ec_fsm_change_code; |
1677 return; |
1678 return; |
1678 } |
1679 } |
1679 |
1680 |
1680 if (get_cycles() - fsm->change_start >= (cycles_t) 10 * cpu_khz) { |
1681 if (get_cycles() - fsm->change_start >= (cycles_t) 10 * cpu_khz) { |
1684 fsm->change_new, slave->ring_position); |
1685 fsm->change_new, slave->ring_position); |
1685 return; |
1686 return; |
1686 } |
1687 } |
1687 |
1688 |
1688 // still old state: check again |
1689 // still old state: check again |
1689 ec_command_nprd(command, slave->station_address, 0x0130, 2); |
1690 ec_datagram_nprd(datagram, slave->station_address, 0x0130, 2); |
1690 ec_master_queue_command(fsm->master, command); |
1691 ec_master_queue_datagram(fsm->master, datagram); |
1691 } |
1692 } |
1692 |
1693 |
1693 /*****************************************************************************/ |
1694 /*****************************************************************************/ |
1694 |
1695 |
1695 /** |
1696 /** |
1722 Change state: CODE. |
1723 Change state: CODE. |
1723 */ |
1724 */ |
1724 |
1725 |
1725 void ec_fsm_change_code(ec_fsm_t *fsm /**< finite state machine */) |
1726 void ec_fsm_change_code(ec_fsm_t *fsm /**< finite state machine */) |
1726 { |
1727 { |
1727 ec_command_t *command = &fsm->command; |
1728 ec_datagram_t *datagram = &fsm->datagram; |
1728 ec_slave_t *slave = fsm->slave; |
1729 ec_slave_t *slave = fsm->slave; |
1729 uint32_t code; |
1730 uint32_t code; |
1730 const ec_code_msg_t *al_msg; |
1731 const ec_code_msg_t *al_msg; |
1731 |
1732 |
1732 if (command->state != EC_CMD_RECEIVED || command->working_counter != 1) { |
1733 if (datagram->state != EC_CMD_RECEIVED || datagram->working_counter != 1) { |
1733 fsm->change_state = ec_fsm_change_error; |
1734 fsm->change_state = ec_fsm_change_error; |
1734 EC_ERR("Reception of AL status code command failed.\n"); |
1735 EC_ERR("Reception of AL status code datagram failed.\n"); |
1735 return; |
1736 return; |
1736 } |
1737 } |
1737 |
1738 |
1738 if ((code = EC_READ_U16(command->data))) { |
1739 if ((code = EC_READ_U16(datagram->data))) { |
1739 for (al_msg = al_status_messages; al_msg->code; al_msg++) { |
1740 for (al_msg = al_status_messages; al_msg->code; al_msg++) { |
1740 if (al_msg->code != code) continue; |
1741 if (al_msg->code != code) continue; |
1741 EC_ERR("AL status message 0x%04X: \"%s\".\n", |
1742 EC_ERR("AL status message 0x%04X: \"%s\".\n", |
1742 al_msg->code, al_msg->message); |
1743 al_msg->code, al_msg->message); |
1743 break; |
1744 break; |
1745 if (!al_msg->code) |
1746 if (!al_msg->code) |
1746 EC_ERR("Unknown AL status code 0x%04X.\n", code); |
1747 EC_ERR("Unknown AL status code 0x%04X.\n", code); |
1747 } |
1748 } |
1748 |
1749 |
1749 // acknowledge "old" slave state |
1750 // acknowledge "old" slave state |
1750 ec_command_npwr(command, slave->station_address, 0x0120, 2); |
1751 ec_datagram_npwr(datagram, slave->station_address, 0x0120, 2); |
1751 EC_WRITE_U16(command->data, slave->current_state); |
1752 EC_WRITE_U16(datagram->data, slave->current_state); |
1752 ec_master_queue_command(fsm->master, command); |
1753 ec_master_queue_datagram(fsm->master, datagram); |
1753 fsm->change_state = ec_fsm_change_ack; |
1754 fsm->change_state = ec_fsm_change_ack; |
1754 } |
1755 } |
1755 |
1756 |
1756 /*****************************************************************************/ |
1757 /*****************************************************************************/ |
1757 |
1758 |
1759 Change state: ACK. |
1760 Change state: ACK. |
1760 */ |
1761 */ |
1761 |
1762 |
1762 void ec_fsm_change_ack(ec_fsm_t *fsm /**< finite state machine */) |
1763 void ec_fsm_change_ack(ec_fsm_t *fsm /**< finite state machine */) |
1763 { |
1764 { |
1764 ec_command_t *command = &fsm->command; |
1765 ec_datagram_t *datagram = &fsm->datagram; |
1765 ec_slave_t *slave = fsm->slave; |
1766 ec_slave_t *slave = fsm->slave; |
1766 |
1767 |
1767 if (command->state != EC_CMD_RECEIVED || command->working_counter != 1) { |
1768 if (datagram->state != EC_CMD_RECEIVED || datagram->working_counter != 1) { |
1768 fsm->change_state = ec_fsm_change_error; |
1769 fsm->change_state = ec_fsm_change_error; |
1769 EC_ERR("Reception of state ack command failed.\n"); |
1770 EC_ERR("Reception of state ack datagram failed.\n"); |
1770 return; |
1771 return; |
1771 } |
1772 } |
1772 |
1773 |
1773 // read new AL status |
1774 // read new AL status |
1774 ec_command_nprd(command, slave->station_address, 0x0130, 2); |
1775 ec_datagram_nprd(datagram, slave->station_address, 0x0130, 2); |
1775 ec_master_queue_command(fsm->master, command); |
1776 ec_master_queue_datagram(fsm->master, datagram); |
1776 fsm->change_state = ec_fsm_change_ack2; |
1777 fsm->change_state = ec_fsm_change_ack2; |
1777 } |
1778 } |
1778 |
1779 |
1779 /*****************************************************************************/ |
1780 /*****************************************************************************/ |
1780 |
1781 |
1783 Acknowledge 2. |
1784 Acknowledge 2. |
1784 */ |
1785 */ |
1785 |
1786 |
1786 void ec_fsm_change_ack2(ec_fsm_t *fsm /**< finite state machine */) |
1787 void ec_fsm_change_ack2(ec_fsm_t *fsm /**< finite state machine */) |
1787 { |
1788 { |
1788 ec_command_t *command = &fsm->command; |
1789 ec_datagram_t *datagram = &fsm->datagram; |
1789 ec_slave_t *slave = fsm->slave; |
1790 ec_slave_t *slave = fsm->slave; |
1790 |
1791 |
1791 if (command->state != EC_CMD_RECEIVED || command->working_counter != 1) { |
1792 if (datagram->state != EC_CMD_RECEIVED || datagram->working_counter != 1) { |
1792 fsm->change_state = ec_fsm_change_error; |
1793 fsm->change_state = ec_fsm_change_error; |
1793 EC_ERR("Reception of state ack check command failed.\n"); |
1794 EC_ERR("Reception of state ack check datagram failed.\n"); |
1794 return; |
1795 return; |
1795 } |
1796 } |
1796 |
1797 |
1797 slave->current_state = EC_READ_U8(command->data); |
1798 slave->current_state = EC_READ_U8(datagram->data); |
1798 |
1799 |
1799 if (slave->current_state == fsm->change_new) { |
1800 if (slave->current_state == fsm->change_new) { |
1800 fsm->change_state = ec_fsm_change_error; |
1801 fsm->change_state = ec_fsm_change_error; |
1801 EC_INFO("Acknowleged state 0x%02X on slave %i.\n", |
1802 EC_INFO("Acknowleged state 0x%02X on slave %i.\n", |
1802 slave->current_state, slave->ring_position); |
1803 slave->current_state, slave->ring_position); |