3737#[ cfg( esp32) ]
3838use core:: cell:: Cell ;
3939use core:: {
40+ cell:: RefCell ,
4041 future:: Future ,
4142 marker:: PhantomData ,
4243 pin:: Pin ,
@@ -639,6 +640,16 @@ struct SpiPinGuard {
639640 sio_pins : [ PinGuard ; SIO_PIN_COUNT ] ,
640641}
641642
643+ impl SpiPinGuard {
644+ const fn new_unconnected ( ) -> Self {
645+ Self {
646+ sclk_pin : PinGuard :: new_unconnected ( ) ,
647+ cs_pin : PinGuard :: new_unconnected ( ) ,
648+ sio_pins : [ const { PinGuard :: new_unconnected ( ) } ; SIO_PIN_COUNT ] ,
649+ }
650+ }
651+ }
652+
642653/// Configuration errors.
643654#[ non_exhaustive]
644655#[ derive( Debug , Clone , Copy , PartialEq , Eq , Hash ) ]
@@ -659,6 +670,42 @@ impl core::fmt::Display for ConfigError {
659670 }
660671 }
661672}
673+
674+ #[ derive( Debug ) ]
675+ #[ cfg_attr( feature = "defmt" , derive( defmt:: Format ) ) ]
676+ struct SpiWrapper < ' d > {
677+ spi : AnySpi < ' d > ,
678+ _guard : PeripheralGuard ,
679+ }
680+
681+ impl SpiWrapper < ' _ > {
682+ fn info ( & self ) -> & ' static Info {
683+ self . spi . info ( )
684+ }
685+
686+ fn state ( & self ) -> & ' static State {
687+ self . spi . state ( )
688+ }
689+
690+ fn parts ( & self ) -> ( & ' static Info , & ' static State ) {
691+ self . spi . parts ( )
692+ }
693+
694+ fn disable_peri_interrupt_on_all_cores ( & self ) {
695+ self . spi . disable_peri_interrupt_on_all_cores ( ) ;
696+ }
697+
698+ fn set_interrupt_handler ( & self , handler : InterruptHandler ) {
699+ self . spi . set_interrupt_handler ( handler) ;
700+ }
701+ }
702+
703+ impl Drop for SpiWrapper < ' _ > {
704+ fn drop ( & mut self ) {
705+ self . spi . state ( ) . deinit ( ) ;
706+ }
707+ }
708+
662709#[ procmacros:: doc_replace]
663710/// SPI peripheral driver
664711///
@@ -684,10 +731,8 @@ impl core::fmt::Display for ConfigError {
684731#[ derive( Debug ) ]
685732#[ cfg_attr( feature = "defmt" , derive( defmt:: Format ) ) ]
686733pub struct Spi < ' d , Dm : DriverMode > {
687- spi : AnySpi < ' d > ,
734+ spi : SpiWrapper < ' d > ,
688735 _mode : PhantomData < Dm > ,
689- guard : PeripheralGuard ,
690- pins : SpiPinGuard ,
691736}
692737
693738impl < Dm : DriverMode > Sealed for Spi < ' _ , Dm > { }
@@ -715,17 +760,14 @@ impl<'d> Spi<'d, Blocking> {
715760 /// # {after_snippet}
716761 /// ```
717762 pub fn new ( spi : impl Instance + ' d , config : Config ) -> Result < Self , ConfigError > {
718- let guard = PeripheralGuard :: new ( spi. info ( ) . peripheral ) ;
763+ let _guard = PeripheralGuard :: new ( spi. info ( ) . peripheral ) ;
719764
720765 let mut this = Spi {
721766 _mode : PhantomData ,
722- guard,
723- pins : SpiPinGuard {
724- sclk_pin : PinGuard :: new_unconnected ( ) ,
725- cs_pin : PinGuard :: new_unconnected ( ) ,
726- sio_pins : [ const { PinGuard :: new_unconnected ( ) } ; SIO_PIN_COUNT ] ,
767+ spi : SpiWrapper {
768+ spi : spi. degrade ( ) ,
769+ _guard,
727770 } ,
728- spi : spi. degrade ( ) ,
729771 } ;
730772
731773 this. driver ( ) . init ( ) ;
@@ -754,8 +796,6 @@ impl<'d> Spi<'d, Blocking> {
754796 Spi {
755797 spi : self . spi ,
756798 _mode : PhantomData ,
757- guard : self . guard ,
758- pins : self . pins ,
759799 }
760800 }
761801
@@ -803,8 +843,6 @@ impl<'d> Spi<'d, Async> {
803843 Spi {
804844 spi : self . spi ,
805845 _mode : PhantomData ,
806- guard : self . guard ,
807- pins : self . pins ,
808846 }
809847 }
810848
@@ -900,8 +938,9 @@ macro_rules! def_with_sio_pin {
900938 #[ doc = " Enables both input and output functionality for the pin, and connects it" ]
901939 #[ doc = concat!( " to the SIO" , stringify!( $n) , " output and input signals." ) ]
902940 #[ instability:: unstable]
903- pub fn $fn( mut self , sio: impl PeripheralInput <' d> + PeripheralOutput <' d>) -> Self {
904- self . pins. sio_pins[ $n] = self . connect_sio_pin( sio. into( ) , $n) ;
941+ pub fn $fn( self , sio: impl PeripheralInput <' d> + PeripheralOutput <' d>) -> Self {
942+ self . driver( ) . state. pins. borrow_mut( ) . sio_pins[ $n] =
943+ self . connect_sio_pin( sio. into( ) , $n) ;
905944
906945 self
907946 }
@@ -963,8 +1002,9 @@ where
9631002 ///
9641003 /// # {after_snippet}
9651004 /// ```
966- pub fn with_sck ( mut self , sclk : impl PeripheralOutput < ' d > ) -> Self {
967- self . pins . sclk_pin = self . connect_output_pin ( sclk. into ( ) , self . driver ( ) . info . sclk ) ;
1005+ pub fn with_sck ( self , sclk : impl PeripheralOutput < ' d > ) -> Self {
1006+ let ( info, state) = self . spi . parts ( ) ;
1007+ state. pins . borrow_mut ( ) . sclk_pin = self . connect_output_pin ( sclk. into ( ) , info. sclk ) ;
9681008
9691009 self
9701010 }
@@ -991,8 +1031,9 @@ where
9911031 ///
9921032 /// # {after_snippet}
9931033 /// ```
994- pub fn with_mosi ( mut self , mosi : impl PeripheralOutput < ' d > ) -> Self {
995- self . pins . sio_pins [ 0 ] = self . connect_sio_output_pin ( mosi. into ( ) , 0 ) ;
1034+ pub fn with_mosi ( self , mosi : impl PeripheralOutput < ' d > ) -> Self {
1035+ self . driver ( ) . state . pins . borrow_mut ( ) . sio_pins [ 0 ] =
1036+ self . connect_sio_output_pin ( mosi. into ( ) , 0 ) ;
9961037
9971038 self
9981039 }
@@ -1042,8 +1083,8 @@ where
10421083 /// See also [Self::with_mosi] when you only need a one-directional MOSI
10431084 /// signal.
10441085 #[ instability:: unstable]
1045- pub fn with_sio0 ( mut self , mosi : impl PeripheralInput < ' d > + PeripheralOutput < ' d > ) -> Self {
1046- self . pins . sio_pins [ 0 ] = self . connect_sio_pin ( mosi. into ( ) , 0 ) ;
1086+ pub fn with_sio0 ( self , mosi : impl PeripheralInput < ' d > + PeripheralOutput < ' d > ) -> Self {
1087+ self . driver ( ) . state . pins . borrow_mut ( ) . sio_pins [ 0 ] = self . connect_sio_pin ( mosi. into ( ) , 0 ) ;
10471088
10481089 self
10491090 }
@@ -1060,8 +1101,8 @@ where
10601101 /// See also [Self::with_miso] when you only need a one-directional MISO
10611102 /// signal.
10621103 #[ instability:: unstable]
1063- pub fn with_sio1 ( mut self , sio1 : impl PeripheralInput < ' d > + PeripheralOutput < ' d > ) -> Self {
1064- self . pins . sio_pins [ 1 ] = self . connect_sio_pin ( sio1. into ( ) , 1 ) ;
1104+ pub fn with_sio1 ( self , sio1 : impl PeripheralInput < ' d > + PeripheralOutput < ' d > ) -> Self {
1105+ self . driver ( ) . state . pins . borrow_mut ( ) . sio_pins [ 1 ] = self . connect_sio_pin ( sio1. into ( ) , 1 ) ;
10651106
10661107 self
10671108 }
@@ -1093,8 +1134,10 @@ where
10931134 /// be set, regardless of the total number available. There is no
10941135 /// mechanism to select which CS line to use.
10951136 #[ instability:: unstable]
1096- pub fn with_cs ( mut self , cs : impl PeripheralOutput < ' d > ) -> Self {
1097- self . pins . cs_pin = self . connect_output_pin ( cs. into ( ) , self . driver ( ) . info . cs ( 0 ) ) ;
1137+ pub fn with_cs ( self , cs : impl PeripheralOutput < ' d > ) -> Self {
1138+ let ( info, state) = self . spi . parts ( ) ;
1139+ state. pins . borrow_mut ( ) . cs_pin = self . connect_output_pin ( cs. into ( ) , info. cs ( 0 ) ) ;
1140+
10981141 self
10991142 }
11001143
@@ -2417,6 +2460,8 @@ for_each_spi_master! {
24172460
24182461 static STATE : State = State {
24192462 waker: AtomicWaker :: new( ) ,
2463+ pins: RefCell :: new( SpiPinGuard :: new_unconnected( ) ) ,
2464+
24202465 #[ cfg( esp32) ]
24212466 esp32_hack: Esp32Hack {
24222467 timing_miso_delay: Cell :: new( None ) ,
@@ -2441,19 +2486,25 @@ impl QspiInstance for AnySpi<'_> {}
24412486#[ doc( hidden) ]
24422487pub struct State {
24432488 waker : AtomicWaker ,
2489+ pins : RefCell < SpiPinGuard > ,
24442490
24452491 #[ cfg( esp32) ]
24462492 esp32_hack : Esp32Hack ,
24472493}
24482494
2495+ impl State {
2496+ fn deinit ( & self ) {
2497+ * self . pins . borrow_mut ( ) = SpiPinGuard :: new_unconnected ( ) ;
2498+ }
2499+ }
2500+
24492501#[ cfg( esp32) ]
24502502struct Esp32Hack {
24512503 timing_miso_delay : Cell < Option < u8 > > ,
24522504 extra_dummy : Cell < u8 > ,
24532505}
24542506
2455- #[ cfg( esp32) ]
2456- unsafe impl Sync for Esp32Hack { }
2507+ unsafe impl Sync for State { }
24572508
24582509#[ ram]
24592510fn handle_async ( info : & ' static Info , state : & ' static State ) {
0 commit comments