2023-08-27 16:07:34 +02:00
|
|
|
#[derive(Copy, Clone, Debug, PartialEq)]
|
|
|
|
#[repr(u8)]
|
2023-08-27 16:12:04 +02:00
|
|
|
#[allow(dead_code)]
|
2023-08-27 16:07:34 +02:00
|
|
|
pub enum RtcClockSource {
|
|
|
|
/// 00: No clock
|
|
|
|
NoClock = 0b00,
|
|
|
|
/// 01: LSE oscillator clock used as RTC clock
|
|
|
|
LSE = 0b01,
|
|
|
|
/// 10: LSI oscillator clock used as RTC clock
|
|
|
|
LSI = 0b10,
|
|
|
|
/// 11: HSE oscillator clock divided by 32 used as RTC clock
|
|
|
|
HSE = 0b11,
|
|
|
|
}
|
|
|
|
|
2023-08-27 22:01:09 +02:00
|
|
|
#[cfg(not(any(rtc_v2l0, rtc_v2l1)))]
|
|
|
|
type Bdcr = crate::pac::rcc::regs::Bdcr;
|
|
|
|
|
|
|
|
#[cfg(any(rtc_v2l0, rtc_v2l1))]
|
|
|
|
type Bdcr = crate::pac::rcc::regs::Csr;
|
|
|
|
|
2023-08-27 16:12:04 +02:00
|
|
|
#[allow(dead_code)]
|
2023-08-27 16:07:34 +02:00
|
|
|
pub struct BackupDomain {}
|
|
|
|
|
|
|
|
impl BackupDomain {
|
|
|
|
#[cfg(any(
|
2023-08-27 22:01:09 +02:00
|
|
|
rtc_v2f0, rtc_v2f2, rtc_v2f3, rtc_v2f4, rtc_v2f7, rtc_v2h7, rtc_v2l0, rtc_v2l1, rtc_v2l4, rtc_v2wb, rtc_v3,
|
|
|
|
rtc_v3u5
|
2023-08-27 16:07:34 +02:00
|
|
|
))]
|
2023-08-27 16:12:04 +02:00
|
|
|
#[allow(dead_code)]
|
2023-08-27 22:01:09 +02:00
|
|
|
fn modify<R>(f: impl FnOnce(&mut Bdcr) -> R) -> R {
|
2023-08-27 16:07:34 +02:00
|
|
|
#[cfg(any(rtc_v2f2, rtc_v2f3, rtc_v2l1))]
|
|
|
|
let cr = crate::pac::PWR.cr();
|
2023-08-27 22:01:09 +02:00
|
|
|
#[cfg(any(rtc_v2f4, rtc_v2f7, rtc_v2h7, rtc_v2l4, rtc_v2wb, rtc_v3, rtc_v3u5))]
|
2023-08-27 16:07:34 +02:00
|
|
|
let cr = crate::pac::PWR.cr1();
|
|
|
|
|
|
|
|
// TODO: Missing from PAC for l0 and f0?
|
2023-08-27 22:01:09 +02:00
|
|
|
#[cfg(not(any(rtc_v2f0, rtc_v2l0, rtc_v3u5)))]
|
2023-08-27 16:07:34 +02:00
|
|
|
{
|
2023-08-27 22:01:09 +02:00
|
|
|
cr.modify(|w| w.set_dbp(true));
|
|
|
|
while !cr.read().dbp() {}
|
2023-08-27 16:07:34 +02:00
|
|
|
}
|
|
|
|
|
2023-08-27 22:01:09 +02:00
|
|
|
crate::pac::RCC.bdcr().modify(|w| f(w))
|
2023-08-27 16:07:34 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg(any(
|
2023-08-27 22:01:09 +02:00
|
|
|
rtc_v2f0, rtc_v2f2, rtc_v2f3, rtc_v2f4, rtc_v2f7, rtc_v2h7, rtc_v2l0, rtc_v2l1, rtc_v2l4, rtc_v2wb, rtc_v3,
|
|
|
|
rtc_v3u5
|
2023-08-27 16:07:34 +02:00
|
|
|
))]
|
2023-08-27 16:12:04 +02:00
|
|
|
#[allow(dead_code)]
|
2023-08-27 22:01:09 +02:00
|
|
|
fn read() -> Bdcr {
|
2023-08-27 16:07:34 +02:00
|
|
|
#[cfg(any(rtc_v2l0, rtc_v2l1))]
|
2023-08-27 22:01:09 +02:00
|
|
|
let r = crate::pac::RCC.csr().read();
|
2023-08-27 16:07:34 +02:00
|
|
|
|
2023-08-27 22:01:09 +02:00
|
|
|
#[cfg(not(any(rtc_v2l0, rtc_v2l1)))]
|
|
|
|
let r = crate::pac::RCC.bdcr().read();
|
2023-08-27 16:07:34 +02:00
|
|
|
|
2023-08-27 22:01:09 +02:00
|
|
|
r
|
2023-08-27 16:07:34 +02:00
|
|
|
}
|
|
|
|
|
2023-08-27 22:01:09 +02:00
|
|
|
#[cfg(any(
|
|
|
|
rtc_v2f0, rtc_v2f2, rtc_v2f3, rtc_v2f4, rtc_v2f7, rtc_v2h7, rtc_v2l0, rtc_v2l1, rtc_v2l4, rtc_v2wb, rtc_v3,
|
|
|
|
rtc_v3u5
|
|
|
|
))]
|
2023-08-27 16:12:04 +02:00
|
|
|
#[allow(dead_code)]
|
2023-08-27 16:07:34 +02:00
|
|
|
pub fn set_rtc_clock_source(clock_source: RtcClockSource) {
|
|
|
|
let clock_source = clock_source as u8;
|
2023-08-27 22:01:09 +02:00
|
|
|
#[cfg(any(
|
|
|
|
all(not(any(rtc_v3, rtc_v3u5)), not(rtc_v2wb)),
|
|
|
|
all(any(rtc_v3, rtc_v3u5), not(any(rcc_wl5, rcc_wle)))
|
|
|
|
))]
|
2023-08-27 16:07:34 +02:00
|
|
|
let clock_source = crate::pac::rcc::vals::Rtcsel::from_bits(clock_source);
|
|
|
|
|
2023-08-27 22:01:09 +02:00
|
|
|
#[cfg(not(rtc_v2wb))]
|
|
|
|
Self::modify(|w| {
|
2023-08-27 16:07:34 +02:00
|
|
|
// Select RTC source
|
|
|
|
w.set_rtcsel(clock_source);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg(any(
|
|
|
|
rtc_v2f0, rtc_v2f2, rtc_v2f3, rtc_v2f4, rtc_v2f7, rtc_v2h7, rtc_v2l0, rtc_v2l1, rtc_v2l4, rtc_v2wb
|
|
|
|
))]
|
2023-08-27 16:12:04 +02:00
|
|
|
#[allow(dead_code)]
|
2023-08-27 16:07:34 +02:00
|
|
|
pub fn enable_rtc() {
|
2023-08-27 22:01:09 +02:00
|
|
|
let reg = Self::read();
|
2023-08-27 16:07:34 +02:00
|
|
|
|
|
|
|
#[cfg(any(rtc_v2h7, rtc_v2l4, rtc_v2wb))]
|
|
|
|
assert!(!reg.lsecsson(), "RTC is not compatible with LSE CSS, yet.");
|
|
|
|
|
|
|
|
if !reg.rtcen() {
|
|
|
|
#[cfg(not(any(rtc_v2l0, rtc_v2l1, rtc_v2f2)))]
|
2023-08-27 22:01:09 +02:00
|
|
|
Self::modify(|w| w.set_bdrst(true));
|
2023-08-27 16:07:34 +02:00
|
|
|
|
2023-08-27 22:01:09 +02:00
|
|
|
Self::modify(|w| {
|
2023-08-27 16:07:34 +02:00
|
|
|
// Reset
|
|
|
|
#[cfg(not(any(rtc_v2l0, rtc_v2l1)))]
|
|
|
|
w.set_bdrst(false);
|
|
|
|
|
|
|
|
w.set_rtcen(true);
|
|
|
|
w.set_rtcsel(reg.rtcsel());
|
|
|
|
|
|
|
|
// Restore bcdr
|
|
|
|
#[cfg(any(rtc_v2l4, rtc_v2wb))]
|
|
|
|
w.set_lscosel(reg.lscosel());
|
|
|
|
#[cfg(any(rtc_v2l4, rtc_v2wb))]
|
|
|
|
w.set_lscoen(reg.lscoen());
|
|
|
|
|
|
|
|
w.set_lseon(reg.lseon());
|
|
|
|
|
|
|
|
#[cfg(any(rtc_v2f0, rtc_v2f7, rtc_v2h7, rtc_v2l4, rtc_v2wb))]
|
|
|
|
w.set_lsedrv(reg.lsedrv());
|
|
|
|
w.set_lsebyp(reg.lsebyp());
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg(any(rtc_v3, rtc_v3u5))]
|
2023-08-27 16:12:04 +02:00
|
|
|
#[allow(dead_code)]
|
2023-08-27 16:07:34 +02:00
|
|
|
pub fn enable_rtc() {
|
2023-08-27 22:01:09 +02:00
|
|
|
let reg = Self::read();
|
2023-08-27 16:07:34 +02:00
|
|
|
assert!(!reg.lsecsson(), "RTC is not compatible with LSE CSS, yet.");
|
|
|
|
|
|
|
|
if !reg.rtcen() {
|
2023-08-27 22:01:09 +02:00
|
|
|
Self::modify(|w| w.set_bdrst(true));
|
2023-08-27 16:07:34 +02:00
|
|
|
|
2023-08-27 22:01:09 +02:00
|
|
|
Self::modify(|w| {
|
2023-08-27 16:07:34 +02:00
|
|
|
w.set_bdrst(false);
|
|
|
|
|
|
|
|
w.set_rtcen(true);
|
|
|
|
w.set_rtcsel(reg.rtcsel());
|
|
|
|
|
|
|
|
// Restore bcdr
|
|
|
|
w.set_lscosel(reg.lscosel());
|
|
|
|
w.set_lscoen(reg.lscoen());
|
|
|
|
|
|
|
|
w.set_lseon(reg.lseon());
|
|
|
|
w.set_lsedrv(reg.lsedrv());
|
|
|
|
w.set_lsebyp(reg.lsebyp());
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|