Skip to content

Commit

Permalink
Merge pull request #657 from stm32-rs/watchdog
Browse files Browse the repository at this point in the history
optimize watchdog
  • Loading branch information
burrbull authored Jun 27, 2023
2 parents 9fed54e + 2c220a5 commit 0fd321e
Show file tree
Hide file tree
Showing 2 changed files with 26 additions and 14 deletions.
9 changes: 6 additions & 3 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,15 @@ and this project adheres to [Semantic Versioning](http://semver.org/).

### Changed

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

### Fixed

- Compilation with `defmt` feature enabled
- Compilation with `defmt` feature enabled

[#657]: https://github.com/stm32-rs/stm32f4xx-hal/pull/657
[#660]: https://github.com/stm32-rs/stm32f4xx-hal/pull/660

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

Expand Down
31 changes: 20 additions & 11 deletions src/watchdog.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,14 +23,16 @@ impl fmt::Debug for IndependentWatchdog {
}
}

const MAX_PR: u8 = 0b110;
const LSI_KHZ: u32 = 32;
const MAX_PR: u32 = 0b110;
const MAX_RL: u16 = 0xFFF;
const KR_ACCESS: u16 = 0x5555;
const KR_RELOAD: u16 = 0xAAAA;
const KR_START: u16 = 0xCCCC;

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

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

let max_period = Self::timeout_period(pr, MAX_RL);
let max_rl = u32::from(MAX_RL);
let rl = (timeout_ms * max_rl / max_period).min(max_rl) as u16;
let rl = (timeout_ms.ticks() * max_rl / max_period).min(max_rl) as u16;

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

/// pr: Prescaler divider bits, rl: reload value
///
/// Returns ms
/// Returns timeout period in ms
fn timeout_period(pr: u8, rl: u16) -> u32 {
let divider: u32 = match pr {
0b000 => 4,
Expand All @@ -85,7 +94,7 @@ impl IndependentWatchdog {
0b111 => 256,
_ => unreachable!(),
};
(u32::from(rl) + 1) * divider / 32
(u32::from(rl) + 1) * divider / LSI_KHZ
}

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

pub fn start(&mut self, period: MilliSeconds) {
self.setup(period.ticks());
self.setup(period);

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

0 comments on commit 0fd321e

Please sign in to comment.