1
1
//! # Direct Memory Access
2
2
#![ allow( dead_code) ]
3
3
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 } ;
6
9
7
10
use crate :: rcc:: AHB ;
8
11
9
12
#[ derive( Debug ) ]
13
+ #[ non_exhaustive]
10
14
pub enum Error {
11
15
Overrun ,
12
- #[ doc( hidden) ]
13
- _Extensible,
14
16
}
15
17
16
18
pub enum Event {
33
35
readable_half : Half ,
34
36
}
35
37
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
+ {
37
43
pub ( crate ) fn new ( buf : & ' static mut [ BUFFER ; 2 ] , payload : PAYLOAD ) -> Self {
38
44
CircBuffer {
39
45
buffer : buf,
@@ -43,22 +49,6 @@ impl<BUFFER, PAYLOAD> CircBuffer<BUFFER, PAYLOAD> {
43
49
}
44
50
}
45
51
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
-
62
52
pub trait DmaExt {
63
53
type Channels ;
64
54
@@ -70,13 +60,19 @@ pub trait TransferPayload {
70
60
fn stop ( & mut self ) ;
71
61
}
72
62
73
- pub struct Transfer < MODE , BUFFER , PAYLOAD > {
63
+ pub struct Transfer < MODE , BUFFER , PAYLOAD >
64
+ where
65
+ PAYLOAD : TransferPayload ,
66
+ {
74
67
_mode : PhantomData < MODE > ,
75
68
buffer : BUFFER ,
76
69
payload : PAYLOAD ,
77
70
}
78
71
79
- impl < BUFFER , PAYLOAD > Transfer < R , BUFFER , PAYLOAD > {
72
+ impl < BUFFER , PAYLOAD > Transfer < R , BUFFER , PAYLOAD >
73
+ where
74
+ PAYLOAD : TransferPayload ,
75
+ {
80
76
pub ( crate ) fn r ( buffer : BUFFER , payload : PAYLOAD ) -> Self {
81
77
Transfer {
82
78
_mode : PhantomData ,
@@ -86,7 +82,10 @@ impl<BUFFER, PAYLOAD> Transfer<R, BUFFER, PAYLOAD> {
86
82
}
87
83
}
88
84
89
- impl < BUFFER , PAYLOAD > Transfer < W , BUFFER , PAYLOAD > {
85
+ impl < BUFFER , PAYLOAD > Transfer < W , BUFFER , PAYLOAD >
86
+ where
87
+ PAYLOAD : TransferPayload ,
88
+ {
90
89
pub ( crate ) fn w ( buffer : BUFFER , payload : PAYLOAD ) -> Self {
91
90
Transfer {
92
91
_mode : PhantomData ,
@@ -96,11 +95,13 @@ impl<BUFFER, PAYLOAD> Transfer<W, BUFFER, PAYLOAD> {
96
95
}
97
96
}
98
97
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 ) ;
104
105
}
105
106
}
106
107
@@ -123,14 +124,14 @@ macro_rules! dma {
123
124
} ) , ) +) => {
124
125
$(
125
126
pub mod $dmaX {
126
- use core:: sync:: atomic:: { self , Ordering } ;
127
- use core:: ptr;
127
+ use core:: { sync:: atomic:: { self , Ordering } , ptr, mem} ;
128
128
129
129
use crate :: pac:: { $DMAX, dma1} ;
130
130
131
131
use crate :: dma:: { CircBuffer , DmaExt , Error , Event , Half , Transfer , W , RxDma , TxDma , TransferPayload } ;
132
132
use crate :: rcc:: { AHB , Enable } ;
133
133
134
+ #[ allow( clippy:: manual_non_exhaustive) ]
134
135
pub struct Channels ( ( ) , $( pub $CX) ,+) ;
135
136
136
137
$(
@@ -316,7 +317,19 @@ macro_rules! dma {
316
317
// we need a fence here for the same reason we need one in `Transfer.wait`
317
318
atomic:: compiler_fence( Ordering :: Acquire ) ;
318
319
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
+ }
320
333
}
321
334
}
322
335
@@ -342,11 +355,23 @@ macro_rules! dma {
342
355
// we need a fence here for the same reason we need one in `Transfer.wait`
343
356
atomic:: compiler_fence( Ordering :: Acquire ) ;
344
357
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
+ }
346
371
}
347
372
}
348
373
349
- impl <BUFFER , PAYLOAD > Transfer <W , & ' static mut BUFFER , RxDma <PAYLOAD , $CX>>
374
+ impl <BUFFER , PAYLOAD > Transfer <W , BUFFER , RxDma <PAYLOAD , $CX>>
350
375
where
351
376
RxDma <PAYLOAD , $CX>: TransferPayload ,
352
377
{
@@ -480,27 +505,30 @@ pub trait Transmit {
480
505
type ReceivedWord ;
481
506
}
482
507
508
+ /// Trait for circular DMA readings from peripheral to memory.
483
509
pub trait CircReadDma < B , RS > : Receive
484
510
where
485
- B : as_slice:: AsMutSlice < Element = RS > ,
511
+ & ' static mut [ B ; 2 ] : StaticWriteBuffer < Word = RS > ,
512
+ B : ' static ,
486
513
Self : core:: marker:: Sized ,
487
514
{
488
515
fn circ_read ( self , buffer : & ' static mut [ B ; 2 ] ) -> CircBuffer < B , Self > ;
489
516
}
490
517
518
+ /// Trait for DMA readings from peripheral to memory.
491
519
pub trait ReadDma < B , RS > : Receive
492
520
where
493
- B : as_slice :: AsMutSlice < Element = RS > ,
494
- Self : core:: marker:: Sized ,
521
+ B : StaticWriteBuffer < Word = RS > ,
522
+ Self : core:: marker:: Sized + TransferPayload ,
495
523
{
496
- fn read ( self , buffer : & ' static mut B ) -> Transfer < W , & ' static mut B , Self > ;
524
+ fn read ( self , buffer : B ) -> Transfer < W , B , Self > ;
497
525
}
498
526
499
- pub trait WriteDma < A , B , TS > : Transmit
527
+ /// Trait for DMA writing from memory to peripheral.
528
+ pub trait WriteDma < B , TS > : Transmit
500
529
where
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 ,
504
532
{
505
533
fn write ( self , buffer : B ) -> Transfer < R , B , Self > ;
506
534
}
0 commit comments