@@ -365,11 +365,13 @@ pub trait Instance {
365365 . ctr
366366 . modify ( |_, w| w. conf_upgate ( ) . set_bit ( ) ) ;
367367
368+ self . reset ( ) ;
369+
368370 Ok ( ( ) )
369371 }
370372
371373 /// Resets the I2C controller (FIFO + FSM + command list)
372- fn reset ( & mut self ) {
374+ fn reset ( & self ) {
373375 // Reset interrupts
374376 // Disable all I2C interrupts
375377 self . register_block ( )
@@ -396,7 +398,7 @@ pub trait Instance {
396398 }
397399
398400 /// Resets the I2C peripheral's command registers
399- fn reset_command_list ( & mut self ) {
401+ fn reset_command_list ( & self ) {
400402 // Confirm that all commands that were configured were actually executed
401403 for cmd in self . register_block ( ) . comd . iter ( ) {
402404 cmd. reset ( ) ;
@@ -632,7 +634,7 @@ pub trait Instance {
632634
633635 add_cmd ( cmd_iterator, Command :: Stop ) ?;
634636
635- self . upgate_config ( ) ;
637+ self . update_config ( ) ;
636638
637639 // Load address and R/W bit into FIFO
638640 write_fifo (
@@ -645,7 +647,7 @@ pub trait Instance {
645647 self . start_transmission ( ) ;
646648
647649 // fill FIFO with remaining bytes
648- self . write_remaining_tx_fifo ( index, bytes) ;
650+ self . write_remaining_tx_fifo ( index, bytes) ? ;
649651
650652 self . wait_for_completion ( ) ?;
651653
@@ -704,7 +706,7 @@ pub trait Instance {
704706
705707 add_cmd ( cmd_iterator, Command :: Stop ) ?;
706708
707- self . upgate_config ( ) ;
709+ self . update_config ( ) ;
708710
709711 // Load address and R/W bit into FIFO
710712 write_fifo ( self . register_block ( ) , addr << 1 | OperationType :: Read as u8 ) ;
@@ -718,121 +720,18 @@ pub trait Instance {
718720 Ok ( ( ) )
719721 }
720722
721- #[ cfg( not( debug_assertions) ) ]
722- fn perform_write_read < ' a , I > (
723- & self ,
724- addr : u8 ,
725- bytes : & [ u8 ] ,
726- buffer : & mut [ u8 ] ,
727- cmd_iterator : & mut I ,
728- ) -> Result < ( ) , Error >
729- where
730- I : Iterator < Item = & ' a COMD > ,
731- {
732- if bytes. len ( ) > 254 {
733- // we could support more by adding multiple write operations
734- return Err ( Error :: ExceedingFifo ) ;
735- }
736-
737- // Clear all I2C interrupts
738- self . clear_all_interrupts ( ) ;
739-
740- // RSTART command
741- add_cmd ( cmd_iterator, Command :: Start ) ?;
742-
743- // WRITE command
744- add_cmd (
745- cmd_iterator,
746- Command :: Write {
747- ack_exp : Ack :: Ack ,
748- ack_check_en : true ,
749- length : 1 + bytes. len ( ) as u8 ,
750- } ,
751- ) ?;
752-
753- add_cmd ( cmd_iterator, Command :: Start ) ?;
754-
755- add_cmd (
756- cmd_iterator,
757- Command :: Write {
758- ack_exp : Ack :: Ack ,
759- ack_check_en : true ,
760- length : 1 ,
761- } ,
762- ) ?;
763-
764- if buffer. len ( ) > 1 {
765- // READ command (N - 1)
766- add_cmd (
767- cmd_iterator,
768- Command :: Read {
769- ack_value : Ack :: Ack ,
770- length : buffer. len ( ) as u8 - 1 ,
771- } ,
772- ) ?;
773- }
774-
775- // READ w/o ACK
776- add_cmd (
777- cmd_iterator,
778- Command :: Read {
779- ack_value : Ack :: Nack ,
780- length : 1 ,
781- } ,
782- ) ?;
783-
784- add_cmd ( cmd_iterator, Command :: Stop ) ?;
785-
786- self . upgate_config ( ) ;
787-
788- // Load address and R/W bit into FIFO
789- write_fifo (
790- self . register_block ( ) ,
791- addr << 1 | OperationType :: Write as u8 ,
792- ) ;
793-
794- let index = self . fill_tx_fifo ( bytes) ;
795-
796- self . start_transmission ( ) ;
797-
798- // fill FIFO with remaining bytes
799- self . write_remaining_tx_fifo ( index, bytes) ;
800-
801- // writing to the FIFO here is too slow in debug mode apparently and the
802- // address isn't loaded fast enough ... therefore in debug mode we do separate
803- // write and reads
804- self . write_remaining_tx_fifo ( 0 , & [ addr << 1 | OperationType :: Read as u8 ] ) ;
805-
806- self . read_all_from_fifo ( buffer) ?;
807-
808- self . wait_for_completion ( ) ?;
809-
810- Ok ( ( ) )
811- }
812-
813723 #[ cfg( not( any( esp32, esp32s2) ) ) ]
814724 fn read_all_from_fifo ( & self , buffer : & mut [ u8 ] ) -> Result < ( ) , Error > {
815725 // Read bytes from FIFO
816726 // FIXME: Handle case where less data has been provided by the slave than
817727 // requested? Or is this prevented from a protocol perspective?
818728 for byte in buffer. iter_mut ( ) {
819729 loop {
820- #[ cfg( not( esp32) ) ]
821- {
822- let reg = self . register_block ( ) . fifo_st . read ( ) ;
823-
824- if reg. rxfifo_raddr ( ) . bits ( ) != reg. rxfifo_waddr ( ) . bits ( ) {
825- break ;
826- }
827- }
828-
829- #[ cfg( esp32) ]
830- {
831- let reg = self . register_block ( ) . rxfifo_st . read ( ) ;
730+ self . check_errors ( ) ?;
832731
833- if reg. rxfifo_start_addr ( ) . bits ( ) != reg . rxfifo_end_addr ( ) . bits ( ) {
834- break ;
835- }
732+ let reg = self . register_block ( ) . fifo_st . read ( ) ;
733+ if reg . rxfifo_raddr ( ) . bits ( ) != reg . rxfifo_waddr ( ) . bits ( ) {
734+ break ;
836735 }
837736 }
838737
@@ -877,30 +776,7 @@ pub trait Instance {
877776 loop {
878777 let interrupts = self . register_block ( ) . int_raw . read ( ) ;
879778
880- // The ESP32 variant has a slightly different interrupt naming
881- // scheme!
882- cfg_if:: cfg_if! {
883- if #[ cfg( esp32) ] {
884- // Handle error cases
885- if interrupts. time_out_int_raw( ) . bit_is_set( ) {
886- return Err ( Error :: TimeOut ) ;
887- } else if interrupts. ack_err_int_raw( ) . bit_is_set( ) {
888- return Err ( Error :: AckCheckFailed ) ;
889- } else if interrupts. arbitration_lost_int_raw( ) . bit_is_set( ) {
890- return Err ( Error :: ArbitrationLost ) ;
891- }
892- }
893- else {
894- // Handle error cases
895- if interrupts. time_out_int_raw( ) . bit_is_set( ) {
896- return Err ( Error :: TimeOut ) ;
897- } else if interrupts. nack_int_raw( ) . bit_is_set( ) {
898- return Err ( Error :: AckCheckFailed ) ;
899- } else if interrupts. arbitration_lost_int_raw( ) . bit_is_set( ) {
900- return Err ( Error :: ArbitrationLost ) ;
901- }
902- }
903- }
779+ self . check_errors ( ) ?;
904780
905781 // Handle completion cases
906782 // A full transmission was completed
@@ -919,7 +795,43 @@ pub trait Instance {
919795 Ok ( ( ) )
920796 }
921797
922- fn upgate_config ( & self ) {
798+ fn check_errors ( & self ) -> Result < ( ) , Error > {
799+ let interrupts = self . register_block ( ) . int_raw . read ( ) ;
800+
801+ // The ESP32 variant has a slightly different interrupt naming
802+ // scheme!
803+ cfg_if:: cfg_if! {
804+ if #[ cfg( esp32) ] {
805+ // Handle error cases
806+ if interrupts. time_out_int_raw( ) . bit_is_set( ) {
807+ self . reset( ) ;
808+ return Err ( Error :: TimeOut ) ;
809+ } else if interrupts. ack_err_int_raw( ) . bit_is_set( ) {
810+ self . reset( ) ;
811+ return Err ( Error :: AckCheckFailed ) ;
812+ } else if interrupts. arbitration_lost_int_raw( ) . bit_is_set( ) {
813+ self . reset( ) ;
814+ return Err ( Error :: ArbitrationLost ) ;
815+ }
816+ }
817+ else {
818+ // Handle error cases
819+ if interrupts. time_out_int_raw( ) . bit_is_set( ) {
820+ self . reset( ) ;
821+ return Err ( Error :: TimeOut ) ;
822+ } else if interrupts. nack_int_raw( ) . bit_is_set( ) {
823+ self . reset( ) ;
824+ return Err ( Error :: AckCheckFailed ) ;
825+ } else if interrupts. arbitration_lost_int_raw( ) . bit_is_set( ) {
826+ return Err ( Error :: ArbitrationLost ) ;
827+ }
828+ }
829+ }
830+
831+ Ok ( ( ) )
832+ }
833+
834+ fn update_config ( & self ) {
923835 // Ensure that the configuration of the peripheral is correctly propagated
924836 // (only necessary for C3 and S3 variant)
925837 #[ cfg( any( esp32c2, esp32c3, esp32s3) ) ]
@@ -965,9 +877,11 @@ pub trait Instance {
965877 }
966878
967879 #[ cfg( not( any( esp32, esp32s2) ) ) ]
968- fn write_remaining_tx_fifo ( & self , start_index : usize , bytes : & [ u8 ] ) {
880+ fn write_remaining_tx_fifo ( & self , start_index : usize , bytes : & [ u8 ] ) -> Result < ( ) , Error > {
969881 let mut index = start_index;
970882 loop {
883+ self . check_errors ( ) ?;
884+
971885 while !self
972886 . register_block ( )
973887 . int_raw
@@ -980,7 +894,7 @@ pub trait Instance {
980894 . write ( |w| w. txfifo_wm_int_clr ( ) . set_bit ( ) ) ;
981895
982896 if index >= bytes. len ( ) {
983- break ;
897+ break Ok ( ( ) ) ;
984898 }
985899
986900 write_fifo ( self . register_block ( ) , bytes[ index] ) ;
@@ -1006,25 +920,28 @@ pub trait Instance {
1006920 }
1007921
1008922 #[ cfg( any( esp32, esp32s2) ) ]
1009- fn write_remaining_tx_fifo ( & self , start_index : usize , bytes : & [ u8 ] ) {
923+ fn write_remaining_tx_fifo ( & self , start_index : usize , bytes : & [ u8 ] ) -> Result < ( ) , Error > {
1010924 // on ESP32/ESP32-S2 we currently don't support I2C transactions larger than the
1011925 // FIFO apparently it would be possible by using non-fifo mode
1012926 // see https://github.com/espressif/arduino-esp32/blob/7e9afe8c5ed7b5bf29624a5cd6e07d431c027b97/cores/esp32/esp32-hal-i2c.c#L615
1013927
1014928 if start_index >= bytes. len ( ) {
1015- return ;
929+ return Ok ( ( ) ) ;
1016930 }
1017931
1018932 // this is only possible when writing the I2C address in release mode
1019933 // from [perform_write_read]
1020934 for b in bytes {
1021935 write_fifo ( self . register_block ( ) , * b) ;
936+ self . check_errors ( ) ?;
1022937 }
938+
939+ Ok ( ( ) )
1023940 }
1024941
1025942 /// Resets the transmit and receive FIFO buffers
1026943 #[ cfg( not( esp32) ) ]
1027- fn reset_fifo ( & mut self ) {
944+ fn reset_fifo ( & self ) {
1028945 // First, reset the fifo buffers
1029946 self . register_block ( ) . fifo_conf . modify ( |_, w| {
1030947 w. tx_fifo_rst ( )
@@ -1035,26 +952,29 @@ pub trait Instance {
1035952 . clear_bit ( )
1036953 . fifo_prt_en ( )
1037954 . set_bit ( )
1038- . tx_fifo_rst ( )
1039- . clear_bit ( )
1040- . rx_fifo_rst ( )
1041- . clear_bit ( )
1042955 . rxfifo_wm_thrhd ( )
1043956 . variant ( 1 )
1044957 . txfifo_wm_thrhd ( )
1045958 . variant ( 8 )
1046959 } ) ;
960+
961+ self . register_block ( )
962+ . fifo_conf
963+ . modify ( |_, w| w. tx_fifo_rst ( ) . clear_bit ( ) . rx_fifo_rst ( ) . clear_bit ( ) ) ;
964+
1047965 self . register_block ( ) . int_clr . write ( |w| {
1048966 w. rxfifo_wm_int_clr ( )
1049967 . set_bit ( )
1050968 . txfifo_wm_int_clr ( )
1051969 . set_bit ( )
1052970 } ) ;
971+
972+ self . update_config ( ) ;
1053973 }
1054974
1055975 /// Resets the transmit and receive FIFO buffers
1056976 #[ cfg( esp32) ]
1057- fn reset_fifo ( & mut self ) {
977+ fn reset_fifo ( & self ) {
1058978 // First, reset the fifo buffers
1059979 self . register_block ( ) . fifo_conf . modify ( |_, w| {
1060980 w. tx_fifo_rst ( )
@@ -1063,15 +983,16 @@ pub trait Instance {
1063983 . set_bit ( )
1064984 . nonfifo_en ( )
1065985 . clear_bit ( )
1066- . tx_fifo_rst ( )
1067- . clear_bit ( )
1068- . rx_fifo_rst ( )
1069- . clear_bit ( )
1070986 . nonfifo_rx_thres ( )
1071987 . variant ( 1 )
1072988 . nonfifo_tx_thres ( )
1073989 . variant ( 32 )
1074990 } ) ;
991+
992+ self . register_block ( )
993+ . fifo_conf
994+ . modify ( |_, w| w. tx_fifo_rst ( ) . clear_bit ( ) . rx_fifo_rst ( ) . clear_bit ( ) ) ;
995+
1075996 self . register_block ( )
1076997 . int_clr
1077998 . write ( |w| w. rxfifo_full_int_clr ( ) . set_bit ( ) ) ;
@@ -1106,20 +1027,12 @@ pub trait Instance {
11061027 bytes : & [ u8 ] ,
11071028 buffer : & mut [ u8 ] ,
11081029 ) -> Result < ( ) , Error > {
1109- #[ cfg( not( debug_assertions) ) ]
1110- {
1111- // Reset FIFO and command list
1112- self . reset_fifo ( ) ;
1113- self . reset_command_list ( ) ;
1114-
1115- self . perform_write_read ( addr, bytes, buffer, & mut self . register_block ( ) . comd . iter ( ) ) ?;
1116- }
1117-
1118- #[ cfg( debug_assertions) ]
1119- {
1120- self . master_write ( addr, bytes) ?;
1121- self . master_read ( addr, buffer) ?;
1122- }
1030+ // it would be possible to combine the write and read
1031+ // in one transaction but filling the tx fifo with
1032+ // the current code is somewhat slow even in release mode
1033+ // which can cause issues
1034+ self . master_write ( addr, bytes) ?;
1035+ self . master_read ( addr, buffer) ?;
11231036 Ok ( ( ) )
11241037 }
11251038}
0 commit comments