1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
use core::cell::Cell;
use kernel::common::VolatileCell;
use kernel::hil;
use pm::{self, Clock, PBDClock};
#[repr(C)]
pub struct WdtRegisters {
cr: VolatileCell<u32>,
clr: VolatileCell<u32>,
sr: VolatileCell<u32>,
ier: VolatileCell<u32>,
idr: VolatileCell<u32>,
imr: VolatileCell<u32>,
isr: VolatileCell<u32>,
icr: VolatileCell<u32>,
}
const BASE_ADDRESS: *mut WdtRegisters = 0x400F0C00 as *mut WdtRegisters;
pub struct Wdt {
registers: *mut WdtRegisters,
enabled: Cell<bool>,
}
pub static mut WDT: Wdt = Wdt::new(BASE_ADDRESS);
impl Wdt {
const fn new(base_address: *mut WdtRegisters) -> Wdt {
Wdt {
registers: base_address,
enabled: Cell::new(false),
}
}
fn start(&self, period: usize) {
let regs: &WdtRegisters = unsafe { &*self.registers };
self.enabled.set(true);
unsafe {
pm::enable_clock(Clock::PBD(PBDClock::WDT));
}
let scaler = match period {
0...2 => 7,
3...6 => 8,
7...12 => 9,
13...24 => 10,
25...48 => 11,
49...96 => 12,
97...192 => 13,
193...384 => 14,
385...768 => 15,
769...1536 => 16,
1537...3072 => 17,
3073...6144 => 18,
6145...12288 => 19,
12289...24576 => 20,
24577...49152 => 21,
49153...98304 => 22,
98305...196608 => 23,
196609...393216 => 24,
393217...786432 => 25,
786433...1572864 => 26,
1572865...3145728 => 27,
3145729...6291456 => 28,
6291457...12582912 => 29,
12582913...25165824 => 30,
_ => 31,
};
let control = (1 << 16) |
(scaler << 8) |
(1 << 7) |
(1 << 1) |
(1 << 0);
regs.cr.set((0x55 << 24) | control);
regs.cr.set((0xAA << 24) | control);
}
fn stop(&self) {
let regs: &WdtRegisters = unsafe { &*self.registers };
let control = regs.cr.get() & !0x01;
regs.cr.set((0x55 << 24) | control);
regs.cr.set((0xAA << 24) | control);
unsafe {
pm::disable_clock(Clock::PBD(PBDClock::WDT));
}
self.enabled.set(false);
}
fn tickle(&self) {
let regs: &WdtRegisters = unsafe { &*self.registers };
regs.clr.set((0x55 << 24) | (1 << 0));
regs.clr.set((0xAA << 24) | (1 << 0));
}
}
impl hil::watchdog::Watchdog for Wdt {
fn start(&self, period: usize) {
self.start(period);
}
fn stop(&self) {
self.stop();
}
fn tickle(&self) {
self.tickle();
}
}