Skip to content

Commit 2c220a5

Browse files
committed
optimize watchdog
1 parent 9fed54e commit 2c220a5

File tree

2 files changed

+26
-14
lines changed

2 files changed

+26
-14
lines changed

CHANGELOG.md

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,15 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
99

1010
### Changed
1111

12-
- enable `defmt` feature for VSCode
13-
- `set_alarm` takes `Into<AlarmDay>`
12+
- enable `defmt` feature for VSCode, `set_alarm` takes `Into<AlarmDay>` [#660]
13+
- Optimize watchdog setup calculation [#657]
1414

1515
### Fixed
1616

17-
- Compilation with `defmt` feature enabled
17+
- Compilation with `defmt` feature enabled
18+
19+
[#657]: https://github.com/stm32-rs/stm32f4xx-hal/pull/657
20+
[#660]: https://github.com/stm32-rs/stm32f4xx-hal/pull/660
1821

1922
## [v0.16.1] - 2023-06-24
2023

src/watchdog.rs

Lines changed: 20 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -23,14 +23,16 @@ impl fmt::Debug for IndependentWatchdog {
2323
}
2424
}
2525

26-
const MAX_PR: u8 = 0b110;
26+
const LSI_KHZ: u32 = 32;
27+
const MAX_PR: u32 = 0b110;
2728
const MAX_RL: u16 = 0xFFF;
2829
const KR_ACCESS: u16 = 0x5555;
2930
const KR_RELOAD: u16 = 0xAAAA;
3031
const KR_START: u16 = 0xCCCC;
3132

3233
impl IndependentWatchdog {
33-
/// Wrap and start the watchdog
34+
/// Creates a new `IndependentWatchDog` without starting it. Call `start` to start the watchdog.
35+
/// See `WatchdogEnable` and `Watchdog` for more info.
3436
pub fn new(iwdg: IWDG) -> Self {
3537
IndependentWatchdog { iwdg }
3638
}
@@ -40,15 +42,22 @@ impl IndependentWatchdog {
4042
dbgmcu.apb1_fz.modify(|_, w| w.dbg_iwdg_stop().bit(stop));
4143
}
4244

43-
fn setup(&self, timeout_ms: u32) {
44-
let mut pr = 0;
45-
while pr < MAX_PR && Self::timeout_period(pr, MAX_RL) < timeout_ms {
46-
pr += 1;
47-
}
45+
/// Sets the watchdog timer timout period. Max: 32768 ms
46+
fn setup(&self, timeout_ms: MilliSeconds) {
47+
assert!(timeout_ms.ticks() < (1 << 15), "Watchdog timeout to high");
48+
let pr = match timeout_ms.ticks() {
49+
t if t == 0 => 0b000, // <= (MAX_PR + 1) * 4 / LSI_KHZ => 0b000,
50+
t if t <= (MAX_PR + 1) * 8 / LSI_KHZ => 0b001,
51+
t if t <= (MAX_PR + 1) * 16 / LSI_KHZ => 0b010,
52+
t if t <= (MAX_PR + 1) * 32 / LSI_KHZ => 0b011,
53+
t if t <= (MAX_PR + 1) * 64 / LSI_KHZ => 0b100,
54+
t if t <= (MAX_PR + 1) * 128 / LSI_KHZ => 0b101,
55+
_ => 0b110,
56+
};
4857

4958
let max_period = Self::timeout_period(pr, MAX_RL);
5059
let max_rl = u32::from(MAX_RL);
51-
let rl = (timeout_ms * max_rl / max_period).min(max_rl) as u16;
60+
let rl = (timeout_ms.ticks() * max_rl / max_period).min(max_rl) as u16;
5261

5362
self.access_registers(|iwdg| {
5463
iwdg.pr.modify(|_, w| w.pr().bits(pr));
@@ -72,7 +81,7 @@ impl IndependentWatchdog {
7281

7382
/// pr: Prescaler divider bits, rl: reload value
7483
///
75-
/// Returns ms
84+
/// Returns timeout period in ms
7685
fn timeout_period(pr: u8, rl: u16) -> u32 {
7786
let divider: u32 = match pr {
7887
0b000 => 4,
@@ -85,7 +94,7 @@ impl IndependentWatchdog {
8594
0b111 => 256,
8695
_ => unreachable!(),
8796
};
88-
(u32::from(rl) + 1) * divider / 32
97+
(u32::from(rl) + 1) * divider / LSI_KHZ
8998
}
9099

91100
fn access_registers<A, F: FnMut(&IWDG) -> A>(&self, mut f: F) -> A {
@@ -99,7 +108,7 @@ impl IndependentWatchdog {
99108
}
100109

101110
pub fn start(&mut self, period: MilliSeconds) {
102-
self.setup(period.ticks());
111+
self.setup(period);
103112

104113
self.iwdg.kr.write(|w| unsafe { w.key().bits(KR_START) });
105114
}

0 commit comments

Comments
 (0)