@@ -40,7 +40,6 @@ static portMUX_TYPE i2c_spinlock[I2C_NUM_MAX] = {portMUX_INITIALIZER_UNLOCKED, p
4040/* DRAM_ATTR is required to avoid I2C array placed in flash, due to accessed from ISR */
4141static DRAM_ATTR i2c_dev_t * const I2C [I2C_NUM_MAX ] = { & I2C0 , & I2C1 };
4242
43-
4443#define I2C_ENTER_CRITICAL_ISR (mux ) portENTER_CRITICAL_ISR(mux)
4544#define I2C_EXIT_CRITICAL_ISR (mux ) portEXIT_CRITICAL_ISR(mux)
4645#define I2C_ENTER_CRITICAL (mux ) portENTER_CRITICAL(mux)
@@ -78,6 +77,7 @@ static DRAM_ATTR i2c_dev_t* const I2C[I2C_NUM_MAX] = { &I2C0, &I2C1 };
7877#define I2C_SLAVE_SDA_SAMPLE_DEFAULT (10) /* I2C slave sample time after scl positive edge default value */
7978#define I2C_SLAVE_SDA_HOLD_DEFAULT (10) /* I2C slave hold time after scl negative edge default value */
8079#define I2C_MASTER_TOUT_CNUM_DEFAULT (8) /* I2C master timeout cycle number of I2C clock, after which the timeout interrupt will be triggered */
80+ #define I2C_ACKERR_CNT_MAX (10)
8181
8282typedef struct {
8383 uint8_t byte_num ; /*!< cmd byte number */
@@ -367,6 +367,7 @@ static void IRAM_ATTR i2c_isr_handler_default(void* arg)
367367 } else if (status & I2C_RX_REC_FULL_INT_ST_M ) {
368368 I2C [i2c_num ]-> int_clr .rx_rec_full = 1 ;
369369 } else if (status & I2C_ACK_ERR_INT_ST_M ) {
370+ I2C [i2c_num ]-> int_ena .ack_err = 0 ;
370371 I2C [i2c_num ]-> int_clr .ack_err = 1 ;
371372 if (p_i2c -> mode == I2C_MODE_MASTER ) {
372373 p_i2c_obj [i2c_num ]-> status = I2C_STATUS_ACK_ERROR ;
@@ -377,6 +378,7 @@ static void IRAM_ATTR i2c_isr_handler_default(void* arg)
377378 } else if (status & I2C_TRANS_START_INT_ST_M ) {
378379 I2C [i2c_num ]-> int_clr .trans_start = 1 ;
379380 } else if (status & I2C_TIME_OUT_INT_ST_M ) {
381+ I2C [i2c_num ]-> int_ena .time_out = 0 ;
380382 I2C [i2c_num ]-> int_clr .time_out = 1 ;
381383 p_i2c_obj [i2c_num ]-> status = I2C_STATUS_TIMEOUT ;
382384 i2c_master_cmd_begin_static (i2c_num );
@@ -388,12 +390,10 @@ static void IRAM_ATTR i2c_isr_handler_default(void* arg)
388390 p_i2c -> data_buf [idx ] = I2C [i2c_num ]-> fifo_data .data ;
389391 }
390392 xRingbufferSendFromISR (p_i2c -> rx_ring_buf , p_i2c -> data_buf , rx_fifo_cnt , & HPTaskAwoken );
391- if (HPTaskAwoken == pdTRUE ) {
392- portYIELD_FROM_ISR ();
393- }
394393 I2C [i2c_num ]-> int_clr .rx_fifo_full = 1 ;
395394 } else {
396- if (p_i2c -> status != I2C_STATUS_ACK_ERROR ) {
395+ // add check for unexcepted situations caused by noise.
396+ if (p_i2c -> status != I2C_STATUS_ACK_ERROR && p_i2c -> status != I2C_STATUS_IDLE ) {
397397 i2c_master_cmd_begin_static (i2c_num );
398398 }
399399 }
@@ -420,9 +420,6 @@ static void IRAM_ATTR i2c_isr_handler_default(void* arg)
420420 WRITE_PERI_REG (I2C_DATA_APB_REG (i2c_num ), data [idx ]);
421421 }
422422 vRingbufferReturnItemFromISR (p_i2c -> tx_ring_buf , data , & HPTaskAwoken );
423- if (HPTaskAwoken == pdTRUE ) {
424- portYIELD_FROM_ISR ();
425- }
426423 I2C [i2c_num ]-> int_ena .tx_fifo_empty = 1 ;
427424 I2C [i2c_num ]-> int_clr .tx_fifo_empty = 1 ;
428425 } else {
@@ -435,9 +432,6 @@ static void IRAM_ATTR i2c_isr_handler_default(void* arg)
435432 p_i2c -> data_buf [idx ] = I2C [i2c_num ]-> fifo_data .data ;
436433 }
437434 xRingbufferSendFromISR (p_i2c -> rx_ring_buf , p_i2c -> data_buf , rx_fifo_cnt , & HPTaskAwoken );
438- if (HPTaskAwoken == pdTRUE ) {
439- portYIELD_FROM_ISR ();
440- }
441435 I2C [i2c_num ]-> int_clr .rx_fifo_full = 1 ;
442436 } else {
443437 I2C [i2c_num ]-> int_clr .val = status ;
@@ -447,9 +441,10 @@ static void IRAM_ATTR i2c_isr_handler_default(void* arg)
447441 i2c_cmd_evt_t evt ;
448442 evt .type = I2C_CMD_EVT_ALIVE ;
449443 xQueueSendFromISR (p_i2c -> cmd_evt_queue , & evt , & HPTaskAwoken );
450- if (HPTaskAwoken == pdTRUE ) {
451- portYIELD_FROM_ISR ();
452- }
444+ }
445+ //We only need to check here if there is a high-priority task needs to be switched.
446+ if (HPTaskAwoken == pdTRUE ) {
447+ portYIELD_FROM_ISR ();
453448 }
454449}
455450
@@ -497,19 +492,17 @@ static esp_err_t i2c_master_clear_bus(i2c_port_t i2c_num)
497492 int sda_io = GPIO .func_in_sel_cfg [sda_in_sig ].func_sel ;
498493 I2C_CHECK ((GPIO_IS_VALID_OUTPUT_GPIO (scl_io )), I2C_SCL_IO_ERR_STR , ESP_ERR_INVALID_ARG );
499494 I2C_CHECK ((GPIO_IS_VALID_GPIO (sda_io )), I2C_SDA_IO_ERR_STR , ESP_ERR_INVALID_ARG );
500-
501- if (gpio_get_level (sda_io ) == 1 ) {
502- return ESP_OK ;
503- }
495+ // We do not check whether the SDA line is low
496+ // because after some serious interference, the bus may keep high all the time and the i2c bus is out of service.
504497 gpio_set_direction (scl_io , GPIO_MODE_OUTPUT_OD );
505498 gpio_set_direction (sda_io , GPIO_MODE_OUTPUT_OD );
506- gpio_set_level (scl_io , 0 );
499+ gpio_set_level (scl_io , 1 );
500+ gpio_set_level (sda_io , 1 );
507501 gpio_set_level (sda_io , 0 );
508502 for (int i = 0 ; i < 9 ; i ++ ) {
509- gpio_set_level (scl_io , 1 );
510503 gpio_set_level (scl_io , 0 );
504+ gpio_set_level (scl_io , 1 );
511505 }
512- gpio_set_level (scl_io , 1 );
513506 gpio_set_level (sda_io , 1 );
514507 i2c_set_pin (i2c_num , sda_io , scl_io , 1 , 1 , I2C_MODE_MASTER );
515508 return ESP_OK ;
@@ -583,6 +576,8 @@ esp_err_t i2c_param_config(i2c_port_t i2c_num, const i2c_config_t* i2c_conf)
583576 if (ret != ESP_OK ) {
584577 return ret ;
585578 }
579+ // Reset the I2C hardware in case there is a soft reboot.
580+ i2c_hw_disable (i2c_num );
586581 i2c_hw_enable (i2c_num );
587582 I2C_ENTER_CRITICAL (& i2c_spinlock [i2c_num ]);
588583 I2C [i2c_num ]-> ctr .rx_lsb_first = I2C_DATA_MODE_MSB_FIRST ; //set rx data msb first
@@ -1047,7 +1042,7 @@ static void IRAM_ATTR i2c_master_cmd_begin_static(i2c_port_t i2c_num)
10471042 portYIELD_FROM_ISR ();
10481043 }
10491044 return ;
1050- } else if (p_i2c -> status == I2C_STATUS_READ ) {
1045+ } else if (p_i2c -> cmd_link . head != NULL && p_i2c -> status == I2C_STATUS_READ ) {
10511046 i2c_cmd_t * cmd = & p_i2c -> cmd_link .head -> cmd ;
10521047 while (p_i2c -> rx_cnt -- > 0 ) {
10531048 * cmd -> data ++ = READ_PERI_REG (I2C_DATA_APB_REG (i2c_num ));
@@ -1066,6 +1061,8 @@ static void IRAM_ATTR i2c_master_cmd_begin_static(i2c_port_t i2c_num)
10661061 if (HPTaskAwoken == pdTRUE ) {
10671062 portYIELD_FROM_ISR ();
10681063 }
1064+ // Return to the IDLE status after cmd_eve_done signal were send out.
1065+ p_i2c -> status = I2C_STATUS_IDLE ;
10691066 return ;
10701067 }
10711068 while (p_i2c -> cmd_link .head ) {
@@ -1121,7 +1118,6 @@ static void IRAM_ATTR i2c_master_cmd_begin_static(i2c_port_t i2c_num)
11211118 if (p_i2c -> cmd_link .head == NULL || p_i2c -> cmd_idx >= 15 ) {
11221119 p_i2c -> tx_fifo_remain = I2C_FIFO_LEN ;
11231120 p_i2c -> cmd_idx = 0 ;
1124- p_i2c -> status = I2C_STATUS_IDLE ;
11251121 break ;
11261122 }
11271123 }
@@ -1139,6 +1135,8 @@ esp_err_t i2c_master_cmd_begin(i2c_port_t i2c_num, i2c_cmd_handle_t cmd_handle,
11391135 I2C_CHECK (p_i2c_obj [i2c_num ]-> mode == I2C_MODE_MASTER , I2C_MASTER_MODE_ERR_STR , ESP_ERR_INVALID_STATE );
11401136 I2C_CHECK (cmd_handle != NULL , I2C_CMD_LINK_INIT_ERR_STR , ESP_ERR_INVALID_ARG );
11411137
1138+ // Sometimes when the FSM get stuck, the ACK_ERR interrupt will occur endlessly until we reset the FSM and clear bus.
1139+ static uint8_t clear_bus_cnt = 0 ;
11421140 esp_err_t ret = ESP_FAIL ;
11431141 i2c_obj_t * p_i2c = p_i2c_obj [i2c_num ];
11441142 portTickType ticks_start = xTaskGetTickCount ();
@@ -1150,6 +1148,7 @@ esp_err_t i2c_master_cmd_begin(i2c_port_t i2c_num, i2c_cmd_handle_t cmd_handle,
11501148 if (p_i2c -> status == I2C_STATUS_TIMEOUT
11511149 || I2C [i2c_num ]-> status_reg .bus_busy == 1 ) {
11521150 i2c_hw_fsm_reset (i2c_num );
1151+ clear_bus_cnt = 0 ;
11531152 }
11541153 i2c_reset_tx_fifo (i2c_num );
11551154 i2c_reset_rx_fifo (i2c_num );
@@ -1164,7 +1163,10 @@ esp_err_t i2c_master_cmd_begin(i2c_port_t i2c_num, i2c_cmd_handle_t cmd_handle,
11641163 p_i2c -> rx_fifo_remain = I2C_FIFO_LEN ;
11651164 i2c_reset_tx_fifo (i2c_num );
11661165 i2c_reset_rx_fifo (i2c_num );
1167-
1166+ // These two interrupts some times can not be cleared when the FSM gets stuck.
1167+ // so we disable them when these two interrupt occurs and re-enable them here.
1168+ I2C [i2c_num ]-> int_ena .ack_err = 1 ;
1169+ I2C [i2c_num ]-> int_ena .time_out = 1 ;
11681170 //start send commands, at most 32 bytes one time, isr handler will process the remaining commands.
11691171 i2c_master_cmd_begin_static (i2c_num );
11701172
@@ -1190,8 +1192,14 @@ esp_err_t i2c_master_cmd_begin(i2c_port_t i2c_num, i2c_cmd_handle_t cmd_handle,
11901192 // If the I2C slave are powered off or the SDA/SCL are connected to ground, for example,
11911193 // I2C hw FSM would get stuck in wrong state, we have to reset the I2C module in this case.
11921194 i2c_hw_fsm_reset (i2c_num );
1195+ clear_bus_cnt = 0 ;
11931196 ret = ESP_ERR_TIMEOUT ;
11941197 } else if (p_i2c -> status == I2C_STATUS_ACK_ERROR ) {
1198+ clear_bus_cnt ++ ;
1199+ if (clear_bus_cnt >= I2C_ACKERR_CNT_MAX ) {
1200+ i2c_master_clear_bus (i2c_num );
1201+ clear_bus_cnt = 0 ;
1202+ }
11951203 ret = ESP_FAIL ;
11961204 } else {
11971205 ret = ESP_OK ;
@@ -1205,6 +1213,7 @@ esp_err_t i2c_master_cmd_begin(i2c_port_t i2c_num, i2c_cmd_handle_t cmd_handle,
12051213 // If the I2C slave are powered off or the SDA/SCL are connected to ground, for example,
12061214 // I2C hw FSM would get stuck in wrong state, we have to reset the I2C module in this case.
12071215 i2c_hw_fsm_reset (i2c_num );
1216+ clear_bus_cnt = 0 ;
12081217 break ;
12091218 }
12101219 }
0 commit comments