@@ -46,6 +46,8 @@ static const char *TAG = "i2c.master";
4646#define I2C_FIFO_LEN (port_num ) (SOC_I2C_FIFO_LEN)
4747#endif
4848
49+ #define I2C_CLR_BUS_TIMEOUT_MS (50) // 50ms is sufficient for clearing the bus
50+
4951// Use the platform to same master bus handle
5052typedef struct i2c_master_bus_platform_t i2c_master_bus_platform_t ;
5153
@@ -57,6 +59,7 @@ static i2c_master_bus_platform_t s_platform;
5759
5860static esp_err_t s_i2c_master_clear_bus (i2c_bus_handle_t handle )
5961{
62+ esp_err_t ret = ESP_OK ;
6063#if !SOC_I2C_SUPPORT_HW_CLR_BUS
6164 const int scl_half_period = 5 ; // use standard 100kHz data rate
6265 int i = 0 ;
@@ -83,9 +86,23 @@ static esp_err_t s_i2c_master_clear_bus(i2c_bus_handle_t handle)
8386 i2c_common_set_pins (handle );
8487#else
8588 i2c_hal_context_t * hal = & handle -> hal ;
86- i2c_ll_master_clr_bus (hal -> dev , I2C_LL_RESET_SLV_SCL_PULSE_NUM_DEFAULT );
89+ i2c_ll_master_clr_bus (hal -> dev , I2C_LL_RESET_SLV_SCL_PULSE_NUM_DEFAULT , true);
90+ // If the i2c master clear bus state machine got disturbed when its work, it would go into error state.
91+ // The solution here is to use freertos tick counter to set time threshold. If its not return on time,
92+ // return invalid state and turn off the state machine for avoiding its always wrong.
93+ TickType_t start_tick = xTaskGetTickCount ();
94+ const TickType_t timeout_ticks = pdMS_TO_TICKS (I2C_CLR_BUS_TIMEOUT_MS );
95+ while (i2c_ll_master_is_bus_clear_done (hal -> dev )) {
96+ if ((xTaskGetTickCount () - start_tick ) > timeout_ticks ) {
97+ ESP_LOGE (TAG , "clear bus failed." );
98+ i2c_ll_master_clr_bus (hal -> dev , 0 , false);
99+ ret = ESP_ERR_INVALID_STATE ;
100+ break ;
101+ }
102+ }
103+ i2c_ll_update (hal -> dev );
87104#endif
88- return ESP_OK ;
105+ return ret ;
89106}
90107
91108/**
@@ -97,6 +114,7 @@ static esp_err_t s_i2c_master_clear_bus(i2c_bus_handle_t handle)
97114 */
98115static esp_err_t s_i2c_hw_fsm_reset (i2c_master_bus_handle_t i2c_master )
99116{
117+ esp_err_t ret = ESP_OK ;
100118 i2c_hal_context_t * hal = & i2c_master -> base -> hal ;
101119#if !SOC_I2C_SUPPORT_HW_FSM_RST
102120 i2c_hal_timing_config_t timing_config ;
@@ -106,7 +124,7 @@ static esp_err_t s_i2c_hw_fsm_reset(i2c_master_bus_handle_t i2c_master)
106124 i2c_ll_master_get_filter (hal -> dev , & filter_cfg );
107125
108126 //to reset the I2C hw module, we need re-enable the hw
109- s_i2c_master_clear_bus (i2c_master -> base );
127+ ret = s_i2c_master_clear_bus (i2c_master -> base );
110128 I2C_RCC_ATOMIC () {
111129 i2c_ll_reset_register (i2c_master -> base -> port_num );
112130 }
@@ -118,9 +136,9 @@ static esp_err_t s_i2c_hw_fsm_reset(i2c_master_bus_handle_t i2c_master)
118136 i2c_ll_master_set_filter (hal -> dev , filter_cfg );
119137#else
120138 i2c_ll_master_fsm_rst (hal -> dev );
121- s_i2c_master_clear_bus (i2c_master -> base );
139+ ret = s_i2c_master_clear_bus (i2c_master -> base );
122140#endif
123- return ESP_OK ;
141+ return ret ;
124142}
125143
126144static void s_i2c_err_log_print (i2c_master_event_t event , bool bypass_nack_log )
@@ -572,7 +590,7 @@ static esp_err_t s_i2c_transaction_start(i2c_master_dev_handle_t i2c_dev, int xf
572590 // Sometimes when the FSM get stuck, the ACK_ERR interrupt will occur endlessly until we reset the FSM and clear bus.
573591 esp_err_t ret = ESP_OK ;
574592 if (i2c_master -> status == I2C_STATUS_TIMEOUT || i2c_ll_is_bus_busy (hal -> dev )) {
575- s_i2c_hw_fsm_reset (i2c_master );
593+ ESP_RETURN_ON_ERROR ( s_i2c_hw_fsm_reset (i2c_master ), TAG , "reset hardware failed" );
576594 }
577595
578596 if (i2c_master -> base -> pm_lock ) {
0 commit comments