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
use r3_core::kernel::{
interrupt::{InterruptHandlerFn, InterruptNum, InterruptPriority},
raw_cfg::{CfgInterruptLine, InterruptLineDescriptor},
};
use crate::{cfg::CfgBuilder, interrupt, utils::Frozen, KernelTraits};
unsafe impl<Traits: KernelTraits> const CfgInterruptLine for CfgBuilder<Traits> {
fn interrupt_line_define<Properties: ~const r3_core::bag::Bag>(
&mut self,
InterruptLineDescriptor {
phantom: _,
line,
priority,
start,
enabled,
}: InterruptLineDescriptor<Self::System>,
_properties: Properties,
) {
self.interrupt_lines.push(CfgBuilderInterruptLine {
line,
priority,
start,
enabled,
});
}
}
#[doc(hidden)]
#[derive(Debug, Clone, Copy)]
pub struct CfgBuilderInterruptLine {
line: InterruptNum,
priority: Option<InterruptPriority>,
start: Option<InterruptHandlerFn>,
enabled: bool,
}
impl CfgBuilderInterruptLine {
pub const fn to_init(&self) -> interrupt::InterruptLineInit {
interrupt::InterruptLineInit {
line: self.line,
priority: self.priority.unwrap_or(0),
flags: {
let mut f = 0;
if self.priority.is_some() {
f |= interrupt::InterruptLineInitFlags::SET_PRIORITY.bits();
}
if self.enabled {
f |= interrupt::InterruptLineInitFlags::ENABLE.bits();
}
interrupt::InterruptLineInitFlags::from_bits_truncate(f)
},
}
}
}
#[doc(hidden)]
pub const fn interrupt_handler_table_len(
interrupt_lines: &[Frozen<CfgBuilderInterruptLine>],
) -> usize {
let mut num = 0;
let mut i = 0;
while i < interrupt_lines.len() {
let k = interrupt_lines[i].get().line + 1;
if k > num {
num = k;
}
i += 1;
}
num
}
#[doc(hidden)]
pub const fn interrupt_handler_table<const LEN: usize>(
interrupt_lines: &[Frozen<CfgBuilderInterruptLine>],
) -> [Option<InterruptHandlerFn>; LEN] {
let mut table = [None; LEN];
let mut i = 0;
while i < interrupt_lines.len() {
if let CfgBuilderInterruptLine {
line,
start: Some(start),
..
} = interrupt_lines[i].get()
{
assert!(
table[line].is_none(),
"an interrupt line's handler is registered twice"
);
table[line] = Some(start);
}
i += 1;
}
table
}
#[derive(Debug)]
pub struct InterruptHandlerTable {
#[doc(hidden)]
pub storage: &'static [Option<InterruptHandlerFn>],
}
impl InterruptHandlerTable {
#[inline]
pub const fn get(&self, line: InterruptNum) -> Option<InterruptHandlerFn> {
self.storage.get(line).copied().flatten()
}
}