@@ -351,10 +351,16 @@ pub enum Event {
351
351
Error ,
352
352
}
353
353
354
+ /// Normal mode - RX and TX pins are independent
355
+ pub struct TransferModeNormal ;
356
+ /// BIDI mode - use TX pin as RX then spi receive data
357
+ pub struct TransferModeBidi ;
358
+
354
359
#[ derive( Debug ) ]
355
- pub struct Spi < SPI , PINS > {
360
+ pub struct Spi < SPI , PINS , TRANSFER_MODE > {
356
361
spi : SPI ,
357
362
pins : PINS ,
363
+ transfer_mode : TRANSFER_MODE ,
358
364
}
359
365
360
366
// Implemented by all SPI instances
@@ -368,7 +374,7 @@ macro_rules! spi {
368
374
( $SPI: ident: ( $spi: ident) ) => {
369
375
impl Instance for $SPI { }
370
376
371
- impl <SCK , MISO , MOSI > Spi <$SPI, ( SCK , MISO , MOSI ) >
377
+ impl <SCK , MISO , MOSI > Spi <$SPI, ( SCK , MISO , MOSI ) , TransferModeNormal >
372
378
where
373
379
SCK : PinSck <$SPI>,
374
380
MISO : PinMiso <$SPI>,
@@ -381,7 +387,7 @@ macro_rules! spi {
381
387
mode: Mode ,
382
388
freq: Hertz ,
383
389
clocks: Clocks ,
384
- ) -> Self {
390
+ ) -> Spi <$SPI , ( SCK , MISO , MOSI ) , TransferModeNormal > {
385
391
Self :: new( spi, pins, mode, freq, clocks)
386
392
}
387
393
}
@@ -403,30 +409,106 @@ spi! { SPI5: (spi5) }
403
409
#[ cfg( feature = "spi6" ) ]
404
410
spi ! { SPI6 : ( spi6) }
405
411
406
- impl < SPI , SCK , MISO , MOSI > Spi < SPI , ( SCK , MISO , MOSI ) >
412
+ impl < SPI , SCK , MISO , MOSI > Spi < SPI , ( SCK , MISO , MOSI ) , TransferModeNormal >
407
413
where
408
414
SPI : Instance ,
409
415
SCK : PinSck < SPI > ,
410
416
MISO : PinMiso < SPI > ,
411
417
MOSI : PinMosi < SPI > ,
412
418
{
413
- pub fn new ( spi : SPI , pins : ( SCK , MISO , MOSI ) , mode : Mode , freq : Hertz , clocks : Clocks ) -> Self {
419
+ pub fn new (
420
+ spi : SPI ,
421
+ pins : ( SCK , MISO , MOSI ) ,
422
+ mode : Mode ,
423
+ freq : Hertz ,
424
+ clocks : Clocks ,
425
+ ) -> Spi < SPI , ( SCK , MISO , MOSI ) , TransferModeNormal > {
426
+ unsafe {
427
+ // NOTE(unsafe) this reference will only be used for atomic writes with no side effects.
428
+ let rcc = & ( * RCC :: ptr ( ) ) ;
429
+ SPI :: enable ( rcc) ;
430
+ SPI :: reset ( rcc) ;
431
+ }
432
+
433
+ Spi {
434
+ spi,
435
+ pins,
436
+ transfer_mode : TransferModeNormal ,
437
+ }
438
+ . pre_init ( mode, freq, SPI :: get_frequency ( & clocks) )
439
+ . init ( )
440
+ }
441
+
442
+ pub fn new_bidi (
443
+ spi : SPI ,
444
+ pins : ( SCK , MISO , MOSI ) ,
445
+ mode : Mode ,
446
+ freq : Hertz ,
447
+ clocks : Clocks ,
448
+ ) -> Spi < SPI , ( SCK , MISO , MOSI ) , TransferModeBidi > {
414
449
unsafe {
415
450
// NOTE(unsafe) this reference will only be used for atomic writes with no side effects.
416
451
let rcc = & ( * RCC :: ptr ( ) ) ;
417
452
SPI :: enable ( rcc) ;
418
453
SPI :: reset ( rcc) ;
419
454
}
420
455
421
- Spi { spi, pins } . init ( mode, freq, SPI :: get_frequency ( & clocks) )
456
+ Spi {
457
+ spi,
458
+ pins,
459
+ transfer_mode : TransferModeBidi ,
460
+ }
461
+ . pre_init ( mode, freq, SPI :: get_frequency ( & clocks) )
462
+ . init ( )
422
463
}
423
464
}
424
465
425
- impl < SPI , PINS > Spi < SPI , PINS >
466
+ impl < SPI , PINS > Spi < SPI , PINS , TransferModeNormal >
426
467
where
427
468
SPI : Instance ,
428
469
{
429
- pub fn init ( self , mode : Mode , freq : Hertz , clock : Hertz ) -> Self {
470
+ pub fn init ( self ) -> Self {
471
+ self . spi . cr1 . modify ( |_, w| {
472
+ // bidimode: 2-line unidirectional
473
+ w. bidimode ( )
474
+ . clear_bit ( )
475
+ . bidioe ( )
476
+ . clear_bit ( )
477
+ // spe: enable the SPI bus
478
+ . spe ( )
479
+ . set_bit ( )
480
+ } ) ;
481
+
482
+ self
483
+ }
484
+ }
485
+
486
+ impl < SPI , PINS > Spi < SPI , PINS , TransferModeBidi >
487
+ where
488
+ SPI : Instance ,
489
+ {
490
+ pub fn init ( self ) -> Self {
491
+ self . spi . cr1 . modify ( |_, w| {
492
+ // bidimode: 1-line unidirectional
493
+ w. bidimode ( )
494
+ . set_bit ( )
495
+ . bidioe ( )
496
+ . set_bit ( )
497
+ // spe: enable the SPI bus
498
+ . spe ( )
499
+ . set_bit ( )
500
+ } ) ;
501
+
502
+ self
503
+ }
504
+ }
505
+
506
+ impl < SPI , PINS , TRANSFER_MODE > Spi < SPI , PINS , TRANSFER_MODE >
507
+ where
508
+ SPI : Instance ,
509
+ {
510
+ /// Pre initializing the SPI bus.
511
+ pub fn pre_init ( self , mode : Mode , freq : Hertz , clock : Hertz ) -> Self {
430
512
// disable SS output
431
513
self . spi . cr2 . write ( |w| w. ssoe ( ) . clear_bit ( ) ) ;
432
514
@@ -466,12 +548,6 @@ where
466
548
// dff: 8 bit frames
467
549
. dff ( )
468
550
. clear_bit ( )
469
- // bidimode: 2-line unidirectional
470
- . bidimode ( )
471
- . clear_bit ( )
472
- // spe: enable the SPI bus
473
- . spe ( )
474
- . set_bit ( )
475
551
} ) ;
476
552
477
553
self
@@ -533,15 +609,9 @@ where
533
609
pub fn free ( self ) -> ( SPI , PINS ) {
534
610
( self . spi , self . pins )
535
611
}
536
- }
537
612
538
- impl < SPI , PINS > spi:: FullDuplex < u8 > for Spi < SPI , PINS >
539
- where
540
- SPI : Instance ,
541
- {
542
- type Error = Error ;
543
-
544
- fn read ( & mut self ) -> nb:: Result < u8 , Error > {
613
+ #[ inline( always) ]
614
+ fn check_read ( & mut self ) -> nb:: Result < u8 , Error > {
545
615
let sr = self . spi . sr . read ( ) ;
546
616
547
617
Err ( if sr. ovr ( ) . bit_is_set ( ) {
@@ -551,15 +621,14 @@ where
551
621
} else if sr. crcerr ( ) . bit_is_set ( ) {
552
622
Error :: Crc . into ( )
553
623
} else if sr. rxne ( ) . bit_is_set ( ) {
554
- // NOTE(read_volatile) read only 1 byte (the svd2rust API only allows
555
- // reading a half-word)
556
- return Ok ( unsafe { ptr:: read_volatile ( & self . spi . dr as * const _ as * const u8 ) } ) ;
624
+ return Ok ( self . read_u8 ( ) ) ;
557
625
} else {
558
626
nb:: Error :: WouldBlock
559
627
} )
560
628
}
561
629
562
- fn send ( & mut self , byte : u8 ) -> nb:: Result < ( ) , Error > {
630
+ #[ inline( always) ]
631
+ fn check_send ( & mut self , byte : u8 ) -> nb:: Result < ( ) , Error > {
563
632
let sr = self . spi . sr . read ( ) ;
564
633
565
634
Err ( if sr. ovr ( ) . bit_is_set ( ) {
@@ -578,21 +647,79 @@ where
578
647
} ) ;
579
648
Error :: Crc . into ( )
580
649
} else if sr. txe ( ) . bit_is_set ( ) {
581
- // NOTE(write_volatile) see note above
582
- unsafe { ptr:: write_volatile ( & self . spi . dr as * const _ as * mut u8 , byte) }
583
- return Ok ( ( ) ) ;
650
+ return Ok ( self . send_u8 ( byte) ) ;
584
651
} else {
585
652
nb:: Error :: WouldBlock
586
653
} )
587
654
}
655
+
656
+ #[ inline( always) ]
657
+ fn read_u8 ( & mut self ) -> u8 {
658
+ // NOTE(read_volatile) read only 1 byte (the svd2rust API only allows reading a half-word)
659
+ unsafe { ptr:: read_volatile ( & self . spi . dr as * const _ as * const u8 ) }
660
+ }
661
+
662
+ #[ inline( always) ]
663
+ fn send_u8 ( & mut self , byte : u8 ) {
664
+ // NOTE(write_volatile) see note above
665
+ unsafe { ptr:: write_volatile ( & self . spi . dr as * const _ as * mut u8 , byte) }
666
+ }
588
667
}
589
668
590
- impl < SPI , PINS > embedded_hal:: blocking:: spi:: transfer:: Default < u8 > for Spi < SPI , PINS > where
591
- SPI : Instance
669
+ impl < SPI , PINS > spi:: FullDuplex < u8 > for Spi < SPI , PINS , TransferModeNormal >
670
+ where
671
+ SPI : Instance ,
672
+ {
673
+ type Error = Error ;
674
+
675
+ fn read ( & mut self ) -> nb:: Result < u8 , Error > {
676
+ self . check_read ( )
677
+ }
678
+
679
+ fn send ( & mut self , byte : u8 ) -> nb:: Result < ( ) , Error > {
680
+ self . check_send ( byte)
681
+ }
682
+ }
683
+
684
+ impl < SPI , PINS > spi:: FullDuplex < u8 > for Spi < SPI , PINS , TransferModeBidi >
685
+ where
686
+ SPI : Instance ,
687
+ {
688
+ type Error = Error ;
689
+
690
+ fn read ( & mut self ) -> nb:: Result < u8 , Error > {
691
+ self . spi . cr1 . modify ( |_, w| w. bidioe ( ) . clear_bit ( ) ) ;
692
+ self . check_read ( )
693
+ }
694
+
695
+ fn send ( & mut self , byte : u8 ) -> nb:: Result < ( ) , Error > {
696
+ self . spi . cr1 . modify ( |_, w| w. bidioe ( ) . set_bit ( ) ) ;
697
+ self . check_send ( byte)
698
+ }
699
+ }
700
+
701
+ impl < SPI , PINS > embedded_hal:: blocking:: spi:: transfer:: Default < u8 >
702
+ for Spi < SPI , PINS , TransferModeNormal >
703
+ where
704
+ SPI : Instance ,
705
+ {
706
+ }
707
+
708
+ impl < SPI , PINS > embedded_hal:: blocking:: spi:: write:: Default < u8 >
709
+ for Spi < SPI , PINS , TransferModeNormal >
710
+ where
711
+ SPI : Instance ,
712
+ {
713
+ }
714
+
715
+ impl < SPI , PINS > embedded_hal:: blocking:: spi:: transfer:: Default < u8 >
716
+ for Spi < SPI , PINS , TransferModeBidi >
717
+ where
718
+ SPI : Instance ,
592
719
{
593
720
}
594
721
595
- impl < SPI , PINS > embedded_hal:: blocking:: spi:: write:: Default < u8 > for Spi < SPI , PINS > where
722
+ impl < SPI , PINS > embedded_hal:: blocking:: spi:: write:: Default < u8 > for Spi < SPI , PINS , TransferModeBidi > where
596
723
SPI : Instance
597
724
{
598
725
}
0 commit comments