stm32h7xx-hal
stm32h7xx-hal copied to clipboard
Writing to uninitialized memory is unreliable
When writing to uninitialized RAM and then rebooting the device, upon reading the memory back sometimes various bytes can be deformed. Apparently this is due to how ECC RAM for the STM32H7 works.
The solution is slightly arcane, reading and writing back the data to make the memory "stick" and persist properly between reboots:
const BUFFER_LEN: usize = 128;
/// BUFFER is linked to the uninitialized RAM, which may or may not be initialized by the user
#[link_section = ".uninit"]
static mut BUFFER: MaybeUninit<[u8; BUFFER_LEN]> = MaybeUninit::uninit();
let buffer: &'static mut [u8; BUFFER_LEN] = {
let buf: &mut [core::mem::MaybeUninit<u8>; BUFFER_LEN] = unsafe { core::mem::transmute(&mut BUFFER) };
unsafe { core::mem::transmute(buf) }
};
// ... Write data to the buffer, which should be persisted between reboots
// To prevent the data from deforming when rebooting: read and write back the data to make it persist properly
for i in 0..BUFFER_LEN {
let ptr: *mut u8 = &mut buffer[i];
ptr.write_volatile(ptr.read_volatile());
}
I'm wondering if the HAL could provide a wrapper or some kind of mechanism to make this easier for people in the future? Otherwise perhaps an example could help people deal with this situation?
The problem isn't specifically about writing to uninitialised memory, but any writes to ECC-protected SRAM that occur just before a reset. The reference manuals describe this in the section on embedded SRAM (e.g. section 2.4 in RM0399):

Any additional write anywhere to the same RAM is OK and ensures your previous writes persist, you don't specifically need to read and write it the same data back, and just a single write at the end will do the trick. The words in the reference manual there are ECC words which are either 32 or 64 bit depending on the SRAM; any full word write will persist by itself too.
There's also the Cortex-M7 store buffer to contend with, so it might be worth issuing a DMB (cortex_m::asm::dmb()) before resetting to ensure that's flushed, too.
Since what's needed is "any write to the same SRAM, only immediately before a reset", I'm not sure exactly what a wrapper in the HAL should look like really. I'd put this down to "fun quirk of the stm32h7 SRAM that you need to be aware of when writing to ram immediately before resetting". I guess there could be something like a flush_sram_ecc() method that just does a read-write to the start of each SRAM or something, but you might only find the function existed after being bit by this problem...