atsamd_hal/dmac/
async_api.rs1use atsamd_hal_macros::hal_cfg;
4use core::sync::atomic;
5
6use crate::{
7 async_hal::interrupts::{DMAC, Handler},
8 dmac::{TriggerSource, waker::WAKERS},
9 util::BitIter,
10};
11
12pub struct InterruptHandler {
14 _private: (),
15}
16
17impl crate::typelevel::Sealed for InterruptHandler {}
18
19#[hal_cfg(any("dmac-d11", "dmac-d21"))]
20impl Handler<DMAC> for InterruptHandler {
21 unsafe fn on_interrupt() {
22 let dmac = unsafe { crate::pac::Peripherals::steal().dmac };
27
28 critical_section::with(|_| {
29 let old_id = dmac.chid().read().id().bits();
30 let pending_interrupts = BitIter(dmac.intstatus().read().bits());
31
32 for pend_channel in pending_interrupts {
34 unsafe { dmac.chid().modify(|_, w| w.id().bits(pend_channel as u8)) };
35
36 let wake = if dmac.chintflag().read().tcmpl().bit_is_set() {
37 dmac.chintenclr().modify(|_, w| w.tcmpl().set_bit());
40 true
41 } else if dmac.chintflag().read().terr().bit_is_set() {
42 dmac.chintenclr().modify(|_, w| w.terr().set_bit());
44 true
45 } else {
46 false
47 };
48
49 if wake {
50 dmac.chctrla().modify(|_, w| w.enable().clear_bit());
51 dmac.chctrlb()
52 .modify(|_, w| w.trigsrc().variant(TriggerSource::Disable));
53
54 while dmac.chctrla().read().enable().bit_is_set() {
55 core::hint::spin_loop();
56 }
57
58 atomic::fence(atomic::Ordering::Acquire); WAKERS[pend_channel as usize].wake();
64 }
65 }
66
67 unsafe {
69 dmac.chid().write(|w| w.id().bits(old_id));
70 }
71 });
72 }
73}
74
75#[hal_cfg("dmac-d5x")]
76impl Handler<DMAC> for InterruptHandler {
77 unsafe fn on_interrupt() {
78 let dmac = unsafe { crate::pac::Peripherals::steal().dmac };
79
80 let pending_channels = BitIter(dmac.intstatus().read().bits());
81 for channel in pending_channels.map(|c| c as usize) {
82 let wake = if dmac
83 .channel(channel)
84 .chintflag()
85 .read()
86 .tcmpl()
87 .bit_is_set()
88 {
89 dmac.channel(channel)
92 .chintenclr()
93 .modify(|_, w| w.tcmpl().set_bit());
94 true
95 } else if dmac.channel(channel).chintflag().read().terr().bit_is_set() {
96 dmac.channel(channel)
98 .chintenclr()
99 .modify(|_, w| w.terr().set_bit());
100 true
101 } else {
102 false
103 };
104
105 if wake {
106 dmac.channel(channel).chctrla().modify(|_, w| {
107 w.enable().clear_bit();
108 w.trigsrc().variant(TriggerSource::Disable)
109 });
110
111 while dmac.channel(channel).chctrla().read().enable().bit_is_set() {
112 core::hint::spin_loop();
113 }
114
115 atomic::fence(atomic::Ordering::Acquire); WAKERS[channel].wake();
121 }
122 }
123 }
124}