From c38ca18f9bfd677980dfa876ff84bd356e2f5a93 Mon Sep 17 00:00:00 2001 From: Florian Pose <fp@igh-essen.com> Date: Wed, 19 Jul 2006 12:57:41 +0000 Subject: [PATCH] Better master state machines. --- master/fsm.c | 248 ++++++++++++++++++++++++++------------------------- 1 file changed, 127 insertions(+), 121 deletions(-) diff --git a/master/fsm.c b/master/fsm.c index 14fb8dec..0823b2d3 100644 --- a/master/fsm.c +++ b/master/fsm.c @@ -46,15 +46,13 @@ void ec_fsm_master_start(ec_fsm_t *); void ec_fsm_master_broadcast(ec_fsm_t *); -void ec_fsm_master_proc_states(ec_fsm_t *); -void ec_fsm_master_scan(ec_fsm_t *); -void ec_fsm_master_states(ec_fsm_t *); +void ec_fsm_master_read_states(ec_fsm_t *); void ec_fsm_master_validate_vendor(ec_fsm_t *); void ec_fsm_master_validate_product(ec_fsm_t *); -void ec_fsm_master_reconfigure(ec_fsm_t *); -void ec_fsm_master_address(ec_fsm_t *); -void ec_fsm_master_conf(ec_fsm_t *); -void ec_fsm_master_eeprom(ec_fsm_t *); +void ec_fsm_master_rewrite_addresses(ec_fsm_t *); +void ec_fsm_master_configure_slave(ec_fsm_t *); +void ec_fsm_master_scan_slaves(ec_fsm_t *); +void ec_fsm_master_write_eeprom(ec_fsm_t *); void ec_fsm_slave_start_reading(ec_fsm_t *); void ec_fsm_slave_read_state(ec_fsm_t *); @@ -265,7 +263,7 @@ void ec_fsm_master_broadcast(ec_fsm_t *fsm /**< finite state machine */) // begin scanning of slaves fsm->slave = list_entry(master->slaves.next, ec_slave_t, list); fsm->slave_state = ec_fsm_slave_start_reading; - fsm->master_state = ec_fsm_master_scan; + fsm->master_state = ec_fsm_master_scan_slaves; fsm->master_state(fsm); // execute immediately return; } @@ -274,7 +272,74 @@ void ec_fsm_master_broadcast(ec_fsm_t *fsm /**< finite state machine */) fsm->slave = list_entry(master->slaves.next, ec_slave_t, list); ec_datagram_nprd(&fsm->datagram, fsm->slave->station_address, 0x0130, 2); ec_master_queue_datagram(master, &fsm->datagram); - fsm->master_state = ec_fsm_master_states; + fsm->master_state = ec_fsm_master_read_states; +} + +/*****************************************************************************/ + +/** + Master action: PROC_STATES. + Processes the slave states. +*/ + +void ec_fsm_master_action_process_states(ec_fsm_t *fsm + /**< finite state machine */ + ) +{ + ec_master_t *master = fsm->master; + ec_slave_t *slave; + + // check if any slaves are not in the state, they're supposed to be + list_for_each_entry(slave, &master->slaves, list) { + if (slave->error_flag || + !slave->online || + slave->requested_state == EC_SLAVE_STATE_UNKNOWN || + slave->current_state == slave->requested_state) continue; + + EC_INFO("Changing state of slave %i from ", slave->ring_position); + ec_print_states(slave->current_state); + printk(" to "); + ec_print_states(slave->requested_state); + printk(".\n"); + + fsm->slave = slave; + fsm->slave_state = ec_fsm_slave_conf; + fsm->change_new = EC_SLAVE_STATE_INIT; + fsm->change_state = ec_fsm_change_start; + fsm->master_state = ec_fsm_master_configure_slave; + fsm->master_state(fsm); // execute immediately + return; + } + + if (master->mode == EC_MASTER_MODE_FREERUN) { + // nothing to configure. check for pending EEPROM write operations. + list_for_each_entry(slave, &master->slaves, list) { + if (!slave->new_eeprom_data) continue; + + if (!slave->online || slave->error_flag) { + kfree(slave->new_eeprom_data); + slave->new_eeprom_data = NULL; + EC_ERR("Discarding EEPROM data, slave %i not ready.\n", + slave->ring_position); + continue; + } + + // found pending EEPROM write operation. execute it! + EC_INFO("Writing EEPROM of slave %i...\n", slave->ring_position); + fsm->sii_offset = 0x0000; + memcpy(fsm->sii_value, slave->new_eeprom_data, 2); + fsm->sii_mode = 1; + fsm->sii_state = ec_fsm_sii_start_writing; + fsm->slave = slave; + fsm->master_state = ec_fsm_master_write_eeprom; + fsm->master_state(fsm); // execute immediately + return; + } + } + + // nothing to do. restart master state machine. + fsm->master_state = ec_fsm_master_start; + fsm->master_state(fsm); // execute immediately } /*****************************************************************************/ @@ -289,18 +354,20 @@ void ec_fsm_master_action_next_slave_state(ec_fsm_t *fsm ec_master_t *master = fsm->master; ec_slave_t *slave = fsm->slave; - // have all states been read? + // is there another slave to query? if (slave->list.next != &master->slaves) { // process next slave fsm->slave = list_entry(fsm->slave->list.next, ec_slave_t, list); ec_datagram_nprd(&fsm->datagram, fsm->slave->station_address, 0x0130, 2); ec_master_queue_datagram(master, &fsm->datagram); - fsm->master_state = ec_fsm_master_states; + fsm->master_state = ec_fsm_master_read_states; return; } - // all slave stated read; check, if a bus validation has to be done + // all slave states read + + // check, if a bus validation has to be done if (fsm->master_validation) { fsm->master_validation = 0; list_for_each_entry(slave, &master->slaves, list) { @@ -318,8 +385,7 @@ void ec_fsm_master_action_next_slave_state(ec_fsm_t *fsm } } - fsm->master_state = ec_fsm_master_proc_states; - fsm->master_state(fsm); // execute immediately + ec_fsm_master_action_process_states(fsm); } /*****************************************************************************/ @@ -329,7 +395,7 @@ void ec_fsm_master_action_next_slave_state(ec_fsm_t *fsm Fetches the AL- and online state of a slave. */ -void ec_fsm_master_states(ec_fsm_t *fsm /**< finite state machine */) +void ec_fsm_master_read_states(ec_fsm_t *fsm /**< finite state machine */) { ec_slave_t *slave = fsm->slave; ec_datagram_t *datagram = &fsm->datagram; @@ -375,71 +441,6 @@ void ec_fsm_master_states(ec_fsm_t *fsm /**< finite state machine */) /*****************************************************************************/ -/** - Master state: PROC_STATES. - Processes the slave states. -*/ - -void ec_fsm_master_proc_states(ec_fsm_t *fsm /**< finite state machine */) -{ - ec_master_t *master = fsm->master; - ec_slave_t *slave; - - // check if any slaves are not in the state, they're supposed to be - list_for_each_entry(slave, &master->slaves, list) { - if (slave->error_flag || - !slave->online || - slave->requested_state == EC_SLAVE_STATE_UNKNOWN || - slave->current_state == slave->requested_state) continue; - - EC_INFO("Changing state of slave %i from ", slave->ring_position); - ec_print_states(slave->current_state); - printk(" to "); - ec_print_states(slave->requested_state); - printk(".\n"); - - fsm->slave = slave; - fsm->slave_state = ec_fsm_slave_conf; - fsm->change_new = EC_SLAVE_STATE_INIT; - fsm->change_state = ec_fsm_change_start; - fsm->master_state = ec_fsm_master_conf; - fsm->master_state(fsm); // execute immediately - return; - } - - if (master->mode == EC_MASTER_MODE_FREERUN) { - // nothing to configure. check for pending EEPROM write operations. - list_for_each_entry(slave, &master->slaves, list) { - if (!slave->new_eeprom_data) continue; - - if (!slave->online || slave->error_flag) { - kfree(slave->new_eeprom_data); - slave->new_eeprom_data = NULL; - EC_ERR("Discarding EEPROM data, slave %i not ready.\n", - slave->ring_position); - continue; - } - - // found pending EEPROM write operation. execute it! - EC_INFO("Writing EEPROM of slave %i...\n", slave->ring_position); - fsm->sii_offset = 0x0000; - memcpy(fsm->sii_value, slave->new_eeprom_data, 2); - fsm->sii_mode = 1; - fsm->sii_state = ec_fsm_sii_start_writing; - fsm->slave = slave; - fsm->master_state = ec_fsm_master_eeprom; - fsm->master_state(fsm); // execute immediately - return; - } - } - - // nothing to do. restart master state machine. - fsm->master_state = ec_fsm_master_start; - fsm->master_state(fsm); // execute immediately -} - -/*****************************************************************************/ - /** Master state: VALIDATE_VENDOR. Validates the vendor ID of a slave. @@ -479,6 +480,37 @@ void ec_fsm_master_validate_vendor(ec_fsm_t *fsm /**< finite state machine */) /*****************************************************************************/ +/** + Master action: ADDRESS. + Looks for slave, that have lost their configuration and writes + their station address, so that they can be reconfigured later. +*/ + +void ec_fsm_master_action_addresses(ec_fsm_t *fsm /**< finite state machine */) +{ + ec_datagram_t *datagram = &fsm->datagram; + + while (fsm->slave->online) { + if (fsm->slave->list.next == &fsm->master->slaves) { // last slave? + fsm->master_state = ec_fsm_master_start; + fsm->master_state(fsm); // execute immediately + return; + } + // check next slave + fsm->slave = list_entry(fsm->slave->list.next, ec_slave_t, list); + } + + EC_INFO("Reinitializing slave %i.\n", fsm->slave->ring_position); + + // write station address + ec_datagram_apwr(datagram, fsm->slave->ring_position, 0x0010, 2); + EC_WRITE_U16(datagram->data, fsm->slave->station_address); + ec_master_queue_datagram(fsm->master, datagram); + fsm->master_state = ec_fsm_master_rewrite_addresses; +} + +/*****************************************************************************/ + /** Master state: VALIDATE_PRODUCT. Validates the product ID of a slave. @@ -513,7 +545,8 @@ void ec_fsm_master_validate_product(ec_fsm_t *fsm /**< finite state machine */) // have all states been validated? if (slave->list.next == &fsm->master->slaves) { fsm->slave = list_entry(fsm->master->slaves.next, ec_slave_t, list); - fsm->master_state = ec_fsm_master_reconfigure; + // start writing addresses to offline slaves + ec_fsm_master_action_addresses(fsm); return; } @@ -528,43 +561,14 @@ void ec_fsm_master_validate_product(ec_fsm_t *fsm /**< finite state machine */) /*****************************************************************************/ -/** - Master state: RECONFIGURE. - Looks for slave, that have lost their configuration and writes - their station address, so that they can be reconfigured later. -*/ - -void ec_fsm_master_reconfigure(ec_fsm_t *fsm /**< finite state machine */) -{ - ec_datagram_t *datagram = &fsm->datagram; - - while (fsm->slave->online) { - if (fsm->slave->list.next == &fsm->master->slaves) { // last slave? - fsm->master_state = ec_fsm_master_start; - fsm->master_state(fsm); // execute immediately - return; - } - // check next slave - fsm->slave = list_entry(fsm->slave->list.next, ec_slave_t, list); - } - - EC_INFO("Reinitializing slave %i.\n", fsm->slave->ring_position); - - // write station address - ec_datagram_apwr(datagram, fsm->slave->ring_position, 0x0010, 2); - EC_WRITE_U16(datagram->data, fsm->slave->station_address); - ec_master_queue_datagram(fsm->master, datagram); - fsm->master_state = ec_fsm_master_address; -} - -/*****************************************************************************/ - /** Master state: ADDRESS. Checks, if the new station address has been written to the slave. */ -void ec_fsm_master_address(ec_fsm_t *fsm /**< finite state machine */) +void ec_fsm_master_rewrite_addresses(ec_fsm_t *fsm + /**< finite state machine */ + ) { ec_slave_t *slave = fsm->slave; ec_datagram_t *datagram = &fsm->datagram; @@ -582,8 +586,8 @@ void ec_fsm_master_address(ec_fsm_t *fsm /**< finite state machine */) // check next slave fsm->slave = list_entry(fsm->slave->list.next, ec_slave_t, list); - fsm->master_state = ec_fsm_master_reconfigure; - fsm->master_state(fsm); // execute immediately + // Write new station address to slave + ec_fsm_master_action_addresses(fsm); } /*****************************************************************************/ @@ -593,7 +597,7 @@ void ec_fsm_master_address(ec_fsm_t *fsm /**< finite state machine */) Executes the sub-statemachine for the scanning of a slave. */ -void ec_fsm_master_scan(ec_fsm_t *fsm /**< finite state machine */) +void ec_fsm_master_scan_slaves(ec_fsm_t *fsm /**< finite state machine */) { ec_master_t *master = fsm->master; ec_slave_t *slave = fsm->slave; @@ -689,12 +693,14 @@ void ec_fsm_master_scan(ec_fsm_t *fsm /**< finite state machine */) Starts configuring a slave. */ -void ec_fsm_master_conf(ec_fsm_t *fsm /**< finite state machine */) +void ec_fsm_master_configure_slave(ec_fsm_t *fsm + /**< finite state machine */ + ) { fsm->slave_state(fsm); // execute slave's state machine if (fsm->slave_state != ec_fsm_slave_end) return; - fsm->master_state = ec_fsm_master_proc_states; - fsm->master_state(fsm); // execute immediately + + ec_fsm_master_action_process_states(fsm); } /*****************************************************************************/ @@ -703,7 +709,7 @@ void ec_fsm_master_conf(ec_fsm_t *fsm /**< finite state machine */) Master state: EEPROM. */ -void ec_fsm_master_eeprom(ec_fsm_t *fsm /**< finite state machine */) +void ec_fsm_master_write_eeprom(ec_fsm_t *fsm /**< finite state machine */) { ec_slave_t *slave = fsm->slave; @@ -736,7 +742,7 @@ void ec_fsm_master_eeprom(ec_fsm_t *fsm /**< finite state machine */) slave->new_eeprom_data = NULL; // restart master state machine. - fsm->master_state = ec_fsm_master_start; + fsm->master_state = ec_fsm_master_start; // TODO: Scan slaves! fsm->master_state(fsm); // execute immediately return; } -- GitLab