aboutsummaryrefslogtreecommitdiff
path: root/embassy-nxp/src/pint.rs
diff options
context:
space:
mode:
Diffstat (limited to 'embassy-nxp/src/pint.rs')
-rw-r--r--embassy-nxp/src/pint.rs440
1 files changed, 440 insertions, 0 deletions
diff --git a/embassy-nxp/src/pint.rs b/embassy-nxp/src/pint.rs
new file mode 100644
index 000000000..3313f91a6
--- /dev/null
+++ b/embassy-nxp/src/pint.rs
@@ -0,0 +1,440 @@
1//! Pin Interrupt module.
2use core::cell::RefCell;
3use core::future::Future;
4use core::pin::Pin as FuturePin;
5use core::task::{Context, Poll};
6
7use critical_section::Mutex;
8use embassy_hal_internal::{Peripheral, PeripheralRef};
9use embassy_sync::waitqueue::AtomicWaker;
10
11use crate::gpio::{self, AnyPin, Level, SealedPin};
12use crate::pac::interrupt;
13use crate::pac_utils::*;
14
15struct PinInterrupt {
16 assigned: bool,
17 waker: AtomicWaker,
18 /// If true, the interrupt was triggered due to this PinInterrupt. This is used to determine if
19 /// an [InputFuture] should return Poll::Ready.
20 at_fault: bool,
21}
22
23impl PinInterrupt {
24 pub fn interrupt_active(&self) -> bool {
25 self.assigned
26 }
27
28 /// Mark the interrupt as assigned to a pin.
29 pub fn enable(&mut self) {
30 self.assigned = true;
31 self.at_fault = false;
32 }
33
34 /// Mark the interrupt as available.
35 pub fn disable(&mut self) {
36 self.assigned = false;
37 self.at_fault = false;
38 }
39
40 /// Returns true if the interrupt was triggered due to this PinInterrupt.
41 ///
42 /// If this function returns true, it will also reset the at_fault flag.
43 pub fn at_fault(&mut self) -> bool {
44 let val = self.at_fault;
45 self.at_fault = false;
46 val
47 }
48
49 /// Set the at_fault flag to true.
50 pub fn fault(&mut self) {
51 self.at_fault = true;
52 }
53}
54
55const NEW_PIN_INTERRUPT: PinInterrupt = PinInterrupt {
56 assigned: false,
57 waker: AtomicWaker::new(),
58 at_fault: false,
59};
60const INTERUPT_COUNT: usize = 8;
61static PIN_INTERRUPTS: Mutex<RefCell<[PinInterrupt; INTERUPT_COUNT]>> =
62 Mutex::new(RefCell::new([NEW_PIN_INTERRUPT; INTERUPT_COUNT]));
63
64fn next_available_interrupt() -> Option<usize> {
65 critical_section::with(|cs| {
66 for (i, pin_interrupt) in PIN_INTERRUPTS.borrow(cs).borrow().iter().enumerate() {
67 if !pin_interrupt.interrupt_active() {
68 return Some(i);
69 }
70 }
71
72 None
73 })
74}
75
76#[derive(Clone, Copy, PartialEq, Eq)]
77enum Edge {
78 Rising,
79 Falling,
80 Both,
81}
82
83#[derive(Clone, Copy, PartialEq, Eq)]
84enum InterruptOn {
85 Level(Level),
86 Edge(Edge),
87}
88
89pub(crate) fn init() {
90 syscon_reg().ahbclkctrl0.modify(|_, w| w.pint().enable());
91
92 // Enable interrupts
93 unsafe {
94 crate::pac::NVIC::unmask(crate::pac::Interrupt::PIN_INT0);
95 crate::pac::NVIC::unmask(crate::pac::Interrupt::PIN_INT1);
96 crate::pac::NVIC::unmask(crate::pac::Interrupt::PIN_INT2);
97 crate::pac::NVIC::unmask(crate::pac::Interrupt::PIN_INT3);
98 crate::pac::NVIC::unmask(crate::pac::Interrupt::PIN_INT4);
99 crate::pac::NVIC::unmask(crate::pac::Interrupt::PIN_INT5);
100 crate::pac::NVIC::unmask(crate::pac::Interrupt::PIN_INT6);
101 crate::pac::NVIC::unmask(crate::pac::Interrupt::PIN_INT7);
102 };
103}
104
105#[must_use = "futures do nothing unless you `.await` or poll them"]
106struct InputFuture<'d> {
107 #[allow(dead_code)]
108 pin: PeripheralRef<'d, AnyPin>,
109 interrupt_number: usize,
110}
111
112impl<'d> InputFuture<'d> {
113 /// Create a new input future. Returns None if all interrupts are in use.
114 fn new(pin: impl Peripheral<P = impl gpio::Pin> + 'd, interrupt_on: InterruptOn) -> Option<Self> {
115 let pin = pin.into_ref().map_into();
116 let interrupt_number = next_available_interrupt()?;
117
118 // Clear interrupt, just in case
119 pint_reg()
120 .rise
121 .write(|w| unsafe { w.rdet().bits(1 << interrupt_number) });
122 pint_reg()
123 .fall
124 .write(|w| unsafe { w.fdet().bits(1 << interrupt_number) });
125
126 // Enable input multiplexing on pin interrupt register 0 for pin (32*bank + pin_number)
127 inputmux_reg().pintsel[interrupt_number]
128 .write(|w| unsafe { w.intpin().bits(32 * pin.pin_bank() as u8 + pin.pin_number()) });
129
130 match interrupt_on {
131 InterruptOn::Level(level) => {
132 // Set pin interrupt register to edge sensitive or level sensitive
133 // 0 = edge sensitive, 1 = level sensitive
134 pint_reg()
135 .isel
136 .modify(|r, w| unsafe { w.bits(r.bits() | (1 << interrupt_number)) });
137
138 // Enable level interrupt.
139 //
140 // Note: Level sensitive interrupts are enabled by the same register as rising edge
141 // is activated.
142
143 // 0 = no-op, 1 = enable
144 pint_reg()
145 .sienr
146 .write(|w| unsafe { w.setenrl().bits(1 << interrupt_number) });
147
148 // Set active level
149 match level {
150 Level::Low => {
151 // 0 = no-op, 1 = select LOW
152 pint_reg()
153 .cienf
154 .write(|w| unsafe { w.cenaf().bits(1 << interrupt_number) });
155 }
156 Level::High => {
157 // 0 = no-op, 1 = select HIGH
158 pint_reg()
159 .sienf
160 .write(|w| unsafe { w.setenaf().bits(1 << interrupt_number) });
161 }
162 }
163 }
164 InterruptOn::Edge(edge) => {
165 // Set pin interrupt register to edge sensitive or level sensitive
166 // 0 = edge sensitive, 1 = level sensitive
167 pint_reg()
168 .isel
169 .modify(|r, w| unsafe { w.bits(r.bits() & !(1 << interrupt_number)) });
170
171 // Enable rising/falling edge detection
172 match edge {
173 Edge::Rising => {
174 // 0 = no-op, 1 = enable rising edge
175 pint_reg()
176 .sienr
177 .write(|w| unsafe { w.setenrl().bits(1 << interrupt_number) });
178 // 0 = no-op, 1 = disable falling edge
179 pint_reg()
180 .cienf
181 .write(|w| unsafe { w.cenaf().bits(1 << interrupt_number) });
182 }
183 Edge::Falling => {
184 // 0 = no-op, 1 = enable falling edge
185 pint_reg()
186 .sienf
187 .write(|w| unsafe { w.setenaf().bits(1 << interrupt_number) });
188 // 0 = no-op, 1 = disable rising edge
189 pint_reg()
190 .cienr
191 .write(|w| unsafe { w.cenrl().bits(1 << interrupt_number) });
192 }
193 Edge::Both => {
194 // 0 = no-op, 1 = enable
195 pint_reg()
196 .sienr
197 .write(|w| unsafe { w.setenrl().bits(1 << interrupt_number) });
198 pint_reg()
199 .sienf
200 .write(|w| unsafe { w.setenaf().bits(1 << interrupt_number) });
201 }
202 }
203 }
204 }
205
206 critical_section::with(|cs| {
207 let mut pin_interrupts = PIN_INTERRUPTS.borrow(cs).borrow_mut();
208 let pin_interrupt = &mut pin_interrupts[interrupt_number];
209
210 pin_interrupt.enable();
211 });
212
213 Some(Self { pin, interrupt_number })
214 }
215
216 /// Returns true if the interrupt was triggered for this pin.
217 fn interrupt_triggered(&self) -> bool {
218 let interrupt_number = self.interrupt_number;
219
220 // Initially, we determine if the interrupt was triggered by this InputFuture by checking
221 // the flags of the interrupt_number. However, by the time we get to this point, the
222 // interrupt may have been triggered again, so we needed to clear the cpu flags immediately.
223 // As a solution, we mark which [PinInterrupt] is responsible for the interrupt ("at fault")
224 critical_section::with(|cs| {
225 let mut pin_interrupts = PIN_INTERRUPTS.borrow(cs).borrow_mut();
226 let pin_interrupt = &mut pin_interrupts[interrupt_number];
227
228 pin_interrupt.at_fault()
229 })
230 }
231}
232
233impl<'d> Drop for InputFuture<'d> {
234 fn drop(&mut self) {
235 let interrupt_number = self.interrupt_number;
236
237 // Disable pin interrupt
238 // 0 = no-op, 1 = disable
239 pint_reg()
240 .cienr
241 .write(|w| unsafe { w.cenrl().bits(1 << interrupt_number) });
242 pint_reg()
243 .cienf
244 .write(|w| unsafe { w.cenaf().bits(1 << interrupt_number) });
245
246 critical_section::with(|cs| {
247 let mut pin_interrupts = PIN_INTERRUPTS.borrow(cs).borrow_mut();
248 let pin_interrupt = &mut pin_interrupts[interrupt_number];
249
250 pin_interrupt.disable();
251 });
252 }
253}
254
255impl<'d> Future for InputFuture<'d> {
256 type Output = ();
257
258 fn poll(self: FuturePin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
259 let interrupt_number = self.interrupt_number;
260
261 critical_section::with(|cs| {
262 let mut pin_interrupts = PIN_INTERRUPTS.borrow(cs).borrow_mut();
263 let pin_interrupt = &mut pin_interrupts[interrupt_number];
264
265 pin_interrupt.waker.register(cx.waker());
266 });
267
268 if self.interrupt_triggered() {
269 Poll::Ready(())
270 } else {
271 Poll::Pending
272 }
273 }
274}
275
276fn handle_interrupt(interrupt_number: usize) {
277 pint_reg()
278 .rise
279 .write(|w| unsafe { w.rdet().bits(1 << interrupt_number) });
280 pint_reg()
281 .fall
282 .write(|w| unsafe { w.fdet().bits(1 << interrupt_number) });
283
284 critical_section::with(|cs| {
285 let mut pin_interrupts = PIN_INTERRUPTS.borrow(cs).borrow_mut();
286 let pin_interrupt = &mut pin_interrupts[interrupt_number];
287
288 pin_interrupt.fault();
289 pin_interrupt.waker.wake();
290 });
291}
292
293#[allow(non_snake_case)]
294#[interrupt]
295fn PIN_INT0() {
296 handle_interrupt(0);
297}
298
299#[allow(non_snake_case)]
300#[interrupt]
301fn PIN_INT1() {
302 handle_interrupt(1);
303}
304
305#[allow(non_snake_case)]
306#[interrupt]
307fn PIN_INT2() {
308 handle_interrupt(2);
309}
310
311#[allow(non_snake_case)]
312#[interrupt]
313fn PIN_INT3() {
314 handle_interrupt(3);
315}
316
317#[allow(non_snake_case)]
318#[interrupt]
319fn PIN_INT4() {
320 handle_interrupt(4);
321}
322
323#[allow(non_snake_case)]
324#[interrupt]
325fn PIN_INT5() {
326 handle_interrupt(5);
327}
328
329#[allow(non_snake_case)]
330#[interrupt]
331fn PIN_INT6() {
332 handle_interrupt(6);
333}
334
335#[allow(non_snake_case)]
336#[interrupt]
337fn PIN_INT7() {
338 handle_interrupt(7);
339}
340
341impl gpio::Flex<'_> {
342 /// Wait for a falling or rising edge on the pin. You can have at most 8 pins waiting. If you
343 /// try to wait for more than 8 pins, this function will return `None`.
344 pub async fn wait_for_any_edge(&mut self) -> Option<()> {
345 InputFuture::new(&mut self.pin, InterruptOn::Edge(Edge::Both))?.await;
346 Some(())
347 }
348
349 /// Wait for a falling edge on the pin. You can have at most 8 pins waiting. If you try to wait
350 /// for more than 8 pins, this function will return `None`.
351 pub async fn wait_for_falling_edge(&mut self) -> Option<()> {
352 InputFuture::new(&mut self.pin, InterruptOn::Edge(Edge::Falling))?.await;
353 Some(())
354 }
355
356 /// Wait for a rising edge on the pin. You can have at most 8 pins waiting. If you try to wait
357 /// for more than 8 pins, this function will return `None`.
358 pub async fn wait_for_rising_edge(&mut self) -> Option<()> {
359 InputFuture::new(&mut self.pin, InterruptOn::Edge(Edge::Rising))?.await;
360 Some(())
361 }
362
363 /// Wait for a low level on the pin. You can have at most 8 pins waiting. If you try to wait for
364 /// more than 8 pins, this function will return `None`.
365 pub async fn wait_for_low(&mut self) -> Option<()> {
366 InputFuture::new(&mut self.pin, InterruptOn::Level(Level::Low))?.await;
367 Some(())
368 }
369
370 /// Wait for a high level on the pin. You can have at most 8 pins waiting. If you try to wait for
371 /// more than 8 pins, this function will return `None`.
372 pub async fn wait_for_high(&mut self) -> Option<()> {
373 InputFuture::new(&mut self.pin, InterruptOn::Level(Level::High))?.await;
374 Some(())
375 }
376}
377
378impl gpio::Input<'_> {
379 /// Wait for a falling or rising edge on the pin. You can have at most 8 pins waiting. If you
380 /// try to wait for more than 8 pins, this function will return `None`.
381 pub async fn wait_for_any_edge(&mut self) -> Option<()> {
382 self.pin.wait_for_any_edge().await
383 }
384
385 /// Wait for a falling edge on the pin. You can have at most 8 pins waiting. If you try to wait
386 /// for more than 8 pins, this function will return `None`.
387 pub async fn wait_for_falling_edge(&mut self) -> Option<()> {
388 self.pin.wait_for_falling_edge().await
389 }
390
391 /// Wait for a rising edge on the pin. You can have at most 8 pins waiting. If you try to wait
392 /// for more than 8 pins, this function will return `None`.
393 pub async fn wait_for_rising_edge(&mut self) -> Option<()> {
394 self.pin.wait_for_rising_edge().await
395 }
396
397 /// Wait for a low level on the pin. You can have at most 8 pins waiting. If you try to wait for
398 /// more than 8 pins, this function will return `None`.
399 pub async fn wait_for_low(&mut self) -> Option<()> {
400 self.pin.wait_for_low().await
401 }
402
403 /// Wait for a high level on the pin. You can have at most 8 pins waiting. If you try to wait for
404 /// more than 8 pins, this function will return `None`.
405 pub async fn wait_for_high(&mut self) -> Option<()> {
406 self.pin.wait_for_high().await
407 }
408}
409
410impl gpio::Output<'_> {
411 /// Wait for a falling or rising edge on the pin. You can have at most 8 pins waiting. If you
412 /// try to wait for more than 8 pins, this function will return `None`.
413 pub async fn wait_for_any_edge(&mut self) -> Option<()> {
414 self.pin.wait_for_any_edge().await
415 }
416
417 /// Wait for a falling edge on the pin. You can have at most 8 pins waiting. If you try to wait
418 /// for more than 8 pins, this function will return `None`.
419 pub async fn wait_for_falling_edge(&mut self) -> Option<()> {
420 self.pin.wait_for_falling_edge().await
421 }
422
423 /// Wait for a rising edge on the pin. You can have at most 8 pins waiting. If you try to wait
424 /// for more than 8 pins, this function will return `None`.
425 pub async fn wait_for_rising_edge(&mut self) -> Option<()> {
426 self.pin.wait_for_rising_edge().await
427 }
428
429 /// Wait for a low level on the pin. You can have at most 8 pins waiting. If you try to wait for
430 /// more than 8 pins, this function will return `None`.
431 pub async fn wait_for_low(&mut self) -> Option<()> {
432 self.pin.wait_for_low().await
433 }
434
435 /// Wait for a high level on the pin. You can have at most 8 pins waiting. If you try to wait for
436 /// more than 8 pins, this function will return `None`.
437 pub async fn wait_for_high(&mut self) -> Option<()> {
438 self.pin.wait_for_high().await
439 }
440}