aboutsummaryrefslogtreecommitdiff
path: root/embassy-stm32
diff options
context:
space:
mode:
authorDario Nieuwenhuis <[email protected]>2023-10-02 22:03:18 +0200
committerDario Nieuwenhuis <[email protected]>2023-10-02 22:12:50 +0200
commitb856d760f4e47bc2b6176eb6ef3b5cb9cf7eee3d (patch)
tree99177fd6268c53cb7c94ff6bfaa8bbb4584577d6 /embassy-stm32
parenteff61648fef3c50b144bbf9611ef7ee893e2c5f7 (diff)
stm32/rcc: reset backup domain before enabling LSE.
Diffstat (limited to 'embassy-stm32')
-rw-r--r--embassy-stm32/src/rcc/bd.rs93
1 files changed, 47 insertions, 46 deletions
diff --git a/embassy-stm32/src/rcc/bd.rs b/embassy-stm32/src/rcc/bd.rs
index de27130f2..026c89d6a 100644
--- a/embassy-stm32/src/rcc/bd.rs
+++ b/embassy-stm32/src/rcc/bd.rs
@@ -88,6 +88,12 @@ impl BackupDomain {
88 ))] 88 ))]
89 #[allow(dead_code, unused_variables)] 89 #[allow(dead_code, unused_variables)]
90 pub fn configure_ls(clock_source: RtcClockSource, lsi: bool, lse: Option<LseDrive>) { 90 pub fn configure_ls(clock_source: RtcClockSource, lsi: bool, lse: Option<LseDrive>) {
91 match clock_source {
92 RtcClockSource::LSI => assert!(lsi),
93 RtcClockSource::LSE => assert!(&lse.is_some()),
94 _ => {}
95 };
96
91 if lsi { 97 if lsi {
92 #[cfg(rtc_v3u5)] 98 #[cfg(rtc_v3u5)]
93 let csr = crate::pac::RCC.bdcr(); 99 let csr = crate::pac::RCC.bdcr();
@@ -111,6 +117,40 @@ impl BackupDomain {
111 while !csr.read().lsi1rdy() {} 117 while !csr.read().lsi1rdy() {}
112 } 118 }
113 119
120 // backup domain configuration (LSEON, RTCEN, RTCSEL) is kept across resets.
121 // once set, changing it requires a backup domain reset.
122 // first check if the configuration matches what we want.
123
124 // check if it's already enabled and in the source we want.
125 let reg = Self::read();
126 let mut ok = true;
127 ok &= reg.rtcsel() == clock_source;
128 #[cfg(not(rcc_wba))]
129 {
130 ok &= reg.rtcen() == (clock_source != RtcClockSource::NOCLOCK);
131 }
132 ok &= reg.lseon() == lse.is_some();
133 #[cfg(any(rtc_v2f7, rtc_v2h7, rtc_v2l0, rtc_v2l4))]
134 if let Some(lse_drive) = lse {
135 ok &= reg.lsedrv() == lse_drive.into();
136 }
137
138 // if configuration is OK, we're done.
139 if ok {
140 // RTC code assumes backup domain is unlocked
141 Self::modify(|w| {});
142
143 trace!("BDCR ok: {:08x}", Self::read().0);
144 return;
145 }
146
147 // If not OK, reset backup domain and configure it.
148 #[cfg(not(any(rcc_l0, rcc_l1)))]
149 {
150 Self::modify(|w| w.set_bdrst(true));
151 Self::modify(|w| w.set_bdrst(false));
152 }
153
114 if let Some(lse_drive) = lse { 154 if let Some(lse_drive) = lse {
115 Self::modify(|w| { 155 Self::modify(|w| {
116 #[cfg(any(rtc_v2f7, rtc_v2h7, rtc_v2l0, rtc_v2l4))] 156 #[cfg(any(rtc_v2f7, rtc_v2h7, rtc_v2l0, rtc_v2l4))]
@@ -121,56 +161,17 @@ impl BackupDomain {
121 while !Self::read().lserdy() {} 161 while !Self::read().lserdy() {}
122 } 162 }
123 163
124 match clock_source { 164 if clock_source != RtcClockSource::NOCLOCK {
125 RtcClockSource::LSI => assert!(lsi),
126 RtcClockSource::LSE => assert!(&lse.is_some()),
127 _ => {}
128 };
129
130 if clock_source == RtcClockSource::NOCLOCK {
131 // disable it
132 Self::modify(|w| { 165 Self::modify(|w| {
166 #[cfg(any(rtc_v2h7, rtc_v2l4, rtc_v2wb, rtc_v3, rtc_v3u5))]
167 assert!(!w.lsecsson(), "RTC is not compatible with LSE CSS, yet.");
168
133 #[cfg(not(rcc_wba))] 169 #[cfg(not(rcc_wba))]
134 w.set_rtcen(false); 170 w.set_rtcen(true);
135 w.set_rtcsel(clock_source); 171 w.set_rtcsel(clock_source);
136 }); 172 });
137 } else {
138 // check if it's already enabled and in the source we want.
139 let reg = Self::read();
140 let ok = reg.rtcsel() == clock_source;
141 #[cfg(not(rcc_wba))]
142 let ok = ok & reg.rtcen();
143
144 // if not, configure it.
145 if !ok {
146 #[cfg(any(rtc_v2h7, rtc_v2l4, rtc_v2wb, rtc_v3, rtc_v3u5))]
147 assert!(!reg.lsecsson(), "RTC is not compatible with LSE CSS, yet.");
148
149 #[cfg(not(any(rcc_l0, rcc_l1)))]
150 Self::modify(|w| w.set_bdrst(true));
151
152 Self::modify(|w| {
153 // Reset
154 #[cfg(not(any(rcc_l0, rcc_l1)))]
155 w.set_bdrst(false);
156
157 #[cfg(not(rcc_wba))]
158 w.set_rtcen(true);
159 w.set_rtcsel(clock_source);
160
161 // Restore bcdr
162 #[cfg(any(rtc_v2l4, rtc_v2wb, rtc_v3, rtc_v3u5))]
163 w.set_lscosel(reg.lscosel());
164 #[cfg(any(rtc_v2l4, rtc_v2wb, rtc_v3, rtc_v3u5))]
165 w.set_lscoen(reg.lscoen());
166
167 w.set_lseon(reg.lseon());
168
169 #[cfg(any(rtc_v2f0, rtc_v2f7, rtc_v2h7, rtc_v2l4, rtc_v2wb, rtc_v3, rtc_v3u5))]
170 w.set_lsedrv(reg.lsedrv());
171 w.set_lsebyp(reg.lsebyp());
172 });
173 }
174 } 173 }
174
175 trace!("BDCR configured: {:08x}", Self::read().0);
175 } 176 }
176} 177}