save tests

This commit is contained in:
2026-04-11 21:34:48 +02:00
parent bc25fef5ec
commit 0d7074bd89
4 changed files with 23 additions and 11 deletions

View File

@@ -563,7 +563,7 @@ impl Esp<'_> {
match self.savegame.load_slot(idx)? {
None => bail!("Slot {idx} is empty or invalid"),
Some(data) => {
Ok(String::from_utf8_lossy(&*data).to_string())
Ok(String::from_utf8_lossy(&data).to_string())
}
}
}

View File

@@ -9,9 +9,10 @@ use crate::hal::shared_flash::MutexFlashStorage;
/// Size of each save slot in bytes (16 KB).
pub const SAVEGAME_SLOT_SIZE: usize = 16384;
//keep a little of space at the end due to partition table offsets
const SAFETY: usize = 5;
/// Number of slots in the 8 MB storage partition.
pub const SAVEGAME_SLOT_COUNT: usize = 8 * 1024 * 1024 / SAVEGAME_SLOT_SIZE; // 512
pub const SAVEGAME_SLOT_COUNT: usize = (8 * 1024 * 1024) / SAVEGAME_SLOT_SIZE - SAFETY; // 507
/// Metadata about a single existing save slot, returned by [`SavegameManager::list_saves`].
#[derive(Serialize, Debug, Clone)]
@@ -51,9 +52,15 @@ impl Flash for SavegameFlashAdapter<'_> {
/// embedded-savegame calls this before writing to a slot, so we erase
/// the entire `SAVEGAME_SLOT_SIZE` bytes so subsequent writes land on
/// pre-erased (0xFF) pages.
/// Ensures addresses are aligned to ERASE_SIZE (4KB) boundaries.
fn erase(&mut self, addr: u32) -> Result<(), Self::Error> {
const ERASE_SIZE: u32 = 4096;
// Align start address down to erase boundary
let aligned_start = (addr / ERASE_SIZE) * ERASE_SIZE;
// Align end address up to erase boundary
let end = addr + SAVEGAME_SLOT_SIZE as u32;
NorFlash::erase(self.region, addr, end).map_err(SavegameFlashError)
let aligned_end = ((end + ERASE_SIZE - 1) / ERASE_SIZE) * ERASE_SIZE;
NorFlash::erase(self.region, aligned_start, aligned_end).map_err(SavegameFlashError)
}
}
@@ -91,9 +98,10 @@ impl SavegameManager {
///
/// `scan()` advances the internal wear-leveling pointer to the latest valid
/// slot before `append()` writes to the next free one.
/// Both operations are performed atomically on the same Storage instance.
pub fn save(&mut self, data: &mut [u8]) -> FatResult<()> {
let mut st = self.storage();
st.scan()?;
let _slot = st.scan()?;
st.append(data)?;
Ok(())
}

View File

@@ -577,9 +577,9 @@ impl<'a> BoardInteraction<'a> for V4<'a> {
start
);
to_write -= part.len();
chunk += 1;
self.get_rtc_module()
.write((BACKUP_HEADER_MAX_SIZE + chunk * EEPROM_PAGE) as u32, part)?;
chunk += 1;
}
info!("Backup complete");
self.clear_progress().await;
@@ -591,13 +591,19 @@ impl<'a> BoardInteraction<'a> for V4<'a> {
let mut store = alloc::vec![0_u8; info.size as usize];
self.rtc_module
.read(BACKUP_HEADER_MAX_SIZE as u32, store.as_mut_slice())?;
info!("Read backup data of size {}", store.len());
let mut checksum = X25.digest();
info!("Calculating CRC");
checksum.update(&store[..]);
let crc = checksum.finalize();
info!("CRC is {:04x}", crc);
if crc != info.crc16 {
warn!("CRC mismatch in backup data");
bail!("CRC mismatch in backup data")
}
info!("CRC is correct");
let (decoded, _) = bincode::decode_from_slice(&store[..], CONFIG)?;
info!("Backup data decoded");
Ok(decoded)
}