diff options
| -rw-r--r-- | embassy-stm32/CHANGELOG.md | 1 | ||||
| -rw-r--r-- | embassy-stm32/build.rs | 21 | ||||
| -rw-r--r-- | embassy-stm32/src/backup_sram.rs | 28 | ||||
| -rw-r--r-- | embassy-stm32/src/lib.rs | 2 | ||||
| -rw-r--r-- | embassy-stm32/src/rcc/bd.rs | 26 | ||||
| -rw-r--r-- | embassy-stm32/src/rcc/mod.rs | 3 | ||||
| -rw-r--r-- | examples/stm32h5/src/bin/backup_sram.rs | 31 |
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 | |||
| 3 | use core::slice; | ||
| 4 | |||
| 5 | use embassy_hal_internal::Peri; | ||
| 6 | |||
| 7 | use crate::_generated::{BKPSRAM_BASE, BKPSRAM_SIZE}; | ||
| 8 | use crate::peripherals::BKPSRAM; | ||
| 9 | |||
| 10 | /// Struct used to initilize backup sram | ||
| 11 | pub struct BackupMemory {} | ||
| 12 | |||
| 13 | impl 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)] |
| 56 | pub mod adc; | 56 | pub mod adc; |
| 57 | #[cfg(backup_sram)] | ||
| 58 | pub mod backup_sram; | ||
| 57 | #[cfg(can)] | 59 | #[cfg(can)] |
| 58 | pub mod can; | 60 | pub 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 @@ | |||
| 1 | use core::sync::atomic::{Ordering, compiler_fence}; | 1 | use core::sync::atomic::{Ordering, compiler_fence}; |
| 2 | 2 | ||
| 3 | use crate::pac::common::{RW, Reg}; | 3 | use crate::pac::common::{RW, Reg}; |
| 4 | #[cfg(backup_sram)] | ||
| 5 | use crate::pac::pwr::vals::Retention; | ||
| 4 | pub use crate::pac::rcc::vals::Rtcsel as RtcClockSource; | 6 | pub use crate::pac::rcc::vals::Rtcsel as RtcClockSource; |
| 5 | use crate::time::Hertz; | 7 | use 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 | ||
| 94 | impl LsConfig { | 98 | impl 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 |
| 49 | pub(crate) static mut REFCOUNT_STOP2: u32 = 0; | 49 | pub(crate) static mut REFCOUNT_STOP2: u32 = 0; |
| 50 | 50 | ||
| 51 | #[cfg(backup_sram)] | ||
| 52 | pub(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 | |||
| 4 | use defmt::*; | ||
| 5 | use embassy_executor::Spawner; | ||
| 6 | use embassy_stm32::Config; | ||
| 7 | use embassy_stm32::backup_sram::BackupMemory; | ||
| 8 | use embassy_time::Timer; | ||
| 9 | use {defmt_rtt as _, panic_probe as _}; | ||
| 10 | |||
| 11 | #[embassy_executor::main] | ||
| 12 | async 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 | } | ||
