Merge pull request #1844 from xoviat/rtc
stm32/rtc: autocompute prescalers
This commit is contained in:
commit
56351cedcb
@ -499,6 +499,7 @@ pub(crate) unsafe fn init(config: Config) {
|
||||
pllsai: None,
|
||||
|
||||
rtc: rtc,
|
||||
rtc_hse: None,
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -78,8 +78,12 @@ pub struct Clocks {
|
||||
pub adc: Option<Hertz>,
|
||||
|
||||
#[cfg(any(rcc_wb, rcc_f4, rcc_f410))]
|
||||
/// Set only if the lsi or lse is configured
|
||||
/// Set only if the lsi or lse is configured, indicates stop is supported
|
||||
pub rtc: Option<Hertz>,
|
||||
|
||||
#[cfg(any(rcc_wb, rcc_f4, rcc_f410))]
|
||||
/// Set if the hse is configured, indicates stop is not supported
|
||||
pub rtc_hse: Option<Hertz>,
|
||||
}
|
||||
|
||||
#[cfg(feature = "low-power")]
|
||||
|
@ -271,6 +271,7 @@ pub(crate) fn compute_clocks(config: &Config) -> Clocks {
|
||||
apb1_tim: apb1_tim_clk,
|
||||
apb2_tim: apb2_tim_clk,
|
||||
rtc: rtc_clk,
|
||||
rtc_hse: None,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -12,6 +12,7 @@ use embassy_sync::blocking_mutex::Mutex;
|
||||
pub use self::datetime::{DateTime, DayOfWeek, Error as DateTimeError};
|
||||
use crate::rcc::bd::BackupDomain;
|
||||
pub use crate::rcc::RtcClockSource;
|
||||
use crate::time::Hertz;
|
||||
|
||||
/// refer to AN4759 to compare features of RTC2 and RTC3
|
||||
#[cfg_attr(any(rtc_v1), path = "v1.rs")]
|
||||
@ -84,47 +85,23 @@ impl core::ops::Sub for RtcInstant {
|
||||
|
||||
/// RTC Abstraction
|
||||
pub struct Rtc {
|
||||
rtc_config: RtcConfig,
|
||||
#[cfg(feature = "low-power")]
|
||||
stop_time: Mutex<CriticalSectionRawMutex, Cell<Option<RtcInstant>>>,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, PartialEq)]
|
||||
pub struct RtcConfig {
|
||||
/// Asynchronous prescaler factor
|
||||
/// This is the asynchronous division factor:
|
||||
/// ck_apre frequency = RTCCLK frequency/(PREDIV_A+1)
|
||||
/// ck_apre drives the subsecond register
|
||||
async_prescaler: u8,
|
||||
/// Synchronous prescaler factor
|
||||
/// This is the synchronous division factor:
|
||||
/// ck_spre frequency = ck_apre frequency/(PREDIV_S+1)
|
||||
/// ck_spre must be 1Hz
|
||||
sync_prescaler: u16,
|
||||
/// The subsecond counter frequency; default is 256
|
||||
///
|
||||
/// A high counter frequency may impact stop power consumption
|
||||
pub frequency: Hertz,
|
||||
}
|
||||
|
||||
impl Default for RtcConfig {
|
||||
/// LSI with prescalers assuming 32.768 kHz.
|
||||
/// Raw sub-seconds in 1/256.
|
||||
fn default() -> Self {
|
||||
RtcConfig {
|
||||
async_prescaler: 127,
|
||||
sync_prescaler: 255,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl RtcConfig {
|
||||
/// Set the asynchronous prescaler of RTC config
|
||||
pub fn async_prescaler(mut self, prescaler: u8) -> Self {
|
||||
self.async_prescaler = prescaler;
|
||||
self
|
||||
}
|
||||
|
||||
/// Set the synchronous prescaler of RTC config
|
||||
pub fn sync_prescaler(mut self, prescaler: u16) -> Self {
|
||||
self.sync_prescaler = prescaler;
|
||||
self
|
||||
RtcConfig { frequency: Hertz(256) }
|
||||
}
|
||||
}
|
||||
|
||||
@ -147,23 +124,37 @@ impl Default for RtcCalibrationCyclePeriod {
|
||||
|
||||
impl Rtc {
|
||||
pub fn new(_rtc: impl Peripheral<P = RTC>, rtc_config: RtcConfig) -> Self {
|
||||
#[cfg(any(rcc_wb, rcc_f4, rcc_f410))]
|
||||
use crate::rcc::get_freqs;
|
||||
|
||||
RTC::enable_peripheral_clk();
|
||||
BackupDomain::enable_rtc();
|
||||
|
||||
#[cfg(not(feature = "low-power"))]
|
||||
let mut rtc_struct = Self { rtc_config };
|
||||
|
||||
#[cfg(feature = "low-power")]
|
||||
let mut rtc_struct = Self {
|
||||
rtc_config,
|
||||
let mut this = Self {
|
||||
#[cfg(feature = "low-power")]
|
||||
stop_time: Mutex::const_new(CriticalSectionRawMutex::new(), Cell::new(None)),
|
||||
};
|
||||
|
||||
BackupDomain::enable_rtc();
|
||||
#[cfg(any(rcc_wb, rcc_f4, rcc_f410))]
|
||||
let freqs = unsafe { get_freqs() };
|
||||
|
||||
rtc_struct.configure(rtc_config);
|
||||
rtc_struct.rtc_config = rtc_config;
|
||||
// Load the clock frequency from the rcc mod, if supported
|
||||
#[cfg(any(rcc_wb, rcc_f4, rcc_f410))]
|
||||
let frequency = match freqs.rtc {
|
||||
Some(hertz) => hertz,
|
||||
None => freqs.rtc_hse.unwrap(),
|
||||
};
|
||||
|
||||
rtc_struct
|
||||
// Assume the default value, if not supported
|
||||
#[cfg(not(any(rcc_wb, rcc_f4, rcc_f410)))]
|
||||
let frequency = Hertz(32_768);
|
||||
|
||||
let async_psc = ((frequency.0 / rtc_config.frequency.0) - 1) as u8;
|
||||
let sync_psc = (rtc_config.frequency.0 - 1) as u16;
|
||||
|
||||
this.configure(async_psc, sync_psc);
|
||||
|
||||
this
|
||||
}
|
||||
|
||||
/// Set the datetime to a new value.
|
||||
@ -228,10 +219,6 @@ impl Rtc {
|
||||
})
|
||||
}
|
||||
|
||||
pub fn get_config(&self) -> RtcConfig {
|
||||
self.rtc_config
|
||||
}
|
||||
|
||||
pub const BACKUP_REGISTER_COUNT: usize = RTC::BACKUP_REGISTER_COUNT;
|
||||
|
||||
/// Read content of the backup register.
|
||||
|
@ -1,6 +1,6 @@
|
||||
use stm32_metapac::rtc::vals::{Init, Osel, Pol};
|
||||
|
||||
use super::{sealed, RtcConfig};
|
||||
use super::sealed;
|
||||
use crate::pac::rtc::Rtc;
|
||||
use crate::peripherals::RTC;
|
||||
use crate::rtc::sealed::Instance;
|
||||
@ -154,7 +154,7 @@ impl super::Rtc {
|
||||
|
||||
/// Applies the RTC config
|
||||
/// It this changes the RTC clock source the time will be reset
|
||||
pub(super) fn configure(&mut self, rtc_config: RtcConfig) {
|
||||
pub(super) fn configure(&mut self, async_psc: u8, sync_psc: u16) {
|
||||
self.write(true, |rtc| {
|
||||
rtc.cr().modify(|w| {
|
||||
#[cfg(rtc_v2f2)]
|
||||
@ -166,8 +166,8 @@ impl super::Rtc {
|
||||
});
|
||||
|
||||
rtc.prer().modify(|w| {
|
||||
w.set_prediv_s(rtc_config.sync_prescaler);
|
||||
w.set_prediv_a(rtc_config.async_prescaler);
|
||||
w.set_prediv_s(sync_psc);
|
||||
w.set_prediv_a(async_psc);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
use stm32_metapac::rtc::vals::{Calp, Calw16, Calw8, Fmt, Init, Key, Osel, Pol, TampalrmPu, TampalrmType};
|
||||
|
||||
use super::{sealed, RtcCalibrationCyclePeriod, RtcConfig};
|
||||
use super::{sealed, RtcCalibrationCyclePeriod};
|
||||
use crate::pac::rtc::Rtc;
|
||||
use crate::peripherals::RTC;
|
||||
use crate::rtc::sealed::Instance;
|
||||
@ -8,7 +8,7 @@ use crate::rtc::sealed::Instance;
|
||||
impl super::Rtc {
|
||||
/// Applies the RTC config
|
||||
/// It this changes the RTC clock source the time will be reset
|
||||
pub(super) fn configure(&mut self, rtc_config: RtcConfig) {
|
||||
pub(super) fn configure(&mut self, async_psc: u8, sync_psc: u16) {
|
||||
self.write(true, |rtc| {
|
||||
rtc.cr().modify(|w| {
|
||||
w.set_fmt(Fmt::TWENTYFOURHOUR);
|
||||
@ -17,8 +17,8 @@ impl super::Rtc {
|
||||
});
|
||||
|
||||
rtc.prer().modify(|w| {
|
||||
w.set_prediv_s(rtc_config.sync_prescaler);
|
||||
w.set_prediv_a(rtc_config.async_prescaler);
|
||||
w.set_prediv_s(sync_psc);
|
||||
w.set_prediv_a(async_psc);
|
||||
});
|
||||
|
||||
// TODO: configuration for output pins
|
||||
|
Loading…
Reference in New Issue
Block a user