atsamd_hal/peripherals/eic/d11/
mod.rs

1use super::{ChId, Channel};
2use crate::pac;
3mod pin;
4
5impl<Id: ChId, F> Channel<Id, F> {
6    /// Run the provided closure with the EIC peripheral disabled. The
7    /// enable-protected registers, such as CONFIGx, should be accessed through
8    /// this method.
9    ///
10    /// # Caution
11    ///
12    /// You should not re-enable the provided EIC PAC object inside the provided
13    /// closure.
14    fn with_disable(&mut self, fun: impl Fn(&mut pac::Eic)) {
15        self.eic.ctrl().modify(|_, w| w.enable().clear_bit());
16        self.enable_sync();
17        fun(&mut self.eic);
18        self.eic.ctrl().modify(|_, w| w.enable().set_bit());
19        self.enable_sync();
20    }
21
22    /// Busy-wait until SYNCBUSY.ENABLE clears
23    fn enable_sync(&mut self) {
24        while self.eic.status().read().syncbusy().bit_is_set() {
25            core::hint::spin_loop();
26        }
27    }
28}
29
30#[cfg(feature = "async")]
31pub(super) mod async_api {
32    use crate::async_hal::interrupts::{Binding, EIC as EicInterrupt, Handler, Interrupt};
33    use crate::eic::{Eic, EicFuture, NUM_CHANNELS};
34    use crate::pac;
35    use crate::util::BitIter;
36
37    use core::marker::PhantomData;
38
39    use embassy_sync::waitqueue::AtomicWaker;
40
41    pub struct InterruptHandler {
42        _private: (),
43    }
44
45    impl crate::typelevel::Sealed for InterruptHandler {}
46
47    impl Handler<EicInterrupt> for InterruptHandler {
48        unsafe fn on_interrupt() {
49            let eic = unsafe { pac::Peripherals::steal().eic };
50
51            let pending_interrupts = BitIter(eic.intflag().read().bits());
52            for channel in pending_interrupts {
53                let mask = 1 << channel;
54                // Disable the interrupt but don't clear; will be cleared
55                // when future is next polled.
56                eic.intenclr().write(|w| unsafe { w.bits(mask) });
57                WAKERS[channel as usize].wake();
58            }
59        }
60    }
61
62    impl Eic {
63        /// Turn an EIC pin into a pin usable as a [`Future`](core::future::Future).
64        /// The correct interrupt source is needed.
65        pub fn into_future<I>(self, _irq: I) -> Eic<EicFuture>
66        where
67            I: Binding<EicInterrupt, InterruptHandler>,
68        {
69            EicInterrupt::unpend();
70            unsafe { EicInterrupt::enable() };
71
72            Eic {
73                eic: self.eic,
74                _irqs: PhantomData,
75            }
76        }
77    }
78
79    #[allow(clippy::declare_interior_mutable_const)]
80    const NEW_WAKER: AtomicWaker = AtomicWaker::new();
81    pub(super) static WAKERS: [AtomicWaker; NUM_CHANNELS] = [NEW_WAKER; NUM_CHANNELS];
82}