HomeAbout UsContact Us

Fixing Zephyr Deep Sleep Backup SRAM Retention on STM32

By Jithin Tom
Published in Embedded Concepts
September 12, 2026
4 min read
Fixing Zephyr Deep Sleep Backup SRAM Retention on STM32

Table Of Contents

01
Problem: Data Loss During Deep Sleep
02
Root Cause: The Backup Regulator & Power Domain Gating
03
Solution: Configuring Backup SRAM in Zephyr RTOS
04
Verification: Two-Phase Retention Validation
05
Engineering Trade-offs & Operational Limits
06
Summary
07
Related Reading
08
References
09
Frequently Asked Questions

When designing battery-powered embedded systems, engineers often face the challenge of preserving critical data across deep sleep cycles. While external EEPROM, FRAM, or battery-backed SPI SRAM are common solutions, they add bill-of-materials (BOM) cost, board footprint, and bus latency. STM32 microcontrollers provide an integrated on-chip alternative: 4KB of battery-backed backup SRAM (BKPSRAM).

In Zephyr RTOS, developers frequently configure devicetree nodes for backup SRAM only to discover that data vanishes the moment the MCU enters Standby mode. This article details the root cause of backup SRAM data loss, examines the hardware power domain architecture, and provides complete, verified Devicetree and C code implementations using Zephyr’s retained memory API.

+-----------------------------+ +-----------------------------+
| MAIN DOMAIN | | BACKUP DOMAIN |
| (Powered by VDD) | | (Powered by VBAT) |
+-----------------------------+ +-----------------------------+
| * Cortex-M Core & Pipeline | | * Backup SRAM (4KB Array) |
| * System SRAM (SRAM1, 2) | | * Low-Power Backup Reg(BRE) |
| * High-Speed Peripherals | | * Real-Time Clock (RTC) |
| * Flash Memory & Cache | | * Backup Registers (BKP) |
+-----------------------------+ +-----------------------------+
| ^
STANDBY ENTRY |
[ VDD Rail Collapses ] BATTERY BACKUP SUPPLY
| [ Coin Cell / Supercap ]
v |
+-----------------------------+ |
| DATA LOST | |
| Core unpowered; SRAM erased | v
+-----------------------------+ +-----------------------------+
| DATA RETAINED |
| Backup Reg keeps cells alive|
+-----------------------------+

Problem: Data Loss During Deep Sleep

Many battery-operated applications require non-volatile persistence for:

  • Cryptographic session keys and monotonic sequence counters
  • Sensor calibration matrices and zero-point offsets
  • Crash dump breadcrumbs and reset reason telemetry
  • Machine state variables for sub-millisecond warm resume

When an STM32 MCU enters Standby mode (PM_STATE_STANDBY in Zephyr), the internal main voltage regulator is deactivated, collapsing the V_CORE rail to zero volts. Consequently, standard system SRAM (e.g., SRAM1, SRAM2) loses all electrical charge, destroying in-memory application context.

While developers turn to on-chip backup SRAM to avoid adding external non-volatile memory, a common trap emerges: allocating a buffer in the backup SRAM memory region does not guarantee retention during Standby mode. Upon wake-up, the memory block consistently reads back arbitrary power-on garbage or reset zeros.

Root Cause: The Backup Regulator & Power Domain Gating

The failure to retain backup SRAM data across Standby mode stems from three interdependent architectural requirements in the STM32 power management hardware:

  1. The Low-Power Backup Regulator (BRE): The backup domain is powered from V_DD when the main power is healthy and automatically switches to V_BAT when V_DD drops below threshold. However, the 4KB backup SRAM array requires an internal dedicated low-power regulator to maintain memory cell retention voltage in Standby and V_BAT modes. This backup regulator is disabled by default after system reset. If software does not set the BRE bit in the Power Control/Status register (PWR_CSR) and wait for the Backup Regulator Ready (BRR) flag, the backup SRAM is unpowered during Standby mode, even if a coin cell battery is connected to V_BAT.

  2. Backup Domain Write Protection (DBP): Following any reset, the backup domain (which encompasses the Real-Time Clock, backup registers, and backup power control bits) is write-protected to prevent accidental corruption during power transitions. Software must assert the DBP (Disable Backup Protection) bit in PWR_CR before the backup regulator can be activated or backup SRAM configuration registers can be updated.

  3. AHB Bus Clock Gating (BKPSRAMEN): In families such as the STM32F4 and STM32F7, the backup SRAM is accessed via the AHB1 peripheral bus. If the backup SRAM clock gate bit (RCC_AHB1ENR_BKPSRAMEN) is not enabled, any read or write attempt to the backup SRAM physical address (0x40024000) triggers an immediate Cortex-M bus fault (BusFault / PRECISERR).

  4. Standby Reset Semantics: Exiting Standby mode in STM32 hardware is functionally equivalent to an external hardware reset (NRST). The core re-executes from Reset_Handler. Any sequential code placed immediately after a sleep entry call is never reached prior to system reboot.

