rp2040_hal/dma/
single_buffer.rs1use core::sync::atomic::{compiler_fence, Ordering};
4
5use super::{
6 single_channel::ChannelConfig, single_channel::SingleChannel, Pace, ReadTarget, WriteTarget,
7};
8
9pub struct Config<CH: SingleChannel, FROM: ReadTarget, TO: WriteTarget> {
11 ch: CH,
12 from: FROM,
13 to: TO,
14 pace: Pace,
15 bswap: bool,
16}
17
18impl<CH, FROM, TO, WORD> Config<CH, FROM, TO>
19where
20 CH: SingleChannel,
21 FROM: ReadTarget<ReceivedWord = WORD>,
22 TO: WriteTarget<TransmittedWord = WORD>,
23{
24 pub fn new(ch: CH, from: FROM, to: TO) -> Config<CH, FROM, TO> {
26 Config {
27 ch,
28 from,
29 to,
30 pace: Pace::PreferSource,
31 bswap: false,
32 }
33 }
34
35 pub fn pace(&mut self, pace: Pace) {
41 self.pace = pace;
42 }
43
44 pub fn bswap(&mut self, bswap: bool) {
52 self.bswap = bswap;
53 }
54
55 pub fn start(mut self) -> Transfer<CH, FROM, TO> {
57 cortex_m::asm::dsb();
62 compiler_fence(Ordering::SeqCst);
63
64 self.ch
66 .config(&self.from, &mut self.to, self.pace, self.bswap, None, true);
67
68 Transfer {
69 ch: self.ch,
70 from: self.from,
71 to: self.to,
72 }
73 }
74}
75
76pub struct Transfer<CH: SingleChannel, FROM: ReadTarget, TO: WriteTarget> {
79 ch: CH,
80 from: FROM,
81 to: TO,
82}
83
84impl<CH, FROM, TO, WORD> Transfer<CH, FROM, TO>
85where
86 CH: SingleChannel,
87 FROM: ReadTarget<ReceivedWord = WORD>,
88 TO: WriteTarget<TransmittedWord = WORD>,
89{
90 pub fn check_irq0(&mut self) -> bool {
92 self.ch.check_irq0()
93 }
94
95 pub fn check_irq1(&mut self) -> bool {
97 self.ch.check_irq1()
98 }
99
100 pub fn is_done(&self) -> bool {
102 !self.ch.ch().ch_ctrl_trig().read().busy().bit_is_set()
103 }
104
105 pub fn wait(self) -> (CH, FROM, TO) {
107 while !self.is_done() {}
108
109 cortex_m::asm::dsb();
111 compiler_fence(Ordering::SeqCst);
112
113 (self.ch, self.from, self.to)
114 }
115
116 pub fn abort(mut self) -> (CH, FROM, TO) {
118 let irq0_was_enabled = self.ch.is_enabled_irq0();
119 let irq1_was_enabled = self.ch.is_enabled_irq1();
120 self.ch.disable_irq0();
121 self.ch.disable_irq1();
122
123 let chan_abort = unsafe { &*crate::pac::DMA::ptr() }.chan_abort();
124 let abort_mask = (1 << self.ch.id()) as u16;
125
126 chan_abort.write(|w| unsafe { w.chan_abort().bits(abort_mask) });
127
128 while chan_abort.read().chan_abort().bits() != 0 {}
129
130 while !self.is_done() {}
131
132 self.ch.check_irq0();
133 self.ch.check_irq1();
134
135 if irq0_was_enabled {
136 self.ch.enable_irq0();
137 }
138
139 if irq1_was_enabled {
140 self.ch.enable_irq1();
141 }
142
143 cortex_m::asm::dsb();
145 compiler_fence(Ordering::SeqCst);
146
147 (self.ch, self.from, self.to)
148 }
149}