esp_hal/interrupt/
mod.rs
1#![doc = crate::before_snippet!()]
33use core::ops::BitAnd;
75
76#[cfg(riscv)]
77pub use self::riscv::*;
78#[cfg(xtensa)]
79pub use self::xtensa::*;
80
81#[cfg(riscv)]
82mod riscv;
83#[cfg(xtensa)]
84mod xtensa;
85
86pub mod software;
87
88#[cfg(xtensa)]
89#[no_mangle]
90extern "C" fn EspDefaultHandler(_level: u32, _interrupt: crate::peripherals::Interrupt) {
91 panic!("Unhandled level {} interrupt: {:?}", _level, _interrupt);
92}
93
94#[cfg(riscv)]
95#[no_mangle]
96extern "C" fn EspDefaultHandler(_interrupt: crate::peripherals::Interrupt) {
97 panic!("Unhandled interrupt: {:?}", _interrupt);
98}
99
100pub const DEFAULT_INTERRUPT_HANDLER: InterruptHandler = InterruptHandler::new(
102 unsafe { core::mem::transmute::<*const (), extern "C" fn()>(EspDefaultHandler as *const ()) },
103 Priority::min(),
104);
105
106pub trait InterruptConfigurable: crate::private::Sealed {
109 #[cfg_attr(
110 not(multi_core),
111 doc = "Registers an interrupt handler for the peripheral."
112 )]
113 #[cfg_attr(
114 multi_core,
115 doc = "Registers an interrupt handler for the peripheral on the current core."
116 )]
117 #[doc = ""]
118 fn set_interrupt_handler(&mut self, handler: InterruptHandler);
125}
126
127#[cfg_attr(
129 multi_core,
130 doc = "**Note**: Interrupts are handled on the core they were setup on, if a driver is initialized on core 0, and moved to core 1, core 0 will still handle the interrupt."
131)]
132#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
133#[cfg_attr(feature = "defmt", derive(defmt::Format))]
134pub struct InterruptHandler {
135 f: extern "C" fn(),
136 prio: Priority,
137}
138
139impl InterruptHandler {
140 pub const fn new(f: extern "C" fn(), prio: Priority) -> Self {
143 Self { f, prio }
144 }
145
146 #[inline]
148 pub fn handler(&self) -> extern "C" fn() {
149 self.f
150 }
151
152 #[inline]
154 pub fn priority(&self) -> Priority {
155 self.prio
156 }
157}
158
159#[cfg(large_intr_status)]
160const STATUS_WORDS: usize = 3;
161
162#[cfg(very_large_intr_status)]
163const STATUS_WORDS: usize = 4;
164
165#[cfg(not(any(large_intr_status, very_large_intr_status)))]
166const STATUS_WORDS: usize = 2;
167
168#[derive(Clone, Copy, Default, Debug)]
170pub struct InterruptStatus {
171 status: [u32; STATUS_WORDS],
172}
173
174impl InterruptStatus {
175 const fn empty() -> Self {
176 InterruptStatus {
177 status: [0u32; STATUS_WORDS],
178 }
179 }
180
181 #[cfg(large_intr_status)]
182 const fn from(w0: u32, w1: u32, w2: u32) -> Self {
183 Self {
184 status: [w0, w1, w2],
185 }
186 }
187
188 #[cfg(very_large_intr_status)]
189 const fn from(w0: u32, w1: u32, w2: u32, w3: u32) -> Self {
190 Self {
191 status: [w0, w1, w2, w3],
192 }
193 }
194
195 #[cfg(not(any(large_intr_status, very_large_intr_status)))]
196 const fn from(w0: u32, w1: u32) -> Self {
197 Self { status: [w0, w1] }
198 }
199
200 pub fn is_set(&self, interrupt: u16) -> bool {
202 (self.status[interrupt as usize / 32] & (1 << (interrupt as u32 % 32))) != 0
203 }
204
205 pub fn set(&mut self, interrupt: u16) {
207 self.status[interrupt as usize / 32] |= 1 << (interrupt as u32 % 32);
208 }
209
210 pub fn iterator(&self) -> InterruptStatusIterator {
212 InterruptStatusIterator {
213 status: *self,
214 idx: 0,
215 }
216 }
217}
218
219impl BitAnd for InterruptStatus {
220 type Output = InterruptStatus;
221
222 fn bitand(self, rhs: Self) -> Self::Output {
223 #[cfg(large_intr_status)]
224 return Self::Output {
225 status: [
226 self.status[0] & rhs.status[0],
227 self.status[1] & rhs.status[1],
228 self.status[2] & rhs.status[2],
229 ],
230 };
231
232 #[cfg(very_large_intr_status)]
233 return Self::Output {
234 status: [
235 self.status[0] & rhs.status[0],
236 self.status[1] & rhs.status[1],
237 self.status[2] & rhs.status[2],
238 self.status[3] & rhs.status[3],
239 ],
240 };
241
242 #[cfg(not(any(large_intr_status, very_large_intr_status)))]
243 return Self::Output {
244 status: [
245 self.status[0] & rhs.status[0],
246 self.status[1] & rhs.status[1],
247 ],
248 };
249 }
250}
251
252pub struct InterruptStatusIterator {
254 status: InterruptStatus,
255 idx: usize,
256}
257
258impl Iterator for InterruptStatusIterator {
259 type Item = u8;
260
261 fn next(&mut self) -> Option<Self::Item> {
262 for i in self.idx..STATUS_WORDS {
263 if self.status.status[i] != 0 {
264 let bit = self.status.status[i].trailing_zeros();
265 self.idx = i;
266 self.status.status[i] &= !1 << bit;
267 return Some((bit + 32 * i as u32) as u8);
268 }
269 }
270 self.idx = usize::MAX;
271 None
272 }
273}