Solution: Configuring Backup SRAM in Zephyr RTOS

To achieve deterministic backup SRAM retention under Zephyr, implement the solution across three distinct layers:

  1. Enable the generic retained memory driver subsystem in Kconfig.
  2. Declare the physical backup SRAM address in a Devicetree overlay.
  3. Unlock the backup regulator and perform persistent I/O via the Zephyr retained_mem API.

Step 1: Enable the Zephyr Retained Memory Subsystem

Add the retained memory driver framework to your application’s prj.conf:

# Enable Zephyr retained memory driver core
CONFIG_RETAINED_MEM=y
# Retained RAM generic driver automatically enables when compatible node is present
CONFIG_RETAINED_MEM_ZEPHYR_RAM=y

CONFIG_RETAINED_MEM compiles the generic driver interface (<zephyr/drivers/retained_mem.h>). When Zephyr identifies a node matching zephyr,retained-ram in Devicetree, CONFIG_RETAINED_MEM_ZEPHYR_RAM initializes the memory-mapped driver instance at boot priority 40.

Step 2: Declare the Backup SRAM Node in Devicetree

Create an application overlay file (e.g., app.overlay or <board>.overlay) defining the physical backup SRAM region.

For the STM32F4 / STM32F7 series, the 4KB backup SRAM is located at base address 0x40024000:

/ {
soc {
sram_backup: sram-backup@40024000 {
compatible = "zephyr,retained-ram";
reg = <0x40024000 0x1000>; /* 4KB Backup SRAM */
status = "okay";
};
};
};

[!NOTE] If targeting the STM32H7 series, the 4KB backup SRAM resides in the D3 power domain at base address 0x38800000. Adjust the reg property accordingly: reg = <0x38800000 0x1000>;.

Step 3: Initialize Hardware Retention & Access Memory in C

Before reading or writing to the retained memory driver, ensure the STM32 backup regulator and AHB clock gating are properly initialized. In Zephyr, this can be handled in application startup code using STM32 Low-Layer (LL) macros or standard CMSIS register accesses:

#include <zephyr/kernel.h>
#include <zephyr/device.h>
#include <zephyr/drivers/retained_mem.h>
#include <zephyr/sys/printk.h>
#include <stm32f4xx_ll_pwr.h>
#include <stm32f4xx_ll_bus.h>
#define BACKUP_SRAM_NODE DT_NODELABEL(sram_backup)
/* Application calibration data structure */
struct sensor_calibration {
float offset;
float gain;
uint32_t crc;
};
/**
* @brief Initialize STM32 hardware clocks and backup regulator
*/
static void stm32_backup_sram_hw_init(void)
{
/* 1. Enable PWR peripheral clock on APB1 */
LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_PWR);
/* 2. Disable backup domain write protection */
LL_PWR_EnableBkUpAccess();
/* 3. Enable AHB1 bus clock to Backup SRAM to allow CPU memory access */
LL_AHB1_GRP1_EnableClock(LL_AHB1_GRP1_PERIPH_BKPSRAM);
/* 4. Enable the Low-Power Backup Regulator (BRE) for Standby/VBAT retention */
LL_PWR_EnableBkUpRegulator();
/* 5. Wait for Backup Regulator to stabilize */
while (!LL_PWR_IsActiveFlag_BRR()) {
/* Busy-wait until backup regulator ready flag is set */
}
}
/**
* @brief Store system state in Backup SRAM using retained_mem API
*/
int save_calibration_to_backup_sram(const struct sensor_calibration *cal)
{
const struct device *dev = DEVICE_DT_GET(BACKUP_SRAM_NODE);
if (!device_is_ready(dev)) {
printk("Error: retained memory device not ready\n");
return -ENODEV;
}
/* Write data at offset 0 of backup SRAM */
int rc = retained_mem_write(dev, 0, (const uint8_t *)cal, sizeof(*cal));
if (rc < 0) {
printk("Failed to write retained memory: %d\n", rc);
return rc;
}
return 0;
}
/**
* @brief Restore system state from Backup SRAM
*/
int load_calibration_from_backup_sram(struct sensor_calibration *cal)
{
const struct device *dev = DEVICE_DT_GET(BACKUP_SRAM_NODE);
if (!device_is_ready(dev)) {
printk("Error: retained memory device not ready\n");
return -ENODEV;
}
/* Read data from offset 0 of backup SRAM */
int rc = retained_mem_read(dev, 0, (uint8_t *)cal, sizeof(*cal));
if (rc < 0) {
printk("Failed to read retained memory: %d\n", rc);
return rc;
}
return 0;
}

