@@ -275,6 +275,19 @@ macro_rules! spi {
275
275
_ => 0 ,
276
276
}
277
277
}
278
+ fn flush_inner( & mut self ) -> Result <( ) , Error > {
279
+ // stop receiving data
280
+ self . set_tx_only( ) ;
281
+ self . spi. cr2. modify( |_, w| w. frxth( ) . set_bit( ) ) ;
282
+ // drain rx fifo
283
+ while match self . nb_read:: <u8 >( ) {
284
+ Ok ( _) => true ,
285
+ Err ( nb:: Error :: WouldBlock ) => false ,
286
+ Err ( nb:: Error :: Other ( e) ) => { return Err ( e) }
287
+ } { core:: hint:: spin_loop( ) } ;
288
+ // wait for idle
289
+ Ok ( while self . spi. sr. read( ) . bsy( ) . bit( ) { core:: hint:: spin_loop( ) } )
290
+ }
278
291
}
279
292
280
293
impl SpiExt <$SPIX> for $SPIX {
@@ -291,13 +304,13 @@ macro_rules! spi {
291
304
type Error = Error ;
292
305
}
293
306
294
- impl <PINS > embedded_hal_one:: spi:: SpiBus for Spi <$SPIX, PINS > {
307
+ impl <PINS > embedded_hal_one:: spi:: SpiBus < u8 > for Spi <$SPIX, PINS > {
295
308
fn read( & mut self , words: & mut [ u8 ] ) -> Result <( ) , Self :: Error > {
296
309
let len = words. len( ) ;
297
310
if len == 0 { return Ok ( ( ) ) }
298
311
299
312
// flush data from previous operations, otherwise we'd get unwanted data
300
- self . flush ( ) ?;
313
+ self . flush_inner ( ) ?;
301
314
// FIFO threshold to 16 bits
302
315
self . spi. cr2. modify( |_, w| w. frxth( ) . clear_bit( ) ) ;
303
316
self . set_bidi( ) ;
@@ -312,9 +325,7 @@ macro_rules! spi {
312
325
}
313
326
314
327
for r in words. chunks_exact_mut( 2 ) . take( half_len - prefill) {
315
- let r_two: u16 = unsafe {
316
- nb:: block!( self . nb_read_no_err( ) ) . unwrap_unchecked( )
317
- } ;
328
+ let r_two: u16 = nb:: block!( self . nb_read_no_err( ) ) . unwrap( ) ;
318
329
nb:: block!( self . nb_write( 0u16 ) ) ?;
319
330
// safety: chunks have exact length of 2
320
331
unsafe { * r. as_mut_ptr( ) . cast( ) = r_two. to_le_bytes( ) ; }
@@ -347,6 +358,7 @@ macro_rules! spi {
347
358
return self . read( read)
348
359
}
349
360
361
+ self . flush_inner( ) ?;
350
362
self . set_bidi( ) ;
351
363
let common_len = core:: cmp:: min( read. len( ) , write. len( ) ) ;
352
364
let half_len = common_len / 2 ;
@@ -372,9 +384,7 @@ macro_rules! spi {
372
384
// write ahead of reading
373
385
let zipped = read. chunks_exact_mut( 2 ) . zip( write_iter) . take( half_len - prefill) ;
374
386
for ( r, w) in zipped {
375
- let r_two: u16 = unsafe {
376
- nb:: block!( self . nb_read_no_err( ) ) . unwrap_unchecked( )
377
- } ;
387
+ let r_two: u16 = nb:: block!( self . nb_read_no_err( ) ) . unwrap( ) ;
378
388
nb:: block!( self . nb_write( w) ) ?;
379
389
// same as above, length is checked by chunks_exact
380
390
unsafe { * r. as_mut_ptr( ) . cast( ) = r_two. to_le_bytes( ) ; }
@@ -409,6 +419,7 @@ macro_rules! spi {
409
419
let len = words. len( ) ;
410
420
if len == 0 { return Ok ( ( ) ) }
411
421
422
+ self . flush_inner( ) ?;
412
423
self . set_bidi( ) ;
413
424
self . spi. cr2. modify( |_, w| w. frxth( ) . clear_bit( ) ) ;
414
425
let half_len = len / 2 ;
@@ -426,7 +437,7 @@ macro_rules! spi {
426
437
427
438
// data is in fifo isn't zero as long as words.len() > 1 so read-then-write is fine
428
439
for i in 0 ..words_alias. len( ) - prefill {
429
- let read: u16 = unsafe { nb:: block!( self . nb_read_no_err( ) ) . unwrap_unchecked ( ) } ;
440
+ let read: u16 = nb:: block!( self . nb_read_no_err( ) ) . unwrap ( ) ;
430
441
words_alias[ i] = read. to_le_bytes( ) ;
431
442
let write = u16 :: from_le_bytes( words_alias[ i + prefill] ) ;
432
443
nb:: block!( self . nb_write( write) ) ?;
@@ -450,16 +461,99 @@ macro_rules! spi {
450
461
} )
451
462
}
452
463
fn flush( & mut self ) -> Result <( ) , Self :: Error > {
453
- // stop receiving data
464
+ self . flush_inner( )
465
+ }
466
+ }
467
+ impl <PINS > embedded_hal_one:: spi:: SpiBus <u16 > for Spi <$SPIX, PINS > {
468
+ fn read( & mut self , words: & mut [ u16 ] ) -> Result <( ) , Self :: Error > {
469
+ let len = words. len( ) ;
470
+ if len == 0 { return Ok ( ( ) ) }
471
+ // flush data from previous operations, otherwise we'd get unwanted data
472
+ self . flush_inner( ) ?;
473
+ // FIFO threshold to 16 bits
474
+ self . spi. cr2. modify( |_, w| w. frxth( ) . clear_bit( ) ) ;
475
+ self . set_bidi( ) ;
476
+ // prefill write fifo so that the clock doen't stop while fetch the read byte
477
+ let prefill = core:: cmp:: min( self . tx_fifo_cap( ) as usize / 2 , len) ;
478
+ for _ in 0 ..prefill {
479
+ nb:: block!( self . nb_write( 0u16 ) ) ?;
480
+ }
481
+
482
+ for w in & mut words[ ..len-prefill] {
483
+ * w = nb:: block!( self . nb_read_no_err( ) ) . unwrap( ) ;
484
+ nb:: block!( self . nb_write( 0u16 ) ) ?;
485
+ }
486
+ Ok ( for w in & mut words[ len-prefill..] {
487
+ * w = nb:: block!( self . nb_read( ) ) ?;
488
+ } )
489
+ }
490
+ fn write( & mut self , words: & [ u16 ] ) -> Result <( ) , Self :: Error > {
454
491
self . set_tx_only( ) ;
455
- // drain rx fifo
456
- while match self . nb_read:: <u8 >( ) {
457
- Ok ( _) => true ,
458
- Err ( nb:: Error :: WouldBlock ) => false ,
459
- Err ( nb:: Error :: Other ( e) ) => { return Err ( e) }
460
- } { core:: hint:: spin_loop( ) } ;
461
- // wait for idle
462
- Ok ( while self . spi. sr. read( ) . bsy( ) . bit( ) { core:: hint:: spin_loop( ) } )
492
+ Ok ( for w in words {
493
+ nb:: block!( self . nb_write( * w) ) ?
494
+ } )
495
+ }
496
+ fn transfer( & mut self , read: & mut [ u16 ] , write: & [ u16 ] ) -> Result <( ) , Self :: Error > {
497
+ if read. len( ) == 0 {
498
+ return self . write( write)
499
+ } else if write. len( ) == 0 {
500
+ return self . read( read)
501
+ }
502
+
503
+ self . flush_inner( ) ?;
504
+ // FIFO threshold to 16 bits
505
+ self . spi. cr2. modify( |_, w| w. frxth( ) . clear_bit( ) ) ;
506
+ self . set_bidi( ) ;
507
+ let common_len = core:: cmp:: min( read. len( ) , write. len( ) ) ;
508
+ // same prefill as in read, this time with actual data
509
+ let prefill = core:: cmp:: min( self . tx_fifo_cap( ) as usize / 2 , common_len) ;
510
+
511
+ let mut write_iter = write. into_iter( ) ;
512
+ for w in write_iter. by_ref( ) . take( prefill) {
513
+ nb:: block!( self . nb_write( * w) ) ?;
514
+ }
515
+
516
+ let zipped = read. into_iter( ) . zip( write_iter) . take( common_len - prefill) ;
517
+ for ( r, w) in zipped {
518
+ * r = nb:: block!( self . nb_read_no_err( ) ) . unwrap( ) ;
519
+ nb:: block!( self . nb_write( * w) ) ?;
520
+ }
521
+
522
+ for r in & mut read[ common_len - prefill..common_len] {
523
+ * r = nb:: block!( self . nb_read( ) ) ?
524
+ }
525
+
526
+ if read. len( ) > common_len {
527
+ self . read( & mut read[ common_len..] )
528
+ } else {
529
+ self . write( & write[ common_len..] )
530
+ }
531
+ }
532
+ fn transfer_in_place( & mut self , words: & mut [ u16 ] ) -> Result <( ) , Self :: Error > {
533
+ let len = words. len( ) ;
534
+ if len == 0 { return Ok ( ( ) ) }
535
+
536
+ self . flush_inner( ) ?;
537
+ self . set_bidi( ) ;
538
+ self . spi. cr2. modify( |_, w| w. frxth( ) . clear_bit( ) ) ;
539
+ let prefill = core:: cmp:: min( self . tx_fifo_cap( ) as usize / 2 , len) ;
540
+
541
+ for w in & words[ ..prefill] {
542
+ nb:: block!( self . nb_write( * w) ) ?;
543
+ }
544
+
545
+ for read_idx in 0 ..len - prefill {
546
+ let write_idx = read_idx + prefill;
547
+ words[ read_idx] = nb:: block!( self . nb_read_no_err( ) ) . unwrap( ) ;
548
+ nb:: block!( self . nb_write( words[ write_idx] ) ) ?;
549
+ }
550
+
551
+ Ok ( for r in & mut words[ len - prefill..] {
552
+ * r = nb:: block!( self . nb_read( ) ) ?;
553
+ } )
554
+ }
555
+ fn flush( & mut self ) -> Result <( ) , Self :: Error > {
556
+ self . flush_inner( )
463
557
}
464
558
}
465
559
0 commit comments