stm32_hal2/
iwdg.rs

1//! Indepdent watchdog
2
3#[cfg(not(any(feature = "h735", feature = "h747cm4", feature = "h747cm7")))]
4use crate::pac::IWDG;
5#[cfg(any(feature = "h735", feature = "h747cm4", feature = "h747cm7"))]
6use crate::pac::IWDG1 as IWDG;
7use crate::{
8    error::{Error, Result},
9    util::bounded_loop,
10};
11
12const IWDG_CLOCK: f32 = 32_000.;
13
14/// Set up (enable), without window option. `timeout` is in seconds.
15/// G4 RM, section 42.3.2
16pub fn setup(timeout: f32) -> Result<()> {
17    unsafe {
18        let regs = &(*IWDG::ptr());
19        // When the window option it is not used, the IWDG can be configured as follows:
20        // 1. Enable the IWDG by writing 0x0000 CCCC in the IWDG key register (IWDG_KR).
21        regs.kr().write(|w| w.bits(0x0000_cccc));
22
23        // 2.Enable register access by writing 0x0000 5555 in the IWDG key register (IWDG_KR).
24        regs.kr().write(|w| w.bits(0x0000_5555));
25
26        // 3. Write the prescaler by programming the IWDG prescaler register (IWDG_PR) from 0 to
27
28        // 32kHz clock.
29        // todo: Hardcoded prescaler of 32. This allows a timeout between 0 and 4.096 seconds.
30        regs.pr().write(|w| w.bits(0b011));
31
32        // 4. Write the IWDG reload register (IWDG_RLR).
33        // A 12-bit value. Assumes a prescaler of 32.
34        let ticks_per_s = IWDG_CLOCK / 32.;
35        let reload_val = (ticks_per_s * timeout) as u16;
36
37        regs.rlr().write(|w| w.bits(reload_val));
38
39        // 5. Wait for the registers to be updated (IWDG_SR = 0x0000 0000).
40        bounded_loop!(regs.sr().read().bits() != 0, Error::RegisterUnchanged);
41
42        // 6. Refresh the counter value with IWDG_RLR (IWDG_KR = 0x0000 AAAA).
43        pet();
44
45        Ok(())
46    }
47}
48
49/// Run this at an interval shorter than the countdown time to prevent a reset.
50pub fn pet() {
51    unsafe {
52        let regs = &(*IWDG::ptr());
53        regs.kr().write(|w| w.bits(0x0000_aaaa));
54    }
55}