Verification: Two-Phase Retention Validation

Because exiting STM32 Standby mode generates a system reset, testing cannot be accomplished in a single sequential function call. The verification sequence must be structured into two phases:

  1. Pre-Sleep Write Phase: Write a known test pattern to retained memory, verify completion, and force entry into Standby mode.
  2. Post-Reset Boot Phase: Inspect the reset source flag in main(). If waking from Standby, read the retained memory offset and confirm the pattern is intact.
#include <zephyr/kernel.h>
#include <zephyr/device.h>
#include <zephyr/drivers/retained_mem.h>
#include <zephyr/pm/pm.h>
#include <zephyr/pm/state.h>
#include <stm32f4xx_ll_pwr.h>
#define BACKUP_SRAM_NODE DT_NODELABEL(sram_backup)
#define TEST_MAGIC_PATTERN 0x5A5AA5A5
void enter_deep_sleep_standby(void)
{
const struct device *dev = DEVICE_DT_GET(BACKUP_SRAM_NODE);
uint32_t magic = TEST_MAGIC_PATTERN;
/* Write validation pattern prior to sleep */
int rc = retained_mem_write(dev, 0, (const uint8_t *)&magic, sizeof(magic));
if (rc < 0) {
printk("Pre-sleep write failed!\n");
return;
}
printk("Test pattern 0x%08X written. Entering Standby mode...\n", magic);
/* Force Zephyr PM into Standby */
const struct pm_state_info standby_state = {
.state = PM_STATE_STANDBY,
.substate_id = 0,
};
pm_state_force(0, &standby_state);
}
int main(void)
{
stm32_backup_sram_hw_init();
const struct device *dev = DEVICE_DT_GET(BACKUP_SRAM_NODE);
if (!device_is_ready(dev)) {
printk("Retained memory device initialization failed.\n");
return 0;
}
/* Check if system woke up from Standby mode */
if (LL_PWR_IsActiveFlag_SB()) {
printk("System woke from STANDBY mode. Verifying retention...\n");
/* Clear Standby flag (SBF) */
LL_PWR_ClearFlag_SB();
uint32_t readback = 0;
int rc = retained_mem_read(dev, 0, (uint8_t *)&readback, sizeof(readback));
if (rc == 0 && readback == TEST_MAGIC_PATTERN) {
printk("SUCCESS: Backup SRAM retained pattern 0x%08X across Standby!\n", readback);
} else {
printk("FAILURE: Backup SRAM readback mismatch! Got 0x%08X, expected 0x%08X\n",
readback, TEST_MAGIC_PATTERN);
}
} else {
printk("Normal Power-On Reset detected. Initiating retention test cycle.\n");
k_sleep(K_SECONDS(2));
enter_deep_sleep_standby();
}
return 0;
}

Engineering Trade-offs & Operational Limits

ParameterOn-Chip Backup SRAMExternal SPI FRAM / EEPROMInternal Flash (Emulated EEPROM)
Capacity4 KB32 KB – 1 MB16 KB – 128 KB
Write LatencyDirect bus access (zero wait-states)Bus serialized (SPI / QSPI)Milliseconds per sector erase
EnduranceUnlimited read/write cycles10^14 cycles (FRAM) / 10^6 (EEPROM)10^4 erase cycles (wear-leveling needed)
Power Overhead~1 to 3 µA V_BAT quiescent drawExternal sleep current + I/O leakageFlash pump current spikes during programming
Standby RetentionDependent on V_BAT and BRE flagNon-volatile (true persistent storage)Non-volatile

