diff --git a/firmware/Cargo.toml b/firmware/Cargo.toml index 5508bac..8d426a5 100644 --- a/firmware/Cargo.toml +++ b/firmware/Cargo.toml @@ -26,3 +26,4 @@ cheapsdo-protocol = { path = "../protocol" } postcard = {version = "1.0.8", features = ["use-defmt"]} heapless = {version = "0.8.0", features = ["defmt-03"]} num = {version = "0.4.1", default-features = false, features = ["libm"]} +serde = { version = "1.0.195", default-features = false } diff --git a/firmware/src/main.rs b/firmware/src/main.rs index 6ba8ba9..96b7a62 100644 --- a/firmware/src/main.rs +++ b/firmware/src/main.rs @@ -6,6 +6,7 @@ use defmt_rtt as _; // global logger use panic_probe as _; use stm32f1xx_hal as _; +mod nvstate; mod si5153; // same panicking *behavior* as `panic-probe` but doesn't print a panic message @@ -24,6 +25,7 @@ mod app { use rtic_monotonics::systick::*; use stm32f1xx_hal::{ + flash::{self, FlashWriter}, gpio::{self, gpioa, gpioc, Alternate, Output, PushPull}, i2c, pac, pac::{RCC, TIM2, TIM3, TIM4}, @@ -41,6 +43,7 @@ mod app { use cheapsdo_protocol::{DeviceMessage, HostMessage, StatusMessage}; + use crate::nvstate::{self, NVState}; use crate::si5153; const USB_BUFFER_SIZE: usize = 64; @@ -51,6 +54,8 @@ mod app { tim2: TIM2, tim3: TIM3, pwm: PwmHz, gpio::Pin<'B', 6, Alternate>>, + nvstate: NVState, + flash: flash::Parts, } #[shared] @@ -229,6 +234,10 @@ mod app { si_pll.set_ms_freq(&mut i2c1, si5153::Multisynth::MS0, 100_000_000); si_pll.enable_ms_output(&mut i2c1, si5153::Multisynth::MS0); + let nvstate = nvstate::load(&mut flash); + + defmt::info!("read nvstate from flash"); + update_pwm::spawn().unwrap(); ( @@ -243,13 +252,15 @@ mod app { tim2, tim3, pwm, + nvstate, + flash, }, ) } const WINDOW_LEN: usize = 100; - #[task(local=[tim2, tim3, pwm, board_led], shared=[device_status])] + #[task(local=[tim2, tim3, pwm, board_led, nvstate, flash], shared=[device_status])] async fn update_pwm(mut cx: update_pwm::Context) { defmt::info!("Update Task started"); @@ -257,9 +268,16 @@ mod app { let tim3 = cx.local.tim3; let pwm = cx.local.pwm; let board_led = cx.local.board_led; + let mut nvstate = cx.local.nvstate; + let mut flash = cx.local.flash; let max_pwm = pwm.get_max_duty() as i32; - let mut cur_pwm = max_pwm / 2; + let mut cur_pwm = nvstate.pwm as i32; + cur_pwm = if cur_pwm < 0 { 0 } else { cur_pwm }; + cur_pwm = if cur_pwm > max_pwm { max_pwm } else { cur_pwm }; + + pwm.set_duty(Channel::C1, cur_pwm as u16); + defmt::info!("pwm:\t{}", cur_pwm); // Inialize last_ic while !tim2.sr.read().cc1if().bit_is_set() || !tim3.sr.read().cc1if().bit_is_set() { @@ -343,6 +361,9 @@ mod app { pwm.set_duty(Channel::C1, cur_pwm as u16); defmt::info!("pwm:\t{}", cur_pwm); + nvstate.pwm = cur_pwm as u16; + nvstate.save(&mut flash); + Systick::delay(500.millis()).await; } } diff --git a/firmware/src/nvstate.rs b/firmware/src/nvstate.rs new file mode 100644 index 0000000..e9b6ead --- /dev/null +++ b/firmware/src/nvstate.rs @@ -0,0 +1,45 @@ +use postcard::{from_bytes_cobs, to_slice_cobs}; +use serde::{Deserialize, Serialize}; +use stm32f1xx_hal::flash::{self, FlashSize, FlashWriter, SectorSize}; + +#[derive(Serialize, Deserialize, Debug, PartialEq)] +pub struct NVState { + pub pwm: u16, +} + +impl Default for NVState { + fn default() -> Self { + Self { pwm: 1500u16 } + } +} + +const PAGE_SIZE: usize = 1024; +const NVSTATE_OFFSET: u32 = 63 * PAGE_SIZE as u32; + +const FLASH_SIZE: FlashSize = FlashSize::Sz64K; +const SECTOR_SIZE: SectorSize = SectorSize::Sz1K; + +pub fn load(flash: &mut flash::Parts) -> NVState { + let mut flash_writer = flash.writer(SECTOR_SIZE, FLASH_SIZE); + + let tmp = flash_writer.read(NVSTATE_OFFSET, PAGE_SIZE).unwrap(); + let mut nvstate_page = [0u8; PAGE_SIZE]; + nvstate_page.copy_from_slice(tmp); + + match from_bytes_cobs::(&mut nvstate_page) { + Ok(nvstate) => nvstate, + Err(_) => NVState::default(), + } +} + +impl NVState { + pub fn save(&self, flash: &mut flash::Parts) { + let mut flash_writer = flash.writer(SECTOR_SIZE, FLASH_SIZE); + + let mut page = [0u8; PAGE_SIZE]; + let used = to_slice_cobs(self, &mut page).unwrap(); + + flash_writer.page_erase(NVSTATE_OFFSET).unwrap(); + flash_writer.write(NVSTATE_OFFSET, &used).unwrap(); + } +} diff --git a/memory.x b/memory.x index 71f245d..ab4c50c 100644 --- a/memory.x +++ b/memory.x @@ -1,6 +1,7 @@ /* Linker script for the STM32F103C8T6 */ MEMORY { - FLASH : ORIGIN = 0x08000000, LENGTH = 64K + FLASH : ORIGIN = 0x08000000, LENGTH = 63K + NVSTATE : ORIGIN = FLASH + 63K, LENGTH = 1K RAM : ORIGIN = 0x20000000, LENGTH = 20K }