branch | stable-1.0 |
changeset 1624 | 9dc190591c0f |
parent 1623 | 05622513f627 |
1623:05622513f627 | 1624:9dc190591c0f |
---|---|
44 |
44 |
45 /*****************************************************************************/ |
45 /*****************************************************************************/ |
46 |
46 |
47 void ec_fsm_master_start(ec_fsm_t *); |
47 void ec_fsm_master_start(ec_fsm_t *); |
48 void ec_fsm_master_broadcast(ec_fsm_t *); |
48 void ec_fsm_master_broadcast(ec_fsm_t *); |
49 void ec_fsm_master_proc_states(ec_fsm_t *); |
49 void ec_fsm_master_read_states(ec_fsm_t *); |
50 void ec_fsm_master_scan(ec_fsm_t *); |
|
51 void ec_fsm_master_states(ec_fsm_t *); |
|
52 void ec_fsm_master_validate_vendor(ec_fsm_t *); |
50 void ec_fsm_master_validate_vendor(ec_fsm_t *); |
53 void ec_fsm_master_validate_product(ec_fsm_t *); |
51 void ec_fsm_master_validate_product(ec_fsm_t *); |
54 void ec_fsm_master_reconfigure(ec_fsm_t *); |
52 void ec_fsm_master_rewrite_addresses(ec_fsm_t *); |
55 void ec_fsm_master_address(ec_fsm_t *); |
53 void ec_fsm_master_configure_slave(ec_fsm_t *); |
56 void ec_fsm_master_conf(ec_fsm_t *); |
54 void ec_fsm_master_scan_slaves(ec_fsm_t *); |
57 void ec_fsm_master_eeprom(ec_fsm_t *); |
55 void ec_fsm_master_write_eeprom(ec_fsm_t *); |
58 |
56 |
59 void ec_fsm_slave_start_reading(ec_fsm_t *); |
57 void ec_fsm_slavescan_start(ec_fsm_t *); |
60 void ec_fsm_slave_read_status(ec_fsm_t *); |
58 void ec_fsm_slavescan_address(ec_fsm_t *); |
61 void ec_fsm_slave_read_base(ec_fsm_t *); |
59 void ec_fsm_slavescan_state(ec_fsm_t *); |
62 void ec_fsm_slave_read_dl(ec_fsm_t *); |
60 void ec_fsm_slavescan_base(ec_fsm_t *); |
63 void ec_fsm_slave_eeprom_size(ec_fsm_t *); |
61 void ec_fsm_slavescan_datalink(ec_fsm_t *); |
64 void ec_fsm_slave_fetch_eeprom(ec_fsm_t *); |
62 void ec_fsm_slavescan_eeprom_size(ec_fsm_t *); |
65 void ec_fsm_slave_fetch_eeprom2(ec_fsm_t *); |
63 void ec_fsm_slavescan_eeprom_data(ec_fsm_t *); |
66 void ec_fsm_slave_end(ec_fsm_t *); |
64 void ec_fsm_slavescan_end(ec_fsm_t *); |
67 |
65 |
68 void ec_fsm_slave_conf(ec_fsm_t *); |
66 void ec_fsm_slaveconf_init(ec_fsm_t *); |
69 void ec_fsm_slave_sync(ec_fsm_t *); |
67 void ec_fsm_slaveconf_sync(ec_fsm_t *); |
70 void ec_fsm_slave_preop(ec_fsm_t *); |
68 void ec_fsm_slaveconf_preop(ec_fsm_t *); |
71 void ec_fsm_slave_fmmu(ec_fsm_t *); |
69 void ec_fsm_slaveconf_fmmu(ec_fsm_t *); |
72 void ec_fsm_slave_saveop(ec_fsm_t *); |
70 void ec_fsm_slaveconf_saveop(ec_fsm_t *); |
73 void ec_fsm_slave_op(ec_fsm_t *); |
71 void ec_fsm_slaveconf_op(ec_fsm_t *); |
74 void ec_fsm_slave_op2(ec_fsm_t *); |
72 void ec_fsm_slaveconf_end(ec_fsm_t *); |
75 |
73 |
76 void ec_fsm_sii_start_reading(ec_fsm_t *); |
74 void ec_fsm_sii_start_reading(ec_fsm_t *); |
77 void ec_fsm_sii_read_check(ec_fsm_t *); |
75 void ec_fsm_sii_read_check(ec_fsm_t *); |
78 void ec_fsm_sii_read_fetch(ec_fsm_t *); |
76 void ec_fsm_sii_read_fetch(ec_fsm_t *); |
79 void ec_fsm_sii_start_writing(ec_fsm_t *); |
77 void ec_fsm_sii_start_writing(ec_fsm_t *); |
85 void ec_fsm_change_start(ec_fsm_t *); |
83 void ec_fsm_change_start(ec_fsm_t *); |
86 void ec_fsm_change_check(ec_fsm_t *); |
84 void ec_fsm_change_check(ec_fsm_t *); |
87 void ec_fsm_change_status(ec_fsm_t *); |
85 void ec_fsm_change_status(ec_fsm_t *); |
88 void ec_fsm_change_code(ec_fsm_t *); |
86 void ec_fsm_change_code(ec_fsm_t *); |
89 void ec_fsm_change_ack(ec_fsm_t *); |
87 void ec_fsm_change_ack(ec_fsm_t *); |
90 void ec_fsm_change_ack2(ec_fsm_t *); |
88 void ec_fsm_change_check_ack(ec_fsm_t *); |
91 void ec_fsm_change_end(ec_fsm_t *); |
89 void ec_fsm_change_end(ec_fsm_t *); |
92 void ec_fsm_change_error(ec_fsm_t *); |
90 void ec_fsm_change_error(ec_fsm_t *); |
93 |
91 |
94 /*****************************************************************************/ |
92 /*****************************************************************************/ |
95 |
93 |
97 Constructor. |
95 Constructor. |
98 */ |
96 */ |
99 |
97 |
100 int ec_fsm_init(ec_fsm_t *fsm, /**< finite state machine */ |
98 int ec_fsm_init(ec_fsm_t *fsm, /**< finite state machine */ |
101 ec_master_t *master /**< EtherCAT master */ |
99 ec_master_t *master /**< EtherCAT master */ |
102 ) |
100 ) |
103 { |
101 { |
104 fsm->master = master; |
102 fsm->master = master; |
105 fsm->master_state = ec_fsm_master_start; |
103 fsm->master_state = ec_fsm_master_start; |
106 fsm->master_slaves_responding = 0; |
104 fsm->master_slaves_responding = 0; |
107 fsm->master_slave_states = EC_SLAVE_STATE_UNKNOWN; |
105 fsm->master_slave_states = EC_SLAVE_STATE_UNKNOWN; |
108 fsm->master_validation = 0; |
106 fsm->master_validation = 0; |
109 |
107 |
110 ec_command_init(&fsm->command); |
108 ec_datagram_init(&fsm->datagram); |
111 if (ec_command_prealloc(&fsm->command, EC_MAX_DATA_SIZE)) { |
109 if (ec_datagram_prealloc(&fsm->datagram, EC_MAX_DATA_SIZE)) { |
112 EC_ERR("FSM failed to allocate FSM command.\n"); |
110 EC_ERR("Failed to allocate FSM datagram.\n"); |
113 return -1; |
111 return -1; |
114 } |
112 } |
115 |
113 |
116 return 0; |
114 return 0; |
117 } |
115 } |
122 Destructor. |
120 Destructor. |
123 */ |
121 */ |
124 |
122 |
125 void ec_fsm_clear(ec_fsm_t *fsm /**< finite state machine */) |
123 void ec_fsm_clear(ec_fsm_t *fsm /**< finite state machine */) |
126 { |
124 { |
127 ec_command_clear(&fsm->command); |
125 ec_datagram_clear(&fsm->datagram); |
128 } |
126 } |
129 |
127 |
130 /*****************************************************************************/ |
128 /*****************************************************************************/ |
131 |
129 |
132 /** |
130 /** |
160 Starts with getting slave count and slave states. |
158 Starts with getting slave count and slave states. |
161 */ |
159 */ |
162 |
160 |
163 void ec_fsm_master_start(ec_fsm_t *fsm) |
161 void ec_fsm_master_start(ec_fsm_t *fsm) |
164 { |
162 { |
165 ec_command_brd(&fsm->command, 0x0130, 2); |
163 ec_datagram_brd(&fsm->datagram, 0x0130, 2); |
166 ec_master_queue_command(fsm->master, &fsm->command); |
164 ec_master_queue_datagram(fsm->master, &fsm->datagram); |
167 fsm->master_state = ec_fsm_master_broadcast; |
165 fsm->master_state = ec_fsm_master_broadcast; |
168 } |
166 } |
169 |
167 |
170 /*****************************************************************************/ |
168 /*****************************************************************************/ |
171 |
169 |
174 Processes the broadcast read slave count and slaves states. |
172 Processes the broadcast read slave count and slaves states. |
175 */ |
173 */ |
176 |
174 |
177 void ec_fsm_master_broadcast(ec_fsm_t *fsm /**< finite state machine */) |
175 void ec_fsm_master_broadcast(ec_fsm_t *fsm /**< finite state machine */) |
178 { |
176 { |
179 ec_command_t *command = &fsm->command; |
177 ec_datagram_t *datagram = &fsm->datagram; |
180 unsigned int topology_change, states_change, i; |
178 unsigned int topology_change, states_change, i; |
181 ec_slave_t *slave; |
179 ec_slave_t *slave; |
182 ec_master_t *master = fsm->master; |
180 ec_master_t *master = fsm->master; |
183 |
181 |
184 if (command->state != EC_CMD_RECEIVED) { |
182 if (datagram->state != EC_CMD_RECEIVED) { |
185 if (!master->device->link_state) { |
183 if (!master->device->link_state) { |
186 fsm->master_slaves_responding = 0; |
184 fsm->master_slaves_responding = 0; |
187 list_for_each_entry(slave, &master->slaves, list) { |
185 list_for_each_entry(slave, &master->slaves, list) { |
188 slave->online = 0; |
186 slave->online = 0; |
189 } |
187 } |
191 fsm->master_state = ec_fsm_master_start; |
189 fsm->master_state = ec_fsm_master_start; |
192 fsm->master_state(fsm); // execute immediately |
190 fsm->master_state(fsm); // execute immediately |
193 return; |
191 return; |
194 } |
192 } |
195 |
193 |
196 topology_change = (command->working_counter != |
194 topology_change = (datagram->working_counter != |
197 fsm->master_slaves_responding); |
195 fsm->master_slaves_responding); |
198 states_change = (EC_READ_U8(command->data) != fsm->master_slave_states); |
196 states_change = (EC_READ_U8(datagram->data) != fsm->master_slave_states); |
199 |
197 |
200 fsm->master_slave_states = EC_READ_U8(command->data); |
198 fsm->master_slave_states = EC_READ_U8(datagram->data); |
201 fsm->master_slaves_responding = command->working_counter; |
199 fsm->master_slaves_responding = datagram->working_counter; |
202 |
200 |
203 if (topology_change) { |
201 if (topology_change) { |
204 EC_INFO("%i slave%s responding.\n", |
202 EC_INFO("%i slave%s responding.\n", |
205 fsm->master_slaves_responding, |
203 fsm->master_slaves_responding, |
206 fsm->master_slaves_responding == 1 ? "" : "s"); |
204 fsm->master_slaves_responding == 1 ? "" : "s"); |
219 EC_INFO("Slave states: "); |
217 EC_INFO("Slave states: "); |
220 ec_print_states(fsm->master_slave_states); |
218 ec_print_states(fsm->master_slave_states); |
221 printk(".\n"); |
219 printk(".\n"); |
222 } |
220 } |
223 |
221 |
224 // topology change in free-run mode: clear all slaves and scan the bus |
222 // topology change in idle mode: clear all slaves and scan the bus |
225 if (topology_change && master->mode == EC_MASTER_MODE_FREERUN) { |
223 if (topology_change && master->mode == EC_MASTER_MODE_IDLE) { |
226 EC_INFO("Scanning bus.\n"); |
224 EC_INFO("Scanning bus.\n"); |
227 |
225 |
228 ec_master_eoe_stop(master); |
226 ec_master_eoe_stop(master); |
229 ec_master_clear_slaves(master); |
227 ec_master_clear_slaves(master); |
230 |
228 |
262 list_add_tail(&slave->list, &master->slaves); |
260 list_add_tail(&slave->list, &master->slaves); |
263 } |
261 } |
264 |
262 |
265 // begin scanning of slaves |
263 // begin scanning of slaves |
266 fsm->slave = list_entry(master->slaves.next, ec_slave_t, list); |
264 fsm->slave = list_entry(master->slaves.next, ec_slave_t, list); |
267 fsm->slave_state = ec_fsm_slave_start_reading; |
265 fsm->slave_state = ec_fsm_slavescan_start; |
268 fsm->master_state = ec_fsm_master_scan; |
266 fsm->master_state = ec_fsm_master_scan_slaves; |
269 fsm->master_state(fsm); // execute immediately |
267 fsm->master_state(fsm); // execute immediately |
270 return; |
268 return; |
271 } |
269 } |
272 |
270 |
273 // fetch state from each slave |
271 // fetch state from each slave |
274 fsm->slave = list_entry(master->slaves.next, ec_slave_t, list); |
272 fsm->slave = list_entry(master->slaves.next, ec_slave_t, list); |
275 ec_command_nprd(&fsm->command, fsm->slave->station_address, 0x0130, 2); |
273 ec_datagram_nprd(&fsm->datagram, fsm->slave->station_address, 0x0130, 2); |
276 ec_master_queue_command(master, &fsm->command); |
274 ec_master_queue_datagram(master, &fsm->datagram); |
277 fsm->master_state = ec_fsm_master_states; |
275 fsm->master_state = ec_fsm_master_read_states; |
276 } |
|
277 |
|
278 /*****************************************************************************/ |
|
279 |
|
280 /** |
|
281 Master action: PROC_STATES. |
|
282 Processes the slave states. |
|
283 */ |
|
284 |
|
285 void ec_fsm_master_action_process_states(ec_fsm_t *fsm |
|
286 /**< finite state machine */ |
|
287 ) |
|
288 { |
|
289 ec_master_t *master = fsm->master; |
|
290 ec_slave_t *slave; |
|
291 |
|
292 // check if any slaves are not in the state, they're supposed to be |
|
293 list_for_each_entry(slave, &master->slaves, list) { |
|
294 if (slave->error_flag || |
|
295 !slave->online || |
|
296 slave->requested_state == EC_SLAVE_STATE_UNKNOWN || |
|
297 slave->current_state == slave->requested_state) continue; |
|
298 |
|
299 EC_INFO("Changing state of slave %i from ", slave->ring_position); |
|
300 ec_print_states(slave->current_state); |
|
301 printk(" to "); |
|
302 ec_print_states(slave->requested_state); |
|
303 printk(".\n"); |
|
304 |
|
305 fsm->slave = slave; |
|
306 fsm->slave_state = ec_fsm_slaveconf_init; |
|
307 fsm->change_new = EC_SLAVE_STATE_INIT; |
|
308 fsm->change_state = ec_fsm_change_start; |
|
309 fsm->master_state = ec_fsm_master_configure_slave; |
|
310 fsm->master_state(fsm); // execute immediately |
|
311 return; |
|
312 } |
|
313 |
|
314 if (master->mode == EC_MASTER_MODE_IDLE) { |
|
315 // nothing to configure. check for pending EEPROM write operations. |
|
316 list_for_each_entry(slave, &master->slaves, list) { |
|
317 if (!slave->new_eeprom_data) continue; |
|
318 |
|
319 if (!slave->online || slave->error_flag) { |
|
320 kfree(slave->new_eeprom_data); |
|
321 slave->new_eeprom_data = NULL; |
|
322 EC_ERR("Discarding EEPROM data, slave %i not ready.\n", |
|
323 slave->ring_position); |
|
324 continue; |
|
325 } |
|
326 |
|
327 // found pending EEPROM write operation. execute it! |
|
328 EC_INFO("Writing EEPROM of slave %i...\n", slave->ring_position); |
|
329 fsm->sii_offset = 0x0000; |
|
330 memcpy(fsm->sii_value, slave->new_eeprom_data, 2); |
|
331 fsm->sii_mode = 1; |
|
332 fsm->sii_state = ec_fsm_sii_start_writing; |
|
333 fsm->slave = slave; |
|
334 fsm->master_state = ec_fsm_master_write_eeprom; |
|
335 fsm->master_state(fsm); // execute immediately |
|
336 return; |
|
337 } |
|
338 } |
|
339 |
|
340 // nothing to do. restart master state machine. |
|
341 fsm->master_state = ec_fsm_master_start; |
|
342 fsm->master_state(fsm); // execute immediately |
|
278 } |
343 } |
279 |
344 |
280 /*****************************************************************************/ |
345 /*****************************************************************************/ |
281 |
346 |
282 /** |
347 /** |
287 /**< finite state machine */) |
352 /**< finite state machine */) |
288 { |
353 { |
289 ec_master_t *master = fsm->master; |
354 ec_master_t *master = fsm->master; |
290 ec_slave_t *slave = fsm->slave; |
355 ec_slave_t *slave = fsm->slave; |
291 |
356 |
292 // have all states been read? |
357 // is there another slave to query? |
293 if (slave->list.next == &master->slaves) { |
358 if (slave->list.next != &master->slaves) { |
294 |
359 // process next slave |
295 // check, if a bus validation has to be done |
360 fsm->slave = list_entry(fsm->slave->list.next, ec_slave_t, list); |
296 if (fsm->master_validation) { |
361 ec_datagram_nprd(&fsm->datagram, fsm->slave->station_address, |
297 fsm->master_validation = 0; |
362 0x0130, 2); |
298 list_for_each_entry(slave, &master->slaves, list) { |
363 ec_master_queue_datagram(master, &fsm->datagram); |
299 if (slave->online) continue; |
364 fsm->master_state = ec_fsm_master_read_states; |
300 |
365 return; |
301 // At least one slave is offline. validate! |
366 } |
302 EC_INFO("Validating bus.\n"); |
367 |
303 fsm->slave = list_entry(master->slaves.next, ec_slave_t, list); |
368 // all slave states read |
304 fsm->master_state = ec_fsm_master_validate_vendor; |
369 |
305 fsm->sii_offset = 0x0008; // vendor ID |
370 // check, if a bus validation has to be done |
306 fsm->sii_mode = 0; |
371 if (fsm->master_validation) { |
307 fsm->sii_state = ec_fsm_sii_start_reading; |
372 fsm->master_validation = 0; |
308 fsm->sii_state(fsm); // execute immediately |
373 list_for_each_entry(slave, &master->slaves, list) { |
309 return; |
374 if (slave->online) continue; |
310 } |
375 |
376 // At least one slave is offline. validate! |
|
377 EC_INFO("Validating bus.\n"); |
|
378 fsm->slave = list_entry(master->slaves.next, ec_slave_t, list); |
|
379 fsm->master_state = ec_fsm_master_validate_vendor; |
|
380 fsm->sii_offset = 0x0008; // vendor ID |
|
381 fsm->sii_mode = 0; |
|
382 fsm->sii_state = ec_fsm_sii_start_reading; |
|
383 fsm->sii_state(fsm); // execute immediately |
|
384 return; |
|
311 } |
385 } |
312 |
386 } |
313 fsm->master_state = ec_fsm_master_proc_states; |
387 |
314 fsm->master_state(fsm); // execute immediately |
388 ec_fsm_master_action_process_states(fsm); |
315 return; |
|
316 } |
|
317 |
|
318 // process next slave |
|
319 fsm->slave = list_entry(fsm->slave->list.next, ec_slave_t, list); |
|
320 ec_command_nprd(&fsm->command, fsm->slave->station_address, 0x0130, 2); |
|
321 ec_master_queue_command(master, &fsm->command); |
|
322 fsm->master_state = ec_fsm_master_states; |
|
323 } |
389 } |
324 |
390 |
325 /*****************************************************************************/ |
391 /*****************************************************************************/ |
326 |
392 |
327 /** |
393 /** |
328 Master state: STATES. |
394 Master state: STATES. |
329 Fetches the AL- and online state of a slave. |
395 Fetches the AL- and online state of a slave. |
330 */ |
396 */ |
331 |
397 |
332 void ec_fsm_master_states(ec_fsm_t *fsm /**< finite state machine */) |
398 void ec_fsm_master_read_states(ec_fsm_t *fsm /**< finite state machine */) |
333 { |
399 { |
334 ec_slave_t *slave = fsm->slave; |
400 ec_slave_t *slave = fsm->slave; |
335 ec_command_t *command = &fsm->command; |
401 ec_datagram_t *datagram = &fsm->datagram; |
336 uint8_t new_state; |
402 uint8_t new_state; |
337 |
403 |
338 if (command->state != EC_CMD_RECEIVED) { |
404 if (datagram->state != EC_CMD_RECEIVED) { |
339 fsm->master_state = ec_fsm_master_start; |
405 fsm->master_state = ec_fsm_master_start; |
340 fsm->master_state(fsm); // execute immediately |
406 fsm->master_state(fsm); // execute immediately |
341 return; |
407 return; |
342 } |
408 } |
343 |
409 |
344 // did the slave not respond to its station address? |
410 // did the slave not respond to its station address? |
345 if (command->working_counter != 1) { |
411 if (datagram->working_counter != 1) { |
346 if (slave->online) { |
412 if (slave->online) { |
347 slave->online = 0; |
413 slave->online = 0; |
348 EC_INFO("Slave %i: offline.\n", slave->ring_position); |
414 EC_INFO("Slave %i: offline.\n", slave->ring_position); |
349 } |
415 } |
350 ec_fsm_master_action_next_slave_state(fsm); |
416 ec_fsm_master_action_next_slave_state(fsm); |
351 return; |
417 return; |
352 } |
418 } |
353 |
419 |
354 // slave responded |
420 // slave responded |
355 new_state = EC_READ_U8(command->data); |
421 new_state = EC_READ_U8(datagram->data); |
356 if (!slave->online) { // slave was offline before |
422 if (!slave->online) { // slave was offline before |
357 slave->online = 1; |
423 slave->online = 1; |
358 slave->state_error = 0; |
424 slave->error_flag = 0; // clear error flag |
359 slave->current_state = new_state; |
425 slave->current_state = new_state; |
360 EC_INFO("Slave %i: online (", slave->ring_position); |
426 EC_INFO("Slave %i: online (", slave->ring_position); |
361 ec_print_states(new_state); |
427 ec_print_states(new_state); |
362 printk(").\n"); |
428 printk(").\n"); |
363 } |
429 } |
374 } |
440 } |
375 |
441 |
376 /*****************************************************************************/ |
442 /*****************************************************************************/ |
377 |
443 |
378 /** |
444 /** |
379 Master state: PROC_STATES. |
|
380 Processes the slave states. |
|
381 */ |
|
382 |
|
383 void ec_fsm_master_proc_states(ec_fsm_t *fsm /**< finite state machine */) |
|
384 { |
|
385 ec_master_t *master = fsm->master; |
|
386 ec_slave_t *slave; |
|
387 |
|
388 // check if any slaves are not in the state, they're supposed to be |
|
389 list_for_each_entry(slave, &master->slaves, list) { |
|
390 if (slave->state_error || !slave->online || |
|
391 slave->requested_state == EC_SLAVE_STATE_UNKNOWN || |
|
392 slave->current_state == slave->requested_state) continue; |
|
393 |
|
394 EC_INFO("Changing state of slave %i from ", slave->ring_position); |
|
395 ec_print_states(slave->current_state); |
|
396 printk(" to "); |
|
397 ec_print_states(slave->requested_state); |
|
398 printk(".\n"); |
|
399 |
|
400 fsm->slave = slave; |
|
401 fsm->slave_state = ec_fsm_slave_conf; |
|
402 fsm->change_new = EC_SLAVE_STATE_INIT; |
|
403 fsm->change_state = ec_fsm_change_start; |
|
404 fsm->master_state = ec_fsm_master_conf; |
|
405 fsm->master_state(fsm); // execute immediately |
|
406 return; |
|
407 } |
|
408 |
|
409 if (master->mode == EC_MASTER_MODE_FREERUN) { |
|
410 // nothing to configure. check for pending EEPROM write operations. |
|
411 list_for_each_entry(slave, &master->slaves, list) { |
|
412 if (!slave->new_eeprom_data) continue; |
|
413 |
|
414 // found pending EEPROM write operation. execute it! |
|
415 EC_INFO("Writing EEPROM of slave %i...\n", slave->ring_position); |
|
416 fsm->sii_offset = 0x0000; |
|
417 memcpy(fsm->sii_value, slave->new_eeprom_data, 2); |
|
418 fsm->sii_mode = 1; |
|
419 fsm->sii_state = ec_fsm_sii_start_writing; |
|
420 fsm->slave = slave; |
|
421 fsm->master_state = ec_fsm_master_eeprom; |
|
422 fsm->master_state(fsm); // execute immediately |
|
423 return; |
|
424 } |
|
425 } |
|
426 |
|
427 // nothing to do. restart master state machine. |
|
428 fsm->master_state = ec_fsm_master_start; |
|
429 fsm->master_state(fsm); // execute immediately |
|
430 } |
|
431 |
|
432 /*****************************************************************************/ |
|
433 |
|
434 /** |
|
435 Master state: VALIDATE_VENDOR. |
445 Master state: VALIDATE_VENDOR. |
436 Validates the vendor ID of a slave. |
446 Validates the vendor ID of a slave. |
437 */ |
447 */ |
438 |
448 |
439 void ec_fsm_master_validate_vendor(ec_fsm_t *fsm /**< finite state machine */) |
449 void ec_fsm_master_validate_vendor(ec_fsm_t *fsm /**< finite state machine */) |
441 ec_slave_t *slave = fsm->slave; |
451 ec_slave_t *slave = fsm->slave; |
442 |
452 |
443 fsm->sii_state(fsm); // execute SII state machine |
453 fsm->sii_state(fsm); // execute SII state machine |
444 |
454 |
445 if (fsm->sii_state == ec_fsm_sii_error) { |
455 if (fsm->sii_state == ec_fsm_sii_error) { |
456 fsm->slave->error_flag = 1; |
|
446 EC_ERR("Failed to validate vendor ID of slave %i.\n", |
457 EC_ERR("Failed to validate vendor ID of slave %i.\n", |
447 slave->ring_position); |
458 slave->ring_position); |
448 fsm->master_state = ec_fsm_master_start; |
459 fsm->master_state = ec_fsm_master_start; |
449 fsm->master_state(fsm); // execute immediately |
460 fsm->master_state(fsm); // execute immediately |
450 return; |
461 return; |
468 } |
479 } |
469 |
480 |
470 /*****************************************************************************/ |
481 /*****************************************************************************/ |
471 |
482 |
472 /** |
483 /** |
473 Master state: VALIDATE_PRODUCT. |
484 Master action: ADDRESS. |
474 Validates the product ID of a slave. |
|
475 */ |
|
476 |
|
477 void ec_fsm_master_validate_product(ec_fsm_t *fsm /**< finite state machine */) |
|
478 { |
|
479 ec_slave_t *slave = fsm->slave; |
|
480 |
|
481 fsm->sii_state(fsm); // execute SII state machine |
|
482 |
|
483 if (fsm->sii_state == ec_fsm_sii_error) { |
|
484 EC_ERR("Failed to validate product code of slave %i.\n", |
|
485 slave->ring_position); |
|
486 fsm->master_state = ec_fsm_master_start; |
|
487 fsm->master_state(fsm); // execute immediately |
|
488 return; |
|
489 } |
|
490 |
|
491 if (fsm->sii_state != ec_fsm_sii_end) return; |
|
492 |
|
493 if (EC_READ_U32(fsm->sii_value) != slave->sii_product_code) { |
|
494 EC_ERR("Slave %i: invalid product code!\n", slave->ring_position); |
|
495 EC_ERR("expected 0x%08X, got 0x%08X.\n", slave->sii_product_code, |
|
496 EC_READ_U32(fsm->sii_value)); |
|
497 fsm->master_state = ec_fsm_master_start; |
|
498 fsm->master_state(fsm); // execute immediately |
|
499 return; |
|
500 } |
|
501 |
|
502 // have all states been validated? |
|
503 if (slave->list.next == &fsm->master->slaves) { |
|
504 fsm->slave = list_entry(fsm->master->slaves.next, ec_slave_t, list); |
|
505 fsm->master_state = ec_fsm_master_reconfigure; |
|
506 return; |
|
507 } |
|
508 |
|
509 // validate next slave |
|
510 fsm->slave = list_entry(fsm->slave->list.next, ec_slave_t, list); |
|
511 fsm->master_state = ec_fsm_master_validate_vendor; |
|
512 fsm->sii_offset = 0x0008; // vendor ID |
|
513 fsm->sii_mode = 0; |
|
514 fsm->sii_state = ec_fsm_sii_start_reading; |
|
515 fsm->sii_state(fsm); // execute immediately |
|
516 } |
|
517 |
|
518 /*****************************************************************************/ |
|
519 |
|
520 /** |
|
521 Master state: RECONFIGURE. |
|
522 Looks for slave, that have lost their configuration and writes |
485 Looks for slave, that have lost their configuration and writes |
523 their station address, so that they can be reconfigured later. |
486 their station address, so that they can be reconfigured later. |
524 */ |
487 */ |
525 |
488 |
526 void ec_fsm_master_reconfigure(ec_fsm_t *fsm /**< finite state machine */) |
489 void ec_fsm_master_action_addresses(ec_fsm_t *fsm /**< finite state machine */) |
527 { |
490 { |
528 ec_command_t *command = &fsm->command; |
491 ec_datagram_t *datagram = &fsm->datagram; |
529 |
492 |
530 while (fsm->slave->online) { |
493 while (fsm->slave->online) { |
531 if (fsm->slave->list.next == &fsm->master->slaves) { // last slave? |
494 if (fsm->slave->list.next == &fsm->master->slaves) { // last slave? |
532 fsm->master_state = ec_fsm_master_start; |
495 fsm->master_state = ec_fsm_master_start; |
533 fsm->master_state(fsm); // execute immediately |
496 fsm->master_state(fsm); // execute immediately |
538 } |
501 } |
539 |
502 |
540 EC_INFO("Reinitializing slave %i.\n", fsm->slave->ring_position); |
503 EC_INFO("Reinitializing slave %i.\n", fsm->slave->ring_position); |
541 |
504 |
542 // write station address |
505 // write station address |
543 ec_command_apwr(command, fsm->slave->ring_position, 0x0010, 2); |
506 ec_datagram_apwr(datagram, fsm->slave->ring_position, 0x0010, 2); |
544 EC_WRITE_U16(command->data, fsm->slave->station_address); |
507 EC_WRITE_U16(datagram->data, fsm->slave->station_address); |
545 ec_master_queue_command(fsm->master, command); |
508 ec_master_queue_datagram(fsm->master, datagram); |
546 fsm->master_state = ec_fsm_master_address; |
509 fsm->master_state = ec_fsm_master_rewrite_addresses; |
510 } |
|
511 |
|
512 /*****************************************************************************/ |
|
513 |
|
514 /** |
|
515 Master state: VALIDATE_PRODUCT. |
|
516 Validates the product ID of a slave. |
|
517 */ |
|
518 |
|
519 void ec_fsm_master_validate_product(ec_fsm_t *fsm /**< finite state machine */) |
|
520 { |
|
521 ec_slave_t *slave = fsm->slave; |
|
522 |
|
523 fsm->sii_state(fsm); // execute SII state machine |
|
524 |
|
525 if (fsm->sii_state == ec_fsm_sii_error) { |
|
526 fsm->slave->error_flag = 1; |
|
527 EC_ERR("Failed to validate product code of slave %i.\n", |
|
528 slave->ring_position); |
|
529 fsm->master_state = ec_fsm_master_start; |
|
530 fsm->master_state(fsm); // execute immediately |
|
531 return; |
|
532 } |
|
533 |
|
534 if (fsm->sii_state != ec_fsm_sii_end) return; |
|
535 |
|
536 if (EC_READ_U32(fsm->sii_value) != slave->sii_product_code) { |
|
537 EC_ERR("Slave %i: invalid product code!\n", slave->ring_position); |
|
538 EC_ERR("expected 0x%08X, got 0x%08X.\n", slave->sii_product_code, |
|
539 EC_READ_U32(fsm->sii_value)); |
|
540 fsm->master_state = ec_fsm_master_start; |
|
541 fsm->master_state(fsm); // execute immediately |
|
542 return; |
|
543 } |
|
544 |
|
545 // have all states been validated? |
|
546 if (slave->list.next == &fsm->master->slaves) { |
|
547 fsm->slave = list_entry(fsm->master->slaves.next, ec_slave_t, list); |
|
548 // start writing addresses to offline slaves |
|
549 ec_fsm_master_action_addresses(fsm); |
|
550 return; |
|
551 } |
|
552 |
|
553 // validate next slave |
|
554 fsm->slave = list_entry(fsm->slave->list.next, ec_slave_t, list); |
|
555 fsm->master_state = ec_fsm_master_validate_vendor; |
|
556 fsm->sii_offset = 0x0008; // vendor ID |
|
557 fsm->sii_mode = 0; |
|
558 fsm->sii_state = ec_fsm_sii_start_reading; |
|
559 fsm->sii_state(fsm); // execute immediately |
|
547 } |
560 } |
548 |
561 |
549 /*****************************************************************************/ |
562 /*****************************************************************************/ |
550 |
563 |
551 /** |
564 /** |
552 Master state: ADDRESS. |
565 Master state: ADDRESS. |
553 Checks, if the new station address has been written to the slave. |
566 Checks, if the new station address has been written to the slave. |
554 */ |
567 */ |
555 |
568 |
556 void ec_fsm_master_address(ec_fsm_t *fsm /**< finite state machine */) |
569 void ec_fsm_master_rewrite_addresses(ec_fsm_t *fsm |
557 { |
570 /**< finite state machine */ |
558 ec_slave_t *slave = fsm->slave; |
571 ) |
559 ec_command_t *command = &fsm->command; |
572 { |
560 |
573 ec_slave_t *slave = fsm->slave; |
561 if (command->state != EC_CMD_RECEIVED || command->working_counter != 1) { |
574 ec_datagram_t *datagram = &fsm->datagram; |
575 |
|
576 if (datagram->state != EC_CMD_RECEIVED || datagram->working_counter != 1) { |
|
562 EC_ERR("Failed to write station address on slave %i.\n", |
577 EC_ERR("Failed to write station address on slave %i.\n", |
563 slave->ring_position); |
578 slave->ring_position); |
564 } |
579 } |
565 |
580 |
566 if (fsm->slave->list.next == &fsm->master->slaves) { // last slave? |
581 if (fsm->slave->list.next == &fsm->master->slaves) { // last slave? |
569 return; |
584 return; |
570 } |
585 } |
571 |
586 |
572 // check next slave |
587 // check next slave |
573 fsm->slave = list_entry(fsm->slave->list.next, ec_slave_t, list); |
588 fsm->slave = list_entry(fsm->slave->list.next, ec_slave_t, list); |
574 fsm->master_state = ec_fsm_master_reconfigure; |
589 // Write new station address to slave |
575 fsm->master_state(fsm); // execute immediately |
590 ec_fsm_master_action_addresses(fsm); |
576 } |
591 } |
577 |
592 |
578 /*****************************************************************************/ |
593 /*****************************************************************************/ |
579 |
594 |
580 /** |
595 /** |
581 Master state: SCAN. |
596 Master state: SCAN. |
582 Executes the sub-statemachine for the scanning of a slave. |
597 Executes the sub-statemachine for the scanning of a slave. |
583 */ |
598 */ |
584 |
599 |
585 void ec_fsm_master_scan(ec_fsm_t *fsm /**< finite state machine */) |
600 void ec_fsm_master_scan_slaves(ec_fsm_t *fsm /**< finite state machine */) |
586 { |
601 { |
587 ec_master_t *master = fsm->master; |
602 ec_master_t *master = fsm->master; |
588 ec_slave_t *slave = fsm->slave; |
603 ec_slave_t *slave = fsm->slave; |
589 uint16_t coupler_index, coupler_subindex; |
604 uint16_t coupler_index, coupler_subindex; |
590 uint16_t reverse_coupler_index, current_coupler_index; |
605 uint16_t reverse_coupler_index, current_coupler_index; |
591 ec_slave_ident_t *ident; |
606 ec_slave_ident_t *ident; |
592 |
607 |
593 fsm->slave_state(fsm); // execute slave state machine |
608 fsm->slave_state(fsm); // execute slave state machine |
594 |
609 |
595 if (fsm->slave_state != ec_fsm_slave_end) return; |
610 if (fsm->slave_state != ec_fsm_slavescan_end) return; |
596 |
611 |
597 // have all slaves been fetched? |
612 // have all slaves been fetched? |
598 if (slave->list.next == &master->slaves) { |
613 if (slave->list.next == &master->slaves) { |
599 EC_INFO("Bus scanning completed.\n"); |
614 EC_INFO("Bus scanning completed.\n"); |
600 |
615 |
617 } |
632 } |
618 ident++; |
633 ident++; |
619 } |
634 } |
620 |
635 |
621 if (!slave->type) { |
636 if (!slave->type) { |
622 EC_WARN("FSM: Unknown slave device (vendor 0x%08X," |
637 EC_WARN("Unknown slave device (vendor 0x%08X," |
623 " code 0x%08X) at position %i.\n", |
638 " code 0x%08X) at position %i.\n", |
624 slave->sii_vendor_id, slave->sii_product_code, |
639 slave->sii_vendor_id, slave->sii_product_code, |
625 slave->ring_position); |
640 slave->ring_position); |
626 } |
641 } |
627 else { |
642 else { |
634 coupler_subindex = 0; |
649 coupler_subindex = 0; |
635 } |
650 } |
636 } |
651 } |
637 |
652 |
638 // determine initial state. |
653 // determine initial state. |
639 if ((slave->type && slave->type->special == EC_TYPE_BUS_COUPLER)) { |
654 if ((slave->type && |
655 (slave->type->special == EC_TYPE_BUS_COUPLER || |
|
656 slave->type->special == EC_TYPE_INFRA))) { |
|
640 slave->requested_state = EC_SLAVE_STATE_OP; |
657 slave->requested_state = EC_SLAVE_STATE_OP; |
641 } |
658 } |
642 else { |
659 else { |
643 if (master->mode == EC_MASTER_MODE_RUNNING) |
660 if (master->mode == EC_MASTER_MODE_RUNNING) |
644 slave->requested_state = EC_SLAVE_STATE_PREOP; |
661 slave->requested_state = EC_SLAVE_STATE_PREOP; |
645 else |
662 else |
646 slave->requested_state = EC_SLAVE_STATE_INIT; |
663 slave->requested_state = EC_SLAVE_STATE_INIT; |
647 } |
664 } |
648 slave->state_error = 0; |
665 slave->error_flag = 0; |
649 |
666 |
650 // calculate coupler-based slave address |
667 // calculate coupler-based slave address |
651 slave->coupler_index = current_coupler_index; |
668 slave->coupler_index = current_coupler_index; |
652 slave->coupler_subindex = coupler_subindex; |
669 slave->coupler_subindex = coupler_subindex; |
653 coupler_subindex++; |
670 coupler_subindex++; |
654 } |
671 } |
655 |
672 |
656 if (master->mode == EC_MASTER_MODE_FREERUN) { |
673 if (master->mode == EC_MASTER_MODE_IDLE) { |
657 // start EoE processing |
674 // start EoE processing |
658 ec_master_eoe_start(master); |
675 ec_master_eoe_start(master); |
659 } |
676 } |
660 |
677 |
661 fsm->master_state = ec_fsm_master_start; |
678 fsm->master_state = ec_fsm_master_start; |
663 return; |
680 return; |
664 } |
681 } |
665 |
682 |
666 // process next slave |
683 // process next slave |
667 fsm->slave = list_entry(fsm->slave->list.next, ec_slave_t, list); |
684 fsm->slave = list_entry(fsm->slave->list.next, ec_slave_t, list); |
668 fsm->slave_state = ec_fsm_slave_start_reading; |
685 fsm->slave_state = ec_fsm_slavescan_start; |
669 fsm->slave_state(fsm); // execute immediately |
686 fsm->slave_state(fsm); // execute immediately |
670 } |
687 } |
671 |
688 |
672 /*****************************************************************************/ |
689 /*****************************************************************************/ |
673 |
690 |
674 /** |
691 /** |
675 Master state: CONF. |
692 Master state: CONF. |
676 Starts configuring a slave. |
693 Starts configuring a slave. |
677 */ |
694 */ |
678 |
695 |
679 void ec_fsm_master_conf(ec_fsm_t *fsm /**< finite state machine */) |
696 void ec_fsm_master_configure_slave(ec_fsm_t *fsm |
697 /**< finite state machine */ |
|
698 ) |
|
680 { |
699 { |
681 fsm->slave_state(fsm); // execute slave's state machine |
700 fsm->slave_state(fsm); // execute slave's state machine |
682 if (fsm->slave_state != ec_fsm_slave_end) return; |
701 if (fsm->slave_state != ec_fsm_slaveconf_end) return; |
683 fsm->master_state = ec_fsm_master_proc_states; |
702 |
684 fsm->master_state(fsm); // execute immediately |
703 ec_fsm_master_action_process_states(fsm); |
685 } |
704 } |
686 |
705 |
687 /*****************************************************************************/ |
706 /*****************************************************************************/ |
688 |
707 |
689 /** |
708 /** |
690 Master state: EEPROM. |
709 Master state: EEPROM. |
691 */ |
710 */ |
692 |
711 |
693 void ec_fsm_master_eeprom(ec_fsm_t *fsm /**< finite state machine */) |
712 void ec_fsm_master_write_eeprom(ec_fsm_t *fsm /**< finite state machine */) |
694 { |
713 { |
695 ec_slave_t *slave = fsm->slave; |
714 ec_slave_t *slave = fsm->slave; |
696 |
715 |
697 fsm->sii_state(fsm); // execute SII state machine |
716 fsm->sii_state(fsm); // execute SII state machine |
698 |
717 |
699 if (fsm->sii_state == ec_fsm_sii_error) { |
718 if (fsm->sii_state == ec_fsm_sii_error) { |
719 fsm->slave->error_flag = 1; |
|
700 EC_ERR("Failed to write EEPROM contents to slave %i.\n", |
720 EC_ERR("Failed to write EEPROM contents to slave %i.\n", |
701 slave->ring_position); |
721 slave->ring_position); |
702 kfree(slave->new_eeprom_data); |
722 kfree(slave->new_eeprom_data); |
703 slave->new_eeprom_data = NULL; |
723 slave->new_eeprom_data = NULL; |
704 fsm->master_state = ec_fsm_master_start; |
724 fsm->master_state = ec_fsm_master_start; |
720 EC_INFO("Finished writing EEPROM of slave %i.\n", slave->ring_position); |
740 EC_INFO("Finished writing EEPROM of slave %i.\n", slave->ring_position); |
721 kfree(slave->new_eeprom_data); |
741 kfree(slave->new_eeprom_data); |
722 slave->new_eeprom_data = NULL; |
742 slave->new_eeprom_data = NULL; |
723 |
743 |
724 // restart master state machine. |
744 // restart master state machine. |
725 fsm->master_state = ec_fsm_master_start; |
745 fsm->master_state = ec_fsm_master_start; // TODO: Evaluate new contents! |
726 fsm->master_state(fsm); // execute immediately |
746 fsm->master_state(fsm); // execute immediately |
727 return; |
747 return; |
728 } |
748 } |
729 |
749 |
730 /****************************************************************************** |
750 /****************************************************************************** |
731 * slave state machine |
751 * slave scan sub state machine |
732 *****************************************************************************/ |
752 *****************************************************************************/ |
733 |
753 |
734 /** |
754 /** |
735 Slave state: START_READING. |
755 Slave state: START_READING. |
736 First state of the slave state machine. Writes the station address to the |
756 First state of the slave state machine. Writes the station address to the |
737 slave, according to its ring position. |
757 slave, according to its ring position. |
738 */ |
758 */ |
739 |
759 |
740 void ec_fsm_slave_start_reading(ec_fsm_t *fsm /**< finite state machine */) |
760 void ec_fsm_slavescan_start(ec_fsm_t *fsm /**< finite state machine */) |
741 { |
761 { |
742 ec_command_t *command = &fsm->command; |
762 ec_datagram_t *datagram = &fsm->datagram; |
743 |
763 |
744 // write station address |
764 // write station address |
745 ec_command_apwr(command, fsm->slave->ring_position, 0x0010, 2); |
765 ec_datagram_apwr(datagram, fsm->slave->ring_position, 0x0010, 2); |
746 EC_WRITE_U16(command->data, fsm->slave->station_address); |
766 EC_WRITE_U16(datagram->data, fsm->slave->station_address); |
747 ec_master_queue_command(fsm->master, command); |
767 ec_master_queue_datagram(fsm->master, datagram); |
748 fsm->slave_state = ec_fsm_slave_read_status; |
768 fsm->slave_state = ec_fsm_slavescan_address; |
749 } |
769 } |
750 |
770 |
751 /*****************************************************************************/ |
771 /*****************************************************************************/ |
752 |
772 |
753 /** |
773 /** |
754 Slave state: READ_STATUS. |
774 Slave state: ADDRESS. |
755 */ |
775 */ |
756 |
776 |
757 void ec_fsm_slave_read_status(ec_fsm_t *fsm /**< finite state machine */) |
777 void ec_fsm_slavescan_address(ec_fsm_t *fsm /**< finite state machine */) |
758 { |
778 { |
759 ec_command_t *command = &fsm->command; |
779 ec_datagram_t *datagram = &fsm->datagram; |
760 |
780 |
761 if (command->state != EC_CMD_RECEIVED || command->working_counter != 1) { |
781 if (datagram->state != EC_CMD_RECEIVED || datagram->working_counter != 1) { |
762 EC_ERR("FSM failed to write station address of slave %i.\n", |
782 fsm->slave->error_flag = 1; |
783 fsm->slave_state = ec_fsm_slavescan_end; |
|
784 EC_ERR("Failed to write station address of slave %i.\n", |
|
763 fsm->slave->ring_position); |
785 fsm->slave->ring_position); |
764 fsm->slave_state = ec_fsm_slave_end; |
786 return; |
765 return; |
787 } |
766 } |
788 |
767 |
789 // Read AL state |
768 // read AL status |
790 ec_datagram_nprd(datagram, fsm->slave->station_address, 0x0130, 2); |
769 ec_command_nprd(command, fsm->slave->station_address, 0x0130, 2); |
791 ec_master_queue_datagram(fsm->master, datagram); |
770 ec_master_queue_command(fsm->master, command); |
792 fsm->slave_state = ec_fsm_slavescan_state; |
771 fsm->slave_state = ec_fsm_slave_read_base; |
793 } |
772 } |
794 |
773 |
795 /*****************************************************************************/ |
774 /*****************************************************************************/ |
796 |
775 |
797 /** |
776 /** |
798 Slave state: STATE. |
777 Slave state: READ_BASE. |
799 */ |
778 */ |
800 |
779 |
801 void ec_fsm_slavescan_state(ec_fsm_t *fsm /**< finite state machine */) |
780 void ec_fsm_slave_read_base(ec_fsm_t *fsm /**< finite state machine */) |
802 { |
781 { |
803 ec_datagram_t *datagram = &fsm->datagram; |
782 ec_command_t *command = &fsm->command; |
804 ec_slave_t *slave = fsm->slave; |
783 ec_slave_t *slave = fsm->slave; |
805 |
784 |
806 if (datagram->state != EC_CMD_RECEIVED || datagram->working_counter != 1) { |
785 if (command->state != EC_CMD_RECEIVED || command->working_counter != 1) { |
807 fsm->slave->error_flag = 1; |
786 EC_ERR("FSM failed to read AL status of slave %i.\n", |
808 fsm->slave_state = ec_fsm_slavescan_end; |
809 EC_ERR("Failed to read AL state of slave %i.\n", |
|
787 fsm->slave->ring_position); |
810 fsm->slave->ring_position); |
788 fsm->slave_state = ec_fsm_slave_end; |
811 return; |
789 return; |
812 } |
790 } |
813 |
791 |
814 slave->current_state = EC_READ_U8(datagram->data); |
792 slave->current_state = EC_READ_U8(command->data); |
|
793 if (slave->current_state & EC_ACK) { |
815 if (slave->current_state & EC_ACK) { |
794 EC_WARN("Slave %i has status error bit set (0x%02X)!\n", |
816 EC_WARN("Slave %i has state error bit set (0x%02X)!\n", |
795 slave->ring_position, slave->current_state); |
817 slave->ring_position, slave->current_state); |
796 slave->current_state &= 0x0F; |
818 slave->current_state &= 0x0F; |
797 } |
819 } |
798 |
820 |
799 // read base data |
821 // read base data |
800 ec_command_nprd(command, fsm->slave->station_address, 0x0000, 6); |
822 ec_datagram_nprd(datagram, fsm->slave->station_address, 0x0000, 6); |
801 ec_master_queue_command(fsm->master, command); |
823 ec_master_queue_datagram(fsm->master, datagram); |
802 fsm->slave_state = ec_fsm_slave_read_dl; |
824 fsm->slave_state = ec_fsm_slavescan_base; |
803 } |
825 } |
804 |
826 |
805 /*****************************************************************************/ |
827 /*****************************************************************************/ |
806 |
828 |
807 /** |
829 /** |
808 Slave state: READ_DL. |
830 Slave state: BASE. |
809 */ |
831 */ |
810 |
832 |
811 void ec_fsm_slave_read_dl(ec_fsm_t *fsm /**< finite state machine */) |
833 void ec_fsm_slavescan_base(ec_fsm_t *fsm /**< finite state machine */) |
812 { |
834 { |
813 ec_command_t *command = &fsm->command; |
835 ec_datagram_t *datagram = &fsm->datagram; |
814 ec_slave_t *slave = fsm->slave; |
836 ec_slave_t *slave = fsm->slave; |
815 |
837 |
816 if (command->state != EC_CMD_RECEIVED || command->working_counter != 1) { |
838 if (datagram->state != EC_CMD_RECEIVED || datagram->working_counter != 1) { |
817 EC_ERR("FSM failed to read base data of slave %i.\n", |
839 fsm->slave->error_flag = 1; |
840 fsm->slave_state = ec_fsm_slavescan_end; |
|
841 EC_ERR("Failed to read base data of slave %i.\n", |
|
818 slave->ring_position); |
842 slave->ring_position); |
819 fsm->slave_state = ec_fsm_slave_end; |
843 return; |
820 return; |
844 } |
821 } |
845 |
822 |
846 slave->base_type = EC_READ_U8 (datagram->data); |
823 slave->base_type = EC_READ_U8 (command->data); |
847 slave->base_revision = EC_READ_U8 (datagram->data + 1); |
824 slave->base_revision = EC_READ_U8 (command->data + 1); |
848 slave->base_build = EC_READ_U16(datagram->data + 2); |
825 slave->base_build = EC_READ_U16(command->data + 2); |
849 slave->base_fmmu_count = EC_READ_U8 (datagram->data + 4); |
826 slave->base_fmmu_count = EC_READ_U8 (command->data + 4); |
850 slave->base_sync_count = EC_READ_U8 (datagram->data + 5); |
827 slave->base_sync_count = EC_READ_U8 (command->data + 5); |
|
828 |
851 |
829 if (slave->base_fmmu_count > EC_MAX_FMMUS) |
852 if (slave->base_fmmu_count > EC_MAX_FMMUS) |
830 slave->base_fmmu_count = EC_MAX_FMMUS; |
853 slave->base_fmmu_count = EC_MAX_FMMUS; |
831 |
854 |
832 // read data link status |
855 // read data link status |
833 ec_command_nprd(command, slave->station_address, 0x0110, 2); |
856 ec_datagram_nprd(datagram, slave->station_address, 0x0110, 2); |
834 ec_master_queue_command(slave->master, command); |
857 ec_master_queue_datagram(slave->master, datagram); |
835 fsm->slave_state = ec_fsm_slave_eeprom_size; |
858 fsm->slave_state = ec_fsm_slavescan_datalink; |
836 } |
859 } |
837 |
860 |
838 /*****************************************************************************/ |
861 /*****************************************************************************/ |
839 |
862 |
840 /** |
863 /** |
841 Slave state: EEPROM_SIZE. |
864 Slave state: DATALINK. |
842 Read the actual size of the EEPROM to allocate the EEPROM image. |
865 */ |
843 */ |
866 |
844 |
867 void ec_fsm_slavescan_datalink(ec_fsm_t *fsm /**< finite state machine */) |
845 void ec_fsm_slave_eeprom_size(ec_fsm_t *fsm /**< finite state machine */) |
868 { |
846 { |
869 ec_datagram_t *datagram = &fsm->datagram; |
847 ec_command_t *command = &fsm->command; |
|
848 ec_slave_t *slave = fsm->slave; |
870 ec_slave_t *slave = fsm->slave; |
849 uint16_t dl_status; |
871 uint16_t dl_status; |
850 unsigned int i; |
872 unsigned int i; |
851 |
873 |
852 if (command->state != EC_CMD_RECEIVED || command->working_counter != 1) { |
874 if (datagram->state != EC_CMD_RECEIVED || datagram->working_counter != 1) { |
853 EC_ERR("FSM failed to read DL status of slave %i.\n", |
875 fsm->slave->error_flag = 1; |
876 fsm->slave_state = ec_fsm_slavescan_end; |
|
877 EC_ERR("Failed to read DL status of slave %i.\n", |
|
854 slave->ring_position); |
878 slave->ring_position); |
855 fsm->slave_state = ec_fsm_slave_end; |
879 return; |
856 return; |
880 } |
857 } |
881 |
858 |
882 dl_status = EC_READ_U16(datagram->data); |
859 dl_status = EC_READ_U16(command->data); |
|
860 for (i = 0; i < 4; i++) { |
883 for (i = 0; i < 4; i++) { |
861 slave->dl_link[i] = dl_status & (1 << (4 + i)) ? 1 : 0; |
884 slave->dl_link[i] = dl_status & (1 << (4 + i)) ? 1 : 0; |
862 slave->dl_loop[i] = dl_status & (1 << (8 + i * 2)) ? 1 : 0; |
885 slave->dl_loop[i] = dl_status & (1 << (8 + i * 2)) ? 1 : 0; |
863 slave->dl_signal[i] = dl_status & (1 << (9 + i * 2)) ? 1 : 0; |
886 slave->dl_signal[i] = dl_status & (1 << (9 + i * 2)) ? 1 : 0; |
864 } |
887 } |
866 // Start fetching EEPROM size |
889 // Start fetching EEPROM size |
867 |
890 |
868 fsm->sii_offset = 0x0040; // first category header |
891 fsm->sii_offset = 0x0040; // first category header |
869 fsm->sii_mode = 1; |
892 fsm->sii_mode = 1; |
870 fsm->sii_state = ec_fsm_sii_start_reading; |
893 fsm->sii_state = ec_fsm_sii_start_reading; |
871 fsm->slave_state = ec_fsm_slave_fetch_eeprom; |
894 fsm->slave_state = ec_fsm_slavescan_eeprom_size; |
872 fsm->slave_state(fsm); // execute state immediately |
895 fsm->slave_state(fsm); // execute state immediately |
873 } |
896 } |
874 |
897 |
875 /*****************************************************************************/ |
898 /*****************************************************************************/ |
876 |
899 |
877 /** |
900 /** |
878 Slave state: FETCH_EEPROM. |
901 Slave state: EEPROM_SIZE. |
879 */ |
902 */ |
880 |
903 |
881 void ec_fsm_slave_fetch_eeprom(ec_fsm_t *fsm /**< finite state machine */) |
904 void ec_fsm_slavescan_eeprom_size(ec_fsm_t *fsm /**< finite state machine */) |
882 { |
905 { |
883 ec_slave_t *slave = fsm->slave; |
906 ec_slave_t *slave = fsm->slave; |
884 uint16_t cat_type, cat_size; |
907 uint16_t cat_type, cat_size; |
885 |
908 |
886 // execute SII state machine |
909 // execute SII state machine |
887 fsm->sii_state(fsm); |
910 fsm->sii_state(fsm); |
888 |
911 |
889 if (fsm->sii_state == ec_fsm_sii_error) { |
912 if (fsm->sii_state == ec_fsm_sii_error) { |
890 fsm->slave_state = ec_fsm_slave_end; |
913 fsm->slave->error_flag = 1; |
914 fsm->slave_state = ec_fsm_slavescan_end; |
|
891 EC_ERR("Failed to read EEPROM size of slave %i.\n", |
915 EC_ERR("Failed to read EEPROM size of slave %i.\n", |
892 slave->ring_position); |
916 slave->ring_position); |
893 return; |
917 return; |
894 } |
918 } |
895 |
919 |
913 kfree(slave->eeprom_data); |
937 kfree(slave->eeprom_data); |
914 } |
938 } |
915 |
939 |
916 if (!(slave->eeprom_data = |
940 if (!(slave->eeprom_data = |
917 (uint8_t *) kmalloc(slave->eeprom_size, GFP_ATOMIC))) { |
941 (uint8_t *) kmalloc(slave->eeprom_size, GFP_ATOMIC))) { |
942 fsm->slave->error_flag = 1; |
|
943 fsm->slave_state = ec_fsm_slavescan_end; |
|
918 EC_ERR("Failed to allocate EEPROM data on slave %i.\n", |
944 EC_ERR("Failed to allocate EEPROM data on slave %i.\n", |
919 slave->ring_position); |
945 slave->ring_position); |
920 fsm->slave_state = ec_fsm_slave_end; |
|
921 return; |
946 return; |
922 } |
947 } |
923 |
948 |
924 // Start fetching EEPROM contents |
949 // Start fetching EEPROM contents |
925 |
950 |
926 fsm->sii_offset = 0x0000; |
951 fsm->sii_offset = 0x0000; |
927 fsm->sii_mode = 1; |
952 fsm->sii_mode = 1; |
928 fsm->sii_state = ec_fsm_sii_start_reading; |
953 fsm->sii_state = ec_fsm_sii_start_reading; |
929 fsm->slave_state = ec_fsm_slave_fetch_eeprom2; |
954 fsm->slave_state = ec_fsm_slavescan_eeprom_data; |
930 fsm->slave_state(fsm); // execute state immediately |
955 fsm->slave_state(fsm); // execute state immediately |
931 } |
956 } |
932 |
957 |
933 /*****************************************************************************/ |
958 /*****************************************************************************/ |
934 |
959 |
935 /** |
960 /** |
936 Slave state: FETCH_EEPROM2. |
961 Slave state: EEPROM_DATA. |
937 */ |
962 */ |
938 |
963 |
939 void ec_fsm_slave_fetch_eeprom2(ec_fsm_t *fsm /**< finite state machine */) |
964 void ec_fsm_slavescan_eeprom_data(ec_fsm_t *fsm /**< finite state machine */) |
940 { |
965 { |
941 ec_slave_t *slave = fsm->slave; |
966 ec_slave_t *slave = fsm->slave; |
942 uint16_t *cat_word, cat_type, cat_size; |
967 uint16_t *cat_word, cat_type, cat_size; |
943 |
968 |
944 // execute SII state machine |
969 // execute SII state machine |
945 fsm->sii_state(fsm); |
970 fsm->sii_state(fsm); |
946 |
971 |
947 if (fsm->sii_state == ec_fsm_sii_error) { |
972 if (fsm->sii_state == ec_fsm_sii_error) { |
948 fsm->slave_state = ec_fsm_slave_end; |
973 fsm->slave->error_flag = 1; |
974 fsm->slave_state = ec_fsm_slavescan_end; |
|
949 EC_ERR("Failed to fetch EEPROM contents of slave %i.\n", |
975 EC_ERR("Failed to fetch EEPROM contents of slave %i.\n", |
950 slave->ring_position); |
976 slave->ring_position); |
951 return; |
977 return; |
952 } |
978 } |
953 |
979 |
1031 } |
1057 } |
1032 |
1058 |
1033 cat_word += cat_size + 2; |
1059 cat_word += cat_size + 2; |
1034 } |
1060 } |
1035 |
1061 |
1036 end: |
1062 fsm->slave_state = ec_fsm_slavescan_end; |
1037 fsm->slave_state = ec_fsm_slave_end; |
1063 |
1038 } |
1064 end: |
1039 |
1065 fsm->slave->error_flag = 1; |
1040 /*****************************************************************************/ |
1066 fsm->slave_state = ec_fsm_slavescan_end; |
1041 |
1067 } |
1042 /** |
1068 |
1043 Slave state: CONF. |
1069 /*****************************************************************************/ |
1044 */ |
1070 |
1045 |
1071 /** |
1046 void ec_fsm_slave_conf(ec_fsm_t *fsm /**< finite state machine */) |
1072 Slave state: END. |
1047 { |
1073 End state of the slave state machine. |
1048 ec_slave_t *slave = fsm->slave; |
1074 */ |
1049 ec_master_t *master = fsm->master; |
1075 |
1050 ec_command_t *command = &fsm->command; |
1076 void ec_fsm_slavescan_end(ec_fsm_t *fsm /**< finite state machine */) |
1077 { |
|
1078 } |
|
1079 |
|
1080 /****************************************************************************** |
|
1081 * slave configuration sub state machine |
|
1082 *****************************************************************************/ |
|
1083 |
|
1084 /** |
|
1085 Slave state: INIT. |
|
1086 */ |
|
1087 |
|
1088 void ec_fsm_slaveconf_init(ec_fsm_t *fsm /**< finite state machine */) |
|
1089 { |
|
1090 ec_slave_t *slave = fsm->slave; |
|
1091 ec_datagram_t *datagram = &fsm->datagram; |
|
1092 const ec_sync_t *sync; |
|
1093 ec_eeprom_sync_t *eeprom_sync, mbox_sync; |
|
1094 unsigned int j; |
|
1051 |
1095 |
1052 fsm->change_state(fsm); // execute state change state machine |
1096 fsm->change_state(fsm); // execute state change state machine |
1053 |
1097 |
1054 if (fsm->change_state == ec_fsm_change_error) { |
1098 if (fsm->change_state == ec_fsm_change_error) { |
1055 fsm->slave_state = ec_fsm_slave_end; |
1099 slave->error_flag = 1; |
1100 fsm->slave_state = ec_fsm_slaveconf_end; |
|
1056 return; |
1101 return; |
1057 } |
1102 } |
1058 |
1103 |
1059 if (fsm->change_state != ec_fsm_change_end) return; |
1104 if (fsm->change_state != ec_fsm_change_end) return; |
1060 |
1105 |
1061 // slave is now in INIT |
1106 // slave is now in INIT |
1062 if (slave->current_state == slave->requested_state) { |
1107 if (slave->current_state == slave->requested_state) { |
1063 fsm->slave_state = ec_fsm_slave_end; |
1108 fsm->slave_state = ec_fsm_slaveconf_end; // successful |
1064 return; |
1109 return; |
1065 } |
1110 } |
1066 |
1111 |
1067 // check for slave registration |
1112 // check for slave registration |
1068 if (!slave->type) { |
1113 if (!slave->type) { |
1069 EC_WARN("Slave %i has unknown type!\n", slave->ring_position); |
1114 EC_WARN("Slave %i has unknown type!\n", slave->ring_position); |
1070 } |
1115 } |
1071 |
1116 |
1072 // check and reset CRC fault counters |
1117 // check and reset CRC fault counters |
1073 //ec_slave_check_crc(slave); |
1118 //ec_slave_check_crc(slave); |
1074 |
1119 // TODO! |
1075 if (!slave->base_fmmu_count) { // no fmmus |
|
1076 fsm->slave_state = ec_fsm_slave_sync; |
|
1077 fsm->slave_state(fsm); // execute immediately |
|
1078 return; |
|
1079 } |
|
1080 |
|
1081 // reset FMMUs |
|
1082 ec_command_npwr(command, slave->station_address, 0x0600, |
|
1083 EC_FMMU_SIZE * slave->base_fmmu_count); |
|
1084 memset(command->data, 0x00, EC_FMMU_SIZE * slave->base_fmmu_count); |
|
1085 ec_master_queue_command(master, command); |
|
1086 fsm->slave_state = ec_fsm_slave_sync; |
|
1087 } |
|
1088 |
|
1089 /*****************************************************************************/ |
|
1090 |
|
1091 /** |
|
1092 Slave state: SYNC. |
|
1093 Configure sync managers. |
|
1094 */ |
|
1095 |
|
1096 void ec_fsm_slave_sync(ec_fsm_t *fsm /**< finite state machine */) |
|
1097 { |
|
1098 ec_command_t *command = &fsm->command; |
|
1099 ec_slave_t *slave = fsm->slave; |
|
1100 unsigned int j; |
|
1101 const ec_sync_t *sync; |
|
1102 ec_eeprom_sync_t *eeprom_sync, mbox_sync; |
|
1103 |
|
1104 if (command->state != EC_CMD_RECEIVED || command->working_counter != 1) { |
|
1105 EC_ERR("Failed to reset FMMUs of slave %i.\n", |
|
1106 slave->ring_position); |
|
1107 slave->state_error = 1; |
|
1108 fsm->slave_state = ec_fsm_slave_end; |
|
1109 return; |
|
1110 } |
|
1111 |
1120 |
1112 if (!slave->base_sync_count) { // no sync managers |
1121 if (!slave->base_sync_count) { // no sync managers |
1113 fsm->slave_state = ec_fsm_slave_preop; |
1122 fsm->slave_state = ec_fsm_slaveconf_preop; |
1114 fsm->slave_state(fsm); // execute immediately |
1123 fsm->change_new = EC_SLAVE_STATE_PREOP; |
1124 fsm->change_state = ec_fsm_change_start; |
|
1125 fsm->change_state(fsm); // execute immediately |
|
1115 return; |
1126 return; |
1116 } |
1127 } |
1117 |
1128 |
1118 // configure sync managers |
1129 // configure sync managers |
1119 ec_command_npwr(command, slave->station_address, 0x0800, |
1130 ec_datagram_npwr(datagram, slave->station_address, 0x0800, |
1120 EC_SYNC_SIZE * slave->base_sync_count); |
1131 EC_SYNC_SIZE * slave->base_sync_count); |
1121 memset(command->data, 0x00, EC_SYNC_SIZE * slave->base_sync_count); |
1132 memset(datagram->data, 0x00, EC_SYNC_SIZE * slave->base_sync_count); |
1133 |
|
1134 // does the slave supply sync manager configurations in its EEPROM? |
|
1135 if (!list_empty(&slave->eeprom_syncs)) { |
|
1136 list_for_each_entry(eeprom_sync, &slave->eeprom_syncs, list) { |
|
1137 if (eeprom_sync->index >= slave->base_sync_count) { |
|
1138 fsm->slave->error_flag = 1; |
|
1139 fsm->slave_state = ec_fsm_slaveconf_end; |
|
1140 EC_ERR("Invalid sync manager configuration found!"); |
|
1141 return; |
|
1142 } |
|
1143 ec_eeprom_sync_config(eeprom_sync, slave, |
|
1144 datagram->data + EC_SYNC_SIZE |
|
1145 * eeprom_sync->index); |
|
1146 } |
|
1147 } |
|
1122 |
1148 |
1123 // known slave type, take type's SM information |
1149 // known slave type, take type's SM information |
1124 if (slave->type) { |
1150 else if (slave->type) { |
1125 for (j = 0; slave->type->sync_managers[j] && j < EC_MAX_SYNC; j++) { |
1151 for (j = 0; slave->type->sync_managers[j] && j < EC_MAX_SYNC; j++) { |
1126 sync = slave->type->sync_managers[j]; |
1152 sync = slave->type->sync_managers[j]; |
1127 ec_sync_config(sync, slave, command->data + EC_SYNC_SIZE * j); |
1153 ec_sync_config(sync, slave, datagram->data + EC_SYNC_SIZE * j); |
1128 } |
1154 } |
1129 } |
1155 } |
1130 |
1156 |
1131 // unknown type, but slave has mailbox |
1157 // unknown type, but slave has mailbox |
1132 else if (slave->sii_mailbox_protocols) |
1158 else if (slave->sii_mailbox_protocols) |
1133 { |
1159 { |
1134 // does it supply sync manager configurations in its EEPROM? |
1160 // guess mailbox settings |
1135 if (!list_empty(&slave->eeprom_syncs)) { |
1161 mbox_sync.physical_start_address = |
1136 list_for_each_entry(eeprom_sync, &slave->eeprom_syncs, list) { |
1162 slave->sii_rx_mailbox_offset; |
1137 if (eeprom_sync->index >= slave->base_sync_count) { |
1163 mbox_sync.length = slave->sii_rx_mailbox_size; |
1138 EC_ERR("Invalid sync manager configuration found!"); |
1164 mbox_sync.control_register = 0x26; |
1139 fsm->slave_state = ec_fsm_slave_end; |
1165 mbox_sync.enable = 1; |
1140 return; |
1166 ec_eeprom_sync_config(&mbox_sync, slave, datagram->data); |
1141 } |
1167 |
1142 ec_eeprom_sync_config(eeprom_sync, |
1168 mbox_sync.physical_start_address = |
1143 command->data + EC_SYNC_SIZE |
1169 slave->sii_tx_mailbox_offset; |
1144 * eeprom_sync->index); |
1170 mbox_sync.length = slave->sii_tx_mailbox_size; |
1145 } |
1171 mbox_sync.control_register = 0x22; |
1146 } |
1172 mbox_sync.enable = 1; |
1147 |
1173 ec_eeprom_sync_config(&mbox_sync, slave, |
1148 // no sync manager information; guess mailbox settings |
1174 datagram->data + EC_SYNC_SIZE); |
1149 else { |
|
1150 mbox_sync.physical_start_address = |
|
1151 slave->sii_rx_mailbox_offset; |
|
1152 mbox_sync.length = slave->sii_rx_mailbox_size; |
|
1153 mbox_sync.control_register = 0x26; |
|
1154 mbox_sync.enable = 1; |
|
1155 ec_eeprom_sync_config(&mbox_sync, command->data); |
|
1156 |
|
1157 mbox_sync.physical_start_address = |
|
1158 slave->sii_tx_mailbox_offset; |
|
1159 mbox_sync.length = slave->sii_tx_mailbox_size; |
|
1160 mbox_sync.control_register = 0x22; |
|
1161 mbox_sync.enable = 1; |
|
1162 ec_eeprom_sync_config(&mbox_sync, |
|
1163 command->data + EC_SYNC_SIZE); |
|
1164 } |
|
1165 |
1175 |
1166 EC_INFO("Mailbox configured for unknown slave %i\n", |
1176 EC_INFO("Mailbox configured for unknown slave %i\n", |
1167 slave->ring_position); |
1177 slave->ring_position); |
1168 } |
1178 } |
1169 |
1179 |
1170 ec_master_queue_command(fsm->master, command); |
1180 ec_master_queue_datagram(fsm->master, datagram); |
1171 fsm->slave_state = ec_fsm_slave_preop; |
1181 fsm->slave_state = ec_fsm_slaveconf_sync; |
1172 } |
1182 } |
1173 |
1183 |
1174 /*****************************************************************************/ |
1184 /*****************************************************************************/ |
1175 |
1185 |
1176 /** |
1186 /** |
1177 Slave state: PREOP. |
1187 Slave state: SYNC. |
1178 Change slave state to PREOP. |
1188 */ |
1179 */ |
1189 |
1180 |
1190 void ec_fsm_slaveconf_sync(ec_fsm_t *fsm /**< finite state machine */) |
1181 void ec_fsm_slave_preop(ec_fsm_t *fsm /**< finite state machine */) |
1191 { |
1182 { |
1192 ec_datagram_t *datagram = &fsm->datagram; |
1183 ec_command_t *command = &fsm->command; |
1193 ec_slave_t *slave = fsm->slave; |
1184 ec_slave_t *slave = fsm->slave; |
1194 |
1185 |
1195 if (datagram->state != EC_CMD_RECEIVED || datagram->working_counter != 1) { |
1186 if (command->state != EC_CMD_RECEIVED || command->working_counter != 1) { |
1196 slave->error_flag = 1; |
1197 fsm->slave_state = ec_fsm_slaveconf_end; |
|
1187 EC_ERR("Failed to set sync managers on slave %i.\n", |
1198 EC_ERR("Failed to set sync managers on slave %i.\n", |
1188 slave->ring_position); |
1199 slave->ring_position); |
1189 slave->state_error = 1; |
1200 return; |
1190 fsm->slave_state = ec_fsm_slave_end; |
1201 } |
1191 return; |
1202 |
1192 } |
1203 fsm->slave_state = ec_fsm_slaveconf_preop; |
1193 |
|
1194 fsm->change_new = EC_SLAVE_STATE_PREOP; |
1204 fsm->change_new = EC_SLAVE_STATE_PREOP; |
1195 fsm->change_state = ec_fsm_change_start; |
1205 fsm->change_state = ec_fsm_change_start; |
1196 fsm->slave_state = ec_fsm_slave_fmmu; |
|
1197 fsm->change_state(fsm); // execute immediately |
1206 fsm->change_state(fsm); // execute immediately |
1198 } |
1207 } |
1199 |
1208 |
1200 /*****************************************************************************/ |
1209 /*****************************************************************************/ |
1201 |
1210 |
1202 /** |
1211 /** |
1203 Slave state: FMMU. |
1212 Slave state: PREOP. |
1204 Configure FMMUs. |
1213 */ |
1205 */ |
1214 |
1206 |
1215 void ec_fsm_slaveconf_preop(ec_fsm_t *fsm /**< finite state machine */) |
1207 void ec_fsm_slave_fmmu(ec_fsm_t *fsm /**< finite state machine */) |
|
1208 { |
1216 { |
1209 ec_slave_t *slave = fsm->slave; |
1217 ec_slave_t *slave = fsm->slave; |
1210 ec_master_t *master = fsm->master; |
1218 ec_master_t *master = fsm->master; |
1211 ec_command_t *command = &fsm->command; |
1219 ec_datagram_t *datagram = &fsm->datagram; |
1212 unsigned int j; |
1220 unsigned int j; |
1213 |
1221 |
1214 fsm->change_state(fsm); // execute state change state machine |
1222 fsm->change_state(fsm); // execute state change state machine |
1215 |
1223 |
1216 if (fsm->change_state == ec_fsm_change_error) { |
1224 if (fsm->change_state == ec_fsm_change_error) { |
1217 fsm->slave_state = ec_fsm_slave_end; |
1225 slave->error_flag = 1; |
1226 fsm->slave_state = ec_fsm_slaveconf_end; |
|
1218 return; |
1227 return; |
1219 } |
1228 } |
1220 |
1229 |
1221 if (fsm->change_state != ec_fsm_change_end) return; |
1230 if (fsm->change_state != ec_fsm_change_end) return; |
1222 |
1231 |
1223 // slave is now in PREOP |
1232 // slave is now in PREOP |
1224 if (slave->current_state == slave->requested_state) { |
1233 if (slave->current_state == slave->requested_state) { |
1225 fsm->slave_state = ec_fsm_slave_end; |
1234 fsm->slave_state = ec_fsm_slaveconf_end; // successful |
1226 return; |
1235 return; |
1227 } |
1236 } |
1228 |
1237 |
1229 // stop activation here for slaves without type |
1238 // stop activation here for slaves without type |
1230 if (!slave->type) { |
1239 if (!slave->type) { |
1231 fsm->slave_state = ec_fsm_slave_end; |
1240 fsm->slave_state = ec_fsm_slaveconf_end; // successful |
1232 return; |
1241 return; |
1233 } |
1242 } |
1234 |
1243 |
1235 if (!slave->base_fmmu_count) { |
1244 if (!slave->base_fmmu_count) { |
1236 fsm->slave_state = ec_fsm_slave_saveop; |
1245 fsm->slave_state = ec_fsm_slaveconf_saveop; |
1237 fsm->slave_state(fsm); // execute immediately |
1246 fsm->change_new = EC_SLAVE_STATE_SAVEOP; |
1247 fsm->change_state = ec_fsm_change_start; |
|
1248 fsm->change_state(fsm); // execute immediately |
|
1238 return; |
1249 return; |
1239 } |
1250 } |
1240 |
1251 |
1241 // configure FMMUs |
1252 // configure FMMUs |
1242 ec_command_npwr(command, slave->station_address, |
1253 ec_datagram_npwr(datagram, slave->station_address, |
1243 0x0600, EC_FMMU_SIZE * slave->base_fmmu_count); |
1254 0x0600, EC_FMMU_SIZE * slave->base_fmmu_count); |
1244 memset(command->data, 0x00, EC_FMMU_SIZE * slave->base_fmmu_count); |
1255 memset(datagram->data, 0x00, EC_FMMU_SIZE * slave->base_fmmu_count); |
1245 for (j = 0; j < slave->fmmu_count; j++) { |
1256 for (j = 0; j < slave->fmmu_count; j++) { |
1246 ec_fmmu_config(&slave->fmmus[j], slave, |
1257 ec_fmmu_config(&slave->fmmus[j], slave, |
1247 command->data + EC_FMMU_SIZE * j); |
1258 datagram->data + EC_FMMU_SIZE * j); |
1248 } |
1259 } |
1249 |
1260 |
1250 ec_master_queue_command(master, command); |
1261 ec_master_queue_datagram(master, datagram); |
1251 fsm->slave_state = ec_fsm_slave_saveop; |
1262 fsm->slave_state = ec_fsm_slaveconf_fmmu; |
1252 } |
1263 } |
1253 |
1264 |
1254 /*****************************************************************************/ |
1265 /*****************************************************************************/ |
1255 |
1266 |
1256 /** |
1267 /** |
1257 Slave state: SAVEOP. |
1268 Slave state: FMMU. |
1258 Set slave state to SAVEOP. |
1269 */ |
1259 */ |
1270 |
1260 |
1271 void ec_fsm_slaveconf_fmmu(ec_fsm_t *fsm /**< finite state machine */) |
1261 void ec_fsm_slave_saveop(ec_fsm_t *fsm /**< finite state machine */) |
1272 { |
1262 { |
1273 ec_datagram_t *datagram = &fsm->datagram; |
1263 ec_command_t *command = &fsm->command; |
1274 |
1264 |
1275 if (datagram->state != EC_CMD_RECEIVED || datagram->working_counter != 1) { |
1265 if (fsm->slave->base_fmmu_count && (command->state != EC_CMD_RECEIVED || |
1276 fsm->slave->error_flag = 1; |
1266 command->working_counter != 1)) { |
1277 fsm->slave_state = ec_fsm_slaveconf_end; |
1267 EC_ERR("FSM failed to set FMMUs on slave %i.\n", |
1278 EC_ERR("Failed to set FMMUs on slave %i.\n", |
1268 fsm->slave->ring_position); |
1279 fsm->slave->ring_position); |
1269 fsm->slave->state_error = 1; |
|
1270 fsm->slave_state = ec_fsm_slave_end; |
|
1271 return; |
1280 return; |
1272 } |
1281 } |
1273 |
1282 |
1274 // set state to SAVEOP |
1283 // set state to SAVEOP |
1275 fsm->slave_state = ec_fsm_slave_op; |
1284 fsm->slave_state = ec_fsm_slaveconf_saveop; |
1276 fsm->change_new = EC_SLAVE_STATE_SAVEOP; |
1285 fsm->change_new = EC_SLAVE_STATE_SAVEOP; |
1277 fsm->change_state = ec_fsm_change_start; |
1286 fsm->change_state = ec_fsm_change_start; |
1278 fsm->change_state(fsm); // execute immediately |
1287 fsm->change_state(fsm); // execute immediately |
1279 } |
1288 } |
1280 |
1289 |
1281 /*****************************************************************************/ |
1290 /*****************************************************************************/ |
1282 |
1291 |
1283 /** |
1292 /** |
1284 Slave state: OP. |
1293 Slave state: SAVEOP. |
1285 Set slave state to OP. |
1294 */ |
1286 */ |
1295 |
1287 |
1296 void ec_fsm_slaveconf_saveop(ec_fsm_t *fsm /**< finite state machine */) |
1288 void ec_fsm_slave_op(ec_fsm_t *fsm /**< finite state machine */) |
|
1289 { |
1297 { |
1290 fsm->change_state(fsm); // execute state change state machine |
1298 fsm->change_state(fsm); // execute state change state machine |
1291 |
1299 |
1292 if (fsm->change_state == ec_fsm_change_error) { |
1300 if (fsm->change_state == ec_fsm_change_error) { |
1293 fsm->slave_state = ec_fsm_slave_end; |
1301 fsm->slave->error_flag = 1; |
1302 fsm->slave_state = ec_fsm_slaveconf_end; |
|
1294 return; |
1303 return; |
1295 } |
1304 } |
1296 |
1305 |
1297 if (fsm->change_state != ec_fsm_change_end) return; |
1306 if (fsm->change_state != ec_fsm_change_end) return; |
1298 |
1307 |
1299 // slave is now in SAVEOP |
1308 // slave is now in SAVEOP |
1300 if (fsm->slave->current_state == fsm->slave->requested_state) { |
1309 if (fsm->slave->current_state == fsm->slave->requested_state) { |
1301 fsm->slave_state = ec_fsm_slave_end; |
1310 fsm->slave_state = ec_fsm_slaveconf_end; // successful |
1302 return; |
1311 return; |
1303 } |
1312 } |
1304 |
1313 |
1305 // set state to OP |
1314 // set state to OP |
1306 fsm->slave_state = ec_fsm_slave_op2; |
1315 fsm->slave_state = ec_fsm_slaveconf_op; |
1307 fsm->change_new = EC_SLAVE_STATE_OP; |
1316 fsm->change_new = EC_SLAVE_STATE_OP; |
1308 fsm->change_state = ec_fsm_change_start; |
1317 fsm->change_state = ec_fsm_change_start; |
1309 fsm->change_state(fsm); // execute immediately |
1318 fsm->change_state(fsm); // execute immediately |
1310 } |
1319 } |
1311 |
1320 |
1312 /*****************************************************************************/ |
1321 /*****************************************************************************/ |
1313 |
1322 |
1314 /** |
1323 /** |
1315 Slave state: OP2 |
1324 Slave state: OP |
1316 Executes the change state machine, until the OP state is set. |
1325 */ |
1317 */ |
1326 |
1318 |
1327 void ec_fsm_slaveconf_op(ec_fsm_t *fsm /**< finite state machine */) |
1319 void ec_fsm_slave_op2(ec_fsm_t *fsm /**< finite state machine */) |
|
1320 { |
1328 { |
1321 fsm->change_state(fsm); // execute state change state machine |
1329 fsm->change_state(fsm); // execute state change state machine |
1322 |
1330 |
1323 if (fsm->change_state == ec_fsm_change_error) { |
1331 if (fsm->change_state == ec_fsm_change_error) { |
1324 fsm->slave_state = ec_fsm_slave_end; |
1332 fsm->slave->error_flag = 1; |
1333 fsm->slave_state = ec_fsm_slaveconf_end; |
|
1325 return; |
1334 return; |
1326 } |
1335 } |
1327 |
1336 |
1328 if (fsm->change_state != ec_fsm_change_end) return; |
1337 if (fsm->change_state != ec_fsm_change_end) return; |
1329 |
1338 |
1330 // slave is now in OP |
1339 // slave is now in OP |
1331 fsm->slave_state = ec_fsm_slave_end; |
1340 fsm->slave_state = ec_fsm_slaveconf_end; // successful |
1332 } |
1341 } |
1333 |
1342 |
1334 /*****************************************************************************/ |
1343 /*****************************************************************************/ |
1335 |
1344 |
1336 /** |
1345 /** |
1337 Slave state: END. |
1346 Slave state: END. |
1338 End state of the slave state machine. |
1347 End state of the slave state machine. |
1339 */ |
1348 */ |
1340 |
1349 |
1341 void ec_fsm_slave_end(ec_fsm_t *fsm /**< finite state machine */) |
1350 void ec_fsm_slaveconf_end(ec_fsm_t *fsm /**< finite state machine */) |
1342 { |
1351 { |
1343 } |
1352 } |
1344 |
1353 |
1345 /****************************************************************************** |
1354 /****************************************************************************** |
1346 * SII state machine |
1355 * SII sub state machine |
1347 *****************************************************************************/ |
1356 *****************************************************************************/ |
1348 |
1357 |
1349 /** |
1358 /** |
1350 SII state: START_READING. |
1359 SII state: START_READING. |
1351 Starts reading the slave information interface. |
1360 Starts reading the slave information interface. |
1352 */ |
1361 */ |
1353 |
1362 |
1354 void ec_fsm_sii_start_reading(ec_fsm_t *fsm /**< finite state machine */) |
1363 void ec_fsm_sii_start_reading(ec_fsm_t *fsm /**< finite state machine */) |
1355 { |
1364 { |
1356 ec_command_t *command = &fsm->command; |
1365 ec_datagram_t *datagram = &fsm->datagram; |
1357 |
1366 |
1358 // initiate read operation |
1367 // initiate read operation |
1359 if (fsm->sii_mode) { |
1368 if (fsm->sii_mode) { |
1360 ec_command_npwr(command, fsm->slave->station_address, 0x502, 4); |
1369 ec_datagram_npwr(datagram, fsm->slave->station_address, 0x502, 4); |
1361 } |
1370 } |
1362 else { |
1371 else { |
1363 ec_command_apwr(command, fsm->slave->ring_position, 0x502, 4); |
1372 ec_datagram_apwr(datagram, fsm->slave->ring_position, 0x502, 4); |
1364 } |
1373 } |
1365 |
1374 |
1366 EC_WRITE_U8 (command->data, 0x00); // read-only access |
1375 EC_WRITE_U8 (datagram->data, 0x00); // read-only access |
1367 EC_WRITE_U8 (command->data + 1, 0x01); // request read operation |
1376 EC_WRITE_U8 (datagram->data + 1, 0x01); // request read operation |
1368 EC_WRITE_U16(command->data + 2, fsm->sii_offset); |
1377 EC_WRITE_U16(datagram->data + 2, fsm->sii_offset); |
1369 ec_master_queue_command(fsm->master, command); |
1378 ec_master_queue_datagram(fsm->master, datagram); |
1370 fsm->sii_state = ec_fsm_sii_read_check; |
1379 fsm->sii_state = ec_fsm_sii_read_check; |
1371 } |
1380 } |
1372 |
1381 |
1373 /*****************************************************************************/ |
1382 /*****************************************************************************/ |
1374 |
1383 |
1375 /** |
1384 /** |
1376 SII state: READ_CHECK. |
1385 SII state: READ_CHECK. |
1377 Checks, if the SII-read-command has been sent and issues a fetch command. |
1386 Checks, if the SII-read-datagram has been sent and issues a fetch datagram. |
1378 */ |
1387 */ |
1379 |
1388 |
1380 void ec_fsm_sii_read_check(ec_fsm_t *fsm /**< finite state machine */) |
1389 void ec_fsm_sii_read_check(ec_fsm_t *fsm /**< finite state machine */) |
1381 { |
1390 { |
1382 ec_command_t *command = &fsm->command; |
1391 ec_datagram_t *datagram = &fsm->datagram; |
1383 |
1392 |
1384 if (command->state != EC_CMD_RECEIVED || command->working_counter != 1) { |
1393 if (datagram->state != EC_CMD_RECEIVED || datagram->working_counter != 1) { |
1385 EC_ERR("SII: Reception of read command failed.\n"); |
1394 EC_ERR("SII: Reception of read datagram failed.\n"); |
1386 fsm->sii_state = ec_fsm_sii_error; |
1395 fsm->sii_state = ec_fsm_sii_error; |
1387 return; |
1396 return; |
1388 } |
1397 } |
1389 |
1398 |
1390 fsm->sii_start = get_cycles(); |
1399 fsm->sii_start = get_cycles(); |
1391 |
1400 |
1392 // issue check/fetch command |
1401 // issue check/fetch datagram |
1393 if (fsm->sii_mode) { |
1402 if (fsm->sii_mode) { |
1394 ec_command_nprd(command, fsm->slave->station_address, 0x502, 10); |
1403 ec_datagram_nprd(datagram, fsm->slave->station_address, 0x502, 10); |
1395 } |
1404 } |
1396 else { |
1405 else { |
1397 ec_command_aprd(command, fsm->slave->ring_position, 0x502, 10); |
1406 ec_datagram_aprd(datagram, fsm->slave->ring_position, 0x502, 10); |
1398 } |
1407 } |
1399 |
1408 |
1400 ec_master_queue_command(fsm->master, command); |
1409 ec_master_queue_datagram(fsm->master, datagram); |
1401 fsm->sii_state = ec_fsm_sii_read_fetch; |
1410 fsm->sii_state = ec_fsm_sii_read_fetch; |
1402 } |
1411 } |
1403 |
1412 |
1404 /*****************************************************************************/ |
1413 /*****************************************************************************/ |
1405 |
1414 |
1406 /** |
1415 /** |
1407 SII state: READ_FETCH. |
1416 SII state: READ_FETCH. |
1408 Fetches the result of an SII-read command. |
1417 Fetches the result of an SII-read datagram. |
1409 */ |
1418 */ |
1410 |
1419 |
1411 void ec_fsm_sii_read_fetch(ec_fsm_t *fsm /**< finite state machine */) |
1420 void ec_fsm_sii_read_fetch(ec_fsm_t *fsm /**< finite state machine */) |
1412 { |
1421 { |
1413 ec_command_t *command = &fsm->command; |
1422 ec_datagram_t *datagram = &fsm->datagram; |
1414 |
1423 |
1415 if (command->state != EC_CMD_RECEIVED || command->working_counter != 1) { |
1424 if (datagram->state != EC_CMD_RECEIVED || datagram->working_counter != 1) { |
1416 EC_ERR("SII: Reception of check/fetch command failed.\n"); |
1425 EC_ERR("SII: Reception of check/fetch datagram failed.\n"); |
1417 fsm->sii_state = ec_fsm_sii_error; |
1426 fsm->sii_state = ec_fsm_sii_error; |
1418 return; |
1427 return; |
1419 } |
1428 } |
1420 |
1429 |
1421 // check "busy bit" |
1430 // check "busy bit" |
1422 if (EC_READ_U8(command->data + 1) & 0x81) { |
1431 if (EC_READ_U8(datagram->data + 1) & 0x81) { |
1423 // still busy... timeout? |
1432 // still busy... timeout? |
1424 if (get_cycles() - fsm->sii_start >= (cycles_t) 10 * cpu_khz) { |
1433 if (get_cycles() - fsm->sii_start >= (cycles_t) 10 * cpu_khz) { |
1425 EC_ERR("SII: Timeout.\n"); |
1434 EC_ERR("SII: Timeout.\n"); |
1426 fsm->sii_state = ec_fsm_sii_error; |
1435 fsm->sii_state = ec_fsm_sii_error; |
1427 #if 0 |
1436 #if 0 |
1428 EC_DBG("SII busy: %02X %02X %02X %02X\n", |
1437 EC_DBG("SII busy: %02X %02X %02X %02X\n", |
1429 EC_READ_U8(command->data + 0), |
1438 EC_READ_U8(datagram->data + 0), |
1430 EC_READ_U8(command->data + 1), |
1439 EC_READ_U8(datagram->data + 1), |
1431 EC_READ_U8(command->data + 2), |
1440 EC_READ_U8(datagram->data + 2), |
1432 EC_READ_U8(command->data + 3)); |
1441 EC_READ_U8(datagram->data + 3)); |
1433 #endif |
1442 #endif |
1434 } |
1443 } |
1435 |
1444 |
1436 // issue check/fetch command again |
1445 // issue check/fetch datagram again |
1437 if (fsm->sii_mode) { |
1446 if (fsm->sii_mode) { |
1438 ec_command_nprd(command, fsm->slave->station_address, 0x502, 10); |
1447 ec_datagram_nprd(datagram, fsm->slave->station_address, 0x502, 10); |
1439 } |
1448 } |
1440 else { |
1449 else { |
1441 ec_command_aprd(command, fsm->slave->ring_position, 0x502, 10); |
1450 ec_datagram_aprd(datagram, fsm->slave->ring_position, 0x502, 10); |
1442 } |
1451 } |
1443 ec_master_queue_command(fsm->master, command); |
1452 ec_master_queue_datagram(fsm->master, datagram); |
1444 return; |
1453 return; |
1445 } |
1454 } |
1446 |
1455 |
1447 #if 0 |
1456 #if 0 |
1448 EC_DBG("SII rec: %02X %02X %02X %02X - %02X %02X %02X %02X\n", |
1457 EC_DBG("SII rec: %02X %02X %02X %02X - %02X %02X %02X %02X\n", |
1449 EC_READ_U8(command->data + 0), EC_READ_U8(command->data + 1), |
1458 EC_READ_U8(datagram->data + 0), EC_READ_U8(datagram->data + 1), |
1450 EC_READ_U8(command->data + 2), EC_READ_U8(command->data + 3), |
1459 EC_READ_U8(datagram->data + 2), EC_READ_U8(datagram->data + 3), |
1451 EC_READ_U8(command->data + 6), EC_READ_U8(command->data + 7), |
1460 EC_READ_U8(datagram->data + 6), EC_READ_U8(datagram->data + 7), |
1452 EC_READ_U8(command->data + 8), EC_READ_U8(command->data + 9)); |
1461 EC_READ_U8(datagram->data + 8), EC_READ_U8(datagram->data + 9)); |
1453 #endif |
1462 #endif |
1454 |
1463 |
1455 // SII value received. |
1464 // SII value received. |
1456 memcpy(fsm->sii_value, command->data + 6, 4); |
1465 memcpy(fsm->sii_value, datagram->data + 6, 4); |
1457 fsm->sii_state = ec_fsm_sii_end; |
1466 fsm->sii_state = ec_fsm_sii_end; |
1458 } |
1467 } |
1459 |
1468 |
1460 /*****************************************************************************/ |
1469 /*****************************************************************************/ |
1461 |
1470 |
1464 Starts reading the slave information interface. |
1473 Starts reading the slave information interface. |
1465 */ |
1474 */ |
1466 |
1475 |
1467 void ec_fsm_sii_start_writing(ec_fsm_t *fsm /**< finite state machine */) |
1476 void ec_fsm_sii_start_writing(ec_fsm_t *fsm /**< finite state machine */) |
1468 { |
1477 { |
1469 ec_command_t *command = &fsm->command; |
1478 ec_datagram_t *datagram = &fsm->datagram; |
1470 |
1479 |
1471 // initiate write operation |
1480 // initiate write operation |
1472 ec_command_npwr(command, fsm->slave->station_address, 0x502, 8); |
1481 ec_datagram_npwr(datagram, fsm->slave->station_address, 0x502, 8); |
1473 EC_WRITE_U8 (command->data, 0x01); // enable write access |
1482 EC_WRITE_U8 (datagram->data, 0x01); // enable write access |
1474 EC_WRITE_U8 (command->data + 1, 0x02); // request write operation |
1483 EC_WRITE_U8 (datagram->data + 1, 0x02); // request write operation |
1475 EC_WRITE_U32(command->data + 2, fsm->sii_offset); |
1484 EC_WRITE_U32(datagram->data + 2, fsm->sii_offset); |
1476 memcpy(command->data + 6, fsm->sii_value, 2); |
1485 memcpy(datagram->data + 6, fsm->sii_value, 2); |
1477 ec_master_queue_command(fsm->master, command); |
1486 ec_master_queue_datagram(fsm->master, datagram); |
1478 fsm->sii_state = ec_fsm_sii_write_check; |
1487 fsm->sii_state = ec_fsm_sii_write_check; |
1479 } |
1488 } |
1480 |
1489 |
1481 /*****************************************************************************/ |
1490 /*****************************************************************************/ |
1482 |
1491 |
1484 SII state: WRITE_CHECK. |
1493 SII state: WRITE_CHECK. |
1485 */ |
1494 */ |
1486 |
1495 |
1487 void ec_fsm_sii_write_check(ec_fsm_t *fsm /**< finite state machine */) |
1496 void ec_fsm_sii_write_check(ec_fsm_t *fsm /**< finite state machine */) |
1488 { |
1497 { |
1489 ec_command_t *command = &fsm->command; |
1498 ec_datagram_t *datagram = &fsm->datagram; |
1490 |
1499 |
1491 if (command->state != EC_CMD_RECEIVED || command->working_counter != 1) { |
1500 if (datagram->state != EC_CMD_RECEIVED || datagram->working_counter != 1) { |
1492 EC_ERR("SII: Reception of write command failed.\n"); |
1501 EC_ERR("SII: Reception of write datagram failed.\n"); |
1493 fsm->sii_state = ec_fsm_sii_error; |
1502 fsm->sii_state = ec_fsm_sii_error; |
1494 return; |
1503 return; |
1495 } |
1504 } |
1496 |
1505 |
1497 fsm->sii_start = get_cycles(); |
1506 fsm->sii_start = get_cycles(); |
1498 |
1507 |
1499 // issue check/fetch command |
1508 // issue check/fetch datagram |
1500 ec_command_nprd(command, fsm->slave->station_address, 0x502, 2); |
1509 ec_datagram_nprd(datagram, fsm->slave->station_address, 0x502, 2); |
1501 ec_master_queue_command(fsm->master, command); |
1510 ec_master_queue_datagram(fsm->master, datagram); |
1502 fsm->sii_state = ec_fsm_sii_write_check2; |
1511 fsm->sii_state = ec_fsm_sii_write_check2; |
1503 } |
1512 } |
1504 |
1513 |
1505 /*****************************************************************************/ |
1514 /*****************************************************************************/ |
1506 |
1515 |
1508 SII state: WRITE_CHECK2. |
1517 SII state: WRITE_CHECK2. |
1509 */ |
1518 */ |
1510 |
1519 |
1511 void ec_fsm_sii_write_check2(ec_fsm_t *fsm /**< finite state machine */) |
1520 void ec_fsm_sii_write_check2(ec_fsm_t *fsm /**< finite state machine */) |
1512 { |
1521 { |
1513 ec_command_t *command = &fsm->command; |
1522 ec_datagram_t *datagram = &fsm->datagram; |
1514 |
1523 |
1515 if (command->state != EC_CMD_RECEIVED || command->working_counter != 1) { |
1524 if (datagram->state != EC_CMD_RECEIVED || datagram->working_counter != 1) { |
1516 EC_ERR("SII: Reception of write check command failed.\n"); |
1525 EC_ERR("SII: Reception of write check datagram failed.\n"); |
1517 fsm->sii_state = ec_fsm_sii_error; |
1526 fsm->sii_state = ec_fsm_sii_error; |
1518 return; |
1527 return; |
1519 } |
1528 } |
1520 |
1529 |
1521 if (EC_READ_U8(command->data + 1) & 0x82) { |
1530 if (EC_READ_U8(datagram->data + 1) & 0x82) { |
1522 // still busy... timeout? |
1531 // still busy... timeout? |
1523 if (get_cycles() - fsm->sii_start >= (cycles_t) 10 * cpu_khz) { |
1532 if (get_cycles() - fsm->sii_start >= (cycles_t) 10 * cpu_khz) { |
1524 EC_ERR("SII: Write timeout.\n"); |
1533 EC_ERR("SII: Write timeout.\n"); |
1525 fsm->sii_state = ec_fsm_sii_error; |
1534 fsm->sii_state = ec_fsm_sii_error; |
1526 } |
1535 } |
1527 |
1536 |
1528 // issue check/fetch command again |
1537 // issue check/fetch datagram again |
1529 ec_master_queue_command(fsm->master, command); |
1538 ec_master_queue_datagram(fsm->master, datagram); |
1530 } |
1539 } |
1531 else if (EC_READ_U8(command->data + 1) & 0x40) { |
1540 else if (EC_READ_U8(datagram->data + 1) & 0x40) { |
1532 EC_ERR("SII: Write operation failed!\n"); |
1541 EC_ERR("SII: Write operation failed!\n"); |
1533 fsm->sii_state = ec_fsm_sii_error; |
1542 fsm->sii_state = ec_fsm_sii_error; |
1534 } |
1543 } |
1535 else { // success |
1544 else { // success |
1536 fsm->sii_state = ec_fsm_sii_end; |
1545 fsm->sii_state = ec_fsm_sii_end; |
1558 void ec_fsm_sii_error(ec_fsm_t *fsm /**< finite state machine */) |
1567 void ec_fsm_sii_error(ec_fsm_t *fsm /**< finite state machine */) |
1559 { |
1568 { |
1560 } |
1569 } |
1561 |
1570 |
1562 /****************************************************************************** |
1571 /****************************************************************************** |
1563 * state change state machine |
1572 * state change sub state machine |
1564 *****************************************************************************/ |
1573 *****************************************************************************/ |
1565 |
1574 |
1566 /** |
1575 /** |
1567 Change state: START. |
1576 Change state: START. |
1568 */ |
1577 */ |
1569 |
1578 |
1570 void ec_fsm_change_start(ec_fsm_t *fsm /**< finite state machine */) |
1579 void ec_fsm_change_start(ec_fsm_t *fsm /**< finite state machine */) |
1571 { |
1580 { |
1572 ec_command_t *command = &fsm->command; |
1581 ec_datagram_t *datagram = &fsm->datagram; |
1573 ec_slave_t *slave = fsm->slave; |
1582 ec_slave_t *slave = fsm->slave; |
1574 |
1583 |
1575 // write new state to slave |
1584 // write new state to slave |
1576 ec_command_npwr(command, slave->station_address, 0x0120, 2); |
1585 ec_datagram_npwr(datagram, slave->station_address, 0x0120, 2); |
1577 EC_WRITE_U16(command->data, fsm->change_new); |
1586 EC_WRITE_U16(datagram->data, fsm->change_new); |
1578 ec_master_queue_command(fsm->master, command); |
1587 ec_master_queue_datagram(fsm->master, datagram); |
1579 fsm->change_state = ec_fsm_change_check; |
1588 fsm->change_state = ec_fsm_change_check; |
1580 } |
1589 } |
1581 |
1590 |
1582 /*****************************************************************************/ |
1591 /*****************************************************************************/ |
1583 |
1592 |
1585 Change state: CHECK. |
1594 Change state: CHECK. |
1586 */ |
1595 */ |
1587 |
1596 |
1588 void ec_fsm_change_check(ec_fsm_t *fsm /**< finite state machine */) |
1597 void ec_fsm_change_check(ec_fsm_t *fsm /**< finite state machine */) |
1589 { |
1598 { |
1590 ec_command_t *command = &fsm->command; |
1599 ec_datagram_t *datagram = &fsm->datagram; |
1591 ec_slave_t *slave = fsm->slave; |
1600 ec_slave_t *slave = fsm->slave; |
1592 |
1601 |
1593 if (command->state != EC_CMD_RECEIVED) { |
1602 if (datagram->state != EC_CMD_RECEIVED) { |
1594 EC_ERR("Failed to send state command to slave %i!\n", |
1603 fsm->change_state = ec_fsm_change_error; |
1604 EC_ERR("Failed to send state datagram to slave %i!\n", |
|
1595 fsm->slave->ring_position); |
1605 fsm->slave->ring_position); |
1596 slave->state_error = 1; |
1606 return; |
1607 } |
|
1608 |
|
1609 if (datagram->working_counter != 1) { |
|
1597 fsm->change_state = ec_fsm_change_error; |
1610 fsm->change_state = ec_fsm_change_error; |
1598 return; |
|
1599 } |
|
1600 |
|
1601 if (command->working_counter != 1) { |
|
1602 EC_ERR("Failed to set state 0x%02X on slave %i: Slave did not" |
1611 EC_ERR("Failed to set state 0x%02X on slave %i: Slave did not" |
1603 " respond.\n", fsm->change_new, fsm->slave->ring_position); |
1612 " respond.\n", fsm->change_new, fsm->slave->ring_position); |
1604 slave->state_error = 1; |
1613 return; |
1614 } |
|
1615 |
|
1616 fsm->change_start = get_cycles(); |
|
1617 |
|
1618 // read AL status from slave |
|
1619 ec_datagram_nprd(datagram, slave->station_address, 0x0130, 2); |
|
1620 ec_master_queue_datagram(fsm->master, datagram); |
|
1621 fsm->change_state = ec_fsm_change_status; |
|
1622 } |
|
1623 |
|
1624 /*****************************************************************************/ |
|
1625 |
|
1626 /** |
|
1627 Change state: STATUS. |
|
1628 */ |
|
1629 |
|
1630 void ec_fsm_change_status(ec_fsm_t *fsm /**< finite state machine */) |
|
1631 { |
|
1632 ec_datagram_t *datagram = &fsm->datagram; |
|
1633 ec_slave_t *slave = fsm->slave; |
|
1634 |
|
1635 if (datagram->state != EC_CMD_RECEIVED || datagram->working_counter != 1) { |
|
1605 fsm->change_state = ec_fsm_change_error; |
1636 fsm->change_state = ec_fsm_change_error; |
1606 return; |
|
1607 } |
|
1608 |
|
1609 fsm->change_start = get_cycles(); |
|
1610 |
|
1611 // read AL status from slave |
|
1612 ec_command_nprd(command, slave->station_address, 0x0130, 2); |
|
1613 ec_master_queue_command(fsm->master, command); |
|
1614 fsm->change_state = ec_fsm_change_status; |
|
1615 } |
|
1616 |
|
1617 /*****************************************************************************/ |
|
1618 |
|
1619 /** |
|
1620 Change state: STATUS. |
|
1621 */ |
|
1622 |
|
1623 void ec_fsm_change_status(ec_fsm_t *fsm /**< finite state machine */) |
|
1624 { |
|
1625 ec_command_t *command = &fsm->command; |
|
1626 ec_slave_t *slave = fsm->slave; |
|
1627 |
|
1628 if (command->state != EC_CMD_RECEIVED || command->working_counter != 1) { |
|
1629 EC_ERR("Failed to check state 0x%02X on slave %i.\n", |
1637 EC_ERR("Failed to check state 0x%02X on slave %i.\n", |
1630 fsm->change_new, slave->ring_position); |
1638 fsm->change_new, slave->ring_position); |
1631 slave->state_error = 1; |
1639 return; |
1632 fsm->change_state = ec_fsm_change_error; |
1640 } |
1633 return; |
1641 |
1634 } |
1642 slave->current_state = EC_READ_U8(datagram->data); |
1635 |
|
1636 slave->current_state = EC_READ_U8(command->data); |
|
1637 |
1643 |
1638 if (slave->current_state == fsm->change_new) { |
1644 if (slave->current_state == fsm->change_new) { |
1639 // state has been set successfully |
1645 // state has been set successfully |
1640 fsm->change_state = ec_fsm_change_end; |
1646 fsm->change_state = ec_fsm_change_end; |
1641 return; |
1647 return; |
1646 fsm->change_new = slave->current_state & 0x0F; |
1652 fsm->change_new = slave->current_state & 0x0F; |
1647 EC_ERR("Failed to set state 0x%02X - Slave %i refused state change" |
1653 EC_ERR("Failed to set state 0x%02X - Slave %i refused state change" |
1648 " (code 0x%02X)!\n", fsm->change_new, slave->ring_position, |
1654 " (code 0x%02X)!\n", fsm->change_new, slave->ring_position, |
1649 slave->current_state); |
1655 slave->current_state); |
1650 // fetch AL status error code |
1656 // fetch AL status error code |
1651 ec_command_nprd(command, slave->station_address, 0x0134, 2); |
1657 ec_datagram_nprd(datagram, slave->station_address, 0x0134, 2); |
1652 ec_master_queue_command(fsm->master, command); |
1658 ec_master_queue_datagram(fsm->master, datagram); |
1653 fsm->change_state = ec_fsm_change_code; |
1659 fsm->change_state = ec_fsm_change_code; |
1654 return; |
1660 return; |
1655 } |
1661 } |
1656 |
1662 |
1657 if (get_cycles() - fsm->change_start >= (cycles_t) 10 * cpu_khz) { |
1663 if (get_cycles() - fsm->change_start >= (cycles_t) 10 * cpu_khz) { |
1658 // timeout while checking |
1664 // timeout while checking |
1659 slave->state_error = 1; |
|
1660 fsm->change_state = ec_fsm_change_error; |
1665 fsm->change_state = ec_fsm_change_error; |
1661 EC_ERR("Timeout while setting state 0x%02X on slave %i.\n", |
1666 EC_ERR("Timeout while setting state 0x%02X on slave %i.\n", |
1662 fsm->change_new, slave->ring_position); |
1667 fsm->change_new, slave->ring_position); |
1663 return; |
1668 return; |
1664 } |
1669 } |
1665 |
1670 |
1666 // still old state: check again |
1671 // still old state: check again |
1667 ec_command_nprd(command, slave->station_address, 0x0130, 2); |
1672 ec_datagram_nprd(datagram, slave->station_address, 0x0130, 2); |
1668 ec_master_queue_command(fsm->master, command); |
1673 ec_master_queue_datagram(fsm->master, datagram); |
1669 } |
1674 } |
1670 |
1675 |
1671 /*****************************************************************************/ |
1676 /*****************************************************************************/ |
1672 |
1677 |
1673 /** |
1678 /** |
1685 {0x0017, "Invalid sync manager configuration"}, |
1690 {0x0017, "Invalid sync manager configuration"}, |
1686 {0x0018, "No valid inputs available"}, |
1691 {0x0018, "No valid inputs available"}, |
1687 {0x0019, "No valid outputs"}, |
1692 {0x0019, "No valid outputs"}, |
1688 {0x001A, "Synchronisation error"}, |
1693 {0x001A, "Synchronisation error"}, |
1689 {0x001B, "Sync manager watchdog"}, |
1694 {0x001B, "Sync manager watchdog"}, |
1695 {0x001C, "Invalid sync manager types"}, |
|
1696 {0x001D, "Invalid output configuration"}, |
|
1697 {0x001E, "Invalid input configuration"}, |
|
1698 {0x001F, "Invalid watchdog configuration"}, |
|
1690 {0x0020, "Slave needs cold start"}, |
1699 {0x0020, "Slave needs cold start"}, |
1691 {0x0021, "Slave needs INIT"}, |
1700 {0x0021, "Slave needs INIT"}, |
1692 {0x0022, "Slave needs PREOP"}, |
1701 {0x0022, "Slave needs PREOP"}, |
1693 {0x0023, "Slave needs SAVEOP"}, |
1702 {0x0023, "Slave needs SAVEOP"}, |
1703 {0x0030, "Invalid DC SYNCH configuration"}, |
|
1704 {0x0031, "Invalid DC latch configuration"}, |
|
1705 {0x0032, "PLL error"}, |
|
1706 {0x0033, "Invalid DC IO error"}, |
|
1707 {0x0034, "Invalid DC timeout error"}, |
|
1708 {0x0042, "MBOX EOE"}, |
|
1709 {0x0043, "MBOX COE"}, |
|
1710 {0x0044, "MBOX FOE"}, |
|
1711 {0x0045, "MBOX SOE"}, |
|
1712 {0x004F, "MBOX VOE"}, |
|
1694 {} |
1713 {} |
1695 }; |
1714 }; |
1696 |
1715 |
1697 /*****************************************************************************/ |
1716 /*****************************************************************************/ |
1698 |
1717 |
1700 Change state: CODE. |
1719 Change state: CODE. |
1701 */ |
1720 */ |
1702 |
1721 |
1703 void ec_fsm_change_code(ec_fsm_t *fsm /**< finite state machine */) |
1722 void ec_fsm_change_code(ec_fsm_t *fsm /**< finite state machine */) |
1704 { |
1723 { |
1705 ec_command_t *command = &fsm->command; |
1724 ec_datagram_t *datagram = &fsm->datagram; |
1706 ec_slave_t *slave = fsm->slave; |
1725 ec_slave_t *slave = fsm->slave; |
1707 uint32_t code; |
1726 uint32_t code; |
1708 const ec_code_msg_t *al_msg; |
1727 const ec_code_msg_t *al_msg; |
1709 |
1728 |
1710 if (command->state != EC_CMD_RECEIVED || command->working_counter != 1) { |
1729 if (datagram->state != EC_CMD_RECEIVED || datagram->working_counter != 1) { |
1711 EC_ERR("Reception of AL status code command failed.\n"); |
|
1712 slave->state_error = 1; |
|
1713 fsm->change_state = ec_fsm_change_error; |
1730 fsm->change_state = ec_fsm_change_error; |
1714 return; |
1731 EC_ERR("Reception of AL status code datagram failed.\n"); |
1715 } |
1732 return; |
1716 |
1733 } |
1717 if ((code = EC_READ_U16(command->data))) { |
1734 |
1735 if ((code = EC_READ_U16(datagram->data))) { |
|
1718 for (al_msg = al_status_messages; al_msg->code; al_msg++) { |
1736 for (al_msg = al_status_messages; al_msg->code; al_msg++) { |
1719 if (al_msg->code != code) continue; |
1737 if (al_msg->code != code) continue; |
1720 EC_ERR("AL status message 0x%04X: \"%s\".\n", |
1738 EC_ERR("AL status message 0x%04X: \"%s\".\n", |
1721 al_msg->code, al_msg->message); |
1739 al_msg->code, al_msg->message); |
1722 break; |
1740 break; |
1724 if (!al_msg->code) |
1742 if (!al_msg->code) |
1725 EC_ERR("Unknown AL status code 0x%04X.\n", code); |
1743 EC_ERR("Unknown AL status code 0x%04X.\n", code); |
1726 } |
1744 } |
1727 |
1745 |
1728 // acknowledge "old" slave state |
1746 // acknowledge "old" slave state |
1729 ec_command_npwr(command, slave->station_address, 0x0120, 2); |
1747 ec_datagram_npwr(datagram, slave->station_address, 0x0120, 2); |
1730 EC_WRITE_U16(command->data, slave->current_state); |
1748 EC_WRITE_U16(datagram->data, slave->current_state); |
1731 ec_master_queue_command(fsm->master, command); |
1749 ec_master_queue_datagram(fsm->master, datagram); |
1732 fsm->change_state = ec_fsm_change_ack; |
1750 fsm->change_state = ec_fsm_change_ack; |
1733 } |
1751 } |
1734 |
1752 |
1735 /*****************************************************************************/ |
1753 /*****************************************************************************/ |
1736 |
1754 |
1738 Change state: ACK. |
1756 Change state: ACK. |
1739 */ |
1757 */ |
1740 |
1758 |
1741 void ec_fsm_change_ack(ec_fsm_t *fsm /**< finite state machine */) |
1759 void ec_fsm_change_ack(ec_fsm_t *fsm /**< finite state machine */) |
1742 { |
1760 { |
1743 ec_command_t *command = &fsm->command; |
1761 ec_datagram_t *datagram = &fsm->datagram; |
1744 ec_slave_t *slave = fsm->slave; |
1762 ec_slave_t *slave = fsm->slave; |
1745 |
1763 |
1746 if (command->state != EC_CMD_RECEIVED || command->working_counter != 1) { |
1764 if (datagram->state != EC_CMD_RECEIVED || datagram->working_counter != 1) { |
1747 EC_ERR("Reception of state ack command failed.\n"); |
|
1748 slave->state_error = 1; |
|
1749 fsm->change_state = ec_fsm_change_error; |
1765 fsm->change_state = ec_fsm_change_error; |
1750 return; |
1766 EC_ERR("Reception of state ack datagram failed.\n"); |
1751 } |
1767 return; |
1768 } |
|
1769 |
|
1770 fsm->change_start = get_cycles(); |
|
1752 |
1771 |
1753 // read new AL status |
1772 // read new AL status |
1754 ec_command_nprd(command, slave->station_address, 0x0130, 2); |
1773 ec_datagram_nprd(datagram, slave->station_address, 0x0130, 2); |
1755 ec_master_queue_command(fsm->master, command); |
1774 ec_master_queue_datagram(fsm->master, datagram); |
1756 fsm->change_state = ec_fsm_change_ack2; |
1775 fsm->change_state = ec_fsm_change_check_ack; |
1757 } |
1776 } |
1758 |
1777 |
1759 /*****************************************************************************/ |
1778 /*****************************************************************************/ |
1760 |
1779 |
1761 /** |
1780 /** |
1762 Change state: ACK. |
1781 Change state: CHECK ACK. |
1763 Acknowledge 2. |
1782 */ |
1764 */ |
1783 |
1765 |
1784 void ec_fsm_change_check_ack(ec_fsm_t *fsm /**< finite state machine */) |
1766 void ec_fsm_change_ack2(ec_fsm_t *fsm /**< finite state machine */) |
1785 { |
1767 { |
1786 ec_datagram_t *datagram = &fsm->datagram; |
1768 ec_command_t *command = &fsm->command; |
1787 ec_slave_t *slave = fsm->slave; |
1769 ec_slave_t *slave = fsm->slave; |
1788 ec_slave_state_t ack_state; |
1770 |
1789 |
1771 if (command->state != EC_CMD_RECEIVED || command->working_counter != 1) { |
1790 if (datagram->state != EC_CMD_RECEIVED || datagram->working_counter != 1) { |
1772 EC_ERR("Reception of state ack check command failed.\n"); |
|
1773 slave->state_error = 1; |
|
1774 fsm->change_state = ec_fsm_change_error; |
1791 fsm->change_state = ec_fsm_change_error; |
1775 return; |
1792 EC_ERR("Reception of state ack check datagram failed.\n"); |
1776 } |
1793 return; |
1777 |
1794 } |
1778 slave->current_state = EC_READ_U8(command->data); |
1795 |
1779 |
1796 ack_state = EC_READ_U8(datagram->data); |
1780 if (slave->current_state == fsm->change_new) { |
1797 |
1798 if (ack_state == slave->current_state) { |
|
1799 fsm->change_state = ec_fsm_change_error; |
|
1781 EC_INFO("Acknowleged state 0x%02X on slave %i.\n", |
1800 EC_INFO("Acknowleged state 0x%02X on slave %i.\n", |
1782 slave->current_state, slave->ring_position); |
1801 slave->current_state, slave->ring_position); |
1783 slave->state_error = 1; |
1802 return; |
1803 } |
|
1804 |
|
1805 if (get_cycles() - fsm->change_start >= (cycles_t) 100 * cpu_khz) { |
|
1806 // timeout while checking |
|
1807 slave->current_state = EC_SLAVE_STATE_UNKNOWN; |
|
1784 fsm->change_state = ec_fsm_change_error; |
1808 fsm->change_state = ec_fsm_change_error; |
1785 return; |
1809 EC_ERR("Timeout while acknowleging state 0x%02X on slave %i.\n", |
1786 } |
1810 fsm->change_new, slave->ring_position); |
1787 |
1811 return; |
1788 EC_WARN("Failed to acknowledge state 0x%02X on slave %i" |
1812 } |
1789 " - Timeout!\n", fsm->change_new, slave->ring_position); |
1813 |
1790 slave->state_error = 1; |
1814 // reread new AL status |
1791 fsm->change_state = ec_fsm_change_error; |
1815 ec_datagram_nprd(datagram, slave->station_address, 0x0130, 2); |
1816 ec_master_queue_datagram(fsm->master, datagram); |
|
1792 } |
1817 } |
1793 |
1818 |
1794 /*****************************************************************************/ |
1819 /*****************************************************************************/ |
1795 |
1820 |
1796 /** |
1821 /** |