#![cfg_attr(not(test), no_main)] #![cfg_attr(not(test), no_std)] use cortex_m_rt::entry; use log::{info, debug}; use stm32f4xx_hal::pac::{CorePeripherals, Peripherals}; mod device; mod laser_diode; mod thermostat; mod net; use device::{boot::bootup, log_setup, sys_timer}; use crate::net::net::IpSettings; 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}; #[cfg(all(feature = "RTT", not(test)))] #[panic_handler] fn panic(info: &PanicInfo) -> ! { rprintln!("{}", info); loop {} } // Otherwise use panic halt #[cfg(all(not(feature = "RTT"), not(test)))] 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, ip_settings: IpSettings, } const CONFIG_KEY: [&str; 3] = ["Device", "Laser_0", "Thermostat_0"]; #[derive(Default)] pub enum State { #[default] LoadFlashSettings, MainLoop, SaveFlashSettings, HardReset, } #[cfg(not(test))] #[entry] fn main() -> ! { log_setup::init_log(); info!("Kirdy init"); 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); let mut device_settings = DeviceSettings { report_readings: false, ip_settings: IpSettings::default() }; let mut state = State::default(); loop { wd.feed(); match state { State::LoadFlashSettings => { // 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; 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); } } } } 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); // State Transition (laser, thermostat, state, device_settings) = net::cmd_handler::execute_cmd(&mut ETH_DATA_BUFFER, bytes, laser, thermostat, state, device_settings); } } } if has_temp_reading { thermostat.start_tec_readings_conversion(); } } } State::SaveFlashSettings => { // 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(); 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(); } } } } }