@@ -726,6 +726,19 @@ impl<SPI: Instance> Inner<SPI> {
726
726
self . spi . sr . read ( ) . ovr ( ) . bit_is_set ( )
727
727
}
728
728
729
+ fn check_errors ( & self ) -> Result < ( ) , Error > {
730
+ let sr = self . spi . sr . read ( ) ;
731
+ if sr. ovr ( ) . bit_is_set ( ) {
732
+ Err ( Error :: Overrun )
733
+ } else if sr. modf ( ) . bit_is_set ( ) {
734
+ Err ( Error :: ModeFault )
735
+ } else if sr. crcerr ( ) . bit_is_set ( ) {
736
+ Err ( Error :: Crc )
737
+ } else {
738
+ Ok ( ( ) )
739
+ }
740
+ }
741
+
729
742
#[ inline]
730
743
fn bidi_output ( & mut self ) {
731
744
self . spi . cr1 . modify ( |_, w| w. bidioe ( ) . set_bit ( ) ) ;
@@ -787,6 +800,39 @@ impl<SPI: Instance> Inner<SPI> {
787
800
nb:: Error :: WouldBlock
788
801
} )
789
802
}
803
+
804
+ // Implement write as per the "Transmit only procedure"
805
+ // RM SPI::3.5. This is more than twice as fast as the
806
+ // default Write<> implementation (which reads and drops each
807
+ // received value)
808
+ fn spi_write < const BIDI : bool , W : FrameSize > ( & mut self , words : impl IntoIterator < Item = W > ) -> Result < ( ) , Error > {
809
+ if BIDI {
810
+ self . bidi_output ( ) ;
811
+ }
812
+ // Write each word when the tx buffer is empty
813
+ for word in words {
814
+ loop {
815
+ let sr = self . spi . sr . read ( ) ;
816
+ if sr. txe ( ) . bit_is_set ( ) {
817
+ self . write_data_reg ( word) ;
818
+ if sr. modf ( ) . bit_is_set ( ) {
819
+ return Err ( Error :: ModeFault ) ;
820
+ }
821
+ break ;
822
+ }
823
+ }
824
+ }
825
+ // Wait for final TXE
826
+ while !self . is_tx_empty ( ) { }
827
+ // Wait for final !BSY
828
+ while self . is_busy ( ) { }
829
+ if !BIDI {
830
+ // Clear OVR set due to dropped received values
831
+ let _: W = self . read_data_reg ( ) ;
832
+ }
833
+ let _ = self . spi . sr . read ( ) ;
834
+ self . check_errors ( )
835
+ }
790
836
}
791
837
792
838
// Spi DMA
@@ -907,35 +953,11 @@ impl<SPI: Instance, const BIDI: bool, W: FrameSize> Spi<SPI, BIDI, W> {
907
953
}
908
954
909
955
pub fn write ( & mut self , words : & [ W ] ) -> Result < ( ) , Error > {
910
- if BIDI {
911
- self . bidi_output ( ) ;
912
- for word in words {
913
- nb:: block!( self . check_send( * word) ) ?;
914
- }
915
- } else {
916
- for word in words {
917
- nb:: block!( self . check_send( * word) ) ?;
918
- nb:: block!( self . check_read:: <W >( ) ) ?;
919
- }
920
- }
921
-
922
- Ok ( ( ) )
956
+ self . spi_write :: < BIDI , W > ( words. iter ( ) . copied ( ) )
923
957
}
924
958
925
959
pub fn write_iter ( & mut self , words : impl IntoIterator < Item = W > ) -> Result < ( ) , Error > {
926
- if BIDI {
927
- self . bidi_output ( ) ;
928
- for word in words. into_iter ( ) {
929
- nb:: block!( self . check_send( word) ) ?;
930
- }
931
- } else {
932
- for word in words. into_iter ( ) {
933
- nb:: block!( self . check_send( word) ) ?;
934
- nb:: block!( self . check_read:: <W >( ) ) ?;
935
- }
936
- }
937
-
938
- Ok ( ( ) )
960
+ self . spi_write :: < BIDI , W > ( words)
939
961
}
940
962
941
963
pub fn read ( & mut self , words : & mut [ W ] ) -> Result < ( ) , Error > {
@@ -995,19 +1017,7 @@ impl<SPI: Instance, const BIDI: bool, W: FrameSize> SpiSlave<SPI, BIDI, W> {
995
1017
}
996
1018
997
1019
pub fn write ( & mut self , words : & [ W ] ) -> Result < ( ) , Error > {
998
- if BIDI {
999
- self . bidi_output ( ) ;
1000
- for word in words {
1001
- nb:: block!( self . check_send( * word) ) ?;
1002
- }
1003
- } else {
1004
- for word in words {
1005
- nb:: block!( self . check_send( * word) ) ?;
1006
- nb:: block!( self . check_read:: <W >( ) ) ?;
1007
- }
1008
- }
1009
-
1010
- Ok ( ( ) )
1020
+ self . spi_write :: < BIDI , W > ( words. iter ( ) . copied ( ) )
1011
1021
}
1012
1022
1013
1023
pub fn read ( & mut self , words : & mut [ W ] ) -> Result < ( ) , Error > {
0 commit comments