@@ -267,6 +267,14 @@ macro_rules! spi {
267
267
. cr1
268
268
. modify( |_, w| w. bidimode( ) . clear_bit( ) . bidioe( ) . clear_bit( ) ) ;
269
269
}
270
+ fn fifo_cap( & self ) -> u8 {
271
+ match self . spi. sr. read( ) . ftlvl( ) . bits( ) {
272
+ 0 => 4 ,
273
+ 1 => 3 ,
274
+ 2 => 2 ,
275
+ _ => 0 ,
276
+ }
277
+ }
270
278
}
271
279
272
280
impl SpiExt <$SPIX> for $SPIX {
@@ -286,21 +294,23 @@ macro_rules! spi {
286
294
impl <PINS > embedded_hal_one:: spi:: SpiBus for Spi <$SPIX, PINS > {
287
295
fn read( & mut self , words: & mut [ u8 ] ) -> Result <( ) , Self :: Error > {
288
296
if words. len( ) == 0 { return Ok ( ( ) ) }
289
- // clear tx-only status in the case the previous operation was a write
290
- self . set_bidi( ) ;
297
+
291
298
// prefill write fifo so that the clock doen't stop while fetch the read byte
292
- // one frame should be enough?
293
- nb:: block!( self . nb_write( 0u8 ) ) ?;
299
+ let prefill = self . fifo_cap( ) as usize ;
300
+ for _ in 0 ..prefill {
301
+ nb:: block!( self . nb_write( 0u8 ) ) ?;
302
+ }
303
+
294
304
let len = words. len( ) ;
295
- for r in words[ ..len-1 ] . iter_mut( ) {
305
+ for r in words[ ..len-prefill ] . iter_mut( ) {
296
306
// TODO: 16 bit frames, bidirectional pins
297
307
nb:: block!( self . nb_write( 0u8 ) ) ?;
298
308
// errors have been checked by the write above
299
309
* r = unsafe { nb:: block!( self . nb_read_no_err( ) ) . unwrap_unchecked( ) } ;
300
310
}
301
- // safety: length > 0 checked at start of function
302
- * words . last_mut ( ) . unwrap ( ) = nb:: block!( self . nb_read( ) ) ?;
303
- Ok ( ( ) )
311
+ Ok ( for r in words [ len-prefill.. ] . iter_mut ( ) {
312
+ * r = nb:: block!( self . nb_read( ) ) ?;
313
+ } )
304
314
}
305
315
306
316
fn write( & mut self , words: & [ u8 ] ) -> Result <( ) , Self :: Error > {
@@ -321,17 +331,28 @@ macro_rules! spi {
321
331
return self . read( read)
322
332
}
323
333
324
- self . set_bidi( ) ;
334
+ let prefill = self . fifo_cap( ) ;
335
+ let mut write_iter = write. into_iter( ) ;
336
+
325
337
// same prefill as in read, this time with actual data
326
- nb:: block!( self . nb_write( write[ 0 ] ) ) ?;
338
+ let mut prefilled = 0 ;
339
+ for b in write_iter. by_ref( ) . take( prefill as usize ) {
340
+ nb:: block!( self . nb_write( * b) ) ?;
341
+ prefilled += 1
342
+ }
343
+
327
344
let common_len = core:: cmp:: min( read. len( ) , write. len( ) ) ;
328
- // take 1 less because write skips the first element
329
- let zipped = read. iter_mut( ) . zip( write . into_iter ( ) . skip ( 1 ) ) . take( common_len - 1 ) ;
345
+ // write ahead of reading
346
+ let zipped = read. iter_mut( ) . zip( write_iter ) . take( common_len - prefilled ) ;
330
347
for ( r, w) in zipped {
331
348
nb:: block!( self . nb_write( * w) ) ?;
332
349
* r = unsafe { nb:: block!( self . nb_read_no_err( ) ) . unwrap_unchecked( ) } ;
333
350
}
334
- read[ common_len-1 ] = nb:: block!( self . nb_read( ) ) ?;
351
+
352
+ // read words left in the fifo
353
+ for r in read[ common_len-prefilled..common_len] . iter_mut( ) {
354
+ * r = nb:: block!( self . nb_read( ) ) ?
355
+ }
335
356
336
357
if read. len( ) > common_len {
337
358
self . read( & mut read[ common_len..] )
@@ -341,19 +362,25 @@ macro_rules! spi {
341
362
}
342
363
fn transfer_in_place( & mut self , words: & mut [ u8 ] ) -> Result <( ) , Self :: Error > {
343
364
if words. len( ) == 0 { return Ok ( ( ) ) }
344
- self . set_bidi( ) ;
345
- nb:: block!( self . nb_write( words[ 0 ] ) ) ?;
365
+
346
366
let cells = core:: cell:: Cell :: from_mut( words) . as_slice_of_cells( ) ;
367
+ let mut write_iter = cells. into_iter( ) ;
368
+ let mut read_iter = cells. into_iter( ) ;
369
+
370
+ let prefill = self . fifo_cap( ) ;
347
371
348
- for rw in cells. windows( 2 ) {
349
- let r = & rw[ 0 ] ;
350
- let w = & rw[ 1 ] ;
351
-
372
+ for w in write_iter. by_ref( ) . take( prefill as usize ) {
373
+ nb:: block!( self . nb_write( w. get( ) ) ) ?;
374
+ }
375
+
376
+ for ( r, w) in write_iter. zip( read_iter. by_ref( ) ) {
352
377
nb:: block!( self . nb_write( w. get( ) ) ) ?;
353
378
r. set( unsafe { nb:: block!( self . nb_read_no_err( ) ) . unwrap_unchecked( ) } ) ;
354
379
}
355
- * words. last_mut( ) . unwrap( ) = nb:: block!( self . nb_read( ) ) ?;
356
- Ok ( ( ) )
380
+
381
+ Ok ( for r in read_iter {
382
+ r. set( nb:: block!( self . nb_read( ) ) ?) ;
383
+ } )
357
384
}
358
385
fn flush( & mut self ) -> Result <( ) , Self :: Error > {
359
386
let catch = |spi: & mut Self | {
0 commit comments