11//! # Direct Memory Access
22#![ allow( dead_code) ]
33
4- use core:: marker:: PhantomData ;
5- use core:: ops;
4+ use core:: {
5+ marker:: PhantomData ,
6+ sync:: atomic:: { compiler_fence, Ordering } ,
7+ } ;
8+ use embedded_dma:: { StaticReadBuffer , StaticWriteBuffer } ;
69
710use crate :: rcc:: AHB ;
811
912#[ derive( Debug ) ]
13+ #[ non_exhaustive]
1014pub enum Error {
1115 Overrun ,
12- #[ doc( hidden) ]
13- _Extensible,
1416}
1517
1618pub enum Event {
3335 readable_half : Half ,
3436}
3537
36- impl < BUFFER , PAYLOAD > CircBuffer < BUFFER , PAYLOAD > {
38+ impl < BUFFER , PAYLOAD > CircBuffer < BUFFER , PAYLOAD >
39+ where
40+ & ' static mut [ BUFFER ; 2 ] : StaticWriteBuffer ,
41+ BUFFER : ' static ,
42+ {
3743 pub ( crate ) fn new ( buf : & ' static mut [ BUFFER ; 2 ] , payload : PAYLOAD ) -> Self {
3844 CircBuffer {
3945 buffer : buf,
@@ -43,22 +49,6 @@ impl<BUFFER, PAYLOAD> CircBuffer<BUFFER, PAYLOAD> {
4349 }
4450}
4551
46- pub trait Static < B > {
47- fn borrow ( & self ) -> & B ;
48- }
49-
50- impl < B > Static < B > for & ' static B {
51- fn borrow ( & self ) -> & B {
52- * self
53- }
54- }
55-
56- impl < B > Static < B > for & ' static mut B {
57- fn borrow ( & self ) -> & B {
58- * self
59- }
60- }
61-
6252pub trait DmaExt {
6353 type Channels ;
6454
@@ -70,13 +60,19 @@ pub trait TransferPayload {
7060 fn stop ( & mut self ) ;
7161}
7262
73- pub struct Transfer < MODE , BUFFER , PAYLOAD > {
63+ pub struct Transfer < MODE , BUFFER , PAYLOAD >
64+ where
65+ PAYLOAD : TransferPayload ,
66+ {
7467 _mode : PhantomData < MODE > ,
7568 buffer : BUFFER ,
7669 payload : PAYLOAD ,
7770}
7871
79- impl < BUFFER , PAYLOAD > Transfer < R , BUFFER , PAYLOAD > {
72+ impl < BUFFER , PAYLOAD > Transfer < R , BUFFER , PAYLOAD >
73+ where
74+ PAYLOAD : TransferPayload ,
75+ {
8076 pub ( crate ) fn r ( buffer : BUFFER , payload : PAYLOAD ) -> Self {
8177 Transfer {
8278 _mode : PhantomData ,
@@ -86,7 +82,10 @@ impl<BUFFER, PAYLOAD> Transfer<R, BUFFER, PAYLOAD> {
8682 }
8783}
8884
89- impl < BUFFER , PAYLOAD > Transfer < W , BUFFER , PAYLOAD > {
85+ impl < BUFFER , PAYLOAD > Transfer < W , BUFFER , PAYLOAD >
86+ where
87+ PAYLOAD : TransferPayload ,
88+ {
9089 pub ( crate ) fn w ( buffer : BUFFER , payload : PAYLOAD ) -> Self {
9190 Transfer {
9291 _mode : PhantomData ,
@@ -96,11 +95,13 @@ impl<BUFFER, PAYLOAD> Transfer<W, BUFFER, PAYLOAD> {
9695 }
9796}
9897
99- impl < BUFFER , PAYLOAD > ops:: Deref for Transfer < R , BUFFER , PAYLOAD > {
100- type Target = BUFFER ;
101-
102- fn deref ( & self ) -> & BUFFER {
103- & self . buffer
98+ impl < MODE , BUFFER , PAYLOAD > Drop for Transfer < MODE , BUFFER , PAYLOAD >
99+ where
100+ PAYLOAD : TransferPayload ,
101+ {
102+ fn drop ( & mut self ) {
103+ self . payload . stop ( ) ;
104+ compiler_fence ( Ordering :: SeqCst ) ;
104105 }
105106}
106107
@@ -123,14 +124,14 @@ macro_rules! dma {
123124 } ) , ) +) => {
124125 $(
125126 pub mod $dmaX {
126- use core:: sync:: atomic:: { self , Ordering } ;
127- use core:: ptr;
127+ use core:: { sync:: atomic:: { self , Ordering } , ptr, mem} ;
128128
129129 use crate :: pac:: { $DMAX, dma1} ;
130130
131131 use crate :: dma:: { CircBuffer , DmaExt , Error , Event , Half , Transfer , W , RxDma , TxDma , TransferPayload } ;
132132 use crate :: rcc:: { AHB , Enable } ;
133133
134+ #[ allow( clippy:: manual_non_exhaustive) ]
134135 pub struct Channels ( ( ) , $( pub $CX) ,+) ;
135136
136137 $(
@@ -316,7 +317,19 @@ macro_rules! dma {
316317 // we need a fence here for the same reason we need one in `Transfer.wait`
317318 atomic:: compiler_fence( Ordering :: Acquire ) ;
318319
319- ( self . buffer, self . payload)
320+ // `Transfer` needs to have a `Drop` implementation, because we accept
321+ // managed buffers that can free their memory on drop. Because of that
322+ // we can't move out of the `Transfer`'s fields, so we use `ptr::read`
323+ // and `mem::forget`.
324+ //
325+ // NOTE(unsafe) There is no panic branch between getting the resources
326+ // and forgetting `self`.
327+ unsafe {
328+ let buffer = ptr:: read( & self . buffer) ;
329+ let payload = ptr:: read( & self . payload) ;
330+ mem:: forget( self ) ;
331+ ( buffer, payload)
332+ }
320333 }
321334 }
322335
@@ -342,11 +355,23 @@ macro_rules! dma {
342355 // we need a fence here for the same reason we need one in `Transfer.wait`
343356 atomic:: compiler_fence( Ordering :: Acquire ) ;
344357
345- ( self . buffer, self . payload)
358+ // `Transfer` needs to have a `Drop` implementation, because we accept
359+ // managed buffers that can free their memory on drop. Because of that
360+ // we can't move out of the `Transfer`'s fields, so we use `ptr::read`
361+ // and `mem::forget`.
362+ //
363+ // NOTE(unsafe) There is no panic branch between getting the resources
364+ // and forgetting `self`.
365+ unsafe {
366+ let buffer = ptr:: read( & self . buffer) ;
367+ let payload = ptr:: read( & self . payload) ;
368+ mem:: forget( self ) ;
369+ ( buffer, payload)
370+ }
346371 }
347372 }
348373
349- impl <BUFFER , PAYLOAD > Transfer <W , & ' static mut BUFFER , RxDma <PAYLOAD , $CX>>
374+ impl <BUFFER , PAYLOAD > Transfer <W , BUFFER , RxDma <PAYLOAD , $CX>>
350375 where
351376 RxDma <PAYLOAD , $CX>: TransferPayload ,
352377 {
@@ -480,27 +505,30 @@ pub trait Transmit {
480505 type ReceivedWord ;
481506}
482507
508+ /// Trait for circular DMA readings from peripheral to memory.
483509pub trait CircReadDma < B , RS > : Receive
484510where
485- B : as_slice:: AsMutSlice < Element = RS > ,
511+ & ' static mut [ B ; 2 ] : StaticWriteBuffer < Word = RS > ,
512+ B : ' static ,
486513 Self : core:: marker:: Sized ,
487514{
488515 fn circ_read ( self , buffer : & ' static mut [ B ; 2 ] ) -> CircBuffer < B , Self > ;
489516}
490517
518+ /// Trait for DMA readings from peripheral to memory.
491519pub trait ReadDma < B , RS > : Receive
492520where
493- B : as_slice :: AsMutSlice < Element = RS > ,
494- Self : core:: marker:: Sized ,
521+ B : StaticWriteBuffer < Word = RS > ,
522+ Self : core:: marker:: Sized + TransferPayload ,
495523{
496- fn read ( self , buffer : & ' static mut B ) -> Transfer < W , & ' static mut B , Self > ;
524+ fn read ( self , buffer : B ) -> Transfer < W , B , Self > ;
497525}
498526
499- pub trait WriteDma < A , B , TS > : Transmit
527+ /// Trait for DMA writing from memory to peripheral.
528+ pub trait WriteDma < B , TS > : Transmit
500529where
501- A : as_slice:: AsSlice < Element = TS > ,
502- B : Static < A > ,
503- Self : core:: marker:: Sized ,
530+ B : StaticReadBuffer < Word = TS > ,
531+ Self : core:: marker:: Sized + TransferPayload ,
504532{
505533 fn write ( self , buffer : B ) -> Transfer < R , B , Self > ;
506534}
0 commit comments