Implement first version of storage #45
+1
-1
@@ -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
@@ -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
@@ -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
@@ -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))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user