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
use kernel::common::volatile_cell::VolatileCell;
#[repr(C)]
struct Registers {
iser: [VolatileCell<u32>; 8],
_reserved1: [u32; 24],
icer: [VolatileCell<u32>; 8],
_reserved2: [u32; 24],
ispr: [VolatileCell<u32>; 8],
_reserved3: [VolatileCell<u32>; 24],
icpr: [VolatileCell<u32>; 8],
}
const BASE_ADDRESS: *mut Registers = 0xe000e100 as *mut Registers;
pub unsafe fn clear_all_pending() {
let nvic: &Registers = &*BASE_ADDRESS;
for icpr in nvic.icpr.iter() {
icpr.set(!0)
}
}
pub unsafe fn enable_all() {
let nvic: &Registers = &*BASE_ADDRESS;
for icer in nvic.iser.iter() {
icer.set(!0)
}
}
pub unsafe fn disable_all() {
let nvic: &Registers = &*BASE_ADDRESS;
for icer in nvic.icer.iter() {
icer.set(!0)
}
}
pub unsafe fn next_pending() -> Option<u32> {
let nvic: &Registers = &*BASE_ADDRESS;
for (block, ispr) in nvic.ispr.iter().enumerate() {
let ispr = ispr.get();
if ispr != 0 {
let bit = ispr.trailing_zeros();
return Some(block as u32 * 32 + bit);
}
}
None
}
pub unsafe fn has_pending() -> bool {
let nvic: &Registers = &*BASE_ADDRESS;
nvic.ispr.iter().fold(0, |i, ispr| ispr.get() | i) != 0
}
pub struct Nvic(u32);
impl Nvic {
pub const unsafe fn new(idx: u32) -> Nvic {
Nvic(idx)
}
pub fn enable(&self) {
let nvic: &Registers = unsafe { &*BASE_ADDRESS };
let idx = self.0 as usize;
nvic.iser[idx / 32].set(1 << (self.0 & 31));
}
pub fn disable(&self) {
let nvic: &Registers = unsafe { &*BASE_ADDRESS };
let idx = self.0 as usize;
nvic.icer[idx / 32].set(1 << (self.0 & 31));
}
pub fn clear_pending(&self) {
let nvic: &Registers = unsafe { &*BASE_ADDRESS };
let idx = self.0 as usize;
nvic.icpr[idx / 32].set(1 << (self.0 & 31));
}
}