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}