Skip to content
This repository was archived by the owner on Feb 13, 2019. It is now read-only.

Commit dd9d6c1

Browse files
committed
implement IWDG
1 parent 044ec7b commit dd9d6c1

File tree

2 files changed

+89
-0
lines changed

2 files changed

+89
-0
lines changed

src/iwdg.rs

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
//! Independent Watchdog
2+
3+
use stm32f103xx::IWDG;
4+
use hal::watchdog::{Watchdog, WatchdogEnable};
5+
6+
use rcc::CSR;
7+
8+
9+
pub struct IndependentWatchdog {
10+
iwdg: IWDG,
11+
}
12+
13+
enum Key {
14+
Feed = 0xAAAA,
15+
Unlock = 0x5555,
16+
Lock = 0x0,
17+
Start = 0xCCCC,
18+
}
19+
20+
impl IndependentWatchdog {
21+
/// Wrap the watchdog peripheral into a struct that implements the
22+
/// embedded_hal `Watchdog` and `WatchdogEnable` traits.
23+
///
24+
/// Pass a `rcc.csr` to initialize the LSI clock.
25+
pub fn new(iwdg: IWDG, csr: &mut CSR) -> Self {
26+
csr.enable_lsi();
27+
28+
IndependentWatchdog { iwdg }
29+
}
30+
31+
fn write_key(&self, key: Key) {
32+
self.iwdg.kr.write(|w| unsafe { w.key().bits(key as u16) });
33+
}
34+
35+
fn unlocked<F, R>(&mut self, f: F) -> R
36+
where
37+
F: FnOnce(&mut IWDG) -> R,
38+
{
39+
self.write_key(Key::Unlock);
40+
let r = f(&mut self.iwdg);
41+
self.write_key(Key::Lock);
42+
r
43+
}
44+
45+
fn configure(&mut self, prescaler: u8, reload: u16) {
46+
self.unlocked(|iwdg| {
47+
iwdg.pr.write(|w| unsafe {
48+
w.pr().bits(prescaler)
49+
});
50+
iwdg.rlr.write(|w| unsafe {
51+
w.rl().bits(reload)
52+
});
53+
});
54+
}
55+
56+
/// Maximum watchdog timeout is 26.214 seconds
57+
pub const MAX_TIMEOUT_MS: u32 = 26214;
58+
59+
const MAX_RELOAD: u16 = 0xFFF;
60+
const MAX_PRESCALE: u8 = 6;
61+
}
62+
63+
impl WatchdogEnable for IndependentWatchdog {
64+
type Time = u32;
65+
66+
fn start<T>(&mut self, period: T) where T: Into<Self::Time> {
67+
let timeout_ms = period.into();
68+
69+
let mut max_timeout_ms = Self::MAX_TIMEOUT_MS;
70+
assert!(timeout_ms <= max_timeout_ms);
71+
72+
let mut prescaler = Self::MAX_PRESCALE;
73+
while prescaler > 0 && timeout_ms <= max_timeout_ms / 2 {
74+
prescaler -= 1;
75+
max_timeout_ms /= 2;
76+
}
77+
78+
let reload = ((Self::MAX_RELOAD as u32) * timeout_ms / max_timeout_ms) as u16;
79+
self.configure(prescaler, reload);
80+
self.write_key(Key::Start);
81+
}
82+
}
83+
84+
impl Watchdog for IndependentWatchdog {
85+
fn feed(&mut self) {
86+
self.write_key(Key::Feed);
87+
}
88+
}

src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,3 +61,4 @@ pub mod serial;
6161
pub mod spi;
6262
pub mod time;
6363
pub mod timer;
64+
pub mod iwdg;

0 commit comments

Comments
 (0)