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#[unsafe(no_mangle)]
89extern "C" fn EspDefaultHandler(_interrupt: crate::peripherals::Interrupt) {
90 panic!("Unhandled interrupt: {:?}", _interrupt);
91}
92
93pub const DEFAULT_INTERRUPT_HANDLER: InterruptHandler = InterruptHandler::new(
95 unsafe { core::mem::transmute::<*const (), extern "C" fn()>(EspDefaultHandler as *const ()) },
96 Priority::min(),
97);
98
99pub trait InterruptConfigurable: crate::private::Sealed {
102 #[cfg_attr(
103 not(multi_core),
104 doc = "Registers an interrupt handler for the peripheral."
105 )]
106 #[cfg_attr(
107 multi_core,
108 doc = "Registers an interrupt handler for the peripheral on the current core."
109 )]
110 #[doc = ""]
111 fn set_interrupt_handler(&mut self, handler: InterruptHandler);
118}
119
120#[cfg_attr(
122 multi_core,
123 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."
124)]
125#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
126#[cfg_attr(feature = "defmt", derive(defmt::Format))]
127pub struct InterruptHandler {
128 f: extern "C" fn(),
129 prio: Priority,
130}
131
132impl InterruptHandler {
133 pub const fn new(f: extern "C" fn(), prio: Priority) -> Self {
136 Self { f, prio }
137 }
138
139 #[inline]
141 pub fn handler(&self) -> extern "C" fn() {
142 self.f
143 }
144
145 #[inline]
147 pub fn priority(&self) -> Priority {
148 self.prio
149 }
150}
151
152#[cfg(large_intr_status)]
153const STATUS_WORDS: usize = 3;
154
155#[cfg(very_large_intr_status)]
156const STATUS_WORDS: usize = 4;
157
158#[cfg(not(any(large_intr_status, very_large_intr_status)))]
159const STATUS_WORDS: usize = 2;
160
161#[derive(Clone, Copy, Default, Debug)]
163pub struct InterruptStatus {
164 status: [u32; STATUS_WORDS],
165}
166
167impl InterruptStatus {
168 const fn empty() -> Self {
169 InterruptStatus {
170 status: [0u32; STATUS_WORDS],
171 }
172 }
173
174 #[cfg(large_intr_status)]
175 const fn from(w0: u32, w1: u32, w2: u32) -> Self {
176 Self {
177 status: [w0, w1, w2],
178 }
179 }
180
181 #[cfg(very_large_intr_status)]
182 const fn from(w0: u32, w1: u32, w2: u32, w3: u32) -> Self {
183 Self {
184 status: [w0, w1, w2, w3],
185 }
186 }
187
188 #[cfg(not(any(large_intr_status, very_large_intr_status)))]
189 const fn from(w0: u32, w1: u32) -> Self {
190 Self { status: [w0, w1] }
191 }
192
193 pub fn is_set(&self, interrupt: u8) -> bool {
195 (self.status[interrupt as usize / 32] & (1 << (interrupt % 32))) != 0
196 }
197
198 pub fn set(&mut self, interrupt: u8) {
200 self.status[interrupt as usize / 32] |= 1 << (interrupt % 32);
201 }
202
203 pub fn iterator(&self) -> InterruptStatusIterator {
205 InterruptStatusIterator {
206 status: *self,
207 idx: 0,
208 }
209 }
210}
211
212impl BitAnd for InterruptStatus {
213 type Output = InterruptStatus;
214
215 fn bitand(self, rhs: Self) -> Self::Output {
216 #[cfg(large_intr_status)]
217 return Self::Output {
218 status: [
219 self.status[0] & rhs.status[0],
220 self.status[1] & rhs.status[1],
221 self.status[2] & rhs.status[2],
222 ],
223 };
224
225 #[cfg(very_large_intr_status)]
226 return Self::Output {
227 status: [
228 self.status[0] & rhs.status[0],
229 self.status[1] & rhs.status[1],
230 self.status[2] & rhs.status[2],
231 self.status[3] & rhs.status[3],
232 ],
233 };
234
235 #[cfg(not(any(large_intr_status, very_large_intr_status)))]
236 return Self::Output {
237 status: [
238 self.status[0] & rhs.status[0],
239 self.status[1] & rhs.status[1],
240 ],
241 };
242 }
243}
244
245pub struct InterruptStatusIterator {
247 status: InterruptStatus,
248 idx: usize,
249}
250
251impl Iterator for InterruptStatusIterator {
252 type Item = u8;
253
254 fn next(&mut self) -> Option<Self::Item> {
255 for i in self.idx..STATUS_WORDS {
256 if self.status.status[i] != 0 {
257 let bit = self.status.status[i].trailing_zeros();
258 self.idx = i;
259 self.status.status[i] &= !1 << bit;
260 return Some((bit + 32 * i as u32) as u8);
261 }
262 }
263 self.idx = usize::MAX;
264 None
265 }
266}