@@ -236,7 +236,7 @@ macro_rules! spi {
236
236
} )
237
237
}
238
238
#[ inline]
239
- fn nb_read_no_err<W : FrameSize >( & mut self ) -> nb:: Result <W , ( ) > {
239
+ fn nb_read_no_err<W : FrameSize >( & mut self ) -> nb:: Result <W , core :: convert :: Infallible > {
240
240
if self . spi. sr. read( ) . rxne( ) . bit_is_set( ) {
241
241
Ok ( self . read_unchecked( ) )
242
242
} else {
@@ -267,7 +267,7 @@ 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 {
270
+ fn tx_fifo_cap ( & self ) -> u8 {
271
271
match self . spi. sr. read( ) . ftlvl( ) . bits( ) {
272
272
0 => 4 ,
273
273
1 => 3 ,
@@ -293,22 +293,22 @@ macro_rules! spi {
293
293
294
294
impl <PINS > embedded_hal_one:: spi:: SpiBus for Spi <$SPIX, PINS > {
295
295
fn read( & mut self , words: & mut [ u8 ] ) -> Result <( ) , Self :: Error > {
296
- if words. len( ) == 0 { return Ok ( ( ) ) }
296
+ let len = words. len( ) ;
297
+ if len == 0 { return Ok ( ( ) ) }
297
298
298
299
// FIFO threshold to 16 bits
299
300
self . spi. cr2. modify( |_, w| w. frxth( ) . clear_bit( ) ) ;
300
301
302
+ let half_len = len / 2 ;
303
+ let pair_left = len % 2 ;
304
+
301
305
// prefill write fifo so that the clock doen't stop while fetch the read byte
302
- let prefill = self . fifo_cap ( ) as usize / 2 ;
306
+ let prefill = core :: cmp :: min ( self . tx_fifo_cap ( ) as usize / 2 , half_len ) ;
303
307
for _ in 0 ..prefill {
304
308
nb:: block!( self . nb_write( 0u16 ) ) ?;
305
309
}
306
310
307
- let len = words. len( ) ;
308
- let half_len = len / 2 ;
309
- let pair_left = len % 2 ;
310
-
311
- for r in words. chunks_exact_mut( 2 ) . take( half_len-prefill) {
311
+ for r in words. chunks_exact_mut( 2 ) . take( half_len - prefill) {
312
312
nb:: block!( self . nb_write( 0u16 ) ) ?;
313
313
let r_two: u16 = unsafe {
314
314
nb:: block!( self . nb_read_no_err( ) ) . unwrap_unchecked( )
@@ -317,13 +317,15 @@ macro_rules! spi {
317
317
unsafe { * r. as_mut_ptr( ) . cast( ) = r_two. to_le_bytes( ) ; }
318
318
}
319
319
320
+ let odd_idx = len. saturating_sub( prefill + pair_left) ;
320
321
// FIFO threshold to 8 bits
321
322
self . spi. cr2. modify( |_, w| w. frxth( ) . set_bit( ) ) ;
322
323
if pair_left == 1 {
323
324
nb:: block!( self . nb_write( 0u8 ) ) ?;
325
+ words[ odd_idx] = nb:: block!( self . nb_read_no_err( ) ) . unwrap( ) ;
324
326
}
325
327
326
- Ok ( for r in words[ len - prefill - pair_left ..] . iter_mut( ) {
328
+ Ok ( for r in words[ odd_idx+ 1 ..] . iter_mut( ) {
327
329
* r = nb:: block!( self . nb_read( ) ) ?;
328
330
} )
329
331
}
@@ -351,31 +353,30 @@ macro_rules! spi {
351
353
let pair_left = common_len % 2 ;
352
354
353
355
// write two bytes at once
354
- let prefill = self . fifo_cap( ) / 2 ;
355
356
let mut write_iter = write. chunks_exact( 2 ) . map( |two|
356
357
// safety: chunks_exact guarantees that chunks have 2 elements
357
358
// second byte in send queue goes to the top of the 16-bit data register for
358
359
// packing
359
360
u16 :: from_le_bytes( unsafe { * two. as_ptr( ) . cast( ) } )
360
361
) ;
361
362
363
+ // FIFO threshold to 16 bits
364
+ self . spi. cr2. modify( |_, w| w. frxth( ) . clear_bit( ) ) ;
365
+
362
366
// same prefill as in read, this time with actual data
363
- let mut prefilled = 0 ;
364
- for b in write_iter. by_ref( ) . take( prefill as usize ) {
367
+ let prefill = core :: cmp :: min ( self . tx_fifo_cap ( ) as usize / 2 , half_len ) ;
368
+ for b in write_iter. by_ref( ) . take( prefill) {
365
369
nb:: block!( self . nb_write( b) ) ?;
366
- prefilled += 2
367
370
}
368
371
369
- // FIFO threshold to 16 bits
370
- self . spi. cr2. modify( |_, w| w. frxth( ) . clear_bit( ) ) ;
371
372
// write ahead of reading
372
- let zipped = read. chunks_exact_mut( 2 ) . zip( write_iter) . take( half_len - prefilled/ 2 ) ;
373
+ let zipped = read. chunks_exact_mut( 2 ) . zip( write_iter) . take( half_len - prefill ) ;
373
374
for ( r, w) in zipped {
374
375
375
- nb:: block!( self . nb_write( w) ) ?;
376
376
let r_two: u16 = unsafe {
377
377
nb:: block!( self . nb_read_no_err( ) ) . unwrap_unchecked( )
378
378
} ;
379
+ nb:: block!( self . nb_write( w) ) ?;
379
380
// same as above, length is checked by chunks_exact
380
381
unsafe { * r. as_mut_ptr( ) . cast( ) = r_two. to_le_bytes( ) ; }
381
382
}
@@ -385,11 +386,17 @@ macro_rules! spi {
385
386
386
387
if pair_left == 1 {
387
388
let write_idx = common_len - 1 ;
388
- nb:: block!( self . nb_write( write[ write_idx] ) ) ?;
389
+ if prefill == 0 {
390
+ nb:: block!( self . nb_write( write[ write_idx] ) ) ?;
391
+ read[ write_idx - 2 * prefill] = nb:: block!( self . nb_read_no_err( ) ) . unwrap( ) ;
392
+ } else { // there's already data in the fifo, so read that before writing more
393
+ read[ write_idx - 2 * prefill] = nb:: block!( self . nb_read_no_err( ) ) . unwrap( ) ;
394
+ nb:: block!( self . nb_write( write[ write_idx] ) ) ?;
395
+ }
389
396
}
390
397
391
398
// read words left in the fifo
392
- for r in read[ common_len-prefilled-pair_left ..common_len] . iter_mut( ) {
399
+ for r in read[ common_len-2 * prefill ..common_len] . iter_mut( ) {
393
400
* r = nb:: block!( self . nb_read( ) ) ?
394
401
}
395
402
@@ -407,35 +414,38 @@ macro_rules! spi {
407
414
let half_len = len / 2 ;
408
415
let pair_left = len % 2 ;
409
416
410
- let prefill = self . fifo_cap ( ) / 2 ;
417
+ let prefill = core :: cmp :: min ( self . tx_fifo_cap ( ) as usize / 2 , half_len ) ;
411
418
let words_alias: & mut [ [ u8 ; 2 ] ] = unsafe {
412
419
let ptr = words. as_mut_ptr( ) ;
413
420
core:: slice:: from_raw_parts_mut( ptr as * mut [ u8 ; 2 ] , half_len)
414
421
} ;
415
422
416
- let mut prefilled = 0 ;
417
423
for b in words_alias. into_iter( ) . take( prefill as usize ) {
418
424
nb:: block!( self . nb_write( u16 :: from_le_bytes( * b) ) ) ?;
419
- prefilled += 2
420
425
}
421
426
422
- for i in 0 ..words_alias. len( ) - prefilled/2 {
427
+ // data is in fifo isn't zero as long as words.len() > 1 so read-then-write is fine
428
+ for i in 0 ..words_alias. len( ) - prefill {
423
429
let read: u16 = unsafe { nb:: block!( self . nb_read_no_err( ) ) . unwrap_unchecked( ) } ;
424
430
words_alias[ i] = read. to_le_bytes( ) ;
425
- let write = u16 :: from_le_bytes( words_alias[ i + prefilled/ 2 ] ) ;
431
+ let write = u16 :: from_le_bytes( words_alias[ i + prefill ] ) ;
426
432
nb:: block!( self . nb_write( write) ) ?;
427
433
}
428
434
self . spi. cr2. modify( |_, w| w. frxth( ) . set_bit( ) ) ;
429
435
430
436
if pair_left == 1 {
431
- nb:: block!( self . nb_write( * words. last( ) . unwrap( ) ) ) ?;
432
- // reading in the last loop lets the rx buffer overrun for some reason i
433
- // haven't figured out, so we read here
434
- words[ len-prefilled-1 ] = nb:: block!( self . nb_read_no_err( ) ) . unwrap( ) ;
437
+ let read_idx = len - 2 * prefill - 1 ;
438
+ if prefill == 0 {
439
+ nb:: block!( self . nb_write( * words. last( ) . unwrap( ) ) ) ?;
440
+ words[ read_idx] = nb:: block!( self . nb_read_no_err( ) ) . unwrap( ) ;
441
+ } else {
442
+ words[ read_idx] = nb:: block!( self . nb_read_no_err( ) ) . unwrap( ) ;
443
+ nb:: block!( self . nb_write( * words. last( ) . unwrap( ) ) ) ?;
444
+ }
435
445
}
436
446
437
447
// read words left in the fifo
438
- Ok ( for r in words. iter_mut( ) . skip( len-prefilled ) {
448
+ Ok ( for r in words. iter_mut( ) . skip( len-2 * prefill ) {
439
449
* r = nb:: block!( self . nb_read( ) ) ?;
440
450
} )
441
451
}
0 commit comments