use log::error; use stm32f4xx_hal::{ flash::{Error, FlashExt}, pac::FLASH, }; use sfkv::{Store, StoreBackend}; // Last flash sector is used to avoid overwriting the code in flash. pub const FLASH_SECTOR: u8 = 11; pub const FLASH_SECTOR_11_OFFSET: u32 = 0xE0000; /// Only 16 KiB out of 128KiB in the Sector is used to save RAM pub const RESERVED_MEMORY: usize = 0x4000; static mut BACKUP_SPACE: [u8; RESERVED_MEMORY] = [0; RESERVED_MEMORY]; pub struct FlashBackend { flash: FLASH, } fn get_offset() -> usize { FLASH_SECTOR_11_OFFSET as usize } impl StoreBackend for FlashBackend { type Data = [u8]; fn data(&self) -> &Self::Data { &self.flash.read()[get_offset()..(get_offset() + RESERVED_MEMORY)] } type Error = Error; fn erase(&mut self) -> Result<(), Self::Error> { self.flash.unlocked().erase(FLASH_SECTOR) } fn program(&mut self, offset: usize, payload: &[u8]) -> Result<(), Self::Error> { self.flash.unlocked() .program(get_offset() + offset, payload.iter()) } fn backup_space(&self) -> &'static mut [u8] { unsafe { BACKUP_SPACE.as_mut() } } } pub type FlashStore = Store; pub fn store(flash: FLASH) -> FlashStore { let backend = FlashBackend { flash }; let mut store = FlashStore::new(backend); match store.get_bytes_used() { Ok(_) => {} Err(e) => { error!("corrupt store, erasing. error: {:?}", e); let _ = store.erase() .map_err(|e| error!("flash erase failed: {:?}", e)); } } store }