From 74325a3cee86e80f635cc4124439927b1475e943 Mon Sep 17 00:00:00 2001 From: linuswck Date: Mon, 15 Jan 2024 16:58:10 +0800 Subject: [PATCH] flash: Add fns to store data in flash - Writing to the wrong flash sector can cause MCU to stall - Only 16KiB out of 128KiB in the sector is used to save RAM for compacting --- Cargo.lock | 105 +++++++++++++++++++++++++++++++++++--- Cargo.toml | 2 +- src/device/flash_store.rs | 62 ++++++++++++++++++++++ src/device/mod.rs | 1 + 4 files changed, 162 insertions(+), 8 deletions(-) create mode 100644 src/device/flash_store.rs diff --git a/Cargo.lock b/Cargo.lock index ff8521d..635c290 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -8,7 +8,19 @@ version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "80a21b9440a626c7fc8573a9e3d3a06b75c7c97754c2949bc7857b90353ca655" dependencies = [ - "as-slice", + "as-slice 0.2.1", +] + +[[package]] +name = "as-slice" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "45403b49e3954a4b8428a0ac21a4b7afadccf92bfd96273f1a58cd4812496ae0" +dependencies = [ + "generic-array 0.12.4", + "generic-array 0.13.3", + "generic-array 0.14.7", + "stable_deref_trait", ] [[package]] @@ -222,7 +234,7 @@ version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "db9efecb57ab54fa918730f2874d7d37647169c50fa1357fecb81abee840b113" dependencies = [ - "heapless", + "heapless 0.7.17", "nb 1.1.0", "no-std-net", ] @@ -267,6 +279,43 @@ version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1d758ba1b47b00caf47f24925c0074ecb20d6dfcffe7f6d53395c0465674841a" +[[package]] +name = "generic-array" +version = "0.12.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffdf9f34f1447443d37393cc6c2b8313aebddcd96906caf34e54c68d8e57d7bd" +dependencies = [ + "typenum", +] + +[[package]] +name = "generic-array" +version = "0.13.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f797e67af32588215eaaab8327027ee8e71b9dd0b2b26996aedf20c030fce309" +dependencies = [ + "typenum", +] + +[[package]] +name = "generic-array" +version = "0.14.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" +dependencies = [ + "typenum", + "version_check", +] + +[[package]] +name = "hash32" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4041af86e63ac4298ce40e5cca669066e75b6f1aa3390fe2561ffa5e1d9f4cc" +dependencies = [ + "byteorder", +] + [[package]] name = "hash32" version = "0.2.1" @@ -276,6 +325,19 @@ dependencies = [ "byteorder", ] +[[package]] +name = "heapless" +version = "0.5.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74911a68a1658cfcfb61bc0ccfbd536e3b6e906f8c2f7883ee50157e3e2184f1" +dependencies = [ + "as-slice 0.1.5", + "generic-array 0.13.3", + "hash32 0.1.1", + "serde", + "stable_deref_trait", +] + [[package]] name = "heapless" version = "0.7.17" @@ -283,7 +345,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cdc6457c0eb62c71aac4bc17216026d8410337c4126773b9c5daba343f17964f" dependencies = [ "atomic-polyfill", - "hash32", + "hash32 0.2.1", "rustc_version 0.4.0", "serde", "spin", @@ -316,6 +378,7 @@ dependencies = [ "panic-halt", "rtt-target", "serde", + "sfkv", "smoltcp", "stm32-eth", "stm32f4xx-hal", @@ -358,7 +421,7 @@ version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "07df30ef660fa32d54836743fbdf8208747a559fc4296ec07dc12b6df65343b2" dependencies = [ - "heapless", + "heapless 0.7.17", "log", "miniconf_derive", "minimq", @@ -387,7 +450,7 @@ dependencies = [ "bit_field", "embedded-nal", "embedded-time", - "heapless", + "heapless 0.7.17", "num_enum", "serde", "smlang", @@ -505,6 +568,23 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "de96540e0ebde571dc55c73d60ef407c653844e6f9a1e2fdbd40c07b9252d812" +[[package]] +name = "postcard" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a9ba0d1b66f31fb374fede892eb4b0818ea819d5e7bc587345ce50a6949e782" +dependencies = [ + "heapless 0.5.6", + "postcard-cobs", + "serde", +] + +[[package]] +name = "postcard-cobs" +version = "0.1.5-pre" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c68cb38ed13fd7bc9dd5db8f165b7c8d9c1a315104083a2b10f11354c2af97f" + [[package]] name = "powerfmt" version = "0.2.0" @@ -635,7 +715,7 @@ version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3c9e1ab533c0bc414c34920ec7e5f097101d126ed5eac1a1aac711222e0bbb33" dependencies = [ - "heapless", + "heapless 0.7.17", "ryu", "serde", ] @@ -651,6 +731,17 @@ dependencies = [ "syn 2.0.41", ] +[[package]] +name = "sfkv" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25f5bfac3f66a7c10a6f37ee81aeaa471f4d35dc21665b59ad7c555adcb9e8aa" +dependencies = [ + "byteorder", + "postcard", + "serde", +] + [[package]] name = "smlang" version = "0.6.0" @@ -680,7 +771,7 @@ dependencies = [ "bitflags", "byteorder", "cfg-if", - "heapless", + "heapless 0.7.17", "log", "managed", ] diff --git a/Cargo.toml b/Cargo.toml index 4f276b6..d337d31 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -33,7 +33,7 @@ fugit = "0.3.6" rtt-target = { version = "0.3.1", features = ["cortex-m"] } miniconf = "0.6.3" serde = { version = "1.0.158", features = ["derive"], default-features = false } - +sfkv = "0.1" [features] semihosting = ["cortex-m-log/semihosting"] RTT = [] diff --git a/src/device/flash_store.rs b/src/device/flash_store.rs new file mode 100644 index 0000000..cec43fd --- /dev/null +++ b/src/device/flash_store.rs @@ -0,0 +1,62 @@ +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 { &mut BACKUP_SPACE } + } +} + +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 +} diff --git a/src/device/mod.rs b/src/device/mod.rs index acfea46..b037c9a 100644 --- a/src/device/mod.rs +++ b/src/device/mod.rs @@ -4,3 +4,4 @@ pub mod log_setup; pub mod rtt_logger; pub mod sys_timer; pub mod usb; +pub mod flash_store;