Skip to content

Commit

Permalink
Clear SP flash errors we should never see
Browse files Browse the repository at this point in the history
The STM32H7 is haunted/contains an errata where the CPU may
speculate into a system area (`0x1ff0_0000`) and trigger a flash
error normally only seen when security features are enabled.
This is not an official errata but seems to be well(?) reported

https://community.st.com/t5/stm32-mcus-products/spurious-rdperr-and-rdserr-when-all-protection-and-security/td-p/279852
zephyrproject-rtos/zephyr#60449

One suggested workaround is to add an extra MPU region which
marks The Danger Zone as NX. For the way hubris is designed this
isn't plausible. Instead clear any errors before we attempt to
write to flash.
  • Loading branch information
labbott committed Oct 23, 2024
1 parent 7819a76 commit 3f84852
Showing 1 changed file with 16 additions and 0 deletions.
16 changes: 16 additions & 0 deletions drv/stm32h7-update-server/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,7 @@ impl<'a> ServerImpl<'a> {
words: &[u32; FLASH_WORD_WORDS],
) -> Result<(), RequestError<UpdateError>> {
ringbuf_entry!(Trace::WriteStart);
self.clear_errors();

// These variables are _philosophically_ constants, but since they're
// generated by taking the address of a linker-generated symbol, we
Expand Down Expand Up @@ -243,9 +244,24 @@ impl<'a> ServerImpl<'a> {
.write(|w| unsafe { w.optkeyr().bits(FLASH_OPT_KEY2) });
}

fn clear_errors(&mut self) {
// https://github.com/zephyrproject-rtos/zephyr/issues/60449
// https://community.st.com/t5/stm32-mcus-products/spurious-rdperr-and-rdserr-when-all-protection-and-security/td-p/279852
// There are issue with the CPU speculating into unknown
// areas. One workaround is to explicitly mark the reigon as NX
// via MPU but that's expensive/costs an MPU region
// Another workaround is to just clear errors we don't
// expect to see
self.flash
.bank2()
.ccr
.modify(|_, w| w.clr_rdperr().set_bit().clr_rdserr().set_bit());
}

fn bank_erase(&mut self) -> Result<(), RequestError<UpdateError>> {
ringbuf_entry!(Trace::EraseStart);

self.clear_errors();
// Enable relevant interrupts for completion (or failure) of erasing
// bank2.
sys_irq_control(notifications::FLASH_IRQ_MASK, true);
Expand Down

0 comments on commit 3f84852

Please sign in to comment.