From df939eb9a38b8e92491c206fb484cff89e085ecc Mon Sep 17 00:00:00 2001 From: linuswck Date: Mon, 4 Mar 2024 11:08:26 +0800 Subject: [PATCH] Use FSM to manage device state in main loop --- src/main.rs | 151 ++++++++++++++++++++++++++++++---------------------- 1 file changed, 86 insertions(+), 65 deletions(-) diff --git a/src/main.rs b/src/main.rs index e003664..a15cf4d 100644 --- a/src/main.rs +++ b/src/main.rs @@ -35,6 +35,15 @@ pub struct DeviceSettings{ report_readings: bool, } +#[derive(Default)] +enum State { + #[default] + LoadFlashSettings, + MainLoop, + SaveFlashSettings, + HardReset, +} + #[cfg(not(test))] #[entry] fn main() -> ! { @@ -84,85 +93,97 @@ fn main() -> ! { report_readings: false, }; + let mut state = State::default(); + loop { wd.feed(); - if !should_reset { - let mut eth_is_pending = false; - let mut has_temp_reading = false; - - laser.poll_and_update_output_current(); - - if thermostat.poll_adc() { - has_temp_reading = true; - thermostat.update_pid(); - if thermostat.get_temp_mon_status().over_temp_alarm { - laser.power_down(); - thermostat.set_pid_engaged(false); - thermostat.power_down(); + match state { + State::LoadFlashSettings => { + wd.feed(); + // Todo + // State Transition + state = State::MainLoop; + } + State::MainLoop => { + let mut eth_is_pending = false; + let mut has_temp_reading = false; + + laser.poll_and_update_output_current(); + + if thermostat.poll_adc() { + has_temp_reading = true; + thermostat.update_pid(); + if thermostat.get_temp_mon_status().over_temp_alarm { + laser.power_down(); + thermostat.set_pid_engaged(false); + thermostat.power_down(); + } + + if net::net::eth_is_socket_active() { + if device_settings.report_readings { + unsafe { + net::cmd_handler::send_status_report(&mut ETH_DATA_BUFFER, &mut laser, &mut thermostat); + } + } + } } - - // info!("curr_dac_vfb: {:?}", volt_fmt.with(thermostat.get_dac_vfb())); - // info!("curr_vref: {:?}", volt_fmt.with(thermostat.get_vref())); - // info!("curr_tec_i: {:?}", amp_fmt.with(thermostat.get_tec_i())); - // info!("curr_tec_v: {:?}", volt_fmt.with(thermostat.get_tec_v())); - - // info!("curr_ld_drive_cuurent: {:?}", milli_amp_fmt.with(laser.get_ld_drive_current())); - // info!("pd_mon_v: {:?}", volt_fmt.with(laser.pd_mon_status().v)); - // info!("power_excursion: {:?}", laser.pd_mon_status().pwr_excursion); - - // info!("Termination Status: {:?}", laser.get_term_status()); - if net::net::eth_is_socket_active() { - if device_settings.report_readings { - unsafe { - net::cmd_handler::send_status_report(&mut ETH_DATA_BUFFER, &mut laser, &mut thermostat); + cortex_m::interrupt::free(|cs| + { + eth_is_pending = net::net::is_pending(cs); + } + ); + + if eth_is_pending { + unsafe{ + cortex_m::interrupt::free(|cs| { + net::net::clear_pending(cs); + }); + let bytes = net::net::eth_recv(&mut ETH_DATA_BUFFER); + if bytes != 0 { + info!("Ts: {:?}", sys_timer::now()); + debug!("Number of bytes recv: {:?}", bytes); + (laser, thermostat, should_reset, device_settings) = net::cmd_handler::execute_cmd(&mut ETH_DATA_BUFFER, bytes, laser, thermostat, device_settings); + } } } - } - } - - if net::net::eth_is_socket_active() { - cortex_m::interrupt::free(|cs| - { - eth_is_pending = net::net::is_pending(cs); - } - ); - - if eth_is_pending { - unsafe{ - cortex_m::interrupt::free(|cs| { - net::net::clear_pending(cs); - }); - let bytes = net::net::eth_recv(&mut ETH_DATA_BUFFER); - if bytes != 0 { - info!("Ts: {:?}", sys_timer::now()); - debug!("Number of bytes recv: {:?}", bytes); - (laser, thermostat, should_reset, device_settings) = net::cmd_handler::execute_cmd(&mut ETH_DATA_BUFFER, bytes, laser, thermostat, device_settings); - } + if has_temp_reading { + thermostat.start_tec_readings_conversion(); } } - if has_temp_reading { - thermostat.start_tec_readings_conversion(); + else { + device_settings.report_readings = false; + } + + // State Transition + if should_reset { + state = State::HardReset; } } - else { - device_settings.report_readings = false; + State::SaveFlashSettings => { + wd.feed(); + // Todo + // State Transition + state = State::MainLoop; } - } else { - // Should reset, close all TCP sockets. - let mut any_socket_alive = false; - if net::net::eth_is_socket_active() { - net::net::eth_close_socket(); - any_socket_alive = true; + State::HardReset => { + wd.feed(); + laser.power_down(); + thermostat.power_down(); + let mut any_socket_alive = false; + if net::net::eth_is_socket_active() { + net::net::eth_close_socket(); + any_socket_alive = true; + } + + // Must let loop run for one more cycle to poll server for RST to be sent, + // this makes sure system does not reset right after socket.abort() is called. + if !any_socket_alive { + SCB::sys_reset(); + } } - - // Must let loop run for one more cycle to poll server for RST to be sent, - // this makes sure system does not reset right after socket.abort() is called. - if !any_socket_alive { - SCB::sys_reset(); - } } } }