@@ -4,7 +4,10 @@ use core::ptr;
4
4
5
5
use crate :: hal:: spi:: FullDuplex ;
6
6
pub use crate :: hal:: spi:: { Mode , Phase , Polarity } ;
7
- use crate :: pac:: { SPI1 , SPI2 , SPI3 } ;
7
+ use crate :: pac:: {
8
+ spi1:: cr2:: { DS_A , FRXTH_A } ,
9
+ SPI1 , SPI2 , SPI3 ,
10
+ } ;
8
11
use crate :: stm32:: spi1;
9
12
10
13
use crate :: gpio:: gpioa:: { PA5 , PA6 , PA7 } ;
@@ -47,6 +50,7 @@ use crate::rcc::APB1;
47
50
) ) ]
48
51
use crate :: rcc:: APB2 ;
49
52
use crate :: time:: Hertz ;
53
+ use core:: marker:: PhantomData ;
50
54
51
55
/// SPI error
52
56
#[ derive( Debug ) ]
@@ -104,16 +108,33 @@ unsafe impl MosiPin<SPI2> for PB15<AF5> {}
104
108
unsafe impl MosiPin < SPI3 > for PB5 < AF6 > { }
105
109
unsafe impl MosiPin < SPI3 > for PC12 < AF6 > { }
106
110
111
+ pub trait Word {
112
+ fn register_config ( ) -> ( FRXTH_A , DS_A ) ;
113
+ }
114
+
115
+ impl Word for u8 {
116
+ fn register_config ( ) -> ( FRXTH_A , DS_A ) {
117
+ ( FRXTH_A :: QUARTER , DS_A :: EIGHTBIT )
118
+ }
119
+ }
120
+
121
+ impl Word for u16 {
122
+ fn register_config ( ) -> ( FRXTH_A , DS_A ) {
123
+ ( FRXTH_A :: HALF , DS_A :: SIXTEENBIT )
124
+ }
125
+ }
126
+
107
127
/// SPI peripheral operating in full duplex master mode
108
- pub struct Spi < SPI , PINS > {
128
+ pub struct Spi < SPI , PINS , WORD = u8 > {
109
129
spi : SPI ,
110
130
pins : PINS ,
131
+ _word : PhantomData < WORD > ,
111
132
}
112
133
113
134
macro_rules! hal {
114
135
( $( $SPIX: ident: ( $spiX: ident, $APBX: ident, $spiXen: ident, $spiXrst: ident, $pclkX: ident) , ) +) => {
115
136
$(
116
- impl <SCK , MISO , MOSI > Spi <$SPIX, ( SCK , MISO , MOSI ) > {
137
+ impl <SCK , MISO , MOSI , WORD > Spi <$SPIX, ( SCK , MISO , MOSI ) , WORD > {
117
138
/// Configures the SPI peripheral to operate in full duplex master mode
118
139
pub fn $spiX<F >(
119
140
spi: $SPIX,
@@ -128,17 +149,20 @@ macro_rules! hal {
128
149
SCK : SckPin <$SPIX>,
129
150
MISO : MisoPin <$SPIX>,
130
151
MOSI : MosiPin <$SPIX>,
152
+ WORD : Word ,
131
153
{
132
154
// enable or reset $SPIX
133
155
apb2. enr( ) . modify( |_, w| w. $spiXen( ) . enabled( ) ) ;
134
156
apb2. rstr( ) . modify( |_, w| w. $spiXrst( ) . reset( ) ) ;
135
157
apb2. rstr( ) . modify( |_, w| w. $spiXrst( ) . clear_bit( ) ) ;
136
158
137
- // FRXTH: RXNE event is generated if the FIFO level is greater than or equal to
138
- // 8-bit
139
- // DS: 8-bit data size
140
- // SSOE: Slave Select output disabled
141
- spi. cr2. write( |w| w. frxth( ) . quarter( ) . ds( ) . eight_bit( ) . ssoe( ) . disabled( ) ) ;
159
+ let ( frxth, ds) = WORD :: register_config( ) ;
160
+ spi. cr2. write( |w| {
161
+ w. frxth( ) . variant( frxth) ;
162
+ w. ds( ) . variant( ds) ;
163
+ // Slave Select output disabled
164
+ w. ssoe( ) . disabled( )
165
+ } ) ;
142
166
143
167
// CPHA: phase
144
168
// CPOL: polarity
@@ -179,7 +203,7 @@ macro_rules! hal {
179
203
. unidirectional( )
180
204
} ) ;
181
205
182
- Spi { spi, pins }
206
+ Spi { spi, pins, _word : PhantomData }
183
207
}
184
208
185
209
/// Releases the SPI peripheral and associated pins
@@ -216,10 +240,10 @@ macro_rules! hal {
216
240
217
241
}
218
242
219
- impl <PINS > FullDuplex <u8 > for Spi <$SPIX, PINS > {
243
+ impl <PINS , WORD > FullDuplex <WORD > for Spi <$SPIX, PINS , WORD > {
220
244
type Error = Error ;
221
245
222
- fn read( & mut self ) -> nb:: Result <u8 , Error > {
246
+ fn read( & mut self ) -> nb:: Result <WORD , Error > {
223
247
let sr = self . spi. sr. read( ) ;
224
248
225
249
Err ( if sr. ovr( ) . is_overrun( ) {
@@ -229,17 +253,16 @@ macro_rules! hal {
229
253
} else if sr. crcerr( ) . is_no_match( ) {
230
254
nb:: Error :: Other ( Error :: Crc )
231
255
} else if sr. rxne( ) . is_not_empty( ) {
232
- // NOTE(read_volatile) read only 1 byte (the svd2rust API only allows
233
- // reading a half-word)
234
- return Ok ( unsafe {
235
- ptr:: read_volatile( & self . spi. dr as * const _ as * const u8 )
236
- } ) ;
256
+ let read_ptr = & self . spi. dr as * const _ as * const WORD ;
257
+ // NOTE(unsafe) read from register owned by this Spi struct
258
+ let value = unsafe { ptr:: read_volatile( read_ptr) } ;
259
+ return Ok ( value) ;
237
260
} else {
238
261
nb:: Error :: WouldBlock
239
262
} )
240
263
}
241
264
242
- fn send( & mut self , byte : u8 ) -> nb:: Result <( ) , Error > {
265
+ fn send( & mut self , word : WORD ) -> nb:: Result <( ) , Error > {
243
266
let sr = self . spi. sr. read( ) ;
244
267
245
268
Err ( if sr. ovr( ) . is_overrun( ) {
@@ -249,18 +272,18 @@ macro_rules! hal {
249
272
} else if sr. crcerr( ) . is_no_match( ) {
250
273
nb:: Error :: Other ( Error :: Crc )
251
274
} else if sr. txe( ) . is_empty( ) {
252
- // NOTE(write_volatile) see note above
253
- unsafe { ptr:: write_volatile( & self . spi. dr as * const _ as * mut u8 , byte) }
275
+ let write_ptr = & self . spi. dr as * const _ as * mut WORD ;
276
+ // NOTE(unsafe) write to register owned by this Spi struct
277
+ unsafe { ptr:: write_volatile( write_ptr, word) } ;
254
278
return Ok ( ( ) ) ;
255
279
} else {
256
280
nb:: Error :: WouldBlock
257
281
} )
258
282
}
259
283
}
260
284
261
- impl <PINS > crate :: hal:: blocking:: spi:: transfer:: Default <u8 > for Spi <$SPIX, PINS > { }
262
-
263
- impl <PINS > crate :: hal:: blocking:: spi:: write:: Default <u8 > for Spi <$SPIX, PINS > { }
285
+ impl <PINS , WORD > crate :: hal:: blocking:: spi:: transfer:: Default <WORD > for Spi <$SPIX, PINS , WORD > { }
286
+ impl <PINS , WORD > crate :: hal:: blocking:: spi:: write:: Default <WORD > for Spi <$SPIX, PINS , WORD > { }
264
287
) +
265
288
}
266
289
}
0 commit comments