atsamd_hal/peripherals/adc/
async_api.rs

1use core::marker::PhantomData;
2
3use crate::{
4    adc::{AdcInstance, Error, Flags},
5    async_hal::interrupts::Handler,
6};
7
8use atsamd_hal_macros::hal_module;
9use embassy_sync::waitqueue::AtomicWaker;
10
11use super::FutureAdc;
12
13#[allow(clippy::declare_interior_mutable_const)]
14const NEW_WAKER: AtomicWaker = AtomicWaker::new();
15
16#[hal_module(any("adc-d11", "adc-d21"))]
17pub static ADC_WAKERS: [AtomicWaker; 1] = [NEW_WAKER; 1];
18#[hal_module("adc-d5x")]
19pub static ADC_WAKERS: [AtomicWaker; 2] = [NEW_WAKER; 2];
20
21/// Interrupt handler for the ADC peripheral.
22pub struct InterruptHandler<A: AdcInstance> {
23    _private: (),
24    _adc: PhantomData<A>,
25}
26
27impl<A: AdcInstance> crate::typelevel::Sealed for InterruptHandler<A> {}
28
29impl<A: AdcInstance> Handler<A::Interrupt> for InterruptHandler<A> {
30    unsafe fn on_interrupt() {
31        let mut peripherals = unsafe { crate::pac::Peripherals::steal() };
32        let adc = A::peripheral_reg_block(&mut peripherals);
33
34        let flags_pending = Flags::from_bits_truncate(adc.intflag().read().bits());
35        let enabled_flags = Flags::from_bits_truncate(adc.intenset().read().bits());
36
37        if enabled_flags.intersects(flags_pending) {
38            adc.intenclr()
39                .write(|w| unsafe { w.bits(flags_pending.bits()) });
40            // Wake up!
41            A::waker().wake();
42        }
43    }
44}
45
46impl<I: AdcInstance, F> FutureAdc<I, F>
47where
48    F: crate::async_hal::interrupts::Binding<I::Interrupt, InterruptHandler<I>>,
49{
50    #[inline]
51    pub(super) async fn wait_flags(&mut self, flags_to_wait: Flags) -> Result<(), Error> {
52        use core::task::Poll;
53
54        // We automatically check for errors
55        let flags_to_wait = flags_to_wait | Flags::OVERRUN;
56        self.inner.disable_interrupts(Flags::all());
57
58        core::future::poll_fn(|cx| {
59            // Scope maybe_pending so we don't forget to re-poll the register later down.
60            {
61                let maybe_pending = self.inner.read_flags();
62                if flags_to_wait.intersects(maybe_pending) {
63                    let result = self.inner.check_overrun(&maybe_pending);
64                    self.inner
65                        .clear_flags(&maybe_pending.intersection(flags_to_wait));
66                    self.inner.disable_interrupts(flags_to_wait);
67                    return Poll::Ready(result);
68                }
69            }
70
71            I::waker().register(cx.waker());
72            self.inner.enable_interrupts(flags_to_wait);
73
74            let maybe_pending = self.inner.read_flags();
75
76            if !flags_to_wait.intersects(maybe_pending) {
77                Poll::Pending
78            } else {
79                let result = self.inner.check_overrun(&maybe_pending);
80                self.inner
81                    .clear_flags(&maybe_pending.intersection(flags_to_wait));
82                self.inner.disable_interrupts(flags_to_wait);
83                Poll::Ready(result)
84            }
85        })
86        .await
87    }
88}