Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions tinyboot-ch32-boot/src/platform/boot_state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,10 +64,10 @@ impl BootMetaStore {
w.erase(OB_BASE);
w.operation_end();
w.write_start();
for (i, &byte) in buf.iter().enumerate() {
if byte != 0xFF {
w.write(OB_BASE + (i as u32 * 2), byte as u16);
}
let mut addr = OB_BASE;
for &byte in buf.iter() {
w.write(addr, byte as u16);
addr += 2;
}
w.operation_end();
}
Expand Down
59 changes: 22 additions & 37 deletions tinyboot-ch32-boot/src/platform/storage.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,13 @@ pub struct StorageConfig {
pub enum StorageError {
NotAligned,
OutOfBounds,
Protected,
}

impl NorFlashError for StorageError {
fn kind(&self) -> NorFlashErrorKind {
match self {
StorageError::NotAligned => NorFlashErrorKind::NotAligned,
StorageError::OutOfBounds => NorFlashErrorKind::OutOfBounds,
StorageError::Protected => NorFlashErrorKind::Other,
}
}
}
Expand Down Expand Up @@ -60,12 +58,11 @@ impl NorFlash for Storage {
const ERASE_SIZE: usize = PAGE_SIZE;

fn erase(&mut self, from: u32, to: u32) -> Result<(), Self::Error> {
if !(from as usize).is_multiple_of(PAGE_SIZE) || !(to as usize).is_multiple_of(PAGE_SIZE) {
return Err(StorageError::NotAligned);
}
if to as usize > self.app_size {
return Err(StorageError::OutOfBounds);
}
debug_assert!(
(from as usize).is_multiple_of(PAGE_SIZE) && (to as usize).is_multiple_of(PAGE_SIZE),
"erase alignment: from={from}, to={to}"
);
debug_assert!(to as usize <= self.app_size, "erase out of bounds");
let writer = FlashWriter::usr();
writer.erase_start();
let mut addr = self.app_base + from;
Expand All @@ -75,48 +72,36 @@ impl NorFlash for Storage {
addr += PAGE_SIZE as u32;
}
writer.operation_end();
// Write-protection check is debug-only: unlock() disables protection
// before the protocol loop, so WRPRTERR should never fire in a correctly
// configured system. The verify step catches silent write failures.
// Keeping this out of release saves ~40-60 bytes against the 1920-byte budget.
#[cfg(debug_assertions)]
if writer.check_wrprterr() {
return Err(StorageError::Protected);
}
Ok(())
}

fn write(&mut self, offset: u32, bytes: &[u8]) -> Result<(), Self::Error> {
if !(offset as usize).is_multiple_of(PAGE_SIZE)
|| bytes.len() > PAGE_SIZE
|| !bytes.len().is_multiple_of(BUF_LOAD_SIZE)
{
return Err(StorageError::NotAligned);
}
if offset as usize + bytes.len() > self.app_size {
return Err(StorageError::OutOfBounds);
}
let base = self.app_base + offset;
let mut addr = base;
let mut ptr = bytes.as_ptr() as *const u32;
debug_assert!(
(offset as usize).is_multiple_of(PAGE_SIZE)
&& bytes.len() <= PAGE_SIZE
&& bytes.len().is_multiple_of(BUF_LOAD_SIZE),
"write alignment: offset={offset}, len={}",
bytes.len()
);
debug_assert!(
offset as usize + bytes.len() <= self.app_size,
"write out of bounds"
);
let page_addr = self.app_base + offset;
let writer = FlashWriter::usr();
writer.write_start();
writer.fast_write_buf_reset();
let mut addr = page_addr;
let mut ptr = bytes.as_ptr() as *const u32;
for _ in 0..bytes.len() / BUF_LOAD_SIZE {
// SAFETY: ptr advances within bounds, read_unaligned handles alignment
let word = unsafe { ptr.read_unaligned() };
// SAFETY: ptr advances within data bounds; RingBuf is repr(align(4)).
let word = unsafe { ptr.read() };
writer.fast_write_buf_load(addr, word);
addr += BUF_LOAD_SIZE as u32;
ptr = unsafe { ptr.add(1) };
}
writer.fast_write_page_program(base);
writer.fast_write_page_program(page_addr);
writer.operation_end();

// See erase() for rationale on debug-only write-protection check.
#[cfg(debug_assertions)]
if writer.check_wrprterr() {
return Err(StorageError::Protected);
}
Ok(())
}
}
Expand Down
18 changes: 5 additions & 13 deletions tinyboot-ch32-hal/src/flash/v0.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@ const FLASH: ch32_metapac::flash::Flash = ch32_metapac::FLASH;
#[inline(always)]
fn wait_busy() {
while FLASH.statr().read().bsy() {}
debug_assert!(
!FLASH.statr().read().wrprterr(),
"flash write protection error"
);
}

/// Unlock flash controller for all operations (KEYR + MODEKEYR + OBKEYR).
Expand Down Expand Up @@ -67,19 +71,6 @@ impl FlashWriter {
}
}

/// check for write protection error
pub fn check_wrprterr(&self) -> bool {
let statr = FLASH.statr().read();
if statr.wrprterr() {
FLASH.statr().write(|w| w.set_wrprterr(true));
return true;
}
if statr.eop() {
FLASH.statr().write(|w| w.set_eop(true));
}
false
}

/// Start write operation
#[inline(always)]
pub fn write_start(&self) {
Expand All @@ -105,6 +96,7 @@ impl FlashWriter {
}

/// Erase (64-byte page for flash, full OB erase for option bytes).
#[inline(always)]
pub fn erase(&self, addr: u32) {
let erase_bit = self.erase_bit as usize;
let ctlr = (1 << OBWRE) | (1 << erase_bit) | (1 << STRT);
Expand Down
Loading