Skip to main content
turbofish
Associate II
January 14, 2019
Solved

SOLVED: Backup SRAM for STM32 is wiped between resets

  • January 14, 2019
  • 4 replies
  • 2845 views

Solved: The problem was an improper reading, the BKSRAM-clock was not initialized when reading back the report. Updating with "correct" code for posterity.

I'm writing a (better) hard-fault handler for my STM32f207zg and want to do the following:

  1. Have a horrible crash
  2. Jump into my (C) fault handler
  3. Save various registers (CFSR, HFSR, LR, PC, ...) in the backup SRAM
  4. Reset
  5. When back in main(), check if the watchdog reset the system
  6. Fetch the "crash report" saved in the SRAM
  7. Dump it on CAN

1,2,4,5,7 is easy, but I'm having problems with saving/restoring from the SRAM.

The hardfault-handler calls the function fault_bksram_init() after filling up the fault_crash_t structure with data. It then calls fault_write_crash() in order to write the "report" to the SRAM. I can see using my debugger that the data is actually written to the address defined in BKPSRAM_BASE; however, after doing a reset using the debugger the memory at BKPSRAM_BASE is wiped with 0xff . In order words, the data is lost between resets.

I have the correct voltage connected to VBat (the RTC works nicely) but I have never used the backup SRAM before.

Am I missing something in the initialization of the SRAM? Is it something with doing this in a hard-fault handler that I'm missing? Or is the debugger reset that messes up the SRAM?

void fault_bksram_init(void) {
 /* Enable PWR clock */
 RCC->APB1ENR |= RCC_APB1ENR_PWREN;
 
 /* Enable backup SRAM Clock */
 RCC->AHB1ENR |= RCC_AHB1ENR_BKPSRAMEN;
 
 /* Disable write protection */
 PWR->CR |= PWR_CR_DBP;
 
 /* Enable backup regulator */
 PWR->CSR |= PWR_CSR_BRE;
 
 /* Wait for backup regulator to be ready */
 while (!(PWR->CSR & (PWR_FLAG_BRR)));
}
void fault_write_crash(fault_crash_t* crash) {
 /* Copy crash to BKSRAM */
 fault_bksram_init();
 memcpy((void*)BKPSRAM_BASE, (void*)crash, sizeof(fault_crash_t));
}
void fault_read_crash(fault_crash_t* crash) {
 /* Copy crash from BKSRAM*/
 fault_bksram_init();
 memcpy((void*)crash, (void*)BKPSRAM_BASE, sizeof(fault_crash_t));
 
 if (crash->magic != FAULT_MAGIC) {
 memset((void*)crash, 0, sizeof(fault_crash_t));
 }
}

This topic has been closed for replies.
Best answer by turbofish

The regular SRAM is kinda used (not completely, but close) and I have this 4KB of BKSRAM just "laying around", and I already have a battery on my PCB (the system needs to have a good RTC in order to function).

4 replies

After Forever
Senior III
January 14, 2019

Can you make sure DBP is "really" enabled after enabling it (by waiting until the bit reports as set)?

Also, from the RM:

Access to the backup SRAM

  1. Enable the power interface clock by setting the PWREN bits in the RCC APB1peripheral clock enable register (RCC_APB1ENR)
  2. Set the DBP bit in the PWR power control register (PWR_CR) to enable access to thebackup domain
  3. Enable the backup SRAM clock by setting BKPSRAMEN bit in the RCC AHB1peripheral clock register (RCC_AHB1ENR)

Just in case, you have 2 and 3 mixed.

turbofish
turbofishAuthor
Associate II
January 16, 2019

The order doesn't seem to affect this particular issue. But in general its a good idea to follow...

S.Ma
Principal
January 14, 2019

Actually, if you don't power off the mcu, why not exclude a small area of the regular SRAM by editing the linker memory map config file? You can override and write this area which won't be initialized by any startup function. There are some system flags to tell if the reset is caused by power on or else to discriminate. Maybe no need to plan for the backup SRAM which maybe dedicated to power failures.

turbofish
turbofishAuthorBest answer
Associate II
January 16, 2019

The regular SRAM is kinda used (not completely, but close) and I have this 4KB of BKSRAM just "laying around", and I already have a battery on my PCB (the system needs to have a good RTC in order to function).