atsamd_hal/dmac/
async_api.rs1use atsamd_hal_macros::hal_cfg;
4
5use crate::{
6    async_hal::interrupts::{DMAC, Handler},
7    dmac::{TriggerSource, waker::WAKERS},
8    util::BitIter,
9};
10
11pub struct InterruptHandler {
13    _private: (),
14}
15
16impl crate::typelevel::Sealed for InterruptHandler {}
17
18#[hal_cfg(any("dmac-d11", "dmac-d21"))]
19impl Handler<DMAC> for InterruptHandler {
20    unsafe fn on_interrupt() {
21        let dmac = unsafe { crate::pac::Peripherals::steal().dmac };
26
27        critical_section::with(|_| {
28            let old_id = dmac.chid().read().id().bits();
29            let pending_interrupts = BitIter(dmac.intstatus().read().bits());
30
31            for pend_channel in pending_interrupts {
33                unsafe { dmac.chid().modify(|_, w| w.id().bits(pend_channel as u8)) };
34
35                let wake = if dmac.chintflag().read().tcmpl().bit_is_set() {
36                    dmac.chintenclr().modify(|_, w| w.tcmpl().set_bit());
39                    true
40                } else if dmac.chintflag().read().terr().bit_is_set() {
41                    dmac.chintenclr().modify(|_, w| w.terr().set_bit());
43                    true
44                } else {
45                    false
46                };
47
48                if wake {
49                    dmac.chctrla().modify(|_, w| w.enable().clear_bit());
50                    dmac.chctrlb()
51                        .modify(|_, w| w.trigsrc().variant(TriggerSource::Disable));
52                    WAKERS[pend_channel as usize].wake();
53                }
54            }
55
56            unsafe {
58                dmac.chid().write(|w| w.id().bits(old_id));
59            }
60        });
61    }
62}
63
64#[hal_cfg("dmac-d5x")]
65impl Handler<DMAC> for InterruptHandler {
66    unsafe fn on_interrupt() {
67        let dmac = unsafe { crate::pac::Peripherals::steal().dmac };
68
69        let pending_channels = BitIter(dmac.intstatus().read().bits());
70        for channel in pending_channels.map(|c| c as usize) {
71            let wake = if dmac
72                .channel(channel)
73                .chintflag()
74                .read()
75                .tcmpl()
76                .bit_is_set()
77            {
78                dmac.channel(channel)
81                    .chintenclr()
82                    .modify(|_, w| w.tcmpl().set_bit());
83                true
84            } else if dmac.channel(channel).chintflag().read().terr().bit_is_set() {
85                dmac.channel(channel)
87                    .chintenclr()
88                    .modify(|_, w| w.terr().set_bit());
89                true
90            } else {
91                false
92            };
93
94            if wake {
95                dmac.channel(channel).chctrla().modify(|_, w| {
96                    w.enable().clear_bit();
97                    w.trigsrc().variant(TriggerSource::Disable)
98                });
99                WAKERS[channel].wake();
100            }
101        }
102    }
103}