aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--embassy-stm32/CHANGELOG.md1
-rw-r--r--embassy-stm32/build.rs21
-rw-r--r--embassy-stm32/src/backup_sram.rs28
-rw-r--r--embassy-stm32/src/lib.rs2
-rw-r--r--embassy-stm32/src/rcc/bd.rs26
-rw-r--r--embassy-stm32/src/rcc/mod.rs3
-rw-r--r--examples/stm32h5/src/bin/backup_sram.rs31
7 files changed, 112 insertions, 0 deletions
diff --git a/embassy-stm32/CHANGELOG.md b/embassy-stm32/CHANGELOG.md
index 2a7a89bc9..f77cf28b1 100644
--- a/embassy-stm32/CHANGELOG.md
+++ b/embassy-stm32/CHANGELOG.md
@@ -37,6 +37,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
37- feat: timer: add ability to set master mode 37- feat: timer: add ability to set master mode
38- fix: sdmmc: don't wait for DBCKEND flag on sdmmc_v2 devices as it never fires (Fixes #4723) 38- fix: sdmmc: don't wait for DBCKEND flag on sdmmc_v2 devices as it never fires (Fixes #4723)
39- fix: usart: fix race condition in ringbuffered usart 39- fix: usart: fix race condition in ringbuffered usart
40- feat: Add backup_sram::init() for H5 devices to access BKPSRAM
40- feat: Add I2C MultiMaster (Slave) support for I2C v1 41- feat: Add I2C MultiMaster (Slave) support for I2C v1
41- feat: stm32/fdcan: add ability to control automatic recovery from bus off ([#4821](https://github.com/embassy-rs/embassy/pull/4821)) 42- feat: stm32/fdcan: add ability to control automatic recovery from bus off ([#4821](https://github.com/embassy-rs/embassy/pull/4821))
42- low-power: update rtc api to allow reconfig 43- low-power: update rtc api to allow reconfig
diff --git a/embassy-stm32/build.rs b/embassy-stm32/build.rs
index eea1acf68..2800c73ac 100644
--- a/embassy-stm32/build.rs
+++ b/embassy-stm32/build.rs
@@ -114,6 +114,8 @@ fn main() {
114 } 114 }
115 }; 115 };
116 116
117 let has_bkpsram = memory.iter().any(|m| m.name == "BKPSRAM");
118
117 // ======== 119 // ========
118 // Generate singletons 120 // Generate singletons
119 121
@@ -124,6 +126,13 @@ fn main() {
124 singletons.push(p.name.to_string()); 126 singletons.push(p.name.to_string());
125 } 127 }
126 128
129 cfgs.declare("backup_sram");
130
131 if has_bkpsram {
132 singletons.push("BKPSRAM".to_string());
133 cfgs.enable("backup_sram")
134 }
135
127 // generate one singleton per peripheral (with many exceptions...) 136 // generate one singleton per peripheral (with many exceptions...)
128 for p in METADATA.peripherals { 137 for p in METADATA.peripherals {
129 if let Some(r) = &p.registers { 138 if let Some(r) = &p.registers {
@@ -1985,6 +1994,18 @@ fn main() {
1985 )); 1994 ));
1986 1995
1987 // ======== 1996 // ========
1997 // Generate backup sram constants
1998 if let Some(m) = memory.iter().find(|m| m.name == "BKPSRAM") {
1999 let bkpsram_base = m.address as usize;
2000 let bkpsram_size = m.size as usize;
2001
2002 g.extend(quote!(
2003 pub const BKPSRAM_BASE: usize = #bkpsram_base;
2004 pub const BKPSRAM_SIZE: usize = #bkpsram_size;
2005 ));
2006 }
2007
2008 // ========
1988 // Generate flash constants 2009 // Generate flash constants
1989 2010
1990 let flash_regions: Vec<&MemoryRegion> = memory 2011 let flash_regions: Vec<&MemoryRegion> = memory
diff --git a/embassy-stm32/src/backup_sram.rs b/embassy-stm32/src/backup_sram.rs
new file mode 100644
index 000000000..31b373c6c
--- /dev/null
+++ b/embassy-stm32/src/backup_sram.rs
@@ -0,0 +1,28 @@
1//! Battary backed SRAM
2
3use core::slice;
4
5use embassy_hal_internal::Peri;
6
7use crate::_generated::{BKPSRAM_BASE, BKPSRAM_SIZE};
8use crate::peripherals::BKPSRAM;
9
10/// Struct used to initilize backup sram
11pub struct BackupMemory {}
12
13impl BackupMemory {
14 /// Setup battery backed sram
15 ///
16 /// Returns slice to sram and whether the sram was retained
17 pub fn new(_backup_sram: Peri<'static, BKPSRAM>) -> (&'static mut [u8], bool) {
18 // Assert bksram has been enabled in rcc
19 assert!(crate::pac::PWR.bdcr().read().bren() == crate::pac::pwr::vals::Retention::PRESERVED);
20
21 unsafe {
22 (
23 slice::from_raw_parts_mut(BKPSRAM_BASE as *mut u8, BKPSRAM_SIZE),
24 critical_section::with(|_| crate::rcc::BKSRAM_RETAINED),
25 )
26 }
27 }
28}
diff --git a/embassy-stm32/src/lib.rs b/embassy-stm32/src/lib.rs
index 85606e7de..e08ab30e6 100644
--- a/embassy-stm32/src/lib.rs
+++ b/embassy-stm32/src/lib.rs
@@ -54,6 +54,8 @@ pub mod timer;
54 54
55#[cfg(adc)] 55#[cfg(adc)]
56pub mod adc; 56pub mod adc;
57#[cfg(backup_sram)]
58pub mod backup_sram;
57#[cfg(can)] 59#[cfg(can)]
58pub mod can; 60pub mod can;
59// FIXME: Cordic driver cause stm32u5a5zj crash 61// FIXME: Cordic driver cause stm32u5a5zj crash
diff --git a/embassy-stm32/src/rcc/bd.rs b/embassy-stm32/src/rcc/bd.rs
index 3b2a10581..5b367c043 100644
--- a/embassy-stm32/src/rcc/bd.rs
+++ b/embassy-stm32/src/rcc/bd.rs
@@ -1,6 +1,8 @@
1use core::sync::atomic::{Ordering, compiler_fence}; 1use core::sync::atomic::{Ordering, compiler_fence};
2 2
3use crate::pac::common::{RW, Reg}; 3use crate::pac::common::{RW, Reg};
4#[cfg(backup_sram)]
5use crate::pac::pwr::vals::Retention;
4pub use crate::pac::rcc::vals::Rtcsel as RtcClockSource; 6pub use crate::pac::rcc::vals::Rtcsel as RtcClockSource;
5use crate::time::Hertz; 7use crate::time::Hertz;
6 8
@@ -89,6 +91,8 @@ pub struct LsConfig {
89 pub rtc: RtcClockSource, 91 pub rtc: RtcClockSource,
90 pub lsi: bool, 92 pub lsi: bool,
91 pub lse: Option<LseConfig>, 93 pub lse: Option<LseConfig>,
94 #[cfg(backup_sram)]
95 pub enable_backup_sram: bool,
92} 96}
93 97
94impl LsConfig { 98impl LsConfig {
@@ -113,6 +117,8 @@ impl LsConfig {
113 peripherals_clocked: false, 117 peripherals_clocked: false,
114 }), 118 }),
115 lsi: false, 119 lsi: false,
120 #[cfg(backup_sram)]
121 enable_backup_sram: false,
116 } 122 }
117 } 123 }
118 124
@@ -121,6 +127,8 @@ impl LsConfig {
121 rtc: RtcClockSource::LSI, 127 rtc: RtcClockSource::LSI,
122 lsi: true, 128 lsi: true,
123 lse: None, 129 lse: None,
130 #[cfg(backup_sram)]
131 enable_backup_sram: false,
124 } 132 }
125 } 133 }
126 134
@@ -129,6 +137,8 @@ impl LsConfig {
129 rtc: RtcClockSource::DISABLE, 137 rtc: RtcClockSource::DISABLE,
130 lsi: false, 138 lsi: false,
131 lse: None, 139 lse: None,
140 #[cfg(backup_sram)]
141 enable_backup_sram: false,
132 } 142 }
133 } 143 }
134} 144}
@@ -193,6 +203,22 @@ impl LsConfig {
193 while !csr.read().lsi1rdy() {} 203 while !csr.read().lsi1rdy() {}
194 } 204 }
195 205
206 // Enable backup regulator for peristent battery backed sram
207 #[cfg(backup_sram)]
208 {
209 unsafe { super::BKSRAM_RETAINED = crate::pac::PWR.bdcr().read().bren() == Retention::PRESERVED };
210
211 crate::pac::PWR.bdcr().modify(|w| {
212 w.set_bren(match self.enable_backup_sram {
213 true => Retention::PRESERVED,
214 false => Retention::LOST,
215 });
216 });
217
218 // Wait for backup regulator voltage to stabilize
219 while self.enable_backup_sram && !crate::pac::PWR.bdsr().read().brrdy() {}
220 }
221
196 // backup domain configuration (LSEON, RTCEN, RTCSEL) is kept across resets. 222 // backup domain configuration (LSEON, RTCEN, RTCSEL) is kept across resets.
197 // once set, changing it requires a backup domain reset. 223 // once set, changing it requires a backup domain reset.
198 // first check if the configuration matches what we want. 224 // first check if the configuration matches what we want.
diff --git a/embassy-stm32/src/rcc/mod.rs b/embassy-stm32/src/rcc/mod.rs
index c817dd4b7..01fa3a475 100644
--- a/embassy-stm32/src/rcc/mod.rs
+++ b/embassy-stm32/src/rcc/mod.rs
@@ -48,6 +48,9 @@ pub(crate) static mut REFCOUNT_STOP1: u32 = 0;
48/// May be read without a critical section 48/// May be read without a critical section
49pub(crate) static mut REFCOUNT_STOP2: u32 = 0; 49pub(crate) static mut REFCOUNT_STOP2: u32 = 0;
50 50
51#[cfg(backup_sram)]
52pub(crate) static mut BKSRAM_RETAINED: bool = false;
53
51#[cfg(not(feature = "_dual-core"))] 54#[cfg(not(feature = "_dual-core"))]
52/// Frozen clock frequencies 55/// Frozen clock frequencies
53/// 56///
diff --git a/examples/stm32h5/src/bin/backup_sram.rs b/examples/stm32h5/src/bin/backup_sram.rs
new file mode 100644
index 000000000..f8db1853e
--- /dev/null
+++ b/examples/stm32h5/src/bin/backup_sram.rs
@@ -0,0 +1,31 @@
1#![no_std]
2#![no_main]
3
4use defmt::*;
5use embassy_executor::Spawner;
6use embassy_stm32::Config;
7use embassy_stm32::backup_sram::BackupMemory;
8use embassy_time::Timer;
9use {defmt_rtt as _, panic_probe as _};
10
11#[embassy_executor::main]
12async fn main(_spawner: Spawner) {
13 let mut config = Config::default();
14 config.rcc.ls.enable_backup_sram = true;
15
16 let p = embassy_stm32::init(config);
17 info!("Started!");
18
19 let (bytes, status) = BackupMemory::new(p.BKPSRAM);
20
21 match status {
22 false => info!("BKPSRAM just enabled"),
23 true => info!("BKPSRAM already enabled"),
24 }
25
26 loop {
27 info!("byte0: {}", bytes[0]);
28 bytes[0] = bytes[0].wrapping_add(1);
29 Timer::after_millis(500).await;
30 }
31}