diff options
| author | Dario Nieuwenhuis <[email protected]> | 2023-10-02 22:03:18 +0200 |
|---|---|---|
| committer | Dario Nieuwenhuis <[email protected]> | 2023-10-02 22:12:50 +0200 |
| commit | b856d760f4e47bc2b6176eb6ef3b5cb9cf7eee3d (patch) | |
| tree | 99177fd6268c53cb7c94ff6bfaa8bbb4584577d6 /embassy-stm32 | |
| parent | eff61648fef3c50b144bbf9611ef7ee893e2c5f7 (diff) | |
stm32/rcc: reset backup domain before enabling LSE.
Diffstat (limited to 'embassy-stm32')
| -rw-r--r-- | embassy-stm32/src/rcc/bd.rs | 93 |
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 | } |
