atsamd_hal/peripherals/eic/d5x/
mod.rs

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