3
3
4
4
mod utilities;
5
5
6
+ use embedded_dma:: { ReadBuffer , WriteBuffer } ;
6
7
use rtic:: app;
7
8
use stm32h5xx_hal:: {
8
- gpdma:: { periph:: DmaDuplex , DmaChannel0 , DmaChannel1 } ,
9
+ gpdma:: { periph:: DmaDuplex , DmaChannel0 , DmaChannel1 , Word } ,
9
10
gpio:: { Output , PA5 } ,
10
11
pac,
11
12
prelude:: * ,
@@ -15,11 +16,51 @@ use stm32h5xx_hal::{
15
16
use rtic_monotonics:: systick:: prelude:: * ;
16
17
systick_monotonic ! ( Mono , 1000 ) ;
17
18
19
+ // Buffer is used to manage a reference to a static buffer returned by the cortex_m::singleton!
20
+ // macro and which can be with the DmaTransfer API (which requires passing ReadBuffer and
21
+ // WriteBuffer implementations by value) and then used to access the buffer after the transfer has
22
+ // completed.
23
+ struct Buffer < T : Word + ' static , const N : usize > {
24
+ data : & ' static mut [ T ; N ] ,
25
+ }
26
+
27
+ impl < T , const N : usize > Buffer < T , N >
28
+ where
29
+ T : Word + ' static ,
30
+ {
31
+ fn new ( data : & ' static mut [ T ; N ] ) -> Self {
32
+ Self { data }
33
+ }
34
+ }
35
+
36
+ unsafe impl < T , const N : usize > ReadBuffer for & mut Buffer < T , N >
37
+ where
38
+ T : Word + ' static ,
39
+ {
40
+ type Word = T ;
41
+
42
+ unsafe fn read_buffer ( & self ) -> ( * const Self :: Word , usize ) {
43
+ ( self . data . as_ptr ( ) , N )
44
+ }
45
+ }
46
+
47
+ unsafe impl < T , const N : usize > WriteBuffer for & mut Buffer < T , N >
48
+ where
49
+ T : Word + ' static ,
50
+ {
51
+ type Word = T ;
52
+
53
+ unsafe fn write_buffer ( & mut self ) -> ( * mut Self :: Word , usize ) {
54
+ ( self . data . as_mut_ptr ( ) , N )
55
+ }
56
+ }
57
+
18
58
#[ app( device = pac, dispatchers = [ USART1 , USART2 ] , peripherals = true ) ]
19
59
mod app {
20
60
61
+ use core:: cell:: Cell ;
62
+
21
63
use cortex_m:: singleton;
22
- use embedded_dma:: { ReadBuffer , WriteBuffer } ;
23
64
use stm32h5:: stm32h503:: { GPDMA1 , NVIC } ;
24
65
25
66
use super :: * ;
@@ -34,8 +75,8 @@ mod app {
34
75
pac:: SPI2 ,
35
76
DmaDuplex < pac:: SPI2 , u8 , DmaChannel0 < GPDMA1 > , DmaChannel1 < GPDMA1 > > ,
36
77
> ,
37
- source : & ' static mut [ u8 ; 40 ] ,
38
- dest : & ' static mut [ u8 ; 40 ] ,
78
+ source : Cell < Buffer < u8 , 40 > > ,
79
+ dest : Cell < Buffer < u8 , 40 > > ,
39
80
}
40
81
41
82
#[ init]
@@ -86,15 +127,18 @@ mod app {
86
127
NVIC :: unmask ( pac:: interrupt:: GPDMA1_CH1 ) ;
87
128
} ;
88
129
130
+ let src = singleton ! ( : [ u8 ; 40 ] = [ 0 ; 40 ] ) . unwrap ( ) ;
131
+ let dest = singleton ! ( : [ u8 ; 40 ] = [ 0 ; 40 ] ) . unwrap ( ) ;
132
+
89
133
tick:: spawn ( ) . unwrap ( ) ;
90
134
spi_transfer:: spawn ( ) . unwrap ( ) ;
91
135
(
92
136
Shared { } ,
93
137
Local {
94
138
led,
95
139
spi,
96
- source : singleton ! ( : [ u8 ; 40 ] = [ 0 ; 40 ] ) . unwrap ( ) ,
97
- dest : singleton ! ( : [ u8 ; 40 ] = [ 0 ; 40 ] ) . unwrap ( ) ,
140
+ source : Cell :: new ( Buffer :: new ( src ) ) ,
141
+ dest : Cell :: new ( Buffer :: new ( dest ) ) ,
98
142
} ,
99
143
)
100
144
}
@@ -113,19 +157,19 @@ mod app {
113
157
async fn spi_transfer ( ctx : spi_transfer:: Context ) {
114
158
loop {
115
159
log:: info!( "Starting SPI transfer" ) ;
116
- ctx. local . source . fill ( * ctx. local . count as u8 ) ;
117
- ctx. local . dest . fill ( 0 ) ;
118
160
119
- let ( src_ptr, src_len) = unsafe { ctx. local . source . read_buffer ( ) } ;
120
- let src = unsafe { core:: slice:: from_raw_parts ( src_ptr, src_len) } ;
121
- let ( dest_ptr, dest_len) = unsafe { ctx. local . dest . write_buffer ( ) } ;
122
- let dest =
123
- unsafe { core:: slice:: from_raw_parts_mut ( dest_ptr, dest_len) } ;
161
+ let src = ctx. local . source . get_mut ( ) ;
162
+ let dest = ctx. local . dest . get_mut ( ) ;
163
+ src. data . fill ( * ctx. local . count as u8 ) ;
164
+ dest. data . fill ( 0 ) ;
124
165
125
166
* ctx. local . count += 1 ;
126
167
ctx. local . spi . transfer_dma ( src, dest) . await . unwrap ( ) ;
127
168
128
- assert_eq ! ( * ctx. local. source, * ctx. local. dest) ;
169
+ assert_eq ! (
170
+ * ctx. local. source. get_mut( ) . data,
171
+ * ctx. local. dest. get_mut( ) . data
172
+ ) ;
129
173
log:: info!( "Success!" ) ;
130
174
Mono :: delay ( 1000 . millis ( ) ) . await ;
131
175
}
0 commit comments