2020-12-13 07:49:15 +08:00
|
|
|
use log::{info, error};
|
2020-12-12 08:25:07 +08:00
|
|
|
use stm32f4xx_hal::{
|
|
|
|
flash::{Error, FlashExt},
|
|
|
|
stm32::FLASH,
|
|
|
|
};
|
|
|
|
use sfkv::{Store, StoreBackend};
|
|
|
|
|
|
|
|
/// 16 KiB
|
|
|
|
pub const FLASH_SECTOR_SIZE: usize = 0x4000;
|
|
|
|
pub const FLASH_SECTOR: u8 = 12;
|
|
|
|
static mut BACKUP_SPACE: [u8; FLASH_SECTOR_SIZE] = [0; FLASH_SECTOR_SIZE];
|
|
|
|
|
2021-01-13 17:30:12 +08:00
|
|
|
extern "C" {
|
|
|
|
// These are from memory.x
|
|
|
|
static _config_start: usize;
|
|
|
|
static _flash_start: usize;
|
|
|
|
}
|
|
|
|
|
2020-12-12 08:25:07 +08:00
|
|
|
pub struct FlashBackend {
|
|
|
|
flash: FLASH,
|
|
|
|
}
|
|
|
|
|
2021-01-13 17:30:12 +08:00
|
|
|
fn get_offset() -> usize {
|
|
|
|
unsafe {
|
|
|
|
(&_config_start as *const usize as usize) - (&_flash_start as *const usize as usize)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-12-12 08:25:07 +08:00
|
|
|
impl StoreBackend for FlashBackend {
|
|
|
|
type Data = [u8];
|
|
|
|
|
|
|
|
fn data(&self) -> &Self::Data {
|
2021-01-13 17:30:12 +08:00
|
|
|
&self.flash.read()[get_offset()..(get_offset() + FLASH_SECTOR_SIZE)]
|
2020-12-12 08:25:07 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
type Error = Error;
|
|
|
|
fn erase(&mut self) -> Result<(), Self::Error> {
|
2020-12-13 07:49:15 +08:00
|
|
|
info!("erasing store flash");
|
2020-12-12 08:25:07 +08:00
|
|
|
self.flash.unlocked().erase(FLASH_SECTOR)
|
|
|
|
}
|
|
|
|
|
|
|
|
fn program(&mut self, offset: usize, payload: &[u8]) -> Result<(), Self::Error> {
|
|
|
|
self.flash.unlocked()
|
2021-01-13 17:30:12 +08:00
|
|
|
.program(get_offset() + offset, payload.iter().cloned())
|
2020-12-12 08:25:07 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
fn backup_space(&self) -> &'static mut [u8] {
|
|
|
|
unsafe { &mut BACKUP_SPACE }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub type FlashStore = Store<FlashBackend>;
|
|
|
|
|
|
|
|
pub fn store(flash: FLASH) -> FlashStore {
|
|
|
|
let backend = FlashBackend { flash };
|
2020-12-13 07:49:15 +08:00
|
|
|
let mut store = FlashStore::new(backend);
|
|
|
|
|
|
|
|
// just try to read the store
|
|
|
|
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
|
2020-12-12 08:25:07 +08:00
|
|
|
}
|