Implement first version of storage #45

Merged
rhetenor merged 10 commits from storage into main 2026-08-29 17:42:47 +02:00
4 changed files with 65 additions and 37 deletions
Showing only changes of commit b63195b943 - Show all commits
+1 -1
View File
@@ -241,7 +241,7 @@ pub struct Card {
pub sprite: Sprite,
}
impl<'a> TryFrom<RawCard> for Card {
impl TryFrom<RawCard> for Card {
type Error = &'static str;
fn try_from(raw_card: RawCard) -> Result<Self, Self::Error> {
+14 -11
View File
@@ -1,27 +1,30 @@
struct MemoryRegion {
pub struct MemoryRegion {
offset: u32,
size: usize,
}
impl MemoryRegion {
const fn end(&self) -> usize {
pub const fn new(offset: u32, size: usize) -> Self {
assert!(offset.is_multiple_of(4), "Flash requires 4 bytes alignment");
assert!(size.is_multiple_of(4), "Flash requires 4 bytes alignment");
Self { offset, size }
}
pub const fn end(&self) -> usize {
self.offset as usize + self.size
}
}
const MAX_FLASH: usize = 16 * 1024 * 1024;
const MAGIC_REGION: MemoryRegion = MemoryRegion { offset: 0, size: 4 };
const MAGIC_REGION: MemoryRegion = MemoryRegion::new(0, 4);
const SETTINGS_REGION: MemoryRegion = MemoryRegion {
offset: MAGIC_REGION.end() as u32,
size: 1024,
};
const SETTINGS_REGION: MemoryRegion = MemoryRegion::new(MAGIC_REGION.end() as u32, 1024);
const CARDSTORE_REGION: MemoryRegion = MemoryRegion {
offset: SETTINGS_REGION.end() as u32,
size: MAX_FLASH - SETTINGS_REGION.end(),
};
const CARDSTORE_REGION: MemoryRegion = MemoryRegion::new(
SETTINGS_REGION.end() as u32,
MAX_FLASH - SETTINGS_REGION.end(),
);
pub mod cardstore;
pub mod settings;
+16 -14
View File
@@ -12,21 +12,17 @@ use crate::storage::{CARDSTORE_REGION, MemoryRegion};
const MAX_CARDS: usize = 20000;
const COUNT_REGION: MemoryRegion = MemoryRegion {
offset: CARDSTORE_REGION.offset,
size: size_of::<u32>(),
};
pub const COUNT_REGION: MemoryRegion = MemoryRegion::new(CARDSTORE_REGION.offset, size_of::<u32>());
const ALLOCATION_TABLE_REGION: MemoryRegion = MemoryRegion {
offset: COUNT_REGION.end() as u32,
size: MAX_CARDS * AllocationTableEntry::SERIALIZED_SIZE,
};
const CARDS_REGION: MemoryRegion = MemoryRegion {
offset: ALLOCATION_TABLE_REGION.end() as u32,
size: CARDSTORE_REGION.size - ALLOCATION_TABLE_REGION.end(),
};
const ALLOCATION_TABLE_REGION: MemoryRegion = MemoryRegion::new(
COUNT_REGION.end() as u32,
MAX_CARDS * AllocationTableEntry::SERIALIZED_SIZE,
);
const CARDS_REGION: MemoryRegion = MemoryRegion::new(
ALLOCATION_TABLE_REGION.end() as u32,
CARDSTORE_REGION.size - ALLOCATION_TABLE_REGION.end(),
);
#[derive(Debug, BinarySerde, PartialEq, Eq, Clone)]
#[repr(C)]
@@ -47,8 +43,11 @@ pub struct AllocationTableEntry {
deleted: bool,
reserved: [u64; 4],
_padding: [u8; 3],
}
static_assertions::const_assert!(AllocationTableEntry::SERIALIZED_SIZE.is_multiple_of(4));
impl AllocationTableEntry {
fn new(uuid: u32, offset: u32, timestamp: u64) -> Self {
Self {
@@ -58,7 +57,8 @@ impl AllocationTableEntry {
last_read_date: timestamp,
read_count: 0,
deleted: true,
reserved: [0; 4],
reserved: Default::default(),
_padding: Default::default(),
}
}
}
@@ -96,6 +96,8 @@ impl CardStore {
let count: u32 = u32::from_ne_bytes(count_bytes);
log::info!("Found {count} cards in flash.");
let mut allocation_table_entries: Vec<u8> =
Vec::with_capacity(AllocationTableEntry::SERIALIZED_SIZE * count as usize);
+34 -11
View File
@@ -2,33 +2,33 @@ use embedded_storage::nor_flash::NorFlash;
use embedded_storage::nor_flash::ReadNorFlash;
use esp_storage::{FlashStorage, FlashStorageError};
use crate::storage::MAGIC_REGION;
use crate::storage::cardstore::COUNT_REGION;
pub type StoreError = FlashStorageError;
const FLASH_ADDR: u32 = 0x9000;
const INITIALIZATION_SIZE: usize = 0x1004;
const INITIALIZATION_SIZE: usize = COUNT_REGION.end();
const FLASH_INITIALIZE_MAGIC: u32 = 0xde6de6de;
pub struct Store {
pub storage: FlashStorage<'static>,
}
fn initialize_flash(storage: &mut FlashStorage) -> Result<(), StoreError> {
let zeros: [u8; INITIALIZATION_SIZE] = [0; INITIALIZATION_SIZE];
storage.write(FLASH_ADDR, &zeros)?;
storage.write(FLASH_ADDR, &FLASH_INITIALIZE_MAGIC.to_ne_bytes())?;
Ok(())
}
impl Store {
pub fn new(flash: esp_hal::peripherals::FLASH<'static>) -> Result<Self, StoreError> {
let mut storage = FlashStorage::new(flash);
let mut magic: [u8; 4] = [0, 0, 0, 0];
storage.read(FLASH_ADDR, &mut magic)?;
storage.read(FLASH_ADDR + MAGIC_REGION.offset, &mut magic)?;
log::debug!("Magic bytes are {magic:?}");
if (u32::from_ne_bytes(magic)) != FLASH_INITIALIZE_MAGIC {
initialize_flash(&mut storage)?;
if Self::has_magic_bytes(&mut storage)? {
log::info!("Skipped flash initialization, magic bytes already present.");
} else {
log::info!("Initializing flash because no magic bytes found.");
Self::initialize_flash(&mut storage)?;
}
Ok(Self { storage })
@@ -42,4 +42,27 @@ impl Store {
log::debug!("Writing {} bytes at offset 0x{offset:08x}", bytes.len());
self.storage.write(FLASH_ADDR + offset, bytes)
}
fn has_magic_bytes(storage: &mut FlashStorage) -> Result<bool, StoreError> {
let mut magic: [u8; 4] = [0, 0, 0, 0];
storage.read(FLASH_ADDR + MAGIC_REGION.offset, &mut magic)?;
log::debug!("Magic bytes are {magic:?}");
Ok(u32::from_ne_bytes(magic) == FLASH_INITIALIZE_MAGIC)
}
fn initialize_flash(storage: &mut FlashStorage) -> Result<(), StoreError> {
let zeros: [u8; INITIALIZATION_SIZE] = [0; INITIALIZATION_SIZE];
storage.write(FLASH_ADDR, &zeros)?;
storage.write(
FLASH_ADDR + MAGIC_REGION.offset,
&FLASH_INITIALIZE_MAGIC.to_ne_bytes(),
)?;
if Self::has_magic_bytes(storage)? {
Ok(())
} else {
Err(StoreError::Other(FLASH_INITIALIZE_MAGIC as i32))
}
}
}