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_slave_start_reading(ec_fsm_t *); |
60 void ec_fsm_slave_read_state(ec_fsm_t *); |
58 void ec_fsm_slave_read_state(ec_fsm_t *); |
61 void ec_fsm_slave_read_base(ec_fsm_t *); |
59 void ec_fsm_slave_read_base(ec_fsm_t *); |
62 void ec_fsm_slave_read_dl(ec_fsm_t *); |
60 void ec_fsm_slave_read_dl(ec_fsm_t *); |
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_slave_start_reading; |
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_datagram_nprd(&fsm->datagram, fsm->slave->station_address, 0x0130, 2); |
273 ec_datagram_nprd(&fsm->datagram, fsm->slave->station_address, 0x0130, 2); |
276 ec_master_queue_datagram(master, &fsm->datagram); |
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_slave_conf; |
|
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_FREERUN) { |
|
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 // process next slave |
359 // process next slave |
295 fsm->slave = list_entry(fsm->slave->list.next, ec_slave_t, list); |
360 fsm->slave = list_entry(fsm->slave->list.next, ec_slave_t, list); |
296 ec_datagram_nprd(&fsm->datagram, fsm->slave->station_address, |
361 ec_datagram_nprd(&fsm->datagram, fsm->slave->station_address, |
297 0x0130, 2); |
362 0x0130, 2); |
298 ec_master_queue_datagram(master, &fsm->datagram); |
363 ec_master_queue_datagram(master, &fsm->datagram); |
299 fsm->master_state = ec_fsm_master_states; |
364 fsm->master_state = ec_fsm_master_read_states; |
300 return; |
365 return; |
301 } |
366 } |
302 |
367 |
303 // all slave stated read; check, if a bus validation has to be done |
368 // all slave states read |
|
369 |
|
370 // check, if a bus validation has to be done |
304 if (fsm->master_validation) { |
371 if (fsm->master_validation) { |
305 fsm->master_validation = 0; |
372 fsm->master_validation = 0; |
306 list_for_each_entry(slave, &master->slaves, list) { |
373 list_for_each_entry(slave, &master->slaves, list) { |
307 if (slave->online) continue; |
374 if (slave->online) continue; |
308 |
375 |
316 fsm->sii_state(fsm); // execute immediately |
383 fsm->sii_state(fsm); // execute immediately |
317 return; |
384 return; |
318 } |
385 } |
319 } |
386 } |
320 |
387 |
321 fsm->master_state = ec_fsm_master_proc_states; |
388 ec_fsm_master_action_process_states(fsm); |
322 fsm->master_state(fsm); // execute immediately |
|
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_datagram_t *datagram = &fsm->datagram; |
401 ec_datagram_t *datagram = &fsm->datagram; |
336 uint8_t new_state; |
402 uint8_t new_state; |
337 |
403 |
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->error_flag || |
|
391 !slave->online || |
|
392 slave->requested_state == EC_SLAVE_STATE_UNKNOWN || |
|
393 slave->current_state == slave->requested_state) continue; |
|
394 |
|
395 EC_INFO("Changing state of slave %i from ", slave->ring_position); |
|
396 ec_print_states(slave->current_state); |
|
397 printk(" to "); |
|
398 ec_print_states(slave->requested_state); |
|
399 printk(".\n"); |
|
400 |
|
401 fsm->slave = slave; |
|
402 fsm->slave_state = ec_fsm_slave_conf; |
|
403 fsm->change_new = EC_SLAVE_STATE_INIT; |
|
404 fsm->change_state = ec_fsm_change_start; |
|
405 fsm->master_state = ec_fsm_master_conf; |
|
406 fsm->master_state(fsm); // execute immediately |
|
407 return; |
|
408 } |
|
409 |
|
410 if (master->mode == EC_MASTER_MODE_FREERUN) { |
|
411 // nothing to configure. check for pending EEPROM write operations. |
|
412 list_for_each_entry(slave, &master->slaves, list) { |
|
413 if (!slave->new_eeprom_data) continue; |
|
414 |
|
415 if (!slave->online || slave->error_flag) { |
|
416 kfree(slave->new_eeprom_data); |
|
417 slave->new_eeprom_data = NULL; |
|
418 EC_ERR("Discarding EEPROM data, slave %i not ready.\n", |
|
419 slave->ring_position); |
|
420 continue; |
|
421 } |
|
422 |
|
423 // found pending EEPROM write operation. execute it! |
|
424 EC_INFO("Writing EEPROM of slave %i...\n", slave->ring_position); |
|
425 fsm->sii_offset = 0x0000; |
|
426 memcpy(fsm->sii_value, slave->new_eeprom_data, 2); |
|
427 fsm->sii_mode = 1; |
|
428 fsm->sii_state = ec_fsm_sii_start_writing; |
|
429 fsm->slave = slave; |
|
430 fsm->master_state = ec_fsm_master_eeprom; |
|
431 fsm->master_state(fsm); // execute immediately |
|
432 return; |
|
433 } |
|
434 } |
|
435 |
|
436 // nothing to do. restart master state machine. |
|
437 fsm->master_state = ec_fsm_master_start; |
|
438 fsm->master_state(fsm); // execute immediately |
|
439 } |
|
440 |
|
441 /*****************************************************************************/ |
|
442 |
|
443 /** |
|
444 Master state: VALIDATE_VENDOR. |
445 Master state: VALIDATE_VENDOR. |
445 Validates the vendor ID of a slave. |
446 Validates the vendor ID of a slave. |
446 */ |
447 */ |
447 |
448 |
448 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 */) |
478 } |
479 } |
479 |
480 |
480 /*****************************************************************************/ |
481 /*****************************************************************************/ |
481 |
482 |
482 /** |
483 /** |
483 Master state: VALIDATE_PRODUCT. |
484 Master action: ADDRESS. |
484 Validates the product ID of a slave. |
|
485 */ |
|
486 |
|
487 void ec_fsm_master_validate_product(ec_fsm_t *fsm /**< finite state machine */) |
|
488 { |
|
489 ec_slave_t *slave = fsm->slave; |
|
490 |
|
491 fsm->sii_state(fsm); // execute SII state machine |
|
492 |
|
493 if (fsm->sii_state == ec_fsm_sii_error) { |
|
494 fsm->slave->error_flag = 1; |
|
495 EC_ERR("Failed to validate product code of slave %i.\n", |
|
496 slave->ring_position); |
|
497 fsm->master_state = ec_fsm_master_start; |
|
498 fsm->master_state(fsm); // execute immediately |
|
499 return; |
|
500 } |
|
501 |
|
502 if (fsm->sii_state != ec_fsm_sii_end) return; |
|
503 |
|
504 if (EC_READ_U32(fsm->sii_value) != slave->sii_product_code) { |
|
505 EC_ERR("Slave %i: invalid product code!\n", slave->ring_position); |
|
506 EC_ERR("expected 0x%08X, got 0x%08X.\n", slave->sii_product_code, |
|
507 EC_READ_U32(fsm->sii_value)); |
|
508 fsm->master_state = ec_fsm_master_start; |
|
509 fsm->master_state(fsm); // execute immediately |
|
510 return; |
|
511 } |
|
512 |
|
513 // have all states been validated? |
|
514 if (slave->list.next == &fsm->master->slaves) { |
|
515 fsm->slave = list_entry(fsm->master->slaves.next, ec_slave_t, list); |
|
516 fsm->master_state = ec_fsm_master_reconfigure; |
|
517 return; |
|
518 } |
|
519 |
|
520 // validate next slave |
|
521 fsm->slave = list_entry(fsm->slave->list.next, ec_slave_t, list); |
|
522 fsm->master_state = ec_fsm_master_validate_vendor; |
|
523 fsm->sii_offset = 0x0008; // vendor ID |
|
524 fsm->sii_mode = 0; |
|
525 fsm->sii_state = ec_fsm_sii_start_reading; |
|
526 fsm->sii_state(fsm); // execute immediately |
|
527 } |
|
528 |
|
529 /*****************************************************************************/ |
|
530 |
|
531 /** |
|
532 Master state: RECONFIGURE. |
|
533 Looks for slave, that have lost their configuration and writes |
485 Looks for slave, that have lost their configuration and writes |
534 their station address, so that they can be reconfigured later. |
486 their station address, so that they can be reconfigured later. |
535 */ |
487 */ |
536 |
488 |
537 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 */) |
538 { |
490 { |
539 ec_datagram_t *datagram = &fsm->datagram; |
491 ec_datagram_t *datagram = &fsm->datagram; |
540 |
492 |
541 while (fsm->slave->online) { |
493 while (fsm->slave->online) { |
542 if (fsm->slave->list.next == &fsm->master->slaves) { // last slave? |
494 if (fsm->slave->list.next == &fsm->master->slaves) { // last slave? |
552 |
504 |
553 // write station address |
505 // write station address |
554 ec_datagram_apwr(datagram, fsm->slave->ring_position, 0x0010, 2); |
506 ec_datagram_apwr(datagram, fsm->slave->ring_position, 0x0010, 2); |
555 EC_WRITE_U16(datagram->data, fsm->slave->station_address); |
507 EC_WRITE_U16(datagram->data, fsm->slave->station_address); |
556 ec_master_queue_datagram(fsm->master, datagram); |
508 ec_master_queue_datagram(fsm->master, datagram); |
557 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 |
558 } |
560 } |
559 |
561 |
560 /*****************************************************************************/ |
562 /*****************************************************************************/ |
561 |
563 |
562 /** |
564 /** |
563 Master state: ADDRESS. |
565 Master state: ADDRESS. |
564 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. |
565 */ |
567 */ |
566 |
568 |
567 void ec_fsm_master_address(ec_fsm_t *fsm /**< finite state machine */) |
569 void ec_fsm_master_rewrite_addresses(ec_fsm_t *fsm |
|
570 /**< finite state machine */ |
|
571 ) |
568 { |
572 { |
569 ec_slave_t *slave = fsm->slave; |
573 ec_slave_t *slave = fsm->slave; |
570 ec_datagram_t *datagram = &fsm->datagram; |
574 ec_datagram_t *datagram = &fsm->datagram; |
571 |
575 |
572 if (datagram->state != EC_CMD_RECEIVED || datagram->working_counter != 1) { |
576 if (datagram->state != EC_CMD_RECEIVED || datagram->working_counter != 1) { |
580 return; |
584 return; |
581 } |
585 } |
582 |
586 |
583 // check next slave |
587 // check next slave |
584 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); |
585 fsm->master_state = ec_fsm_master_reconfigure; |
589 // Write new station address to slave |
586 fsm->master_state(fsm); // execute immediately |
590 ec_fsm_master_action_addresses(fsm); |
587 } |
591 } |
588 |
592 |
589 /*****************************************************************************/ |
593 /*****************************************************************************/ |
590 |
594 |
591 /** |
595 /** |
592 Master state: SCAN. |
596 Master state: SCAN. |
593 Executes the sub-statemachine for the scanning of a slave. |
597 Executes the sub-statemachine for the scanning of a slave. |
594 */ |
598 */ |
595 |
599 |
596 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 */) |
597 { |
601 { |
598 ec_master_t *master = fsm->master; |
602 ec_master_t *master = fsm->master; |
599 ec_slave_t *slave = fsm->slave; |
603 ec_slave_t *slave = fsm->slave; |
600 uint16_t coupler_index, coupler_subindex; |
604 uint16_t coupler_index, coupler_subindex; |
601 uint16_t reverse_coupler_index, current_coupler_index; |
605 uint16_t reverse_coupler_index, current_coupler_index; |
687 /** |
691 /** |
688 Master state: CONF. |
692 Master state: CONF. |
689 Starts configuring a slave. |
693 Starts configuring a slave. |
690 */ |
694 */ |
691 |
695 |
692 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 ) |
693 { |
699 { |
694 fsm->slave_state(fsm); // execute slave's state machine |
700 fsm->slave_state(fsm); // execute slave's state machine |
695 if (fsm->slave_state != ec_fsm_slave_end) return; |
701 if (fsm->slave_state != ec_fsm_slave_end) return; |
696 fsm->master_state = ec_fsm_master_proc_states; |
702 |
697 fsm->master_state(fsm); // execute immediately |
703 ec_fsm_master_action_process_states(fsm); |
698 } |
704 } |
699 |
705 |
700 /*****************************************************************************/ |
706 /*****************************************************************************/ |
701 |
707 |
702 /** |
708 /** |
703 Master state: EEPROM. |
709 Master state: EEPROM. |
704 */ |
710 */ |
705 |
711 |
706 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 */) |
707 { |
713 { |
708 ec_slave_t *slave = fsm->slave; |
714 ec_slave_t *slave = fsm->slave; |
709 |
715 |
710 fsm->sii_state(fsm); // execute SII state machine |
716 fsm->sii_state(fsm); // execute SII state machine |
711 |
717 |
734 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); |
735 kfree(slave->new_eeprom_data); |
741 kfree(slave->new_eeprom_data); |
736 slave->new_eeprom_data = NULL; |
742 slave->new_eeprom_data = NULL; |
737 |
743 |
738 // restart master state machine. |
744 // restart master state machine. |
739 fsm->master_state = ec_fsm_master_start; |
745 fsm->master_state = ec_fsm_master_start; // TODO: Scan slaves! |
740 fsm->master_state(fsm); // execute immediately |
746 fsm->master_state(fsm); // execute immediately |
741 return; |
747 return; |
742 } |
748 } |
743 |
749 |
744 /****************************************************************************** |
750 /****************************************************************************** |