When selecting backup SRAM for battery-sensitive products:

  • Quiescent Current Consumption: Enabling the backup regulator adds roughly 1 µA to 3 µA of continuous draw to the V_BAT rail. For products targeting 10-year coin cell longevity, budget this continuous draw against self-discharge rates.
  • Minimum V_BAT Operating Voltage: Review the STM32 datasheet for the minimum voltage required to sustain backup SRAM retention (typically 1.65 V to 1.8 V). If a coin cell falls below this threshold, retention is compromised before the RTC ceases ticking.
  • Cold Boot State: On initial power-on (when both V_DD and V_BAT were previously depleted), the backup SRAM contains uninitialized data. Always include a cryptographic checksum (e.g., CRC32) or magic header to detect fresh cold boots.

Summary

Preserving critical state in STM32 microcontrollers during Zephyr deep sleep eliminates external EEPROM costs without sacrificing instant resume capabilities. The resolution to data loss requires understanding that hardware power gating is distinct from RTOS memory abstractions:

  1. Enable CONFIG_RETAINED_MEM=y and CONFIG_RETAINED_MEM_ZEPHYR_RAM=y in Kconfig.
  2. Bind the 4KB backup SRAM address (0x40024000 for STM32F4/F7, 0x38800000 for STM32H7) using the zephyr,retained-ram compatible string.
  3. Assert PWR_CR_DBP, enable the AHB1 bus clock (BKPSRAMEN), and activate the internal low-power backup regulator (PWR_CSR_BRE), waiting for PWR_CSR_BRR before sleep entry.
  4. Structure application logic to accommodate Standby wake-up reset semantics.


References

  1. STMicroelectronics. “STM32F405/415, STM32F407/417, STM32F427/437 and STM32F429/439 Advanced Arm-Based 32-bit MCUs Reference Manual.” RM0090 Rev 20, 2022. https://www.st.com/resource/en/reference_manual/dm00031020-stm32f405415-stm32f407417-stm32f427437-and-stm32f429439-advanced-armbased-32bit-mcus-stmicroelectronics.pdf
  2. STMicroelectronics. “STM32H742, STM32H743/753 and STM32H750 Value Line Reference Manual.” RM0433 Rev 7, 2021. https://www.st.com/resource/en/reference_manual/dm00314099-stm32h742-stm32h743-753-and-stm32h750-value-line-advanced-arm-based-32-bit-mcus-stmicroelectronics.pdf
  3. STMicroelectronics. “STM32F4 and STM32F7 backup SRAM retention in Standby mode.” Application Note AN4621. https://www.st.com/resource/en/application_note/an4621-stm32f4-and-stm32f7-backup-sram-retention-in-standby-mode-stmicroelectronics.pdf
  4. Zephyr Project. “Retained Memory API Documentation.” https://docs.zephyrproject.org/latest/hardware/peripherals/retained_mem.html.
  5. Zephyr Project. “Power Management Service Architecture.” https://docs.zephyrproject.org/latest/services/power_management.html.
  6. Arm Limited. “Arm Cortex-M4 Devices Generic User Guide.” Arm DUI 0553B, 2020. https://support.arm.com/documentation/dui0553/latest/

Frequently Asked Questions

What is backup SRAM retention in STM32 microcontrollers?

Backup SRAM retention is a feature in STM32 microcontrollers that allows a dedicated section of internal SRAM (typically 4KB) to maintain its contents during deep sleep modes such as Standby or VBAT mode, powered by the backup domain when the main VDD supply is off.

Why does STM32 backup SRAM lose data in Standby mode even with VBAT connected?

The backup SRAM requires the internal low-power backup regulator (BRE bit in PWR_CSR) to be explicitly enabled before entering Standby mode. If BRE is disabled, the backup SRAM power rail is cut during Standby regardless of whether VBAT is powered.

How do you enable backup SRAM retention in Zephyr on STM32?

Enable the retained memory subsystem via Kconfig (CONFIG_RETAINED_MEM=y), map the physical backup SRAM block in devicetree using the zephyr,retained-ram compatible binding, enable the backup regulator in hardware, and access the block using the retained_mem API.

Tags

zephyrstm32low-powerbackup-sram

Share


Previous Article
Software UART for Embedded Debugging: GPIO-Based Serial
Jithin Tom

Jithin Tom

A Closer Look at C/C++, RTOS, and Embedded Systems

Related Posts

Zephyr Workqueue API for Deferred Work in Embedded Systems
Zephyr Workqueue API for Deferred Work in Embedded Systems
September 27, 2026
6 min
© 2026, All Rights Reserved.
Powered By Netlyft

Quick Links

Advertise with usAbout UsContact Us

Social Media