stm32g0xx_hal/
watchdog.rs1use 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 self.iwdg.kr.write(|w| unsafe { w.key().bits(0xcccc) });
31
32 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}