52 void ec_fsm_master_rewrite_addresses(ec_fsm_t *); |
52 void ec_fsm_master_rewrite_addresses(ec_fsm_t *); |
53 void ec_fsm_master_configure_slave(ec_fsm_t *); |
53 void ec_fsm_master_configure_slave(ec_fsm_t *); |
54 void ec_fsm_master_scan_slaves(ec_fsm_t *); |
54 void ec_fsm_master_scan_slaves(ec_fsm_t *); |
55 void ec_fsm_master_write_eeprom(ec_fsm_t *); |
55 void ec_fsm_master_write_eeprom(ec_fsm_t *); |
56 |
56 |
|
57 void ec_fsm_startup_start(ec_fsm_t *); |
|
58 void ec_fsm_startup_broadcast(ec_fsm_t *); |
|
59 void ec_fsm_startup_scan(ec_fsm_t *); |
|
60 |
|
61 void ec_fsm_configuration_start(ec_fsm_t *); |
|
62 void ec_fsm_configuration_conf(ec_fsm_t *); |
|
63 |
57 void ec_fsm_slavescan_start(ec_fsm_t *); |
64 void ec_fsm_slavescan_start(ec_fsm_t *); |
58 void ec_fsm_slavescan_address(ec_fsm_t *); |
65 void ec_fsm_slavescan_address(ec_fsm_t *); |
59 void ec_fsm_slavescan_state(ec_fsm_t *); |
66 void ec_fsm_slavescan_state(ec_fsm_t *); |
60 void ec_fsm_slavescan_base(ec_fsm_t *); |
67 void ec_fsm_slavescan_base(ec_fsm_t *); |
61 void ec_fsm_slavescan_datalink(ec_fsm_t *); |
68 void ec_fsm_slavescan_datalink(ec_fsm_t *); |
62 void ec_fsm_slavescan_eeprom_size(ec_fsm_t *); |
69 void ec_fsm_slavescan_eeprom_size(ec_fsm_t *); |
63 void ec_fsm_slavescan_eeprom_data(ec_fsm_t *); |
70 void ec_fsm_slavescan_eeprom_data(ec_fsm_t *); |
64 void ec_fsm_slavescan_end(ec_fsm_t *); |
|
65 |
71 |
66 void ec_fsm_slaveconf_init(ec_fsm_t *); |
72 void ec_fsm_slaveconf_init(ec_fsm_t *); |
67 void ec_fsm_slaveconf_sync(ec_fsm_t *); |
73 void ec_fsm_slaveconf_sync(ec_fsm_t *); |
68 void ec_fsm_slaveconf_preop(ec_fsm_t *); |
74 void ec_fsm_slaveconf_preop(ec_fsm_t *); |
69 void ec_fsm_slaveconf_fmmu(ec_fsm_t *); |
75 void ec_fsm_slaveconf_fmmu(ec_fsm_t *); |
70 void ec_fsm_slaveconf_saveop(ec_fsm_t *); |
76 void ec_fsm_slaveconf_saveop(ec_fsm_t *); |
71 void ec_fsm_slaveconf_op(ec_fsm_t *); |
77 void ec_fsm_slaveconf_op(ec_fsm_t *); |
72 void ec_fsm_slaveconf_end(ec_fsm_t *); |
|
73 |
78 |
74 void ec_fsm_sii_start_reading(ec_fsm_t *); |
79 void ec_fsm_sii_start_reading(ec_fsm_t *); |
75 void ec_fsm_sii_read_check(ec_fsm_t *); |
80 void ec_fsm_sii_read_check(ec_fsm_t *); |
76 void ec_fsm_sii_read_fetch(ec_fsm_t *); |
81 void ec_fsm_sii_read_fetch(ec_fsm_t *); |
77 void ec_fsm_sii_start_writing(ec_fsm_t *); |
82 void ec_fsm_sii_start_writing(ec_fsm_t *); |
78 void ec_fsm_sii_write_check(ec_fsm_t *); |
83 void ec_fsm_sii_write_check(ec_fsm_t *); |
79 void ec_fsm_sii_write_check2(ec_fsm_t *); |
84 void ec_fsm_sii_write_check2(ec_fsm_t *); |
80 void ec_fsm_sii_end(ec_fsm_t *); |
|
81 void ec_fsm_sii_error(ec_fsm_t *); |
|
82 |
85 |
83 void ec_fsm_change_start(ec_fsm_t *); |
86 void ec_fsm_change_start(ec_fsm_t *); |
84 void ec_fsm_change_check(ec_fsm_t *); |
87 void ec_fsm_change_check(ec_fsm_t *); |
85 void ec_fsm_change_status(ec_fsm_t *); |
88 void ec_fsm_change_status(ec_fsm_t *); |
86 void ec_fsm_change_code(ec_fsm_t *); |
89 void ec_fsm_change_code(ec_fsm_t *); |
87 void ec_fsm_change_ack(ec_fsm_t *); |
90 void ec_fsm_change_ack(ec_fsm_t *); |
88 void ec_fsm_change_check_ack(ec_fsm_t *); |
91 void ec_fsm_change_check_ack(ec_fsm_t *); |
89 void ec_fsm_change_end(ec_fsm_t *); |
92 |
90 void ec_fsm_change_error(ec_fsm_t *); |
93 void ec_fsm_end(ec_fsm_t *); |
|
94 void ec_fsm_error(ec_fsm_t *); |
91 |
95 |
92 /*****************************************************************************/ |
96 /*****************************************************************************/ |
93 |
97 |
94 /** |
98 /** |
95 Constructor. |
99 Constructor. |
96 */ |
100 */ |
97 |
101 |
98 int ec_fsm_init(ec_fsm_t *fsm, /**< finite state machine */ |
102 int ec_fsm_init(ec_fsm_t *fsm, /**< finite state machine */ |
99 ec_master_t *master /**< EtherCAT master */ |
103 ec_master_t *master /**< EtherCAT master */ |
100 ) |
104 ) |
101 { |
105 { |
102 fsm->master = master; |
106 fsm->master = master; |
103 fsm->master_state = ec_fsm_master_start; |
107 fsm->master_state = ec_fsm_master_start; |
104 fsm->master_slaves_responding = 0; |
108 fsm->master_slaves_responding = 0; |
105 fsm->master_slave_states = EC_SLAVE_STATE_UNKNOWN; |
109 fsm->master_slave_states = EC_SLAVE_STATE_UNKNOWN; |
147 void ec_fsm_execute(ec_fsm_t *fsm /**< finite state machine */) |
151 void ec_fsm_execute(ec_fsm_t *fsm /**< finite state machine */) |
148 { |
152 { |
149 fsm->master_state(fsm); |
153 fsm->master_state(fsm); |
150 } |
154 } |
151 |
155 |
|
156 /*****************************************************************************/ |
|
157 |
|
158 void ec_fsm_startup(ec_fsm_t *fsm) |
|
159 { |
|
160 fsm->master_state = ec_fsm_startup_start; |
|
161 } |
|
162 |
|
163 /*****************************************************************************/ |
|
164 |
|
165 int ec_fsm_startup_running(ec_fsm_t *fsm) |
|
166 { |
|
167 return fsm->master_state != ec_fsm_end && |
|
168 fsm->master_state != ec_fsm_error; |
|
169 } |
|
170 |
|
171 /*****************************************************************************/ |
|
172 |
|
173 int ec_fsm_startup_success(ec_fsm_t *fsm) |
|
174 { |
|
175 return fsm->master_state == ec_fsm_end; |
|
176 } |
|
177 |
|
178 /*****************************************************************************/ |
|
179 |
|
180 void ec_fsm_configuration(ec_fsm_t *fsm) |
|
181 { |
|
182 fsm->master_state = ec_fsm_configuration_start; |
|
183 } |
|
184 |
|
185 /*****************************************************************************/ |
|
186 |
|
187 int ec_fsm_configuration_running(ec_fsm_t *fsm) |
|
188 { |
|
189 return fsm->master_state != ec_fsm_end && |
|
190 fsm->master_state != ec_fsm_error; |
|
191 } |
|
192 |
|
193 /*****************************************************************************/ |
|
194 |
|
195 int ec_fsm_configuration_success(ec_fsm_t *fsm) |
|
196 { |
|
197 return fsm->master_state == ec_fsm_end; |
|
198 } |
|
199 |
152 /****************************************************************************** |
200 /****************************************************************************** |
153 * master state machine |
201 * master startup state machine |
|
202 *****************************************************************************/ |
|
203 |
|
204 /** |
|
205 Master state: START. |
|
206 Starts with getting slave count and slave states. |
|
207 */ |
|
208 |
|
209 void ec_fsm_startup_start(ec_fsm_t *fsm) |
|
210 { |
|
211 ec_datagram_brd(&fsm->datagram, 0x0130, 2); |
|
212 ec_master_queue_datagram(fsm->master, &fsm->datagram); |
|
213 fsm->master_state = ec_fsm_startup_broadcast; |
|
214 } |
|
215 |
|
216 /*****************************************************************************/ |
|
217 |
|
218 /** |
|
219 Master state: BROADCAST. |
|
220 Processes the broadcast read slave count and slaves states. |
|
221 */ |
|
222 |
|
223 void ec_fsm_startup_broadcast(ec_fsm_t *fsm /**< finite state machine */) |
|
224 { |
|
225 ec_datagram_t *datagram = &fsm->datagram; |
|
226 unsigned int i; |
|
227 ec_slave_t *slave; |
|
228 ec_master_t *master = fsm->master; |
|
229 |
|
230 if (datagram->state != EC_DATAGRAM_RECEIVED) { |
|
231 EC_ERR("Failed tor receive broadcast datagram.\n"); |
|
232 fsm->master_state = ec_fsm_error; |
|
233 return; |
|
234 } |
|
235 |
|
236 EC_INFO("Scanning bus.\n"); |
|
237 |
|
238 ec_master_clear_slaves(master); |
|
239 |
|
240 master->slave_count = datagram->working_counter; |
|
241 |
|
242 if (!master->slave_count) { |
|
243 // no slaves present -> finish state machine. |
|
244 fsm->master_state = ec_fsm_end; |
|
245 return; |
|
246 } |
|
247 |
|
248 // init slaves |
|
249 for (i = 0; i < master->slave_count; i++) { |
|
250 if (!(slave = (ec_slave_t *) kmalloc(sizeof(ec_slave_t), |
|
251 GFP_KERNEL))) { |
|
252 EC_ERR("Failed to allocate slave %i!\n", i); |
|
253 fsm->master_state = ec_fsm_error; |
|
254 return; |
|
255 } |
|
256 |
|
257 if (ec_slave_init(slave, master, i, i + 1)) { |
|
258 fsm->master_state = ec_fsm_error; |
|
259 return; |
|
260 } |
|
261 |
|
262 if (kobject_add(&slave->kobj)) { |
|
263 EC_ERR("Failed to add kobject.\n"); |
|
264 kobject_put(&slave->kobj); // free |
|
265 fsm->master_state = ec_fsm_error; |
|
266 return; |
|
267 } |
|
268 |
|
269 list_add_tail(&slave->list, &master->slaves); |
|
270 } |
|
271 |
|
272 // begin scanning of slaves |
|
273 fsm->slave = list_entry(master->slaves.next, ec_slave_t, list); |
|
274 fsm->slave_state = ec_fsm_slavescan_start; |
|
275 fsm->master_state = ec_fsm_startup_scan; |
|
276 fsm->master_state(fsm); // execute immediately |
|
277 return; |
|
278 } |
|
279 |
|
280 /*****************************************************************************/ |
|
281 |
|
282 /** |
|
283 Master state: SCAN. |
|
284 Executes the sub-statemachine for the scanning of a slave. |
|
285 */ |
|
286 |
|
287 void ec_fsm_startup_scan(ec_fsm_t *fsm /**< finite state machine */) |
|
288 { |
|
289 ec_master_t *master = fsm->master; |
|
290 ec_slave_t *slave = fsm->slave; |
|
291 |
|
292 fsm->slave_state(fsm); // execute slave state machine |
|
293 |
|
294 if (fsm->slave_state == ec_fsm_error) { |
|
295 EC_ERR("Slave scanning failed.\n"); |
|
296 fsm->master_state = ec_fsm_error; |
|
297 return; |
|
298 } |
|
299 |
|
300 if (fsm->slave_state != ec_fsm_end) return; |
|
301 |
|
302 // another slave to scan? |
|
303 if (slave->list.next != &master->slaves) { |
|
304 fsm->slave = list_entry(fsm->slave->list.next, ec_slave_t, list); |
|
305 fsm->slave_state = ec_fsm_slavescan_start; |
|
306 fsm->slave_state(fsm); // execute immediately |
|
307 return; |
|
308 } |
|
309 |
|
310 EC_INFO("Bus scanning completed.\n"); |
|
311 |
|
312 ec_master_calc_addressing(master); |
|
313 |
|
314 fsm->master_state = ec_fsm_end; |
|
315 } |
|
316 |
|
317 /****************************************************************************** |
|
318 * master configuration state machine |
|
319 *****************************************************************************/ |
|
320 |
|
321 void ec_fsm_configuration_start(ec_fsm_t *fsm /**< finite state machine */) |
|
322 { |
|
323 ec_master_t *master = fsm->master; |
|
324 |
|
325 if (list_empty(&master->slaves)) { |
|
326 fsm->master_state = ec_fsm_end; |
|
327 return; |
|
328 } |
|
329 |
|
330 // begin configuring slaves |
|
331 fsm->slave = list_entry(master->slaves.next, ec_slave_t, list); |
|
332 fsm->slave_state = ec_fsm_slaveconf_init; |
|
333 fsm->change_new = EC_SLAVE_STATE_INIT; |
|
334 fsm->change_state = ec_fsm_change_start; |
|
335 fsm->master_state = ec_fsm_configuration_conf; |
|
336 fsm->master_state(fsm); // execute immediately |
|
337 } |
|
338 |
|
339 /*****************************************************************************/ |
|
340 |
|
341 /** |
|
342 Master state: CONF. |
|
343 */ |
|
344 |
|
345 void ec_fsm_configuration_conf(ec_fsm_t *fsm /**< finite state machine */) |
|
346 { |
|
347 ec_master_t *master = fsm->master; |
|
348 ec_slave_t *slave = fsm->slave; |
|
349 |
|
350 fsm->slave_state(fsm); // execute slave's state machine |
|
351 |
|
352 if (fsm->slave_state == ec_fsm_error) { |
|
353 fsm->master_state = ec_fsm_error; |
|
354 return; |
|
355 } |
|
356 |
|
357 if (fsm->slave_state != ec_fsm_end) return; |
|
358 |
|
359 // another slave to configure? |
|
360 if (slave->list.next != &master->slaves) { |
|
361 fsm->slave = list_entry(fsm->slave->list.next, ec_slave_t, list); |
|
362 fsm->slave_state = ec_fsm_slaveconf_init; |
|
363 fsm->change_new = EC_SLAVE_STATE_INIT; |
|
364 fsm->change_state = ec_fsm_change_start; |
|
365 fsm->master_state(fsm); // execute immediately |
|
366 return; |
|
367 } |
|
368 |
|
369 fsm->master_state = ec_fsm_end; |
|
370 } |
|
371 |
|
372 /****************************************************************************** |
|
373 * operation / idle state machine |
154 *****************************************************************************/ |
374 *****************************************************************************/ |
155 |
375 |
156 /** |
376 /** |
157 Master state: START. |
377 Master state: START. |
158 Starts with getting slave count and slave states. |
378 Starts with getting slave count and slave states. |
201 if (topology_change) { |
421 if (topology_change) { |
202 EC_INFO("%i slave%s responding.\n", |
422 EC_INFO("%i slave%s responding.\n", |
203 fsm->master_slaves_responding, |
423 fsm->master_slaves_responding, |
204 fsm->master_slaves_responding == 1 ? "" : "s"); |
424 fsm->master_slaves_responding == 1 ? "" : "s"); |
205 |
425 |
206 if (master->mode == EC_MASTER_MODE_RUNNING) { |
426 if (master->mode == EC_MASTER_MODE_OPERATION) { |
207 if (fsm->master_slaves_responding == master->slave_count) { |
427 if (fsm->master_slaves_responding == master->slave_count) { |
208 fsm->master_validation = 1; // start validation later |
428 fsm->master_validation = 1; // start validation later |
209 } |
429 } |
210 else { |
430 else { |
211 EC_WARN("Invalid slave count. Bus in tainted state.\n"); |
431 EC_WARN("Invalid slave count. Bus in tainted state.\n"); |
212 } |
432 } |
213 } |
433 } |
214 } |
434 } |
215 |
435 |
216 if (states_change) { |
436 if (states_change) { |
217 EC_INFO("Slave states: "); |
437 char states[25]; |
218 ec_print_states(fsm->master_slave_states); |
438 ec_state_string(fsm->master_slave_states, states); |
219 printk(".\n"); |
439 EC_INFO("Slave states: %s.\n", states); |
220 } |
440 } |
221 |
441 |
222 // topology change in idle mode: clear all slaves and scan the bus |
442 // topology change in idle mode: clear all slaves and scan the bus |
223 if (topology_change && master->mode == EC_MASTER_MODE_IDLE) { |
443 if (topology_change && master->mode == EC_MASTER_MODE_IDLE) { |
224 EC_INFO("Scanning bus.\n"); |
444 EC_INFO("Scanning bus.\n"); |
225 |
445 |
226 ec_master_eoe_stop(master); |
446 ec_master_eoe_stop(master); |
227 ec_master_clear_slaves(master); |
447 ec_master_clear_slaves(master); |
228 |
448 |
229 if (!fsm->master_slaves_responding) { |
449 master->slave_count = datagram->working_counter; |
|
450 |
|
451 if (!master->slave_count) { |
230 // no slaves present -> finish state machine. |
452 // no slaves present -> finish state machine. |
231 fsm->master_state = ec_fsm_master_start; |
453 fsm->master_state = ec_fsm_master_start; |
232 fsm->master_state(fsm); // execute immediately |
454 fsm->master_state(fsm); // execute immediately |
233 return; |
455 return; |
234 } |
456 } |
235 |
457 |
236 // init slaves |
458 // init slaves |
237 for (i = 0; i < fsm->master_slaves_responding; i++) { |
459 for (i = 0; i < master->slave_count; i++) { |
238 if (!(slave = (ec_slave_t *) kmalloc(sizeof(ec_slave_t), |
460 if (!(slave = (ec_slave_t *) kmalloc(sizeof(ec_slave_t), |
239 GFP_ATOMIC))) { |
461 GFP_ATOMIC))) { |
240 EC_ERR("Failed to allocate slave %i!\n", i); |
462 EC_ERR("Failed to allocate slave %i!\n", i); |
|
463 ec_master_clear_slaves(master); |
241 fsm->master_state = ec_fsm_master_start; |
464 fsm->master_state = ec_fsm_master_start; |
242 fsm->master_state(fsm); // execute immediately |
465 fsm->master_state(fsm); // execute immediately |
243 return; |
466 return; |
244 } |
467 } |
245 |
468 |
246 if (ec_slave_init(slave, master, i, i + 1)) { |
469 if (ec_slave_init(slave, master, i, i + 1)) { |
|
470 // freeing of "slave" already done |
|
471 ec_master_clear_slaves(master); |
247 fsm->master_state = ec_fsm_master_start; |
472 fsm->master_state = ec_fsm_master_start; |
248 fsm->master_state(fsm); // execute immediately |
473 fsm->master_state(fsm); // execute immediately |
249 return; |
474 return; |
250 } |
475 } |
251 |
476 |
252 if (kobject_add(&slave->kobj)) { |
477 if (kobject_add(&slave->kobj)) { |
253 EC_ERR("Failed to add kobject.\n"); |
478 EC_ERR("Failed to add kobject.\n"); |
254 kobject_put(&slave->kobj); // free |
479 kobject_put(&slave->kobj); // free |
|
480 ec_master_clear_slaves(master); |
255 fsm->master_state = ec_fsm_master_start; |
481 fsm->master_state = ec_fsm_master_start; |
256 fsm->master_state(fsm); // execute immediately |
482 fsm->master_state(fsm); // execute immediately |
257 return; |
483 return; |
258 } |
484 } |
259 |
485 |
286 /**< finite state machine */ |
512 /**< finite state machine */ |
287 ) |
513 ) |
288 { |
514 { |
289 ec_master_t *master = fsm->master; |
515 ec_master_t *master = fsm->master; |
290 ec_slave_t *slave; |
516 ec_slave_t *slave; |
|
517 char old_state[25], new_state[25]; |
291 |
518 |
292 // check if any slaves are not in the state, they're supposed to be |
519 // check if any slaves are not in the state, they're supposed to be |
293 list_for_each_entry(slave, &master->slaves, list) { |
520 list_for_each_entry(slave, &master->slaves, list) { |
294 if (slave->error_flag || |
521 if (slave->error_flag || |
295 !slave->online || |
522 !slave->online || |
296 slave->requested_state == EC_SLAVE_STATE_UNKNOWN || |
523 slave->requested_state == EC_SLAVE_STATE_UNKNOWN || |
297 slave->current_state == slave->requested_state) continue; |
524 slave->current_state == slave->requested_state) continue; |
298 |
525 |
299 EC_INFO("Changing state of slave %i from ", slave->ring_position); |
526 ec_state_string(slave->current_state, old_state); |
300 ec_print_states(slave->current_state); |
527 ec_state_string(slave->requested_state, new_state); |
301 printk(" to "); |
528 EC_INFO("Changing state of slave %i from %s to %s.\n", |
302 ec_print_states(slave->requested_state); |
529 slave->ring_position, old_state, new_state); |
303 printk(".\n"); |
|
304 |
530 |
305 fsm->slave = slave; |
531 fsm->slave = slave; |
306 fsm->slave_state = ec_fsm_slaveconf_init; |
532 fsm->slave_state = ec_fsm_slaveconf_init; |
307 fsm->change_new = EC_SLAVE_STATE_INIT; |
533 fsm->change_new = EC_SLAVE_STATE_INIT; |
308 fsm->change_state = ec_fsm_change_start; |
534 fsm->change_state = ec_fsm_change_start; |
309 fsm->master_state = ec_fsm_master_configure_slave; |
535 fsm->master_state = ec_fsm_master_configure_slave; |
310 fsm->master_state(fsm); // execute immediately |
536 fsm->master_state(fsm); // execute immediately |
311 return; |
537 return; |
312 } |
538 } |
|
539 |
|
540 // Check, if EoE processing has to be started |
|
541 ec_master_eoe_start(master); |
313 |
542 |
314 if (master->mode == EC_MASTER_MODE_IDLE) { |
543 if (master->mode == EC_MASTER_MODE_IDLE) { |
315 // nothing to configure. check for pending EEPROM write operations. |
544 // nothing to configure. check for pending EEPROM write operations. |
316 list_for_each_entry(slave, &master->slaves, list) { |
545 list_for_each_entry(slave, &master->slaves, list) { |
317 if (!slave->new_eeprom_data) continue; |
546 if (!slave->new_eeprom_data) continue; |
418 } |
647 } |
419 |
648 |
420 // slave responded |
649 // slave responded |
421 new_state = EC_READ_U8(datagram->data); |
650 new_state = EC_READ_U8(datagram->data); |
422 if (!slave->online) { // slave was offline before |
651 if (!slave->online) { // slave was offline before |
|
652 char cur_state[25]; |
423 slave->online = 1; |
653 slave->online = 1; |
424 slave->error_flag = 0; // clear error flag |
654 slave->error_flag = 0; // clear error flag |
425 slave->current_state = new_state; |
655 slave->current_state = new_state; |
426 EC_INFO("Slave %i: online (", slave->ring_position); |
656 ec_state_string(slave->current_state, cur_state); |
427 ec_print_states(new_state); |
657 EC_INFO("Slave %i: online (%s).\n", slave->ring_position, cur_state); |
428 printk(").\n"); |
|
429 } |
658 } |
430 else if (new_state != slave->current_state) { |
659 else if (new_state != slave->current_state) { |
431 EC_INFO("Slave %i: ", slave->ring_position); |
660 char old_state[25], cur_state[25]; |
432 ec_print_states(slave->current_state); |
661 ec_state_string(slave->current_state, old_state); |
433 printk(" -> "); |
662 ec_state_string(new_state, cur_state); |
434 ec_print_states(new_state); |
663 EC_INFO("Slave %i: %s -> %s.\n", |
435 printk(".\n"); |
664 slave->ring_position, old_state, cur_state); |
436 slave->current_state = new_state; |
665 slave->current_state = new_state; |
437 } |
666 } |
438 |
667 |
439 ec_fsm_master_action_next_slave_state(fsm); |
668 ec_fsm_master_action_next_slave_state(fsm); |
440 } |
669 } |
450 { |
679 { |
451 ec_slave_t *slave = fsm->slave; |
680 ec_slave_t *slave = fsm->slave; |
452 |
681 |
453 fsm->sii_state(fsm); // execute SII state machine |
682 fsm->sii_state(fsm); // execute SII state machine |
454 |
683 |
455 if (fsm->sii_state == ec_fsm_sii_error) { |
684 if (fsm->sii_state == ec_fsm_error) { |
456 fsm->slave->error_flag = 1; |
685 fsm->slave->error_flag = 1; |
457 EC_ERR("Failed to validate vendor ID of slave %i.\n", |
686 EC_ERR("Failed to validate vendor ID of slave %i.\n", |
458 slave->ring_position); |
687 slave->ring_position); |
459 fsm->master_state = ec_fsm_master_start; |
688 fsm->master_state = ec_fsm_master_start; |
460 fsm->master_state(fsm); // execute immediately |
689 fsm->master_state(fsm); // execute immediately |
461 return; |
690 return; |
462 } |
691 } |
463 |
692 |
464 if (fsm->sii_state != ec_fsm_sii_end) return; |
693 if (fsm->sii_state != ec_fsm_end) return; |
465 |
694 |
466 if (EC_READ_U32(fsm->sii_value) != slave->sii_vendor_id) { |
695 if (EC_READ_U32(fsm->sii_value) != slave->sii_vendor_id) { |
467 EC_ERR("Slave %i: invalid vendor ID!\n", slave->ring_position); |
696 EC_ERR("Slave %i: invalid vendor ID!\n", slave->ring_position); |
468 fsm->master_state = ec_fsm_master_start; |
697 fsm->master_state = ec_fsm_master_start; |
469 fsm->master_state(fsm); // execute immediately |
698 fsm->master_state(fsm); // execute immediately |
520 { |
749 { |
521 ec_slave_t *slave = fsm->slave; |
750 ec_slave_t *slave = fsm->slave; |
522 |
751 |
523 fsm->sii_state(fsm); // execute SII state machine |
752 fsm->sii_state(fsm); // execute SII state machine |
524 |
753 |
525 if (fsm->sii_state == ec_fsm_sii_error) { |
754 if (fsm->sii_state == ec_fsm_error) { |
526 fsm->slave->error_flag = 1; |
755 fsm->slave->error_flag = 1; |
527 EC_ERR("Failed to validate product code of slave %i.\n", |
756 EC_ERR("Failed to validate product code of slave %i.\n", |
528 slave->ring_position); |
757 slave->ring_position); |
529 fsm->master_state = ec_fsm_master_start; |
758 fsm->master_state = ec_fsm_master_start; |
530 fsm->master_state(fsm); // execute immediately |
759 fsm->master_state(fsm); // execute immediately |
531 return; |
760 return; |
532 } |
761 } |
533 |
762 |
534 if (fsm->sii_state != ec_fsm_sii_end) return; |
763 if (fsm->sii_state != ec_fsm_end) return; |
535 |
764 |
536 if (EC_READ_U32(fsm->sii_value) != slave->sii_product_code) { |
765 if (EC_READ_U32(fsm->sii_value) != slave->sii_product_code) { |
537 EC_ERR("Slave %i: invalid product code!\n", slave->ring_position); |
766 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, |
767 EC_ERR("expected 0x%08X, got 0x%08X.\n", slave->sii_product_code, |
539 EC_READ_U32(fsm->sii_value)); |
768 EC_READ_U32(fsm->sii_value)); |
599 |
829 |
600 void ec_fsm_master_scan_slaves(ec_fsm_t *fsm /**< finite state machine */) |
830 void ec_fsm_master_scan_slaves(ec_fsm_t *fsm /**< finite state machine */) |
601 { |
831 { |
602 ec_master_t *master = fsm->master; |
832 ec_master_t *master = fsm->master; |
603 ec_slave_t *slave = fsm->slave; |
833 ec_slave_t *slave = fsm->slave; |
604 uint16_t coupler_index, coupler_subindex; |
834 |
605 uint16_t reverse_coupler_index, current_coupler_index; |
|
606 ec_slave_ident_t *ident; |
|
607 |
835 |
608 fsm->slave_state(fsm); // execute slave state machine |
836 fsm->slave_state(fsm); // execute slave state machine |
609 |
837 |
610 if (fsm->slave_state != ec_fsm_slavescan_end) return; |
838 if (fsm->slave_state != ec_fsm_end |
611 |
839 && fsm->slave_state != ec_fsm_error) return; |
612 // have all slaves been fetched? |
840 |
613 if (slave->list.next == &master->slaves) { |
841 // another slave to fetch? |
614 EC_INFO("Bus scanning completed.\n"); |
842 if (slave->list.next != &master->slaves) { |
615 |
843 fsm->slave = list_entry(fsm->slave->list.next, ec_slave_t, list); |
616 // identify all slaves and calculate coupler addressing |
844 fsm->slave_state = ec_fsm_slavescan_start; |
617 |
845 fsm->slave_state(fsm); // execute immediately |
618 coupler_index = 0; |
846 return; |
619 reverse_coupler_index = 0xFFFF; |
847 } |
620 current_coupler_index = 0x3FFF; |
848 |
621 coupler_subindex = 0; |
849 EC_INFO("Bus scanning completed.\n"); |
622 |
850 |
623 list_for_each_entry(slave, &master->slaves, list) |
851 ec_master_calc_addressing(master); |
624 { |
852 |
625 // search for identification in "database" |
853 // determine initial states. |
626 ident = slave_idents; |
854 list_for_each_entry(slave, &master->slaves, list) { |
627 while (ident->type) { |
855 if (ec_slave_is_coupler(slave)) { |
628 if (ident->vendor_id == slave->sii_vendor_id |
856 slave->requested_state = EC_SLAVE_STATE_OP; |
629 && ident->product_code == slave->sii_product_code) { |
857 } |
630 slave->type = ident->type; |
858 else { |
631 break; |
859 if (master->mode == EC_MASTER_MODE_OPERATION) |
632 } |
860 slave->requested_state = EC_SLAVE_STATE_PREOP; |
633 ident++; |
861 else |
634 } |
862 slave->requested_state = EC_SLAVE_STATE_INIT; |
635 |
863 } |
636 if (!slave->type) { |
864 } |
637 EC_WARN("Unknown slave device (vendor 0x%08X," |
865 |
638 " code 0x%08X) at position %i.\n", |
866 fsm->master_state = ec_fsm_master_start; |
639 slave->sii_vendor_id, slave->sii_product_code, |
867 fsm->master_state(fsm); // execute immediately |
640 slave->ring_position); |
|
641 } |
|
642 else { |
|
643 // if the slave is a bus coupler, change adressing base |
|
644 if (slave->type->special == EC_TYPE_BUS_COUPLER) { |
|
645 if (slave->sii_alias) |
|
646 current_coupler_index = reverse_coupler_index--; |
|
647 else |
|
648 current_coupler_index = coupler_index++; |
|
649 coupler_subindex = 0; |
|
650 } |
|
651 } |
|
652 |
|
653 // determine initial state. |
|
654 if ((slave->type && |
|
655 (slave->type->special == EC_TYPE_BUS_COUPLER || |
|
656 slave->type->special == EC_TYPE_INFRA))) { |
|
657 slave->requested_state = EC_SLAVE_STATE_OP; |
|
658 } |
|
659 else { |
|
660 if (master->mode == EC_MASTER_MODE_RUNNING) |
|
661 slave->requested_state = EC_SLAVE_STATE_PREOP; |
|
662 else |
|
663 slave->requested_state = EC_SLAVE_STATE_INIT; |
|
664 } |
|
665 slave->error_flag = 0; |
|
666 |
|
667 // calculate coupler-based slave address |
|
668 slave->coupler_index = current_coupler_index; |
|
669 slave->coupler_subindex = coupler_subindex; |
|
670 coupler_subindex++; |
|
671 } |
|
672 |
|
673 if (master->mode == EC_MASTER_MODE_IDLE) { |
|
674 // start EoE processing |
|
675 ec_master_eoe_start(master); |
|
676 } |
|
677 |
|
678 fsm->master_state = ec_fsm_master_start; |
|
679 fsm->master_state(fsm); // execute immediately |
|
680 return; |
|
681 } |
|
682 |
|
683 // process next slave |
|
684 fsm->slave = list_entry(fsm->slave->list.next, ec_slave_t, list); |
|
685 fsm->slave_state = ec_fsm_slavescan_start; |
|
686 fsm->slave_state(fsm); // execute immediately |
|
687 } |
868 } |
688 |
869 |
689 /*****************************************************************************/ |
870 /*****************************************************************************/ |
690 |
871 |
691 /** |
872 /** |
713 { |
896 { |
714 ec_slave_t *slave = fsm->slave; |
897 ec_slave_t *slave = fsm->slave; |
715 |
898 |
716 fsm->sii_state(fsm); // execute SII state machine |
899 fsm->sii_state(fsm); // execute SII state machine |
717 |
900 |
718 if (fsm->sii_state == ec_fsm_sii_error) { |
901 if (fsm->sii_state == ec_fsm_error) { |
719 fsm->slave->error_flag = 1; |
902 fsm->slave->error_flag = 1; |
720 EC_ERR("Failed to write EEPROM contents to slave %i.\n", |
903 EC_ERR("Failed to write EEPROM contents to slave %i.\n", |
721 slave->ring_position); |
904 slave->ring_position); |
722 kfree(slave->new_eeprom_data); |
905 kfree(slave->new_eeprom_data); |
723 slave->new_eeprom_data = NULL; |
906 slave->new_eeprom_data = NULL; |
724 fsm->master_state = ec_fsm_master_start; |
907 fsm->master_state = ec_fsm_master_start; |
725 fsm->master_state(fsm); // execute immediately |
908 fsm->master_state(fsm); // execute immediately |
726 return; |
909 return; |
727 } |
910 } |
728 |
911 |
729 if (fsm->sii_state != ec_fsm_sii_end) return; |
912 if (fsm->sii_state != ec_fsm_end) return; |
730 |
913 |
731 fsm->sii_offset++; |
914 fsm->sii_offset++; |
732 if (fsm->sii_offset < slave->new_eeprom_size) { |
915 if (fsm->sii_offset < slave->new_eeprom_size) { |
733 memcpy(fsm->sii_value, slave->new_eeprom_data + fsm->sii_offset, 2); |
916 memcpy(fsm->sii_value, slave->new_eeprom_data + fsm->sii_offset, 2); |
734 fsm->sii_state = ec_fsm_sii_start_writing; |
917 fsm->sii_state = ec_fsm_sii_start_writing; |
739 // finished writing EEPROM |
922 // finished writing EEPROM |
740 EC_INFO("Finished writing EEPROM of slave %i.\n", slave->ring_position); |
923 EC_INFO("Finished writing EEPROM of slave %i.\n", slave->ring_position); |
741 kfree(slave->new_eeprom_data); |
924 kfree(slave->new_eeprom_data); |
742 slave->new_eeprom_data = NULL; |
925 slave->new_eeprom_data = NULL; |
743 |
926 |
|
927 // TODO: Evaluate new EEPROM contents! |
|
928 |
744 // restart master state machine. |
929 // restart master state machine. |
745 fsm->master_state = ec_fsm_master_start; // TODO: Evaluate new contents! |
930 fsm->master_state = ec_fsm_master_start; |
746 fsm->master_state(fsm); // execute immediately |
931 fsm->master_state(fsm); // execute immediately |
747 return; |
932 return; |
748 } |
933 } |
749 |
934 |
750 /****************************************************************************** |
935 /****************************************************************************** |
751 * slave scan sub state machine |
936 * slave scan state machine |
752 *****************************************************************************/ |
937 *****************************************************************************/ |
753 |
938 |
754 /** |
939 /** |
755 Slave state: START_READING. |
940 Slave state: START_READING. |
756 First state of the slave state machine. Writes the station address to the |
941 First state of the slave state machine. Writes the station address to the |
1057 } |
1245 } |
1058 |
1246 |
1059 cat_word += cat_size + 2; |
1247 cat_word += cat_size + 2; |
1060 } |
1248 } |
1061 |
1249 |
1062 fsm->slave_state = ec_fsm_slavescan_end; |
1250 fsm->slave_state = ec_fsm_end; |
|
1251 return; |
1063 |
1252 |
1064 end: |
1253 end: |
|
1254 EC_ERR("Failed to analyze category data.\n"); |
1065 fsm->slave->error_flag = 1; |
1255 fsm->slave->error_flag = 1; |
1066 fsm->slave_state = ec_fsm_slavescan_end; |
1256 fsm->slave_state = ec_fsm_error; |
1067 } |
|
1068 |
|
1069 /*****************************************************************************/ |
|
1070 |
|
1071 /** |
|
1072 Slave state: END. |
|
1073 End state of the slave state machine. |
|
1074 */ |
|
1075 |
|
1076 void ec_fsm_slavescan_end(ec_fsm_t *fsm /**< finite state machine */) |
|
1077 { |
|
1078 } |
1257 } |
1079 |
1258 |
1080 /****************************************************************************** |
1259 /****************************************************************************** |
1081 * slave configuration sub state machine |
1260 * slave configuration state machine |
1082 *****************************************************************************/ |
1261 *****************************************************************************/ |
1083 |
1262 |
1084 /** |
1263 /** |
1085 Slave state: INIT. |
1264 Slave state: INIT. |
1086 */ |
1265 */ |
1087 |
1266 |
1088 void ec_fsm_slaveconf_init(ec_fsm_t *fsm /**< finite state machine */) |
1267 void ec_fsm_slaveconf_init(ec_fsm_t *fsm /**< finite state machine */) |
1089 { |
1268 { |
1090 ec_slave_t *slave = fsm->slave; |
1269 ec_slave_t *slave = fsm->slave; |
1091 ec_datagram_t *datagram = &fsm->datagram; |
1270 ec_datagram_t *datagram = &fsm->datagram; |
1092 const ec_sync_t *sync; |
1271 const ec_sii_sync_t *sync; |
1093 ec_eeprom_sync_t *eeprom_sync, mbox_sync; |
|
1094 unsigned int j; |
|
1095 |
1272 |
1096 fsm->change_state(fsm); // execute state change state machine |
1273 fsm->change_state(fsm); // execute state change state machine |
1097 |
1274 |
1098 if (fsm->change_state == ec_fsm_change_error) { |
1275 if (fsm->change_state == ec_fsm_error) { |
1099 slave->error_flag = 1; |
1276 slave->error_flag = 1; |
1100 fsm->slave_state = ec_fsm_slaveconf_end; |
1277 fsm->slave_state = ec_fsm_error; |
1101 return; |
1278 return; |
1102 } |
1279 } |
1103 |
1280 |
1104 if (fsm->change_state != ec_fsm_change_end) return; |
1281 if (fsm->change_state != ec_fsm_end) return; |
1105 |
1282 |
1106 // slave is now in INIT |
1283 // slave is now in INIT |
1107 if (slave->current_state == slave->requested_state) { |
1284 if (slave->current_state == slave->requested_state) { |
1108 fsm->slave_state = ec_fsm_slaveconf_end; // successful |
1285 fsm->slave_state = ec_fsm_end; // successful |
1109 return; |
1286 return; |
1110 } |
|
1111 |
|
1112 // check for slave registration |
|
1113 if (!slave->type) { |
|
1114 EC_WARN("Slave %i has unknown type!\n", slave->ring_position); |
|
1115 } |
1287 } |
1116 |
1288 |
1117 // check and reset CRC fault counters |
1289 // check and reset CRC fault counters |
1118 //ec_slave_check_crc(slave); |
1290 //ec_slave_check_crc(slave); |
1119 // TODO! |
1291 // TODO: Implement state machine for CRC checking. |
1120 |
1292 |
1121 if (!slave->base_sync_count) { // no sync managers |
1293 if (!slave->base_sync_count) { // no sync managers |
1122 fsm->slave_state = ec_fsm_slaveconf_preop; |
1294 fsm->slave_state = ec_fsm_slaveconf_preop; |
1123 fsm->change_new = EC_SLAVE_STATE_PREOP; |
1295 fsm->change_new = EC_SLAVE_STATE_PREOP; |
1124 fsm->change_state = ec_fsm_change_start; |
1296 fsm->change_state = ec_fsm_change_start; |
1129 // configure sync managers |
1301 // configure sync managers |
1130 ec_datagram_npwr(datagram, slave->station_address, 0x0800, |
1302 ec_datagram_npwr(datagram, slave->station_address, 0x0800, |
1131 EC_SYNC_SIZE * slave->base_sync_count); |
1303 EC_SYNC_SIZE * slave->base_sync_count); |
1132 memset(datagram->data, 0x00, EC_SYNC_SIZE * slave->base_sync_count); |
1304 memset(datagram->data, 0x00, EC_SYNC_SIZE * slave->base_sync_count); |
1133 |
1305 |
1134 // does the slave supply sync manager configurations in its EEPROM? |
1306 list_for_each_entry(sync, &slave->sii_syncs, list) { |
1135 if (!list_empty(&slave->eeprom_syncs)) { |
1307 if (sync->index >= slave->base_sync_count) { |
1136 list_for_each_entry(eeprom_sync, &slave->eeprom_syncs, list) { |
1308 EC_ERR("Invalid sync manager configuration found!"); |
1137 if (eeprom_sync->index >= slave->base_sync_count) { |
1309 fsm->slave->error_flag = 1; |
1138 fsm->slave->error_flag = 1; |
1310 fsm->slave_state = ec_fsm_error; |
1139 fsm->slave_state = ec_fsm_slaveconf_end; |
1311 return; |
1140 EC_ERR("Invalid sync manager configuration found!"); |
1312 } |
1141 return; |
1313 ec_sync_config(sync, slave, |
1142 } |
1314 datagram->data + EC_SYNC_SIZE * sync->index); |
1143 ec_eeprom_sync_config(eeprom_sync, slave, |
|
1144 datagram->data + EC_SYNC_SIZE |
|
1145 * eeprom_sync->index); |
|
1146 } |
|
1147 } |
|
1148 |
|
1149 // known slave type, take type's SM information |
|
1150 else if (slave->type) { |
|
1151 for (j = 0; slave->type->sync_managers[j] && j < EC_MAX_SYNC; j++) { |
|
1152 sync = slave->type->sync_managers[j]; |
|
1153 ec_sync_config(sync, slave, datagram->data + EC_SYNC_SIZE * j); |
|
1154 } |
|
1155 } |
|
1156 |
|
1157 // unknown type, but slave has mailbox |
|
1158 else if (slave->sii_mailbox_protocols) |
|
1159 { |
|
1160 // guess mailbox settings |
|
1161 mbox_sync.physical_start_address = |
|
1162 slave->sii_rx_mailbox_offset; |
|
1163 mbox_sync.length = slave->sii_rx_mailbox_size; |
|
1164 mbox_sync.control_register = 0x26; |
|
1165 mbox_sync.enable = 1; |
|
1166 ec_eeprom_sync_config(&mbox_sync, slave, datagram->data); |
|
1167 |
|
1168 mbox_sync.physical_start_address = |
|
1169 slave->sii_tx_mailbox_offset; |
|
1170 mbox_sync.length = slave->sii_tx_mailbox_size; |
|
1171 mbox_sync.control_register = 0x22; |
|
1172 mbox_sync.enable = 1; |
|
1173 ec_eeprom_sync_config(&mbox_sync, slave, |
|
1174 datagram->data + EC_SYNC_SIZE); |
|
1175 |
|
1176 EC_INFO("Mailbox configured for unknown slave %i\n", |
|
1177 slave->ring_position); |
|
1178 } |
1315 } |
1179 |
1316 |
1180 ec_master_queue_datagram(fsm->master, datagram); |
1317 ec_master_queue_datagram(fsm->master, datagram); |
1181 fsm->slave_state = ec_fsm_slaveconf_sync; |
1318 fsm->slave_state = ec_fsm_slaveconf_sync; |
1182 } |
1319 } |
1326 |
1459 |
1327 void ec_fsm_slaveconf_op(ec_fsm_t *fsm /**< finite state machine */) |
1460 void ec_fsm_slaveconf_op(ec_fsm_t *fsm /**< finite state machine */) |
1328 { |
1461 { |
1329 fsm->change_state(fsm); // execute state change state machine |
1462 fsm->change_state(fsm); // execute state change state machine |
1330 |
1463 |
1331 if (fsm->change_state == ec_fsm_change_error) { |
1464 if (fsm->change_state == ec_fsm_error) { |
1332 fsm->slave->error_flag = 1; |
1465 fsm->slave->error_flag = 1; |
1333 fsm->slave_state = ec_fsm_slaveconf_end; |
1466 fsm->slave_state = ec_fsm_error; |
1334 return; |
1467 return; |
1335 } |
1468 } |
1336 |
1469 |
1337 if (fsm->change_state != ec_fsm_change_end) return; |
1470 if (fsm->change_state != ec_fsm_end) return; |
1338 |
1471 |
1339 // slave is now in OP |
1472 // slave is now in OP |
1340 fsm->slave_state = ec_fsm_slaveconf_end; // successful |
1473 fsm->slave_state = ec_fsm_end; // successful |
1341 } |
|
1342 |
|
1343 /*****************************************************************************/ |
|
1344 |
|
1345 /** |
|
1346 Slave state: END. |
|
1347 End state of the slave state machine. |
|
1348 */ |
|
1349 |
|
1350 void ec_fsm_slaveconf_end(ec_fsm_t *fsm /**< finite state machine */) |
|
1351 { |
|
1352 } |
1474 } |
1353 |
1475 |
1354 /****************************************************************************** |
1476 /****************************************************************************** |
1355 * SII sub state machine |
1477 * SII state machine |
1356 *****************************************************************************/ |
1478 *****************************************************************************/ |
1357 |
1479 |
1358 /** |
1480 /** |
1359 SII state: START_READING. |
1481 SII state: START_READING. |
1360 Starts reading the slave information interface. |
1482 Starts reading the slave information interface. |
1419 |
1542 |
1420 void ec_fsm_sii_read_fetch(ec_fsm_t *fsm /**< finite state machine */) |
1543 void ec_fsm_sii_read_fetch(ec_fsm_t *fsm /**< finite state machine */) |
1421 { |
1544 { |
1422 ec_datagram_t *datagram = &fsm->datagram; |
1545 ec_datagram_t *datagram = &fsm->datagram; |
1423 |
1546 |
1424 if (datagram->state != EC_CMD_RECEIVED || datagram->working_counter != 1) { |
1547 if (datagram->state != EC_DATAGRAM_RECEIVED |
|
1548 || datagram->working_counter != 1) { |
1425 EC_ERR("SII: Reception of check/fetch datagram failed.\n"); |
1549 EC_ERR("SII: Reception of check/fetch datagram failed.\n"); |
1426 fsm->sii_state = ec_fsm_sii_error; |
1550 fsm->sii_state = ec_fsm_error; |
1427 return; |
1551 return; |
1428 } |
1552 } |
1429 |
1553 |
1430 // check "busy bit" |
1554 // check "busy bit" |
1431 if (EC_READ_U8(datagram->data + 1) & 0x81) { |
1555 if (EC_READ_U8(datagram->data + 1) & 0x81) { |
1432 // still busy... timeout? |
1556 // still busy... timeout? |
1433 if (get_cycles() - fsm->sii_start >= (cycles_t) 10 * cpu_khz) { |
1557 if (get_cycles() - fsm->sii_start >= (cycles_t) 10 * cpu_khz) { |
1434 EC_ERR("SII: Timeout.\n"); |
1558 EC_ERR("SII: Timeout.\n"); |
1435 fsm->sii_state = ec_fsm_sii_error; |
1559 fsm->sii_state = ec_fsm_error; |
1436 #if 0 |
1560 #if 0 |
1437 EC_DBG("SII busy: %02X %02X %02X %02X\n", |
1561 EC_DBG("SII busy: %02X %02X %02X %02X\n", |
1438 EC_READ_U8(datagram->data + 0), |
1562 EC_READ_U8(datagram->data + 0), |
1439 EC_READ_U8(datagram->data + 1), |
1563 EC_READ_U8(datagram->data + 1), |
1440 EC_READ_U8(datagram->data + 2), |
1564 EC_READ_U8(datagram->data + 2), |
1519 |
1644 |
1520 void ec_fsm_sii_write_check2(ec_fsm_t *fsm /**< finite state machine */) |
1645 void ec_fsm_sii_write_check2(ec_fsm_t *fsm /**< finite state machine */) |
1521 { |
1646 { |
1522 ec_datagram_t *datagram = &fsm->datagram; |
1647 ec_datagram_t *datagram = &fsm->datagram; |
1523 |
1648 |
1524 if (datagram->state != EC_CMD_RECEIVED || datagram->working_counter != 1) { |
1649 if (datagram->state != EC_DATAGRAM_RECEIVED |
|
1650 || datagram->working_counter != 1) { |
1525 EC_ERR("SII: Reception of write check datagram failed.\n"); |
1651 EC_ERR("SII: Reception of write check datagram failed.\n"); |
1526 fsm->sii_state = ec_fsm_sii_error; |
1652 fsm->sii_state = ec_fsm_error; |
1527 return; |
1653 return; |
1528 } |
1654 } |
1529 |
1655 |
1530 if (EC_READ_U8(datagram->data + 1) & 0x82) { |
1656 if (EC_READ_U8(datagram->data + 1) & 0x82) { |
1531 // still busy... timeout? |
1657 // still busy... timeout? |
1532 if (get_cycles() - fsm->sii_start >= (cycles_t) 10 * cpu_khz) { |
1658 if (get_cycles() - fsm->sii_start >= (cycles_t) 10 * cpu_khz) { |
1533 EC_ERR("SII: Write timeout.\n"); |
1659 EC_ERR("SII: Write timeout.\n"); |
1534 fsm->sii_state = ec_fsm_sii_error; |
1660 fsm->sii_state = ec_fsm_error; |
1535 } |
1661 } |
1536 |
1662 |
1537 // issue check/fetch datagram again |
1663 // issue check/fetch datagram again |
1538 ec_master_queue_datagram(fsm->master, datagram); |
1664 ec_master_queue_datagram(fsm->master, datagram); |
1539 } |
1665 } |
1540 else if (EC_READ_U8(datagram->data + 1) & 0x40) { |
1666 else if (EC_READ_U8(datagram->data + 1) & 0x40) { |
1541 EC_ERR("SII: Write operation failed!\n"); |
1667 EC_ERR("SII: Write operation failed!\n"); |
1542 fsm->sii_state = ec_fsm_sii_error; |
1668 fsm->sii_state = ec_fsm_error; |
1543 } |
1669 } |
1544 else { // success |
1670 else { // success |
1545 fsm->sii_state = ec_fsm_sii_end; |
1671 fsm->sii_state = ec_fsm_end; |
1546 } |
1672 } |
1547 } |
|
1548 |
|
1549 /*****************************************************************************/ |
|
1550 |
|
1551 /** |
|
1552 SII state: END. |
|
1553 End state of the slave SII state machine. |
|
1554 */ |
|
1555 |
|
1556 void ec_fsm_sii_end(ec_fsm_t *fsm /**< finite state machine */) |
|
1557 { |
|
1558 } |
|
1559 |
|
1560 /*****************************************************************************/ |
|
1561 |
|
1562 /** |
|
1563 SII state: ERROR. |
|
1564 End state of the slave SII state machine. |
|
1565 */ |
|
1566 |
|
1567 void ec_fsm_sii_error(ec_fsm_t *fsm /**< finite state machine */) |
|
1568 { |
|
1569 } |
1673 } |
1570 |
1674 |
1571 /****************************************************************************** |
1675 /****************************************************************************** |
1572 * state change sub state machine |
1676 * state change state machine |
1573 *****************************************************************************/ |
1677 *****************************************************************************/ |
1574 |
1678 |
1575 /** |
1679 /** |
1576 Change state: START. |
1680 Change state: START. |
1577 */ |
1681 */ |
1578 |
1682 |
1579 void ec_fsm_change_start(ec_fsm_t *fsm /**< finite state machine */) |
1683 void ec_fsm_change_start(ec_fsm_t *fsm /**< finite state machine */) |
1580 { |
1684 { |
1581 ec_datagram_t *datagram = &fsm->datagram; |
1685 ec_datagram_t *datagram = &fsm->datagram; |
1582 ec_slave_t *slave = fsm->slave; |
1686 ec_slave_t *slave = fsm->slave; |
|
1687 |
|
1688 fsm->change_start = get_cycles(); |
1583 |
1689 |
1584 // write new state to slave |
1690 // write new state to slave |
1585 ec_datagram_npwr(datagram, slave->station_address, 0x0120, 2); |
1691 ec_datagram_npwr(datagram, slave->station_address, 0x0120, 2); |
1586 EC_WRITE_U16(datagram->data, fsm->change_new); |
1692 EC_WRITE_U16(datagram->data, fsm->change_new); |
1587 ec_master_queue_datagram(fsm->master, datagram); |
1693 ec_master_queue_datagram(fsm->master, datagram); |
1597 void ec_fsm_change_check(ec_fsm_t *fsm /**< finite state machine */) |
1703 void ec_fsm_change_check(ec_fsm_t *fsm /**< finite state machine */) |
1598 { |
1704 { |
1599 ec_datagram_t *datagram = &fsm->datagram; |
1705 ec_datagram_t *datagram = &fsm->datagram; |
1600 ec_slave_t *slave = fsm->slave; |
1706 ec_slave_t *slave = fsm->slave; |
1601 |
1707 |
1602 if (datagram->state != EC_CMD_RECEIVED) { |
1708 if (datagram->state != EC_DATAGRAM_RECEIVED) { |
1603 fsm->change_state = ec_fsm_change_error; |
1709 fsm->change_state = ec_fsm_error; |
1604 EC_ERR("Failed to send state datagram to slave %i!\n", |
1710 EC_ERR("Failed to send state datagram to slave %i!\n", |
1605 fsm->slave->ring_position); |
1711 fsm->slave->ring_position); |
1606 return; |
1712 return; |
1607 } |
1713 } |
1608 |
1714 |
1609 if (datagram->working_counter != 1) { |
1715 if (datagram->working_counter != 1) { |
1610 fsm->change_state = ec_fsm_change_error; |
1716 if (get_cycles() - fsm->change_start >= (cycles_t) 100 * cpu_khz) { |
1611 EC_ERR("Failed to set state 0x%02X on slave %i: Slave did not" |
1717 fsm->change_state = ec_fsm_error; |
1612 " respond.\n", fsm->change_new, fsm->slave->ring_position); |
1718 EC_ERR("Failed to set state 0x%02X on slave %i: Slave did not" |
|
1719 " respond.\n", fsm->change_new, fsm->slave->ring_position); |
|
1720 return; |
|
1721 } |
|
1722 |
|
1723 // repeat writing new state to slave |
|
1724 ec_datagram_npwr(datagram, slave->station_address, 0x0120, 2); |
|
1725 EC_WRITE_U16(datagram->data, fsm->change_new); |
|
1726 ec_master_queue_datagram(fsm->master, datagram); |
1613 return; |
1727 return; |
1614 } |
1728 } |
1615 |
1729 |
1616 fsm->change_start = get_cycles(); |
1730 fsm->change_start = get_cycles(); |
1617 |
1731 |
1630 void ec_fsm_change_status(ec_fsm_t *fsm /**< finite state machine */) |
1744 void ec_fsm_change_status(ec_fsm_t *fsm /**< finite state machine */) |
1631 { |
1745 { |
1632 ec_datagram_t *datagram = &fsm->datagram; |
1746 ec_datagram_t *datagram = &fsm->datagram; |
1633 ec_slave_t *slave = fsm->slave; |
1747 ec_slave_t *slave = fsm->slave; |
1634 |
1748 |
1635 if (datagram->state != EC_CMD_RECEIVED || datagram->working_counter != 1) { |
1749 if (datagram->state != EC_DATAGRAM_RECEIVED |
1636 fsm->change_state = ec_fsm_change_error; |
1750 || datagram->working_counter != 1) { |
|
1751 fsm->change_state = ec_fsm_error; |
1637 EC_ERR("Failed to check state 0x%02X on slave %i.\n", |
1752 EC_ERR("Failed to check state 0x%02X on slave %i.\n", |
1638 fsm->change_new, slave->ring_position); |
1753 fsm->change_new, slave->ring_position); |
1639 return; |
1754 return; |
1640 } |
1755 } |
1641 |
1756 |
1642 slave->current_state = EC_READ_U8(datagram->data); |
1757 slave->current_state = EC_READ_U8(datagram->data); |
1643 |
1758 |
1644 if (slave->current_state == fsm->change_new) { |
1759 if (slave->current_state == fsm->change_new) { |
1645 // state has been set successfully |
1760 // state has been set successfully |
1646 fsm->change_state = ec_fsm_change_end; |
1761 fsm->change_state = ec_fsm_end; |
1647 return; |
1762 return; |
1648 } |
1763 } |
1649 |
1764 |
1650 if (slave->current_state & 0x10) { |
1765 if (slave->current_state & 0x10) { |
1651 // state change error |
1766 // state change error |
1785 { |
1902 { |
1786 ec_datagram_t *datagram = &fsm->datagram; |
1903 ec_datagram_t *datagram = &fsm->datagram; |
1787 ec_slave_t *slave = fsm->slave; |
1904 ec_slave_t *slave = fsm->slave; |
1788 ec_slave_state_t ack_state; |
1905 ec_slave_state_t ack_state; |
1789 |
1906 |
1790 if (datagram->state != EC_CMD_RECEIVED || datagram->working_counter != 1) { |
1907 if (datagram->state != EC_DATAGRAM_RECEIVED |
1791 fsm->change_state = ec_fsm_change_error; |
1908 || datagram->working_counter != 1) { |
|
1909 fsm->change_state = ec_fsm_error; |
1792 EC_ERR("Reception of state ack check datagram failed.\n"); |
1910 EC_ERR("Reception of state ack check datagram failed.\n"); |
1793 return; |
1911 return; |
1794 } |
1912 } |
1795 |
1913 |
1796 ack_state = EC_READ_U8(datagram->data); |
1914 ack_state = EC_READ_U8(datagram->data); |
1797 |
1915 |
1798 if (ack_state == slave->current_state) { |
1916 if (ack_state == slave->current_state) { |
1799 fsm->change_state = ec_fsm_change_error; |
1917 fsm->change_state = ec_fsm_error; |
1800 EC_INFO("Acknowleged state 0x%02X on slave %i.\n", |
1918 EC_INFO("Acknowleged state 0x%02X on slave %i.\n", |
1801 slave->current_state, slave->ring_position); |
1919 slave->current_state, slave->ring_position); |
1802 return; |
1920 return; |
1803 } |
1921 } |
1804 |
1922 |
1805 if (get_cycles() - fsm->change_start >= (cycles_t) 100 * cpu_khz) { |
1923 if (get_cycles() - fsm->change_start >= (cycles_t) 100 * cpu_khz) { |
1806 // timeout while checking |
1924 // timeout while checking |
1807 slave->current_state = EC_SLAVE_STATE_UNKNOWN; |
1925 slave->current_state = EC_SLAVE_STATE_UNKNOWN; |
1808 fsm->change_state = ec_fsm_change_error; |
1926 fsm->change_state = ec_fsm_error; |
1809 EC_ERR("Timeout while acknowleging state 0x%02X on slave %i.\n", |
1927 EC_ERR("Timeout while acknowleging state 0x%02X on slave %i.\n", |
1810 fsm->change_new, slave->ring_position); |
1928 fsm->change_new, slave->ring_position); |
1811 return; |
1929 return; |
1812 } |
1930 } |
1813 |
1931 |