Implement Save & Load Flash Settings in FSM & cmd

master
linuswck 2024-03-04 16:11:22 +08:00
parent a58b0954ec
commit a3885c365e
2 changed files with 112 additions and 61 deletions

View File

@ -10,12 +10,9 @@ mod thermostat;
mod net;
use device::{boot::bootup, log_setup, sys_timer};
use uom::fmt::DisplayStyle::Abbreviation;
use uom::si::electric_potential::volt;
use uom::si::electric_current::{ampere, milliampere};
use uom::si::f32::{ElectricPotential, ElectricCurrent};
use serde::{Deserialize, Serialize};
use stm32f4xx_hal::pac::SCB;
// If RTT is used, print panic info through RTT
#[cfg(all(feature = "RTT", not(test)))]
use {core::panic::PanicInfo, rtt_target::rprintln};
@ -31,12 +28,15 @@ use panic_halt as _;
static mut ETH_DATA_BUFFER: [u8; 1024] = [0; 1024];
#[derive(Deserialize, Serialize, Clone, Copy, Debug)]
pub struct DeviceSettings{
report_readings: bool,
}
const CONFIG_KEY: [&str; 3] = ["Device", "Laser_0", "Thermostat_0"];
#[derive(Default)]
enum State {
pub enum State {
#[default]
LoadFlashSettings,
MainLoop,
@ -53,41 +53,7 @@ fn main() -> ! {
let core_perif = CorePeripherals::take().unwrap();
let perif = Peripherals::take().unwrap();
let (mut wd, mut _flash_store, mut laser, mut thermostat,) = bootup(core_perif, perif);
// Demo Fns for reading and writing stm32 Internal Flash
/*
let key = "test";
info!("Read the Flash Content Stored");
match flash_store.read(key).unwrap() {
Some(val) => {info!("Flash Valued Read: {:?}", val)}
_ => {info!("Key does not match")}
}
info!("Erasing Flash");
flash_store.erase().unwrap();
match flash_store.read(key).unwrap() {
Some(val) => {info!("Flash Valued Read: {:?}", val)}
_ => {info!("Key does not match")}
}
info!("Writing Flash");
let buf = [1, 2, 3, 4];
flash_store.write(key, &buf).unwrap();
info!("Reading Flash");
match flash_store.read(key).unwrap() {
Some(val) => {info!("Val: {:?}", val)}
_ => {info!("Key does not match")}
};
*/
// https://github.com/iliekturtles/uom/blob/master/examples/si.rs
let volt_fmt = ElectricPotential::format_args(volt, Abbreviation);
let amp_fmt = ElectricCurrent::format_args(ampere, Abbreviation);
let milli_amp_fmt = ElectricCurrent::format_args(milliampere, Abbreviation);
let mut should_reset = false;
let (mut wd, mut flash_store, mut laser, mut thermostat,) = bootup(core_perif, perif);
let mut device_settings = DeviceSettings {
report_readings: false,
@ -100,10 +66,64 @@ fn main() -> ! {
match state {
State::LoadFlashSettings => {
wd.feed();
// Todo
// State Transition
state = State::MainLoop;
wd.feed();
let device_settings_flash: DeviceSettings;
match flash_store.read_value(CONFIG_KEY[0]) {
Ok(Some(config)) => {
device_settings_flash = config;
debug!("Found Device Settings");
}
Ok(None) => {
debug!("Flash does not have Device Settings");
continue;
}
Err(e) => {
debug!("Cannot Store Flash: {:?}", e);
continue;
}
}
wd.feed();
let laser_settings: laser_diode::laser_diode::LdSettingsSummary;
match flash_store.read_value(CONFIG_KEY[1]) {
Ok(Some(config)) => {
laser_settings = config;
debug!("Found Laser Diode Settings");
}
Ok(None) => {
debug!("Does not have laser diode Settings");
continue;
}
Err(e) => {
debug!("Cannot Store Flash: {:?}", e);
continue;
}
}
wd.feed();
let thermostat_settings: thermostat::thermostat::ThermostatSettingsSummary;
match flash_store.read_value(CONFIG_KEY[2]) {
Ok(Some(config)) => {
thermostat_settings = config;
debug!("Found Thermostat Settings");
}
Ok(None) => {
debug!("Does not have thermostat Settings");
continue;
}
Err(e) => {
debug!("Cannot Store Flash: {:?}", e);
continue;
}
}
wd.feed();
device_settings = device_settings_flash;
thermostat.load_settings_from_summary(thermostat_settings);
laser.load_settings_from_summary(laser_settings);
}
State::MainLoop => {
let mut eth_is_pending = false;
@ -145,7 +165,8 @@ fn main() -> ! {
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);
// State Transition
(laser, thermostat, state, device_settings) = net::cmd_handler::execute_cmd(&mut ETH_DATA_BUFFER, bytes, laser, thermostat, state, device_settings);
}
}
}
@ -153,20 +174,41 @@ fn main() -> ! {
thermostat.start_tec_readings_conversion();
}
}
else {
device_settings.report_readings = false;
}
// State Transition
if should_reset {
state = State::HardReset;
}
}
State::SaveFlashSettings => {
wd.feed();
// Todo
// State Transition
state = State::MainLoop;
wd.feed();
let mut store_value_buf = [0u8; 1024];
match flash_store.write_value(CONFIG_KEY[0], &device_settings, &mut store_value_buf) {
Ok(()) => {
debug!("Device Settings is stored in flash");
}
Err(e) => {
debug!("Cannot Store Flash: {:?}", e);
}
}
wd.feed();
match flash_store.write_value(CONFIG_KEY[1], &laser.get_settings_summary(), &mut store_value_buf) {
Ok(()) => {
debug!("Laser Diode Settings is stored in flash");
}
Err(e) => {
debug!("Cannot Store Flash: {:?}", e);
}
}
wd.feed();
match flash_store.write_value(CONFIG_KEY[2], &thermostat.get_settings_summary(), &mut store_value_buf) {
Ok(()) => {
debug!("Thermostat Settings is stored in flash");
}
Err(e) => {
debug!("Cannot Store Flash: {:?}", e);
}
}
}
State::HardReset => {
wd.feed();

View File

@ -19,7 +19,7 @@ use crate::thermostat::thermostat::{Thermostat, ThermostatSettingsSummary};
use crate::thermostat::pid_state::PidSettings::*;
use crate::device::{dfu, sys_timer};
use log::info;
use crate::DeviceSettings;
use crate::{DeviceSettings, State};
#[derive(Deserialize, Serialize, Copy, Clone, Default, Debug)]
enum DeviceCmd {
@ -29,6 +29,9 @@ enum DeviceCmd {
GetStatusReport,
GetSettingsSummary,
Dfu,
SaveFlashSettings,
LoadFlashSettings,
HardReset,
}
#[derive(Deserialize, Serialize, Copy, Clone, Default, Debug)]
@ -160,16 +163,14 @@ pub struct TecSetICmd {
/// Make sure kirdy's firmware is flashed with release builds.
/// The received message must contain only one json cmd. TCP client should set TCP_NODELAY or equivalent flag in its TCP Socket
/// Settings to avoid unwanted buffering on TX Data and minimize TX latency.
pub fn execute_cmd(buffer: &mut [u8], buffer_size: usize, mut laser: LdDrive, mut tec: Thermostat, mut device_settings: DeviceSettings)->(LdDrive, Thermostat, bool, DeviceSettings){
let mut should_reset = false;
pub fn execute_cmd(buffer: &mut [u8], buffer_size: usize, mut laser: LdDrive, mut tec: Thermostat, mut state: State, mut device_settings: DeviceSettings)->(LdDrive, Thermostat, State, DeviceSettings){
let mut cmd = TecSetICmd {
json: TecSetICmdJson::default()
};
match cmd.set_json("/json", &buffer[0..buffer_size]){
Ok(_) => {
tec.set_i(ElectricCurrent::new::<milliampere>(cmd.json.tec_set_i));
return (laser, tec, should_reset, device_settings);
return (laser, tec, state, device_settings);
}
Err(_) => { /* Do Nothing */}
}
@ -188,7 +189,6 @@ pub fn execute_cmd(buffer: &mut [u8], buffer_size: usize, mut laser: LdDrive, mu
unsafe {
dfu::set_dfu_trigger();
}
should_reset = true;
}
Some(DeviceCmd::SetActiveReportMode) => {
match cmd.json.data_bool{
@ -206,6 +206,15 @@ pub fn execute_cmd(buffer: &mut [u8], buffer_size: usize, mut laser: LdDrive, mu
Some(DeviceCmd::GetSettingsSummary) => {
send_settings_summary(buffer, &mut laser, &mut tec);
}
Some(DeviceCmd::SaveFlashSettings) => {
state = State::SaveFlashSettings;
}
Some(DeviceCmd::LoadFlashSettings) => {
state = State::LoadFlashSettings;
}
Some(DeviceCmd::HardReset) => {
state = State::HardReset;
}
None => { /* Do Nothing */}
_ => {
info!("Unimplemented Command")
@ -536,5 +545,5 @@ pub fn execute_cmd(buffer: &mut [u8], buffer_size: usize, mut laser: LdDrive, mu
info!("Invalid Command: {:?}", err);
}
}
(laser, tec, should_reset, device_settings)
(laser, tec, state, device_settings)
}