stm32g0xx_hal/
watchdog.rs

1use crate::prelude::*;
2use crate::rcc::{Enable, Rcc};
3use crate::stm32::{IWDG, WWDG};
4use crate::time::{Hertz, MicroSecond};
5use hal::watchdog;
6
7pub struct IndependedWatchdog {
8    iwdg: IWDG,
9}
10
11impl IndependedWatchdog {
12    pub fn feed(&mut self) {
13        self.iwdg.kr.write(|w| unsafe { w.key().bits(0xaaaa) });
14    }
15
16    pub fn start(&mut self, period: MicroSecond) {
17        let mut cycles = crate::time::cycles(period, 16_384.Hz());
18        let mut psc = 0;
19        let mut reload = 0;
20        while psc < 6 {
21            reload = cycles;
22            if reload <= 0xfff {
23                break;
24            }
25            psc += 1;
26            cycles /= 2;
27        }
28
29        // Enable watchdog
30        self.iwdg.kr.write(|w| unsafe { w.key().bits(0xcccc) });
31
32        // Enable access to RLR/PR
33        self.iwdg.kr.write(|w| unsafe { w.key().bits(0x5555) });
34
35        self.iwdg.pr.write(|w| unsafe { w.pr().bits(psc) });
36        self.iwdg
37            .rlr
38            .write(|w| unsafe { w.rl().bits(reload as u16) });
39
40        while self.iwdg.sr.read().bits() > 0 {}
41
42        self.iwdg.kr.write(|w| unsafe { w.key().bits(0xaaaa) });
43    }
44}
45
46impl watchdog::Watchdog for IndependedWatchdog {
47    fn feed(&mut self) {
48        self.feed();
49    }
50}
51
52impl watchdog::WatchdogEnable for IndependedWatchdog {
53    type Time = MicroSecond;
54
55    fn start<T>(&mut self, period: T)
56    where
57        T: Into<MicroSecond>,
58    {
59        self.start(period.into())
60    }
61}
62
63pub trait IWDGExt {
64    fn constrain(self) -> IndependedWatchdog;
65}
66
67impl IndependedWatchdog {
68    pub fn release(self) -> IWDG {
69        self.iwdg
70    }
71}
72
73impl IWDGExt for IWDG {
74    fn constrain(self) -> IndependedWatchdog {
75        IndependedWatchdog { iwdg: self }
76    }
77}
78
79pub struct WindowWatchdog {
80    wwdg: WWDG,
81    clk: Hertz,
82}
83
84impl WindowWatchdog {
85    pub fn feed(&mut self) {
86        self.wwdg.cr.write(|w| unsafe { w.t().bits(0xff) });
87    }
88
89    pub fn set_window(&mut self, window: MicroSecond) {
90        let mut cycles = crate::time::cycles(window, self.clk);
91        let mut psc = 0u8;
92        let mut window = 0;
93        while psc < 8 {
94            window = cycles;
95            if window <= 0x40 {
96                break;
97            }
98            psc += 1;
99            cycles /= 2;
100        }
101        assert!(window <= 0x40);
102        self.wwdg
103            .cfr
104            .write(|w| unsafe { w.wdgtb().bits(psc).w().bits(window as u8) });
105    }
106
107    pub fn listen(&mut self) {
108        self.wwdg.cfr.write(|w| w.ewi().set_bit());
109    }
110
111    pub fn unlisten(&mut self) {
112        self.wwdg.cfr.write(|w| w.ewi().clear_bit());
113    }
114
115    pub fn release(self) -> WWDG {
116        self.wwdg
117    }
118
119    pub fn start(&mut self, period: MicroSecond) {
120        self.set_window(period);
121        self.feed();
122        self.wwdg.cr.write(|w| w.wdga().set_bit());
123    }
124}
125
126impl watchdog::Watchdog for WindowWatchdog {
127    fn feed(&mut self) {
128        self.feed();
129    }
130}
131
132impl watchdog::WatchdogEnable for WindowWatchdog {
133    type Time = MicroSecond;
134
135    fn start<T>(&mut self, period: T)
136    where
137        T: Into<MicroSecond>,
138    {
139        self.start(period.into())
140    }
141}
142
143pub trait WWDGExt {
144    fn constrain(self, rcc: &mut Rcc) -> WindowWatchdog;
145}
146
147impl WWDGExt for WWDG {
148    fn constrain(self, rcc: &mut Rcc) -> WindowWatchdog {
149        WWDG::enable(rcc);
150        let clk = rcc.clocks.apb_clk.raw() / 4096;
151        WindowWatchdog {
152            wwdg: self,
153            clk: clk.Hz(),
154        }
155    }
156}