atsamd_hal/peripherals/adc/
async_api.rs1use 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
21pub 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 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 let flags_to_wait = flags_to_wait | Flags::OVERRUN;
56 self.inner.disable_interrupts(Flags::all());
57
58 core::future::poll_fn(|cx| {
59 {
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}