1use core::marker::PhantomData;
6use core::sync::atomic::{self, compiler_fence, Ordering};
7use core::{mem, ptr};
8use embedded_dma::{ReadBuffer, WriteBuffer};
9
10pub struct R;
12
13pub struct W;
15
16pub struct RxDma<PAYLOAD> {
18 pub(crate) payload: PAYLOAD,
19}
20
21pub struct TxDma<PAYLOAD> {
23 pub(crate) payload: PAYLOAD,
24}
25
26pub struct RxTxDma<PAYLOAD> {
28 pub(crate) payload: PAYLOAD,
29}
30
31pub trait Receive {
32 type TransmittedWord;
33}
34
35pub trait Transmit {
36 type ReceivedWord;
37}
38
39pub trait ReadDma<B, RS>: Receive
41where
42 B: WriteBuffer<Word = RS>,
43 Self: core::marker::Sized + TransferPayload,
44{
45 fn read(self, buffer: B) -> Transfer<W, B, Self>;
46}
47
48pub trait ReadDmaPaused<B, RS>: Receive
50where
51 B: WriteBuffer<Word = RS>,
52 Self: core::marker::Sized + TransferPayload,
53{
54 fn read_paused(self, buffer: B) -> Transfer<W, B, Self>;
55}
56
57pub trait WriteDma<B, TS>: Transmit
59where
60 B: ReadBuffer<Word = TS>,
61 Self: core::marker::Sized + TransferPayload,
62{
63 fn write(self, buffer: B) -> Transfer<R, B, Self>;
64}
65
66pub trait ReadWriteDma<RXB, TXB, TS>: Transmit + Receive
68where
69 RXB: WriteBuffer<Word = TS>,
70 TXB: ReadBuffer<Word = TS>,
71 Self: core::marker::Sized + TransferPayload,
72{
73 fn read_write(self, rx_buffer: RXB, tx_buffer: TXB) -> Transfer<W, (RXB, TXB), Self>;
74}
75
76pub trait ReadWriteDmaLen<RXB, TXB, TS>: Transmit + Receive
79where
80 RXB: WriteBuffer<Word = TS>,
81 TXB: ReadBuffer<Word = TS>,
82 Self: core::marker::Sized + TransferPayload,
83{
84 fn read_write_len(
85 self,
86 rx_buffer: RXB,
87 rx_buf_len: usize,
88 tx_buffer: TXB,
89 tx_buf_len: usize,
90 ) -> Transfer<W, (RXB, TXB), Self>;
91}
92
93pub trait TransferPayload {
94 fn start(&mut self);
95 fn stop(&mut self);
96 fn in_progress(&self) -> bool;
97}
98
99pub struct Transfer<MODE, BUFFER, PAYLOAD>
100where
101 PAYLOAD: TransferPayload,
102{
103 _mode: PhantomData<MODE>,
104 buffer: BUFFER,
105 payload: PAYLOAD,
106}
107
108impl<BUFFER, PAYLOAD> Transfer<R, BUFFER, PAYLOAD>
109where
110 PAYLOAD: TransferPayload,
111{
112 pub(crate) fn r(buffer: BUFFER, payload: PAYLOAD) -> Self {
113 Transfer {
114 _mode: PhantomData,
115 buffer,
116 payload,
117 }
118 }
119}
120
121impl<BUFFER, PAYLOAD> Transfer<W, BUFFER, PAYLOAD>
122where
123 PAYLOAD: TransferPayload,
124{
125 pub(crate) fn w(buffer: BUFFER, payload: PAYLOAD) -> Self {
126 Transfer {
127 _mode: PhantomData,
128 buffer,
129 payload,
130 }
131 }
132}
133
134impl<MODE, BUFFER, PAYLOAD> Drop for Transfer<MODE, BUFFER, PAYLOAD>
135where
136 PAYLOAD: TransferPayload,
137{
138 fn drop(&mut self) {
139 self.payload.stop();
140 compiler_fence(Ordering::SeqCst);
141 }
142}
143
144macro_rules! pdc_transfer {
145 (
146 $DmaType:ident
147 ) => {
148 impl<BUFFER, PAYLOAD, MODE> Transfer<MODE, BUFFER, $DmaType<PAYLOAD>>
149 where
150 $DmaType<PAYLOAD>: TransferPayload,
151 {
152 pub fn is_done(&self) -> bool {
153 !self.payload.in_progress()
154 }
155
156 pub fn wait(mut self) -> (BUFFER, $DmaType<PAYLOAD>) {
157 while !self.is_done() {}
158
159 atomic::compiler_fence(Ordering::Acquire);
160
161 self.payload.stop();
162
163 unsafe {
166 ptr::read_volatile(&0);
167 }
168
169 atomic::compiler_fence(Ordering::Acquire);
171
172 unsafe {
180 let buffer = ptr::read(&self.buffer);
181 let payload = ptr::read(&self.payload);
182 mem::forget(self);
183 (buffer, payload)
184 }
185 }
186
187 pub fn pause(&mut self) {
188 self.payload.stop();
189 }
190
191 pub fn resume(&mut self) {
192 self.payload.start();
193 }
194 }
195 };
196}
197
198pdc_transfer!(RxDma);
199pdc_transfer!(TxDma);
200pdc_transfer!(RxTxDma);
201
202macro_rules! pdc_rx {
203 (
204 $Periph:ident: $periph:ident, $isr:ident
205 ) => {
206 impl $Periph {
207 pub fn set_receive_address(&mut self, address: u32) {
209 self.$periph
210 .rpr
211 .write(|w| unsafe { w.rxptr().bits(address) });
212 }
213
214 pub fn set_receive_counter(&mut self, count: u16) {
217 self.$periph.rcr.write(|w| unsafe { w.rxctr().bits(count) });
218 }
219
220 pub fn set_receive_next_address(&mut self, address: u32) {
222 self.$periph
223 .rnpr
224 .write(|w| unsafe { w.rxnptr().bits(address) });
225 }
226
227 pub fn set_receive_next_counter(&mut self, count: u16) {
230 self.$periph
231 .rncr
232 .write(|w| unsafe { w.rxnctr().bits(count) });
233 }
234
235 pub fn start_rx_pdc(&mut self) {
237 unsafe { self.$periph.ptcr.write_with_zero(|w| w.rxten().set_bit()) };
238 }
239
240 pub fn stop_rx_pdc(&mut self) {
242 unsafe { self.$periph.ptcr.write_with_zero(|w| w.rxtdis().set_bit()) };
243 }
244
245 pub fn active_rx_pdc(&self) -> bool {
247 self.$periph.ptsr.read().rxten().bit()
248 }
249
250 pub fn rx_in_progress(&self) -> bool {
253 !self.$periph.$isr.read().rxbuff().bit()
254 }
255
256 pub fn enable_endrx_interrupt(&mut self) {
259 unsafe { self.$periph.ier.write_with_zero(|w| w.endrx().set_bit()) };
260 }
261
262 pub fn disable_endrx_interrupt(&mut self) {
264 unsafe { self.$periph.idr.write_with_zero(|w| w.endrx().set_bit()) };
265 }
266
267 pub fn enable_rxbuff_interrupt(&mut self) {
270 unsafe { self.$periph.ier.write_with_zero(|w| w.rxbuff().set_bit()) };
271 }
272
273 pub fn disable_rxbuff_interrupt(&mut self) {
275 unsafe { self.$periph.idr.write_with_zero(|w| w.rxbuff().set_bit()) };
276 }
277 }
278 };
279}
280pub(crate) use pdc_rx;
281
282macro_rules! pdc_tx {
283 (
284 $Periph:ident: $periph:ident, $isr:ident
285 ) => {
286 impl $Periph {
287 pub fn set_transmit_address(&mut self, address: u32) {
289 self.$periph
290 .tpr
291 .write(|w| unsafe { w.txptr().bits(address) });
292 }
293
294 pub fn set_transmit_counter(&mut self, count: u16) {
297 self.$periph.tcr.write(|w| unsafe { w.txctr().bits(count) });
298 }
299
300 pub fn set_transmit_next_address(&mut self, address: u32) {
302 self.$periph
303 .tnpr
304 .write(|w| unsafe { w.txnptr().bits(address) });
305 }
306
307 pub fn set_transmit_next_counter(&mut self, count: u16) {
310 self.$periph
311 .tncr
312 .write(|w| unsafe { w.txnctr().bits(count) });
313 }
314
315 pub fn start_tx_pdc(&mut self) {
317 unsafe {
318 self.$periph.ptcr.write_with_zero(|w| w.txten().set_bit());
319 }
320 }
321
322 pub fn stop_tx_pdc(&mut self) {
324 unsafe {
325 self.$periph.ptcr.write_with_zero(|w| w.txtdis().set_bit());
326 }
327 }
328
329 pub fn active_tx_pdc(&self) -> bool {
331 self.$periph.ptsr.read().txten().bit()
332 }
333
334 pub fn tx_in_progress(&self) -> bool {
337 !self.$periph.$isr.read().txbufe().bit()
338 }
339
340 pub fn enable_endtx_interrupt(&mut self) {
343 unsafe {
344 self.$periph.ier.write_with_zero(|w| w.endtx().set_bit());
345 }
346 }
347
348 pub fn disable_endtx_interrupt(&mut self) {
350 unsafe {
351 self.$periph.idr.write_with_zero(|w| w.endtx().set_bit());
352 }
353 }
354
355 pub fn enable_txbufe_interrupt(&mut self) {
358 unsafe {
359 self.$periph.ier.write_with_zero(|w| w.txbufe().set_bit());
360 }
361 }
362
363 pub fn disable_txbufe_interrupt(&mut self) {
365 unsafe {
366 self.$periph.idr.write_with_zero(|w| w.txbufe().set_bit());
367 }
368 }
369 }
370 };
371}
372pub(crate) use pdc_tx;
373
374macro_rules! pdc_rxtx {
375 (
376 $Periph:ident: $periph:ident
377 ) => {
378 impl $Periph {
379 pub fn start_rxtx_pdc(&mut self) {
381 unsafe {
382 self.$periph
383 .ptcr
384 .write_with_zero(|w| w.txten().set_bit().rxten().set_bit());
385 }
386 }
387
388 pub fn stop_rxtx_pdc(&mut self) {
390 unsafe {
391 self.$periph
392 .ptcr
393 .write_with_zero(|w| w.txtdis().set_bit().rxtdis().set_bit());
394 }
395 }
396 }
397 };
398}
399pub(crate) use pdc_rxtx;