diff --git a/components/driver/i2c.c b/components/driver/i2c.c index b66d592874..04f67c156b 100644 --- a/components/driver/i2c.c +++ b/components/driver/i2c.c @@ -470,52 +470,63 @@ static void IRAM_ATTR i2c_isr_handler_default(void *arg) int i2c_num = p_i2c->i2c_num; i2c_intr_event_t evt_type = I2C_INTR_EVENT_ERR; portBASE_TYPE HPTaskAwoken = pdFALSE; - if (p_i2c->mode == I2C_MODE_MASTER) { - if (p_i2c->status == I2C_STATUS_WRITE) { - i2c_hal_master_handle_tx_event(&(i2c_context[i2c_num].hal), &evt_type); - } else if (p_i2c->status == I2C_STATUS_READ) { - i2c_hal_master_handle_rx_event(&(i2c_context[i2c_num].hal), &evt_type); - } - if (evt_type == I2C_INTR_EVENT_NACK) { - p_i2c_obj[i2c_num]->status = I2C_STATUS_ACK_ERROR; - i2c_master_cmd_begin_static(i2c_num); - } else if (evt_type == I2C_INTR_EVENT_TOUT) { - p_i2c_obj[i2c_num]->status = I2C_STATUS_TIMEOUT; - i2c_master_cmd_begin_static(i2c_num); - } else if (evt_type == I2C_INTR_EVENT_ARBIT_LOST) { - p_i2c_obj[i2c_num]->status = I2C_STATUS_TIMEOUT; - i2c_master_cmd_begin_static(i2c_num); - } else if (evt_type == I2C_INTR_EVENT_END_DET) { - i2c_master_cmd_begin_static(i2c_num); - } else if (evt_type == I2C_INTR_EVENT_TRANS_DONE) { - if (p_i2c->status != I2C_STATUS_ACK_ERROR && p_i2c->status != I2C_STATUS_IDLE) { - i2c_master_cmd_begin_static(i2c_num); + + uint32_t int_mask; + i2c_hal_get_intsts_mask(&(i2c_context[i2c_num].hal), &int_mask); + if (int_mask != 0) { + if (p_i2c->mode == I2C_MODE_MASTER) { + if (p_i2c->status == I2C_STATUS_WRITE) { + i2c_hal_master_handle_tx_event(&(i2c_context[i2c_num].hal), &evt_type); + } else if (p_i2c->status == I2C_STATUS_READ) { + i2c_hal_master_handle_rx_event(&(i2c_context[i2c_num].hal), &evt_type); } - } - i2c_cmd_evt_t evt = { - .type = I2C_CMD_EVT_ALIVE - }; - xQueueSendFromISR(p_i2c->cmd_evt_queue, &evt, &HPTaskAwoken); - } else { - i2c_hal_slave_handle_event(&(i2c_context[i2c_num].hal), &evt_type); - if (evt_type == I2C_INTR_EVENT_TRANS_DONE || evt_type == I2C_INTR_EVENT_RXFIFO_FULL) { - uint32_t rx_fifo_cnt; - i2c_hal_get_rxfifo_cnt(&(i2c_context[i2c_num].hal), &rx_fifo_cnt); - i2c_hal_read_rxfifo(&(i2c_context[i2c_num].hal), p_i2c->data_buf, rx_fifo_cnt); - xRingbufferSendFromISR(p_i2c->rx_ring_buf, p_i2c->data_buf, rx_fifo_cnt, &HPTaskAwoken); - i2c_hal_slave_clr_rx_it(&(i2c_context[i2c_num].hal)); - } else if (evt_type == I2C_INTR_EVENT_TXFIFO_EMPTY) { - uint32_t tx_fifo_rem; - i2c_hal_get_txfifo_cnt(&(i2c_context[i2c_num].hal), &tx_fifo_rem); - size_t size = 0; - uint8_t *data = (uint8_t *) xRingbufferReceiveUpToFromISR(p_i2c->tx_ring_buf, &size, tx_fifo_rem); - if (data) { - i2c_hal_write_txfifo(&(i2c_context[i2c_num].hal), data, size); - vRingbufferReturnItemFromISR(p_i2c->tx_ring_buf, data, &HPTaskAwoken); + if (evt_type == I2C_INTR_EVENT_NACK) { + p_i2c_obj[i2c_num]->status = I2C_STATUS_ACK_ERROR; + i2c_master_cmd_begin_static(i2c_num); + } else if (evt_type == I2C_INTR_EVENT_TOUT) { + p_i2c_obj[i2c_num]->status = I2C_STATUS_TIMEOUT; + i2c_master_cmd_begin_static(i2c_num); + } else if (evt_type == I2C_INTR_EVENT_ARBIT_LOST) { + p_i2c_obj[i2c_num]->status = I2C_STATUS_TIMEOUT; + i2c_master_cmd_begin_static(i2c_num); + } else if (evt_type == I2C_INTR_EVENT_END_DET) { + i2c_master_cmd_begin_static(i2c_num); + } else if (evt_type == I2C_INTR_EVENT_TRANS_DONE) { + if (p_i2c->status != I2C_STATUS_ACK_ERROR && p_i2c->status != I2C_STATUS_IDLE) { + i2c_master_cmd_begin_static(i2c_num); + } } else { - i2c_hal_disable_slave_tx_it(&(i2c_context[i2c_num].hal)); + uint32_t int_mask; + i2c_hal_get_intsts_mask(&(i2c_context[i2c_num].hal), &int_mask); + esp_rom_printf("the int_msk is %x\n", int_mask); + esp_rom_printf("the p_i2c->status is %x\n", p_i2c->status); + esp_rom_printf("evt type is %x\n", evt_type); + } + i2c_cmd_evt_t evt = { + .type = I2C_CMD_EVT_ALIVE + }; + xQueueSendFromISR(p_i2c->cmd_evt_queue, &evt, &HPTaskAwoken); + } else { + i2c_hal_slave_handle_event(&(i2c_context[i2c_num].hal), &evt_type); + if (evt_type == I2C_INTR_EVENT_TRANS_DONE || evt_type == I2C_INTR_EVENT_RXFIFO_FULL) { + uint32_t rx_fifo_cnt; + i2c_hal_get_rxfifo_cnt(&(i2c_context[i2c_num].hal), &rx_fifo_cnt); + i2c_hal_read_rxfifo(&(i2c_context[i2c_num].hal), p_i2c->data_buf, rx_fifo_cnt); + xRingbufferSendFromISR(p_i2c->rx_ring_buf, p_i2c->data_buf, rx_fifo_cnt, &HPTaskAwoken); + i2c_hal_slave_clr_rx_it(&(i2c_context[i2c_num].hal)); + } else if (evt_type == I2C_INTR_EVENT_TXFIFO_EMPTY) { + uint32_t tx_fifo_rem; + i2c_hal_get_txfifo_cnt(&(i2c_context[i2c_num].hal), &tx_fifo_rem); + size_t size = 0; + uint8_t *data = (uint8_t *) xRingbufferReceiveUpToFromISR(p_i2c->tx_ring_buf, &size, tx_fifo_rem); + if (data) { + i2c_hal_write_txfifo(&(i2c_context[i2c_num].hal), data, size); + vRingbufferReturnItemFromISR(p_i2c->tx_ring_buf, data, &HPTaskAwoken); + } else { + i2c_hal_disable_slave_tx_it(&(i2c_context[i2c_num].hal)); + } + i2c_hal_slave_clr_tx_it(&(i2c_context[i2c_num].hal)); } - i2c_hal_slave_clr_tx_it(&(i2c_context[i2c_num].hal)); } } //We only need to check here if there is a high-priority task needs to be switched. @@ -531,6 +542,7 @@ esp_err_t i2c_set_data_mode(i2c_port_t i2c_num, i2c_trans_mode_t tx_trans_mode, I2C_CHECK(rx_trans_mode < I2C_DATA_MODE_MAX, I2C_TRANS_MODE_ERR_STR, ESP_ERR_INVALID_ARG); I2C_ENTER_CRITICAL(&(i2c_context[i2c_num].spinlock)); i2c_hal_set_data_mode(&(i2c_context[i2c_num].hal), tx_trans_mode, rx_trans_mode); + i2c_hal_update_config(&(i2c_context[i2c_num].hal)); I2C_EXIT_CRITICAL(&(i2c_context[i2c_num].spinlock)); return ESP_OK; } @@ -587,7 +599,8 @@ static esp_err_t i2c_master_clear_bus(i2c_port_t i2c_num) **/ static esp_err_t i2c_hw_fsm_reset(i2c_port_t i2c_num) { -#if !SOC_I2C_SUPPORT_HW_FSM_RST +#if 1 // Enable software reset. + esp_rom_printf("log-1: enter fsm sft reset\n"); int scl_low_period, scl_high_period; int scl_start_hold, scl_rstart_setup; int scl_stop_hold, scl_stop_setup; @@ -616,6 +629,7 @@ static esp_err_t i2c_hw_fsm_reset(i2c_port_t i2c_num) i2c_hal_set_sda_timing(&(i2c_context[i2c_num].hal), sda_sample, sda_hold); i2c_hal_set_tout(&(i2c_context[i2c_num].hal), timeout); i2c_hal_set_filter(&(i2c_context[i2c_num].hal), filter_cfg); + esp_rom_printf("log-2: leave fsm sft reset\n"); #else i2c_hal_master_fsm_rst(&(i2c_context[i2c_num].hal)); i2c_master_clear_bus(i2c_num); @@ -665,12 +679,12 @@ esp_err_t i2c_param_config(i2c_port_t i2c_num, const i2c_config_t *i2c_conf) i2c_hal_set_sda_timing(&(i2c_context[i2c_num].hal), I2C_SLAVE_SDA_SAMPLE_DEFAULT, I2C_SLAVE_SDA_HOLD_DEFAULT); i2c_hal_set_tout(&(i2c_context[i2c_num].hal), I2C_SLAVE_TIMEOUT_DEFAULT); i2c_hal_enable_slave_rx_it(&(i2c_context[i2c_num].hal)); - i2c_hal_update_config(&(i2c_context[i2c_num].hal)); } else { i2c_hal_master_init(&(i2c_context[i2c_num].hal), i2c_num); //Default, we enable hardware filter i2c_hal_set_filter(&(i2c_context[i2c_num].hal), I2C_FILTER_CYC_NUM_DEF); i2c_hal_set_bus_timing(&(i2c_context[i2c_num].hal), i2c_conf->master.clk_speed, i2c_get_clk_src(i2c_conf)); + i2c_hal_update_config(&(i2c_context[i2c_num].hal)); } I2C_EXIT_CRITICAL(&(i2c_context[i2c_num].spinlock)); return ESP_OK; @@ -684,6 +698,7 @@ esp_err_t i2c_set_period(i2c_port_t i2c_num, int high_period, int low_period) I2C_ENTER_CRITICAL(&(i2c_context[i2c_num].spinlock)); i2c_hal_set_scl_timing(&(i2c_context[i2c_num].hal), high_period, low_period); + i2c_hal_update_config(&(i2c_context[i2c_num].hal)); I2C_EXIT_CRITICAL(&(i2c_context[i2c_num].spinlock)); return ESP_OK; } @@ -703,6 +718,7 @@ esp_err_t i2c_filter_enable(i2c_port_t i2c_num, uint8_t cyc_num) I2C_CHECK(p_i2c_obj[i2c_num] != NULL, I2C_DRIVER_ERR_STR, ESP_FAIL); I2C_ENTER_CRITICAL(&(i2c_context[i2c_num].spinlock)); i2c_hal_set_filter(&(i2c_context[i2c_num].hal), cyc_num); + i2c_hal_update_config(&(i2c_context[i2c_num].hal)); I2C_EXIT_CRITICAL(&(i2c_context[i2c_num].spinlock)); return ESP_OK; } @@ -712,6 +728,7 @@ esp_err_t i2c_filter_disable(i2c_port_t i2c_num) I2C_CHECK(i2c_num < I2C_NUM_MAX, I2C_NUM_ERROR_STR, ESP_ERR_INVALID_ARG); I2C_ENTER_CRITICAL(&(i2c_context[i2c_num].spinlock)); i2c_hal_set_filter(&(i2c_context[i2c_num].hal), 0); + i2c_hal_update_config(&(i2c_context[i2c_num].hal)); I2C_EXIT_CRITICAL(&(i2c_context[i2c_num].spinlock)); return ESP_OK; } @@ -724,6 +741,7 @@ esp_err_t i2c_set_start_timing(i2c_port_t i2c_num, int setup_time, int hold_time I2C_ENTER_CRITICAL(&(i2c_context[i2c_num].spinlock)); i2c_hal_set_start_timing(&(i2c_context[i2c_num].hal), setup_time, hold_time); + i2c_hal_update_config(&(i2c_context[i2c_num].hal)); I2C_EXIT_CRITICAL(&(i2c_context[i2c_num].spinlock)); return ESP_OK; } @@ -745,6 +763,7 @@ esp_err_t i2c_set_stop_timing(i2c_port_t i2c_num, int setup_time, int hold_time) I2C_ENTER_CRITICAL(&(i2c_context[i2c_num].spinlock)); i2c_hal_set_stop_timing(&(i2c_context[i2c_num].hal), setup_time, hold_time); + i2c_hal_update_config(&(i2c_context[i2c_num].hal)); I2C_EXIT_CRITICAL(&(i2c_context[i2c_num].spinlock)); return ESP_OK; } @@ -766,6 +785,7 @@ esp_err_t i2c_set_data_timing(i2c_port_t i2c_num, int sample_time, int hold_time I2C_ENTER_CRITICAL(&(i2c_context[i2c_num].spinlock)); i2c_hal_set_sda_timing(&(i2c_context[i2c_num].hal), sample_time, hold_time); + i2c_hal_update_config(&(i2c_context[i2c_num].hal)); I2C_EXIT_CRITICAL(&(i2c_context[i2c_num].spinlock)); return ESP_OK; } @@ -1232,14 +1252,17 @@ esp_err_t i2c_master_cmd_begin(i2c_port_t i2c_num, i2c_cmd_handle_t cmd_handle, if (evt_res == pdTRUE) { if (evt.type == I2C_CMD_EVT_DONE) { if (p_i2c->status == I2C_STATUS_TIMEOUT) { + esp_rom_printf("log-4: timeout\n"); // If the I2C slave are powered off or the SDA/SCL are connected to ground, for example, // I2C hw FSM would get stuck in wrong state, we have to reset the I2C module in this case. i2c_hw_fsm_reset(i2c_num); clear_bus_cnt = 0; ret = ESP_ERR_TIMEOUT; } else if (p_i2c->status == I2C_STATUS_ACK_ERROR) { + esp_rom_printf("log-6: ACK ERROR\n"); clear_bus_cnt++; if (clear_bus_cnt >= I2C_ACKERR_CNT_MAX) { + esp_rom_printf("log-7: CNT MAX\n"); clear_bus_cnt = 0; } ret = ESP_FAIL; @@ -1251,6 +1274,7 @@ esp_err_t i2c_master_cmd_begin(i2c_port_t i2c_num, i2c_cmd_handle_t cmd_handle, if (evt.type == I2C_CMD_EVT_ALIVE) { } } else { + esp_rom_printf("log-3: timeout\n"); ret = ESP_ERR_TIMEOUT; // If the I2C slave are powered off or the SDA/SCL are connected to ground, for example, // I2C hw FSM would get stuck in wrong state, we have to reset the I2C module in this case. diff --git a/components/hal/esp32c3/include/hal/i2c_ll.h b/components/hal/esp32c3/include/hal/i2c_ll.h index 9abe26d513..438841e04e 100644 --- a/components/hal/esp32c3/include/hal/i2c_ll.h +++ b/components/hal/esp32c3/include/hal/i2c_ll.h @@ -799,9 +799,12 @@ static inline void i2c_ll_master_fsm_rst(i2c_dev_t *hw) static inline void i2c_ll_master_clr_bus(i2c_dev_t *hw) { hw->scl_sp_conf.scl_rst_slv_num = 9; - hw->scl_sp_conf.scl_rst_slv_en = 0; - hw->ctr.conf_upgate = 1; hw->scl_sp_conf.scl_rst_slv_en = 1; + hw->ctr.conf_upgate = 1; + // hardward will clear scl_rst_slv_en after sending SCL pulses, + // and we should set conf_upgate bit to synchronize register value. + while (hw->scl_sp_conf.scl_rst_slv_en); + hw->ctr.conf_upgate = 1; } /** diff --git a/components/hal/i2c_hal_iram.c b/components/hal/i2c_hal_iram.c index 80c490009b..f40d4a3a0b 100644 --- a/components/hal/i2c_hal_iram.c +++ b/components/hal/i2c_hal_iram.c @@ -16,25 +16,30 @@ void i2c_hal_master_handle_tx_event(i2c_hal_context_t *hal, i2c_intr_event_t *event) { - i2c_ll_master_get_event(hal->dev, event); - if ((*event < I2C_INTR_EVENT_END_DET) || - (*event == I2C_INTR_EVENT_TRANS_DONE)) { - i2c_ll_master_disable_tx_it(hal->dev); - i2c_ll_master_clr_tx_it(hal->dev); - } else if (*event == I2C_INTR_EVENT_END_DET) { - i2c_ll_master_clr_tx_it(hal->dev); + if (i2c_ll_get_intsts_mask(hal->dev) != 0) { + // If intr status is 0, no need to handle it. + i2c_ll_master_get_event(hal->dev, event); + if ((*event < I2C_INTR_EVENT_END_DET) || + (*event == I2C_INTR_EVENT_TRANS_DONE)) { + i2c_ll_master_disable_tx_it(hal->dev); + i2c_ll_master_clr_tx_it(hal->dev); + } else if (*event == I2C_INTR_EVENT_END_DET) { + i2c_ll_master_clr_tx_it(hal->dev); + } } } void i2c_hal_master_handle_rx_event(i2c_hal_context_t *hal, i2c_intr_event_t *event) { - i2c_ll_master_get_event(hal->dev, event); - if ((*event < I2C_INTR_EVENT_END_DET) || - (*event == I2C_INTR_EVENT_TRANS_DONE)) { - i2c_ll_master_disable_rx_it(hal->dev); - i2c_ll_master_clr_rx_it(hal->dev); - } else if (*event == I2C_INTR_EVENT_END_DET) { - i2c_ll_master_clr_rx_it(hal->dev); + if (i2c_ll_get_intsts_mask(hal->dev) != 0) { + i2c_ll_master_get_event(hal->dev, event); + if ((*event < I2C_INTR_EVENT_END_DET) || + (*event == I2C_INTR_EVENT_TRANS_DONE)) { + i2c_ll_master_disable_rx_it(hal->dev); + i2c_ll_master_clr_rx_it(hal->dev); + } else if (*event == I2C_INTR_EVENT_END_DET) { + i2c_ll_master_clr_rx_it(hal->dev); + } } }