diff --git a/CHANGELOG.md b/CHANGELOG.md index 43acf6e2..e8b3229c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/). - Move from bors/manual merge to GH merge queue - Add tools/check.py python script for local check - Add changelog check on PRs +- `Rtc::restore_or_new`: adds restoring mechanism of running Rtc +- `Rtc::select_frequency`: fix for LSI and HSE, where correct frequency was not selected ## [v0.10.0] - 2022-12-12 diff --git a/src/rtc.rs b/src/rtc.rs index 292fd0f3..56d69bad 100644 --- a/src/rtc.rs +++ b/src/rtc.rs @@ -8,6 +8,7 @@ use crate::time::{Hertz, Hz}; use core::convert::Infallible; use core::marker::PhantomData; +use fugit::RateExtU32; // The LSE runs at at 32 768 hertz unless an external clock is provided const LSE_HERTZ: Hertz = Hz(32_768); @@ -44,6 +45,7 @@ pub enum RestoredOrNewRtc { pub struct Rtc { regs: RTC, + frequency: Hertz, _clock_source: PhantomData, } @@ -64,20 +66,12 @@ impl Rtc { [`restore_or_new`](Rtc::::restore_or_new) instead. */ pub fn new(regs: RTC, bkp: &mut BackupDomain) -> Self { - let mut result = Rtc { - regs, - _clock_source: PhantomData, - }; + let mut result = Self::init(regs); Self::enable_rtc(bkp); // Set the prescaler to make it count up once every second. - let prl = LSE_HERTZ.raw() - 1; - assert!(prl < 1 << 20); - result.perform_write(|s| { - s.regs.prlh.write(|w| unsafe { w.bits(prl >> 16) }); - s.regs.prll.write(|w| unsafe { w.bits(prl as u16 as u32) }); - }); + result.select_frequency(1u32.Hz()); result } @@ -100,10 +94,15 @@ impl Rtc { if !Self::is_enabled() { RestoredOrNewRtc::New(Rtc::new(regs, bkp)) } else { - RestoredOrNewRtc::Restored(Rtc { - regs, - _clock_source: PhantomData, - }) + RestoredOrNewRtc::Restored(Self::init(regs)) + } + } + + fn init(regs: RTC) -> Self { + Self { + regs, + frequency: LSE_HERTZ, + _clock_source: PhantomData, } } @@ -150,20 +149,12 @@ impl Rtc { [`restore_or_new_lsi`](Rtc::::restore_or_new_lsi) instead. */ pub fn new_lsi(regs: RTC, bkp: &mut BackupDomain) -> Self { - let mut result = Rtc { - regs, - _clock_source: PhantomData, - }; + let mut result = Self::init(regs); Self::enable_rtc(bkp); // Set the prescaler to make it count up once every second. - let prl = LSI_HERTZ.raw() - 1; - assert!(prl < 1 << 20); - result.perform_write(|s| { - s.regs.prlh.write(|w| unsafe { w.bits(prl >> 16) }); - s.regs.prll.write(|w| unsafe { w.bits(prl as u16 as u32) }); - }); + result.select_frequency(1u32.Hz()); result } @@ -174,10 +165,15 @@ impl Rtc { if !Rtc::::is_enabled() { RestoredOrNewRtc::New(Rtc::new_lsi(regs, bkp)) } else { - RestoredOrNewRtc::Restored(Rtc { - regs, - _clock_source: PhantomData, - }) + RestoredOrNewRtc::Restored(Self::init(regs)) + } + } + + fn init(regs: RTC) -> Self { + Self { + regs, + frequency: LSI_HERTZ, + _clock_source: PhantomData, } } @@ -228,20 +224,12 @@ impl Rtc { [`restore_or_new_hse`](Rtc::::restore_or_new_hse) instead. */ pub fn new_hse(regs: RTC, bkp: &mut BackupDomain, hse: Hertz) -> Self { - let mut result = Rtc { - regs, - _clock_source: PhantomData, - }; + let mut result = Self::init(regs, hse); Self::enable_rtc(bkp); // Set the prescaler to make it count up once every second. - let prl = hse.raw() / 128 - 1; - assert!(prl < 1 << 20); - result.perform_write(|s| { - s.regs.prlh.write(|w| unsafe { w.bits(prl >> 16) }); - s.regs.prll.write(|w| unsafe { w.bits(prl as u16 as u32) }); - }); + result.select_frequency(1u32.Hz()); result } @@ -256,10 +244,15 @@ impl Rtc { if !Self::is_enabled() { RestoredOrNewRtc::New(Rtc::new_hse(regs, bkp, hse)) } else { - RestoredOrNewRtc::Restored(Rtc { - regs, - _clock_source: PhantomData, - }) + RestoredOrNewRtc::Restored(Self::init(regs, hse)) + } + } + + fn init(regs: RTC, hse: Hertz) -> Self { + Self { + regs, + frequency: hse / 128, + _clock_source: PhantomData, } } @@ -294,9 +287,10 @@ impl Rtc { pub fn select_frequency(&mut self, frequency: Hertz) { // The manual says that the zero value for the prescaler is not recommended, thus the // minimum division factor is 2 (prescaler + 1) - assert!(frequency <= LSE_HERTZ / 2); + assert!(frequency <= self.frequency / 2); - let prescaler = LSE_HERTZ / frequency - 1; + let prescaler = self.frequency / frequency - 1; + assert!(prescaler < 1 << 20); self.perform_write(|s| { s.regs.prlh.write(|w| unsafe { w.bits(prescaler >> 16) }); s.regs