kirdy/src/device/flash_store.rs

63 lines
1.6 KiB
Rust

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<FlashBackend>;
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
}