@@ -37,6 +37,16 @@ pub enum Error {
37
37
Crc ,
38
38
}
39
39
40
+ impl embedded_hal_one:: spi:: Error for Error {
41
+ fn kind ( & self ) -> embedded_hal_one:: spi:: ErrorKind {
42
+ match self {
43
+ Self :: Overrun => embedded_hal_one:: spi:: ErrorKind :: Overrun ,
44
+ Self :: ModeFault => embedded_hal_one:: spi:: ErrorKind :: ModeFault ,
45
+ Self :: Crc => embedded_hal_one:: spi:: ErrorKind :: Other ,
46
+ }
47
+ }
48
+ }
49
+
40
50
/// A filler type for when the SCK pin is unnecessary
41
51
pub struct NoSck ;
42
52
/// A filler type for when the Miso pin is unnecessary
@@ -73,6 +83,17 @@ pub trait SpiExt<SPI>: Sized {
73
83
T : Into < Hertz > ;
74
84
}
75
85
86
+ pub trait FrameSize : Copy + Default {
87
+ const DFF : bool ;
88
+ }
89
+
90
+ impl FrameSize for u8 {
91
+ const DFF : bool = false ;
92
+ }
93
+ impl FrameSize for u16 {
94
+ const DFF : bool = true ;
95
+ }
96
+
76
97
macro_rules! spi {
77
98
( $SPIX: ident, $spiX: ident,
78
99
sck: [ $( $( #[ $pmetasck: meta ] ) * $SCK: ty, ) + ] ,
@@ -181,22 +202,9 @@ macro_rules! spi {
181
202
}
182
203
}
183
204
184
- impl SpiExt <$SPIX> for $SPIX {
185
- fn spi<PINS , T >( self , pins: PINS , mode: Mode , freq: T , rcc: & mut Rcc ) -> Spi <$SPIX, PINS >
186
- where
187
- PINS : Pins <$SPIX>,
188
- T : Into <Hertz >
189
- {
190
- Spi :: $spiX( self , pins, mode, freq, rcc)
191
- }
192
- }
193
-
194
- impl <PINS > hal:: spi:: FullDuplex <u8 > for Spi <$SPIX, PINS > {
195
- type Error = Error ;
196
-
197
- fn read( & mut self ) -> nb:: Result <u8 , Error > {
205
+ impl <PINS > Spi <$SPIX, PINS > {
206
+ fn nb_read<W : FrameSize >( & mut self ) -> nb:: Result <W , Error > {
198
207
let sr = self . spi. sr. read( ) ;
199
-
200
208
Err ( if sr. ovr( ) . bit_is_set( ) {
201
209
nb:: Error :: Other ( Error :: Overrun )
202
210
} else if sr. modf( ) . bit_is_set( ) {
@@ -207,31 +215,146 @@ macro_rules! spi {
207
215
// NOTE(read_volatile) read only 1 byte (the svd2rust API only allows
208
216
// reading a half-word)
209
217
return Ok ( unsafe {
210
- ptr:: read_volatile( & self . spi. dr as * const _ as * const u8 )
218
+ ptr:: read_volatile( & self . spi. dr as * const _ as * const W )
211
219
} ) ;
212
220
} else {
213
221
nb:: Error :: WouldBlock
214
222
} )
215
223
}
216
-
217
- fn send( & mut self , byte: u8 ) -> nb:: Result <( ) , Error > {
224
+ fn nb_write<W : FrameSize >( & mut self , word: W ) -> nb:: Result <( ) , Error > {
218
225
let sr = self . spi. sr. read( ) ;
219
-
220
226
Err ( if sr. ovr( ) . bit_is_set( ) {
221
227
nb:: Error :: Other ( Error :: Overrun )
222
228
} else if sr. modf( ) . bit_is_set( ) {
223
229
nb:: Error :: Other ( Error :: ModeFault )
224
230
} else if sr. crcerr( ) . bit_is_set( ) {
225
231
nb:: Error :: Other ( Error :: Crc )
226
232
} else if sr. txe( ) . bit_is_set( ) {
227
- let dr = & self . spi. dr as * const _ as * const UnsafeCell <u8 >;
233
+ let dr = & self . spi. dr as * const _ as * const UnsafeCell <W >;
228
234
// NOTE(write_volatile) see note above
229
- unsafe { ptr:: write_volatile( UnsafeCell :: raw_get( dr) , byte ) } ;
235
+ unsafe { ptr:: write_volatile( UnsafeCell :: raw_get( dr) , word ) } ;
230
236
return Ok ( ( ) ) ;
231
237
} else {
232
238
nb:: Error :: WouldBlock
233
239
} )
234
240
}
241
+ fn set_tx_only( & mut self ) {
242
+ self . spi
243
+ . cr1
244
+ . modify( |_, w| w. bidimode( ) . set_bit( ) . bidioe( ) . set_bit( ) ) ;
245
+ }
246
+ fn set_bidi( & mut self ) {
247
+ self . spi
248
+ . cr1
249
+ . modify( |_, w| w. bidimode( ) . clear_bit( ) . bidioe( ) . clear_bit( ) ) ;
250
+ }
251
+ }
252
+
253
+ impl SpiExt <$SPIX> for $SPIX {
254
+ fn spi<PINS , T >( self , pins: PINS , mode: Mode , freq: T , rcc: & mut Rcc ) -> Spi <$SPIX, PINS >
255
+ where
256
+ PINS : Pins <$SPIX>,
257
+ T : Into <Hertz >
258
+ {
259
+ Spi :: $spiX( self , pins, mode, freq, rcc)
260
+ }
261
+ }
262
+
263
+ impl <PINS > embedded_hal_one:: spi:: ErrorType for Spi <$SPIX, PINS > {
264
+ type Error = Error ;
265
+ }
266
+
267
+ impl <PINS > embedded_hal_one:: spi:: SpiBus for Spi <$SPIX, PINS > {
268
+ fn read( & mut self , words: & mut [ u8 ] ) -> Result <( ) , Self :: Error > {
269
+ if words. len( ) == 0 { return Ok ( ( ) ) }
270
+ // clear tx-only status in the case the previous operation was a write
271
+ self . set_bidi( ) ;
272
+ // prefill write fifo so that the clock doen't stop while fetch the read byte
273
+ // one frame should be enough?
274
+ nb:: block!( self . nb_write( 0u8 ) ) ?;
275
+ let len = words. len( ) ;
276
+ for w in words[ ..len-1 ] . iter_mut( ) {
277
+ // TODO: 16 bit frames, bidirectional pins
278
+ nb:: block!( self . nb_write( 0u8 ) ) ?;
279
+ * w = nb:: block!( self . nb_read( ) ) ?;
280
+ }
281
+ // safety: length > 0 checked at start of function
282
+ * words. last_mut( ) . unwrap( ) = nb:: block!( self . nb_read( ) ) ?;
283
+ Ok ( ( ) )
284
+ }
285
+
286
+ fn write( & mut self , words: & [ u8 ] ) -> Result <( ) , Self :: Error > {
287
+ self . set_tx_only( ) ;
288
+ Ok ( for w in words {
289
+ nb:: block!( self . nb_write( * w) ) ?
290
+ } )
291
+ }
292
+
293
+ fn transfer( & mut self , read: & mut [ u8 ] , write: & [ u8 ] ) -> Result <( ) , Self :: Error > {
294
+ if read. len( ) == 0 {
295
+ return self . write( write)
296
+ } else if write. len( ) == 0 {
297
+ return self . read( read)
298
+ }
299
+
300
+ self . set_bidi( ) ;
301
+ // same prefill as in read, this time with actual data
302
+ nb:: block!( self . nb_write( write[ 0 ] ) ) ?;
303
+ let common_len = core:: cmp:: min( read. len( ) , write. len( ) ) ;
304
+ // take 1 less because write skips the first element
305
+ let zipped = read. iter_mut( ) . zip( write. into_iter( ) . skip( 1 ) ) . take( common_len - 1 ) ;
306
+ for ( r, w) in zipped {
307
+ nb:: block!( self . nb_write( * w) ) ?;
308
+ * r = nb:: block!( self . nb_read( ) ) ?;
309
+ }
310
+ read[ common_len-1 ] = nb:: block!( self . nb_read( ) ) ?;
311
+
312
+ if read. len( ) > common_len {
313
+ self . read( & mut read[ common_len..] )
314
+ } else {
315
+ self . write( & write[ common_len..] )
316
+ }
317
+ }
318
+ fn transfer_in_place( & mut self , words: & mut [ u8 ] ) -> Result <( ) , Self :: Error > {
319
+ if words. len( ) == 0 { return Ok ( ( ) ) }
320
+ self . set_bidi( ) ;
321
+ nb:: block!( self . nb_write( words[ 0 ] ) ) ?;
322
+ let cells = core:: cell:: Cell :: from_mut( words) . as_slice_of_cells( ) ;
323
+
324
+ for rw in cells. windows( 2 ) {
325
+ let r = & rw[ 0 ] ;
326
+ let w = & rw[ 1 ] ;
327
+
328
+ nb:: block!( self . nb_write( w. get( ) ) ) ?;
329
+ r. set( nb:: block!( self . nb_read( ) ) ?) ;
330
+ }
331
+ * words. last_mut( ) . unwrap( ) = nb:: block!( self . nb_read( ) ) ?;
332
+ Ok ( ( ) )
333
+ }
334
+ fn flush( & mut self ) -> Result <( ) , Self :: Error > {
335
+ // stop receiving data
336
+ self . set_tx_only( ) ;
337
+ // wait for tx fifo to be drained by the peripheral
338
+ while self . spi. sr. read( ) . ftlvl( ) != 0 { core:: hint:: spin_loop( ) } ;
339
+ // drain rx fifo
340
+ Ok ( while match self . nb_read:: <u8 >( ) {
341
+ Ok ( _) => true ,
342
+ Err ( nb:: Error :: WouldBlock ) => false ,
343
+ Err ( nb:: Error :: Other ( e) ) => return Err ( e)
344
+ } { core:: hint:: spin_loop( ) } )
345
+ }
346
+ }
347
+
348
+ impl <PINS > hal:: spi:: FullDuplex <u8 > for Spi <$SPIX, PINS > {
349
+ type Error = Error ;
350
+
351
+ fn read( & mut self ) -> nb:: Result <u8 , Error > {
352
+ self . nb_read( )
353
+ }
354
+
355
+ fn send( & mut self , byte: u8 ) -> nb:: Result <( ) , Error > {
356
+ self . nb_write( byte)
357
+ }
235
358
}
236
359
unsafe impl <Pin > TargetAddress <MemoryToPeripheral > for Spi <$SPIX, Pin > {
237
360
#[ inline( always) ]
0 commit comments