cancel
Showing results for 
Search instead for 
Did you mean: 

FAQ: STM32 SRAM/Backup SRAM content is not preserved after reset

Adam BERLINGER
ST Employee

Problem

Backup SRAM or normal SRAM content is not preserved after reset or wake up from standby. After a reset, the last few bytes written are not kept. 

Solution

This issue appears on STM32 devices that have ECC (Error Code Correction) on internal SRAM. This article focuses on STM32H7, but a similar approach can be applied to other STM32 series such as STM32H5 and STM32N6.

On STM32H7, the ECC is computed for each word of SRAM (64-bit for AXI SRAM, 32-bit for other SRAMs, including backup SRAM).
All "word-aligned" write accesses are directly written to the SRAM. Word-aligned access is when the whole SRAM word is written to an aligned address:

  • For AXI SRAM, this is a 64-bit write to an aligned address, which is a multiple of 8.
  • For other SRAMs, this is a 32-bit write to an aligned address, which is a multiple of 4.

All other access ("word-unaligned") ends in one word cache, which is part of SRAM. This cache is used to optimize ECC computation by waiting for the next data, which could be part of the same SRAM word. Otherwise, the SRAM must perform a read-modify-write operation to have the correct ECC for the whole SRAM word.

To flush this cache after "word-unaligned" access, there are two options:

  • Perform other "unaligned" access to other SRAM word.
  • Perform a read and write aligned operation on the same SRAM word as the last access.

Performing aligned write access to different part of SRAM does not flush the cache.
The code for flushing the ECC can look like this:

void FlushECC(void *ptr, int bytes){
	uint32_t addr = (uint32_t)ptr;
	/* Check if accessing AXI SRAM => 64-bit words*/
	if(addr >= 0x24000000 && addr < 0x24080000){
		volatile uint64_t temp;
		volatile uint64_t* flush_ptr = (uint64_t*) (addr & 0xFFFFFFF8);
		uint64_t *end_ptr = (uint64_t*) ((addr+bytes) & 0xFFFFFFF8);

		do{
			temp = *flush_ptr;
			*flush_ptr = temp;
			flush_ptr++;
		}while(flush_ptr != end_ptr);
	}
	/* Otherwise 32-bit words */
	else {
		volatile uint32_t temp;
		volatile uint32_t* flush_ptr = (uint32_t*) (addr & 0xFFFFFFFC);
		uint32_t *end_ptr = (uint32_t*) ((addr+bytes) & 0xFFFFFFFC);

		do{
			temp = *flush_ptr;
			*flush_ptr = temp;
			flush_ptr++;
		}while(flush_ptr != end_ptr);
	}
}

This can be useful, for example, flushing the whole C structure, when we are not sure which variable was written last.
Note that this issue only affects data retention after reset or exit from standby mode (which acts as reset). It does not affect coherency between core and DMA, since this one word cache is a part of SRAM.

First published on Oct 10, 2020

Version history
Last update:
‎2025-12-04 4:48 AM
Updated by: