diff --git a/src/card/model.rs b/src/card/model.rs index e42764e..22721a0 100644 --- a/src/card/model.rs +++ b/src/card/model.rs @@ -241,7 +241,7 @@ pub struct Card { pub sprite: Sprite, } -impl<'a> TryFrom for Card { +impl TryFrom for Card { type Error = &'static str; fn try_from(raw_card: RawCard) -> Result { diff --git a/src/storage.rs b/src/storage.rs index 7cfc291..93a2d8f 100644 --- a/src/storage.rs +++ b/src/storage.rs @@ -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; diff --git a/src/storage/cardstore.rs b/src/storage/cardstore.rs index 15ce0f9..db4fe20 100644 --- a/src/storage/cardstore.rs +++ b/src/storage/cardstore.rs @@ -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::(), -}; +pub const COUNT_REGION: MemoryRegion = MemoryRegion::new(CARDSTORE_REGION.offset, size_of::()); -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 = Vec::with_capacity(AllocationTableEntry::SERIALIZED_SIZE * count as usize); diff --git a/src/storage/store.rs b/src/storage/store.rs index 37d3563..c9702db 100644 --- a/src/storage/store.rs +++ b/src/storage/store.rs @@ -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 { 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 { + 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)) + } + } }