1use crate::pac::INT;
6use crate::pac_crate::{Reg, RegisterSpec};
7use core::marker::PhantomData;
8use core::ptr::{read_volatile, write_volatile};
9
10pub use crate::pac::interrupt::InterruptSource;
14
15pub use crate::pac::interrupt::Interrupt;
19
20#[derive(Debug, Copy, Clone)]
22pub struct PriorityConvertError;
23
24#[derive(Copy, Clone, Debug)]
26pub struct Ipl(u8);
27
28impl TryFrom<u8> for Ipl {
29 type Error = PriorityConvertError;
30
31 fn try_from(ipl: u8) -> Result<Self, Self::Error> {
32 if ipl <= 7 {
33 Ok(Ipl(ipl))
34 } else {
35 Err(PriorityConvertError)
36 }
37 }
38}
39
40impl From<Ipl> for u8 {
41 fn from(ipl: Ipl) -> Self {
42 ipl.0
43 }
44}
45
46pub const IPL0: Ipl = Ipl(0);
48pub const IPL1: Ipl = Ipl(1);
50pub const IPL2: Ipl = Ipl(2);
52pub const IPL3: Ipl = Ipl(3);
54pub const IPL4: Ipl = Ipl(4);
56pub const IPL5: Ipl = Ipl(5);
58pub const IPL6: Ipl = Ipl(6);
60pub const IPL7: Ipl = Ipl(7);
62
63#[derive(Copy, Clone, Debug)]
65pub struct Isl(u8);
66
67impl TryFrom<u8> for Isl {
68 type Error = PriorityConvertError;
69
70 fn try_from(isl: u8) -> Result<Self, Self::Error> {
71 if isl <= 3 {
72 Ok(Isl(isl))
73 } else {
74 Err(PriorityConvertError)
75 }
76 }
77}
78
79impl From<Isl> for u8 {
80 fn from(isl: Isl) -> Self {
81 isl.0
82 }
83}
84
85pub const ISL0: Isl = Isl(0);
87pub const ISL1: Isl = Isl(1);
89pub const ISL2: Isl = Isl(2);
91pub const ISL3: Isl = Isl(3);
93
94pub struct Int {
96 _int: PhantomData<INT>,
97}
98
99impl Int {
100 pub fn new(int: INT) -> Int {
105 int.intconset.write(|w| w.mvec().bit(true));
106 Int { _int: PhantomData }
107 }
108
109 fn bitaddr<REG: RegisterSpec>(s: InterruptSource, breg: &Reg<REG>) -> (*mut u32, u32) {
110 let regndx = (s as usize) / 32;
111 let mask = 1 << ((s as usize) % 32);
112 let base = breg as *const _ as usize;
113 let reg = (base + regndx * 0x10) as *mut u32;
114 (reg, mask)
115 }
116
117 pub fn ei(&self, s: InterruptSource) {
119 let (reg, mask) = Self::bitaddr(s, unsafe { &(*INT::ptr()).iec0set });
120 unsafe { write_volatile(reg, mask) };
121 }
122
123 pub fn di(&self, s: InterruptSource) {
125 let (reg, mask) = Self::bitaddr(s, unsafe { &(*INT::ptr()).iec0clr });
126 unsafe { write_volatile(reg, mask) };
127 }
128
129 pub fn is_ie(&self, s: InterruptSource) -> bool {
131 let (reg, mask) = Self::bitaddr(s, unsafe { &(*INT::ptr()).iec0 });
132 unsafe { read_volatile(reg) & mask != 0 }
133 }
134
135 pub fn get_if(&self, s: InterruptSource) -> bool {
137 let (reg, mask) = Self::bitaddr(s, unsafe { &(*INT::ptr()).ifs0 });
138 unsafe { read_volatile(reg) & mask != 0 }
139 }
140
141 pub fn clear_if(&self, s: InterruptSource) {
144 let (reg, mask) = Self::bitaddr(s, unsafe { &(*INT::ptr()).ifs0clr });
145 unsafe { write_volatile(reg, mask) };
146 }
147
148 pub fn set_if(&self, s: InterruptSource) {
150 let (reg, mask) = Self::bitaddr(s, unsafe { &(*INT::ptr()).ifs0set });
151 unsafe { write_volatile(reg, mask) };
152 }
153
154 fn byteaddr<REG: RegisterSpec>(iv: Interrupt, breg: &Reg<REG>) -> (*mut u32, usize) {
155 let regndx = (iv as usize) / 4;
156 let bytepos = ((iv as usize) % 4) * 8;
157 let base = breg as *const _ as usize;
158 let reg = (base + regndx * 0x10) as *mut u32;
159 (reg, bytepos)
160 }
161
162 pub fn set_ipl(&self, iv: Interrupt, ipl: Ipl) {
164 let (reg, bytepos) = Self::byteaddr(iv, unsafe { &(*INT::ptr()).ipc0 });
165 let bitpos = bytepos + 2;
166 let mask = 0x07 << bitpos;
167 unsafe { write_volatile(reg, read_volatile(reg) & !mask | ((ipl.0 as u32) << bitpos)) };
168 }
169
170 pub fn ipl(&self, iv: Interrupt) -> Ipl {
172 let (reg, bytepos) = Self::byteaddr(iv, unsafe { &(*INT::ptr()).ipc0 });
173 let bitpos = bytepos + 2;
174 unsafe { Ipl((read_volatile(reg) >> bitpos) as u8 & 0x07) }
175 }
176
177 pub fn set_isl(&self, iv: Interrupt, isl: Isl) {
179 let (reg, bitpos) = Self::byteaddr(iv, unsafe { &(*INT::ptr()).ipc0 });
180 let mask = 0x03 << bitpos;
181 unsafe { write_volatile(reg, read_volatile(reg) & !mask | ((isl.0 as u32) << bitpos)) };
182 }
183
184 pub fn isl(&self, iv: Interrupt) -> Isl {
186 let (reg, bitpos) = Self::byteaddr(iv, unsafe { &(*INT::ptr()).ipc0 });
187 unsafe { Isl((read_volatile(reg) >> bitpos) as u8 & 0x03) }
188 }
189}