aboutsummaryrefslogtreecommitdiff
path: root/embassy-stm32/src/rcc/bd.rs
diff options
context:
space:
mode:
Diffstat (limited to 'embassy-stm32/src/rcc/bd.rs')
-rw-r--r--embassy-stm32/src/rcc/bd.rs140
1 files changed, 116 insertions, 24 deletions
diff --git a/embassy-stm32/src/rcc/bd.rs b/embassy-stm32/src/rcc/bd.rs
index 63fc195dd..219be208f 100644
--- a/embassy-stm32/src/rcc/bd.rs
+++ b/embassy-stm32/src/rcc/bd.rs
@@ -1,6 +1,10 @@
1use core::sync::atomic::{compiler_fence, Ordering}; 1#[cfg(not(stm32n6))]
2use core::sync::atomic::{Ordering, compiler_fence};
2 3
3use crate::pac::common::{Reg, RW}; 4#[cfg(not(stm32n6))]
5use crate::pac::common::{RW, Reg};
6#[cfg(backup_sram)]
7use crate::pac::pwr::vals::Retention;
4pub use crate::pac::rcc::vals::Rtcsel as RtcClockSource; 8pub use crate::pac::rcc::vals::Rtcsel as RtcClockSource;
5use crate::time::Hertz; 9use crate::time::Hertz;
6 10
@@ -52,7 +56,7 @@ impl From<LseDrive> for crate::pac::rcc::vals::Lsedrv {
52 } 56 }
53} 57}
54 58
55#[cfg(not(any(rtc_v2_l0, rtc_v2_l1, stm32c0)))] 59#[cfg(not(any(rtc_v2_l0, rtc_v2_l1, stm32c0, stm32n6)))]
56type Bdcr = crate::pac::rcc::regs::Bdcr; 60type Bdcr = crate::pac::rcc::regs::Bdcr;
57#[cfg(any(rtc_v2_l0, rtc_v2_l1))] 61#[cfg(any(rtc_v2_l0, rtc_v2_l1))]
58type Bdcr = crate::pac::rcc::regs::Csr; 62type Bdcr = crate::pac::rcc::regs::Csr;
@@ -62,19 +66,22 @@ type Bdcr = crate::pac::rcc::regs::Csr1;
62#[cfg(any(stm32c0))] 66#[cfg(any(stm32c0))]
63fn unlock() {} 67fn unlock() {}
64 68
65#[cfg(not(any(stm32c0)))] 69#[cfg(not(any(stm32c0, stm32n6)))]
66fn unlock() { 70fn unlock() {
67 #[cfg(any(stm32f0, stm32f1, stm32f2, stm32f3, stm32l0, stm32l1))] 71 #[cfg(any(stm32f0, stm32f1, stm32f2, stm32f3, stm32l0, stm32l1))]
68 let cr = crate::pac::PWR.cr(); 72 let cr = crate::pac::PWR.cr();
69 #[cfg(not(any(stm32f0, stm32f1, stm32f2, stm32f3, stm32l0, stm32l1, stm32u5, stm32h5, stm32wba)))] 73 #[cfg(not(any(
74 stm32f0, stm32f1, stm32f2, stm32f3, stm32l0, stm32l1, stm32u5, stm32h5, stm32wba, stm32n6
75 )))]
70 let cr = crate::pac::PWR.cr1(); 76 let cr = crate::pac::PWR.cr1();
71 #[cfg(any(stm32u5, stm32h5, stm32wba))] 77 #[cfg(any(stm32u5, stm32h5, stm32wba, stm32n6))]
72 let cr = crate::pac::PWR.dbpcr(); 78 let cr = crate::pac::PWR.dbpcr();
73 79
74 cr.modify(|w| w.set_dbp(true)); 80 cr.modify(|w| w.set_dbp(true));
75 while !cr.read().dbp() {} 81 while !cr.read().dbp() {}
76} 82}
77 83
84#[cfg(not(stm32n6))]
78fn bdcr() -> Reg<Bdcr, RW> { 85fn bdcr() -> Reg<Bdcr, RW> {
79 #[cfg(any(rtc_v2_l0, rtc_v2_l1))] 86 #[cfg(any(rtc_v2_l0, rtc_v2_l1))]
80 return crate::pac::RCC.csr(); 87 return crate::pac::RCC.csr();
@@ -89,6 +96,8 @@ pub struct LsConfig {
89 pub rtc: RtcClockSource, 96 pub rtc: RtcClockSource,
90 pub lsi: bool, 97 pub lsi: bool,
91 pub lse: Option<LseConfig>, 98 pub lse: Option<LseConfig>,
99 #[cfg(backup_sram)]
100 pub enable_backup_sram: bool,
92} 101}
93 102
94impl LsConfig { 103impl LsConfig {
@@ -113,6 +122,8 @@ impl LsConfig {
113 peripherals_clocked: false, 122 peripherals_clocked: false,
114 }), 123 }),
115 lsi: false, 124 lsi: false,
125 #[cfg(backup_sram)]
126 enable_backup_sram: false,
116 } 127 }
117 } 128 }
118 129
@@ -121,6 +132,8 @@ impl LsConfig {
121 rtc: RtcClockSource::LSI, 132 rtc: RtcClockSource::LSI,
122 lsi: true, 133 lsi: true,
123 lse: None, 134 lse: None,
135 #[cfg(backup_sram)]
136 enable_backup_sram: false,
124 } 137 }
125 } 138 }
126 139
@@ -129,6 +142,8 @@ impl LsConfig {
129 rtc: RtcClockSource::DISABLE, 142 rtc: RtcClockSource::DISABLE,
130 lsi: false, 143 lsi: false,
131 lse: None, 144 lse: None,
145 #[cfg(backup_sram)]
146 enable_backup_sram: false,
132 } 147 }
133 } 148 }
134} 149}
@@ -140,6 +155,7 @@ impl Default for LsConfig {
140} 155}
141 156
142impl LsConfig { 157impl LsConfig {
158 #[cfg(not(stm32n6))]
143 pub(crate) fn init(&self) -> Option<Hertz> { 159 pub(crate) fn init(&self) -> Option<Hertz> {
144 let rtc_clk = match self.rtc { 160 let rtc_clk = match self.rtc {
145 RtcClockSource::LSI => { 161 RtcClockSource::LSI => {
@@ -175,14 +191,19 @@ impl LsConfig {
175 if self.lsi { 191 if self.lsi {
176 #[cfg(any(stm32u5, stm32h5, stm32wba))] 192 #[cfg(any(stm32u5, stm32h5, stm32wba))]
177 let csr = crate::pac::RCC.bdcr(); 193 let csr = crate::pac::RCC.bdcr();
178 #[cfg(not(any(stm32u5, stm32h5, stm32wba, stm32c0)))] 194 #[cfg(stm32n6)]
195 let csr = crate::pac::RCC.sr();
196 #[cfg(not(any(stm32u5, stm32h5, stm32wba, stm32c0, stm32n6)))]
179 let csr = crate::pac::RCC.csr(); 197 let csr = crate::pac::RCC.csr();
180 #[cfg(any(stm32c0))] 198 #[cfg(stm32c0)]
181 let csr = crate::pac::RCC.csr2(); 199 let csr = crate::pac::RCC.csr2();
182 200
183 #[cfg(not(any(rcc_wb, rcc_wba)))] 201 #[cfg(not(any(rcc_wb, rcc_wba, rcc_n6)))]
184 csr.modify(|w| w.set_lsion(true)); 202 csr.modify(|w| w.set_lsion(true));
185 203
204 #[cfg(rcc_n6)]
205 crate::pac::RCC.cr().modify(|w| w.set_lsion(true));
206
186 #[cfg(any(rcc_wb, rcc_wba))] 207 #[cfg(any(rcc_wb, rcc_wba))]
187 csr.modify(|w| w.set_lsi1on(true)); 208 csr.modify(|w| w.set_lsi1on(true));
188 209
@@ -193,28 +214,77 @@ impl LsConfig {
193 while !csr.read().lsi1rdy() {} 214 while !csr.read().lsi1rdy() {}
194 } 215 }
195 216
217 // Enable backup regulator for peristent battery backed sram
218 #[cfg(backup_sram)]
219 {
220 unsafe { super::BKSRAM_RETAINED = crate::pac::PWR.bdcr().read().bren() == Retention::PRESERVED };
221
222 crate::pac::PWR.bdcr().modify(|w| {
223 w.set_bren(match self.enable_backup_sram {
224 true => Retention::PRESERVED,
225 false => Retention::LOST,
226 });
227 });
228
229 // Wait for backup regulator voltage to stabilize
230 while self.enable_backup_sram && !crate::pac::PWR.bdsr().read().brrdy() {}
231 }
232
196 // backup domain configuration (LSEON, RTCEN, RTCSEL) is kept across resets. 233 // backup domain configuration (LSEON, RTCEN, RTCSEL) is kept across resets.
197 // once set, changing it requires a backup domain reset. 234 // once set, changing it requires a backup domain reset.
198 // first check if the configuration matches what we want. 235 // first check if the configuration matches what we want.
236 // N6 has all the fields spread across multiple registers under RCC.
199 237
200 // check if it's already enabled and in the source we want. 238 // check if it's already enabled and in the source we want.
239 #[cfg(not(rcc_n6))]
201 let reg = bdcr().read(); 240 let reg = bdcr().read();
241 #[cfg(rcc_n6)]
242 let reg = crate::pac::RCC.cr().read();
243 #[cfg(rcc_n6)]
244 let apb4lenr = crate::pac::RCC.apb4lenr().read();
245 #[cfg(rcc_n6)]
246 let ccipr7 = crate::pac::RCC.ccipr7().read();
247 #[cfg(rcc_n6)]
248 let lsecfgr = crate::pac::RCC.lsecfgr().read();
249
202 let mut ok = true; 250 let mut ok = true;
203 ok &= reg.rtcsel() == self.rtc; 251 #[cfg(not(rcc_n6))]
204 #[cfg(not(rcc_wba))] 252 {
253 ok &= reg.rtcsel() == self.rtc;
254 }
255 #[cfg(rcc_n6)]
256 {
257 ok &= ccipr7.rtcsel() == self.rtc;
258 }
259 #[cfg(not(any(rcc_wba, rcc_n6)))]
205 { 260 {
206 ok &= reg.rtcen() == (self.rtc != RtcClockSource::DISABLE); 261 ok &= reg.rtcen() == (self.rtc != RtcClockSource::DISABLE);
207 } 262 }
263 #[cfg(rcc_n6)]
264 {
265 ok &= apb4lenr.rtcen() == (self.rtc != RtcClockSource::DISABLE);
266 }
208 ok &= reg.lseon() == lse_en; 267 ok &= reg.lseon() == lse_en;
209 ok &= reg.lsebyp() == lse_byp; 268 #[cfg(not(rcc_n6))]
269 {
270 ok &= reg.lsebyp() == lse_byp;
271 }
272 #[cfg(rcc_n6)]
273 {
274 ok &= lsecfgr.lsebyp() == lse_byp;
275 }
210 #[cfg(any(rcc_l5, rcc_u5, rcc_wle, rcc_wl5, rcc_wba, rcc_u0))] 276 #[cfg(any(rcc_l5, rcc_u5, rcc_wle, rcc_wl5, rcc_wba, rcc_u0))]
211 if let Some(lse_sysen) = lse_sysen { 277 if let Some(lse_sysen) = lse_sysen {
212 ok &= reg.lsesysen() == lse_sysen; 278 ok &= reg.lsesysen() == lse_sysen;
213 } 279 }
214 #[cfg(not(any(rcc_f1, rcc_f1cl, rcc_f100, rcc_f2, rcc_f4, rcc_f410, rcc_l1)))] 280 #[cfg(not(any(rcc_f1, rcc_f1cl, rcc_f100, rcc_f2, rcc_f4, rcc_f410, rcc_l1, rcc_n6)))]
215 if let Some(lse_drv) = lse_drv { 281 if let Some(lse_drv) = lse_drv {
216 ok &= reg.lsedrv() == lse_drv.into(); 282 ok &= reg.lsedrv() == lse_drv.into();
217 } 283 }
284 #[cfg(rcc_n6)]
285 if let Some(lse_drv) = lse_drv {
286 ok &= lsecfgr.lsedrv() == lse_drv.into();
287 }
218 288
219 // if configuration is OK, we're done. 289 // if configuration is OK, we're done.
220 if ok { 290 if ok {
@@ -223,7 +293,7 @@ impl LsConfig {
223 } 293 }
224 294
225 // If not OK, reset backup domain and configure it. 295 // If not OK, reset backup domain and configure it.
226 #[cfg(not(any(rcc_l0, rcc_l0_v2, rcc_l1, stm32h5, stm32h7rs, stm32c0)))] 296 #[cfg(not(any(rcc_l0, rcc_l0_v2, rcc_l1, stm32h5, stm32h7rs, stm32c0, stm32n6)))]
227 { 297 {
228 bdcr().modify(|w| w.set_bdrst(true)); 298 bdcr().modify(|w| w.set_bdrst(true));
229 bdcr().modify(|w| w.set_bdrst(false)); 299 bdcr().modify(|w| w.set_bdrst(false));
@@ -236,7 +306,7 @@ impl LsConfig {
236 // STM32H503CB/EB/KB/RB device errata - 2.2.8 SRAM2 unduly erased upon a backup domain reset 306 // STM32H503CB/EB/KB/RB device errata - 2.2.8 SRAM2 unduly erased upon a backup domain reset
237 // STM32H562xx/563xx/573xx device errata - 2.2.14 SRAM2 is erased when the backup domain is reset 307 // STM32H562xx/563xx/573xx device errata - 2.2.14 SRAM2 is erased when the backup domain is reset
238 //#[cfg(any(stm32h5, stm32h7rs))] 308 //#[cfg(any(stm32h5, stm32h7rs))]
239 #[cfg(any(stm32h7rs))] 309 #[cfg(any(stm32h7rs, stm32n6))]
240 { 310 {
241 bdcr().modify(|w| w.set_vswrst(true)); 311 bdcr().modify(|w| w.set_vswrst(true));
242 bdcr().modify(|w| w.set_vswrst(false)); 312 bdcr().modify(|w| w.set_vswrst(false));
@@ -248,16 +318,31 @@ impl LsConfig {
248 } 318 }
249 319
250 if lse_en { 320 if lse_en {
251 bdcr().modify(|w| { 321 #[cfg(not(rcc_n6))]
252 #[cfg(not(any(rcc_f1, rcc_f1cl, rcc_f100, rcc_f2, rcc_f4, rcc_f410, rcc_l1)))] 322 {
253 if let Some(lse_drv) = lse_drv { 323 bdcr().modify(|w| {
254 w.set_lsedrv(lse_drv.into()); 324 #[cfg(not(any(rcc_f1, rcc_f1cl, rcc_f100, rcc_f2, rcc_f4, rcc_f410, rcc_l1)))]
255 } 325 if let Some(lse_drv) = lse_drv {
256 w.set_lsebyp(lse_byp); 326 w.set_lsedrv(lse_drv.into());
257 w.set_lseon(true); 327 }
258 }); 328 w.set_lsebyp(lse_byp);
329 w.set_lseon(true);
330 });
331
332 while !bdcr().read().lserdy() {}
333 }
334 #[cfg(rcc_n6)]
335 {
336 crate::pac::RCC.lsecfgr().modify(|w| {
337 if let Some(lse_drv) = lse_drv {
338 w.set_lsedrv(lse_drv.into());
339 }
340 w.set_lsebyp(lse_byp);
341 });
342 crate::pac::RCC.cr().modify(|w| w.set_lseon(true));
259 343
260 while !bdcr().read().lserdy() {} 344 while !crate::pac::RCC.sr().read().lserdy() {}
345 }
261 346
262 #[cfg(any(rcc_l5, rcc_u5, rcc_wle, rcc_wl5, rcc_wba, rcc_u0))] 347 #[cfg(any(rcc_l5, rcc_u5, rcc_wle, rcc_wl5, rcc_wba, rcc_u0))]
263 if let Some(lse_sysen) = lse_sysen { 348 if let Some(lse_sysen) = lse_sysen {
@@ -272,6 +357,7 @@ impl LsConfig {
272 } 357 }
273 358
274 if self.rtc != RtcClockSource::DISABLE { 359 if self.rtc != RtcClockSource::DISABLE {
360 #[cfg(not(rcc_n6))]
275 bdcr().modify(|w| { 361 bdcr().modify(|w| {
276 #[cfg(any(rtc_v2_h7, rtc_v2_l4, rtc_v2_wb, rtc_v3_base, rtc_v3_u5))] 362 #[cfg(any(rtc_v2_h7, rtc_v2_l4, rtc_v2_wb, rtc_v3_base, rtc_v3_u5))]
277 assert!(!w.lsecsson(), "RTC is not compatible with LSE CSS, yet."); 363 assert!(!w.lsecsson(), "RTC is not compatible with LSE CSS, yet.");
@@ -280,6 +366,12 @@ impl LsConfig {
280 w.set_rtcen(true); 366 w.set_rtcen(true);
281 w.set_rtcsel(self.rtc); 367 w.set_rtcsel(self.rtc);
282 }); 368 });
369
370 #[cfg(rcc_n6)]
371 {
372 crate::pac::RCC.ccipr7().modify(|w| w.set_rtcsel(self.rtc));
373 crate::pac::RCC.apb4lenr().modify(|w| w.set_rtcen(true))
374 }
283 } 375 }
284 376
285 trace!("BDCR configured: {:08x}", bdcr().read().0); 377 trace!("BDCR configured: {:08x}", bdcr().read().0);