Skip to content

Conversation

usbalbin
Copy link

@usbalbin usbalbin commented Sep 14, 2025

I do not have any experience with the structure of embassy-stm32, its build script, linker script etc. Hopefully at the very least this can serve as something to discuss around for how to actually solve something like this :)

With that said, here is the beginning of my attempt at adding support for the battery backed sram available for several of the stm32 families.

Example usage:

#![no_std]
#![no_main]

use defmt::*;
use embassy_executor::Spawner;
use embassy_stm32::pac::pwr::vals::Retention;
use embassy_stm32::{backup_sram, Config};
use embassy_time::Timer;
use {defmt_rtt as _, panic_probe as _};

#[embassy_executor::main]
async fn main(_spawner: Spawner) {
    let mut config = Config::default();
    config.rcc.ls.backup_ram_retention = Retention::PRESERVED;

    let p = embassy_stm32::init(config);
    info!("Started!");

    let (bytes, status) = backup_sram::init(p.BKPSRAM);

    match status {
        backup_sram::Status::BackupRamDisabled => info!("BKPSRAM just enabled"),
        backup_sram::Status::AlreadyActive => info!("BKPSRAM already enabled"),
    }

    loop {
        info!("byte0: {}", bytes[0]);
        bytes[0] = bytes[0].wrapping_add(1);
        Timer::after_millis(500).await;
    }
}
First (no longer representative) attempt: ```rust #[repr(C)] struct MyStruct { foo: u32, }
// This will be run the first time to set the defaults and on struct layout missmatch
let fn_to_setup_defaults = |_reason: ReasonForDataReset| MyStruct { foo: 42 };

// Here we get a mutable reference to the value stored in battery backed ram
let x: &'static mut MyStruct = backup_sram::init::<MyStruct>(p.BACKUP_RAM, fn_to_setup_defaults);

loop {
    x.foo += 1; // These writes will persist resets and loss of vcc
    defmt::info!("I have ran {} iterations since I was programmed/battery was inserted", x.foo);
}
```
**see [examples/stm32h5/src/bin/backup_sram.rs](https://github.com/embassy-rs/embassy/pull/4663/files#diff-f103015bff8cb3773f1339f98ea4d0e2f99385e9486dfdfafa3a6e0cb97d7bef) instead**

@usbalbin usbalbin mentioned this pull request Sep 15, 2025
@Dirbaio
Copy link
Member

Dirbaio commented Sep 15, 2025

nice! a few tips:

  • it'd be better to add the the address+size of the backup sram to stm32-data here, so we can then use it from embassy-stm32 without massive cfg spam. https://github.com/embassy-rs/stm32-data/blob/main/stm32-data-gen/src/memory.rs
  • it's simpler to just offer raw byte access. Instead of unsafe trait Storable and checksums I'd just offer the user &mut [u8] (if the hardware allows it, otherwise read/write fns could work), and let the user take care of serialization/checksumming themselves. This way is less opinionated, it allows the user to do more things that wouldn't be possible with this "store struct, load struct" api.

@usbalbin
Copy link
Author

it'd be better to add the the address+size of the backup sram to stm32-data here, so we can then use it from embassy-stm32 without massive cfg spam. https://github.com/embassy-rs/stm32-data/blob/main/stm32-data-gen/src/memory.rs

Thanks! Something like this? embassy-rs/stm32-data#671

it's simpler to just offer raw byte access [...]

Fair enough :)

Comment on lines 207 to 226
// Enable backup regulator for peristent battery backed sram
#[cfg(rcc_h5)]
crate::pac::PWR.bdcr().modify(|w| w.set_bren(self.backup_ram_retention));

#[cfg(rcc_h5)]
if self.backup_ram_retention == Retention::PRESERVED {
// Wait for backup regulator voltage to stabilize
while !crate::pac::PWR.bdsr().read().brrdy() {}
}
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you want this in this file or should it be in backup_sram.rs?

Also, related question, I think it would be nice to let the user know if the retention was already enabled(SRAM contains data since last run) or if not. I think that would probably be easier if this was done as part of backup_sram::init()?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

think it would be nice to let the user know if the retention was already enabled

Done using WAS_BKPSRAM_ALREADY_POWERED_BY_BATTERY

@usbalbin
Copy link
Author

I will try to test in the near future.

In the mean time, what do you think of this now?

@usbalbin
Copy link
Author

This has now been tested on a custom board with an stm32h523ret with a clock battery

@usbalbin usbalbin marked this pull request as ready for review September 30, 2025 20:13
@usbalbin
Copy link
Author

usbalbin commented Oct 1, 2025

@Dirbaio, is this better? Also let me know and I'll rebase and clean up the history

use core::sync::atomic::{compiler_fence, Ordering};

#[cfg(backup_sram)]
use stm32_metapac::pwr::vals::Retention;
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since this is exposed in the config, do you want this reexported or exposed as a new type?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants