@@ -726,6 +726,19 @@ impl<SPI: Instance> Inner<SPI> {
726726 self . spi . sr . read ( ) . ovr ( ) . bit_is_set ( )
727727 }
728728
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+
729742 #[ inline]
730743 fn bidi_output ( & mut self ) {
731744 self . spi . cr1 . modify ( |_, w| w. bidioe ( ) . set_bit ( ) ) ;
@@ -787,6 +800,39 @@ impl<SPI: Instance> Inner<SPI> {
787800 nb:: Error :: WouldBlock
788801 } )
789802 }
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+ }
790836}
791837
792838// Spi DMA
@@ -907,35 +953,11 @@ impl<SPI: Instance, const BIDI: bool, W: FrameSize> Spi<SPI, BIDI, W> {
907953 }
908954
909955 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 ( ) )
923957 }
924958
925959 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)
939961 }
940962
941963 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> {
9951017 }
9961018
9971019 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 ( ) )
10111021 }
10121022
10131023 pub fn read ( & mut self , words : & mut [ W ] ) -> Result < ( ) , Error > {
0 commit comments