atsamd_hal/peripherals/eic/d11/
mod.rs

1mod pin;
2
3#[cfg(feature = "async")]
4pub(super) mod async_api {
5    use crate::async_hal::interrupts::{Binding, Handler, Interrupt, EIC as EicInterrupt};
6    use crate::eic::{Eic, EicFuture, NUM_CHANNELS};
7    use crate::pac;
8    use crate::util::BitIter;
9
10    use core::marker::PhantomData;
11
12    use embassy_sync::waitqueue::AtomicWaker;
13
14    pub struct InterruptHandler {
15        _private: (),
16    }
17
18    impl crate::typelevel::Sealed for InterruptHandler {}
19
20    impl Handler<EicInterrupt> for InterruptHandler {
21        unsafe fn on_interrupt() {
22            let eic = pac::Peripherals::steal().eic;
23
24            let pending_interrupts = BitIter(eic.intflag().read().bits());
25            for channel in pending_interrupts {
26                let mask = 1 << channel;
27                // Disable the interrupt but don't clear; will be cleared
28                // when future is next polled.
29                eic.intenclr().write(|w| w.bits(mask));
30                WAKERS[channel as usize].wake();
31            }
32        }
33    }
34
35    impl Eic {
36        /// Turn an EIC pin into a pin usable as a [`Future`](core::future::Future).
37        /// The correct interrupt source is needed.
38        pub fn into_future<I>(self, _irq: I) -> Eic<EicFuture>
39        where
40            I: Binding<EicInterrupt, InterruptHandler>,
41        {
42            EicInterrupt::unpend();
43            unsafe { EicInterrupt::enable() };
44
45            Eic {
46                eic: self.eic,
47                _irqs: PhantomData,
48            }
49        }
50    }
51
52    #[allow(clippy::declare_interior_mutable_const)]
53    const NEW_WAKER: AtomicWaker = AtomicWaker::new();
54    pub(super) static WAKERS: [AtomicWaker; NUM_CHANNELS] = [NEW_WAKER; NUM_CHANNELS];
55}