Skip to content

Commit 798705b

Browse files
committed
Fix RTC selection of frequency for LSI and HSE
So far, Rtc::select_frequency did not take into account other frequency than LSE_HERTZ, that was valid only for LSE that has 32.768 kHz. For LSI, that has 40 kHz, and HSE, that may have arbitrary frequency in a given range, the frequency was selected based on wrong RTC frequency.
1 parent 773836d commit 798705b

File tree

1 file changed

+38
-44
lines changed

1 file changed

+38
-44
lines changed

src/rtc.rs

+38-44
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ use crate::time::{Hertz, Hz};
88

99
use core::convert::Infallible;
1010
use core::marker::PhantomData;
11+
use fugit::RateExtU32;
1112

1213
// The LSE runs at at 32 768 hertz unless an external clock is provided
1314
const LSE_HERTZ: Hertz = Hz(32_768);
@@ -44,6 +45,7 @@ pub enum RestoredOrNewRtc<CS> {
4445

4546
pub struct Rtc<CS = RtcClkLse> {
4647
regs: RTC,
48+
frequency: Hertz,
4749
_clock_source: PhantomData<CS>,
4850
}
4951

@@ -64,20 +66,12 @@ impl Rtc<RtcClkLse> {
6466
[`restore_or_new`](Rtc::<RtcClkLse>::restore_or_new) instead.
6567
*/
6668
pub fn new(regs: RTC, bkp: &mut BackupDomain) -> Self {
67-
let mut result = Rtc {
68-
regs,
69-
_clock_source: PhantomData,
70-
};
69+
let mut result = Self::init(regs);
7170

7271
Self::enable_rtc(bkp);
7372

7473
// Set the prescaler to make it count up once every second.
75-
let prl = LSE_HERTZ.raw() - 1;
76-
assert!(prl < 1 << 20);
77-
result.perform_write(|s| {
78-
s.regs.prlh.write(|w| unsafe { w.bits(prl >> 16) });
79-
s.regs.prll.write(|w| unsafe { w.bits(prl as u16 as u32) });
80-
});
74+
result.select_frequency(1u32.Hz());
8175

8276
result
8377
}
@@ -100,10 +94,15 @@ impl Rtc<RtcClkLse> {
10094
if !Self::is_enabled() {
10195
RestoredOrNewRtc::New(Rtc::new(regs, bkp))
10296
} else {
103-
RestoredOrNewRtc::Restored(Rtc {
104-
regs,
105-
_clock_source: PhantomData,
106-
})
97+
RestoredOrNewRtc::Restored(Self::init(regs))
98+
}
99+
}
100+
101+
fn init(regs: RTC) -> Self {
102+
Self {
103+
regs,
104+
frequency: LSE_HERTZ,
105+
_clock_source: PhantomData,
107106
}
108107
}
109108

@@ -150,20 +149,12 @@ impl Rtc<RtcClkLsi> {
150149
[`restore_or_new_lsi`](Rtc::<RtcClkLsi>::restore_or_new_lsi) instead.
151150
*/
152151
pub fn new_lsi(regs: RTC, bkp: &mut BackupDomain) -> Self {
153-
let mut result = Rtc {
154-
regs,
155-
_clock_source: PhantomData,
156-
};
152+
let mut result = Self::init(regs);
157153

158154
Self::enable_rtc(bkp);
159155

160156
// Set the prescaler to make it count up once every second.
161-
let prl = LSI_HERTZ.raw() - 1;
162-
assert!(prl < 1 << 20);
163-
result.perform_write(|s| {
164-
s.regs.prlh.write(|w| unsafe { w.bits(prl >> 16) });
165-
s.regs.prll.write(|w| unsafe { w.bits(prl as u16 as u32) });
166-
});
157+
result.select_frequency(1u32.Hz());
167158

168159
result
169160
}
@@ -174,10 +165,15 @@ impl Rtc<RtcClkLsi> {
174165
if !Rtc::<RtcClkLsi>::is_enabled() {
175166
RestoredOrNewRtc::New(Rtc::new_lsi(regs, bkp))
176167
} else {
177-
RestoredOrNewRtc::Restored(Rtc {
178-
regs,
179-
_clock_source: PhantomData,
180-
})
168+
RestoredOrNewRtc::Restored(Self::init(regs))
169+
}
170+
}
171+
172+
fn init(regs: RTC) -> Self {
173+
Self {
174+
regs,
175+
frequency: LSI_HERTZ,
176+
_clock_source: PhantomData,
181177
}
182178
}
183179

@@ -228,20 +224,12 @@ impl Rtc<RtcClkHseDiv128> {
228224
[`restore_or_new_hse`](Rtc::<RtcClkHseDiv128>::restore_or_new_hse) instead.
229225
*/
230226
pub fn new_hse(regs: RTC, bkp: &mut BackupDomain, hse: Hertz) -> Self {
231-
let mut result = Rtc {
232-
regs,
233-
_clock_source: PhantomData,
234-
};
227+
let mut result = Self::init(regs, hse);
235228

236229
Self::enable_rtc(bkp);
237230

238231
// Set the prescaler to make it count up once every second.
239-
let prl = hse.raw() / 128 - 1;
240-
assert!(prl < 1 << 20);
241-
result.perform_write(|s| {
242-
s.regs.prlh.write(|w| unsafe { w.bits(prl >> 16) });
243-
s.regs.prll.write(|w| unsafe { w.bits(prl as u16 as u32) });
244-
});
232+
result.select_frequency(1u32.Hz());
245233

246234
result
247235
}
@@ -256,10 +244,15 @@ impl Rtc<RtcClkHseDiv128> {
256244
if !Self::is_enabled() {
257245
RestoredOrNewRtc::New(Rtc::new_hse(regs, bkp, hse))
258246
} else {
259-
RestoredOrNewRtc::Restored(Rtc {
260-
regs,
261-
_clock_source: PhantomData,
262-
})
247+
RestoredOrNewRtc::Restored(Self::init(regs, hse))
248+
}
249+
}
250+
251+
fn init(regs: RTC, hse: Hertz) -> Self {
252+
Self {
253+
regs,
254+
frequency: hse / 128,
255+
_clock_source: PhantomData,
263256
}
264257
}
265258

@@ -294,9 +287,10 @@ impl<CS> Rtc<CS> {
294287
pub fn select_frequency(&mut self, frequency: Hertz) {
295288
// The manual says that the zero value for the prescaler is not recommended, thus the
296289
// minimum division factor is 2 (prescaler + 1)
297-
assert!(frequency <= LSE_HERTZ / 2);
290+
assert!(frequency <= self.frequency / 2);
298291

299-
let prescaler = LSE_HERTZ / frequency - 1;
292+
let prescaler = self.frequency / frequency - 1;
293+
assert!(prescaler < 1 << 20);
300294
self.perform_write(|s| {
301295
s.regs.prlh.write(|w| unsafe { w.bits(prescaler >> 16) });
302296
s.regs

0 commit comments

Comments
 (0)