cancel
Showing results for 
Search instead for 
Did you mean: 

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

Adam BERLINGER
ST Employee
Backup SRAM or normal SRAM content is not preserved after reset or wake up from standby. After reset last few bytes written are not kept. What is the problem?This issue appears on STM32H7 devices and is caused by the ECC (Error Code Correction) which 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 whole SRAM word is written to aligned address:
  • For AXI SRAM, this is 64-bit write to aligned address which is multiply of 8
  • For other SRAMs this is 32-bit write to aligned address which is multiply of 4
All other access ("word-unaligned") will end in one word cache, which is part of SRAM. This cache is used to optimize ECC computation by waiting for next data, which could be part of the same SRAM word. Otherwise the SRAM must perform read-modify-write operation to have correct ECC for whole SRAM word.
To flush this cache after "word-unaligned" access, there are two options:
  • perform other "unaligned" access to other SRAM word
  • perform read and write aligned operation on the same SRAM word as the last access
Performing aligned write access to different part of SRAM will 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 e.g. for flushing whole C structure, when we are not sure which variable was written last.
Please note this issue only affects data retention after reset or exit from standby mode (which acts as reset). It doesn't affect coherency between core and DMA, since this one word cache is a part of SRAM.
0 REPLIES 0