Merge branch 'bugfix/i2c_notify_task_in_ISR_v4.2' into 'release/v4.2'

I2C: Fix a bug making the I2C task wait too long on an event

See merge request espressif/esp-idf!19619
This commit is contained in:
Zim Kalinowski 2022-09-13 16:27:40 +08:00
commit eb128229a9

View File

@ -166,7 +166,7 @@ static i2c_context_t i2c_context[I2C_NUM_MAX] = {
static i2c_obj_t *p_i2c_obj[I2C_NUM_MAX] = {0};
static void i2c_isr_handler_default(void *arg);
static void IRAM_ATTR i2c_master_cmd_begin_static(i2c_port_t i2c_num);
static void IRAM_ATTR i2c_master_cmd_begin_static(i2c_port_t i2c_num, portBASE_TYPE* HPTaskAwoken);
static esp_err_t IRAM_ATTR i2c_hw_fsm_reset(i2c_port_t i2c_num);
static void i2c_hw_disable(i2c_port_t i2c_num)
@ -437,6 +437,7 @@ 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;
portBASE_TYPE HPTaskAwokenCallee = 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);
@ -445,18 +446,18 @@ static void IRAM_ATTR i2c_isr_handler_default(void *arg)
}
if (evt_type == I2C_INTR_EVENT_NACK) {
p_i2c_obj[i2c_num]->status = I2C_STATUS_ACK_ERROR;
i2c_master_cmd_begin_static(i2c_num);
i2c_master_cmd_begin_static(i2c_num, &HPTaskAwokenCallee);
} else if (evt_type == I2C_INTR_EVENT_TOUT) {
p_i2c_obj[i2c_num]->status = I2C_STATUS_TIMEOUT;
i2c_master_cmd_begin_static(i2c_num);
i2c_master_cmd_begin_static(i2c_num, &HPTaskAwokenCallee);
} 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);
i2c_master_cmd_begin_static(i2c_num, &HPTaskAwokenCallee);
} else if (evt_type == I2C_INTR_EVENT_END_DET) {
i2c_master_cmd_begin_static(i2c_num);
i2c_master_cmd_begin_static(i2c_num, &HPTaskAwokenCallee);
} 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);
i2c_master_cmd_begin_static(i2c_num, &HPTaskAwokenCallee);
}
}
i2c_cmd_evt_t evt = {
@ -486,7 +487,7 @@ static void IRAM_ATTR i2c_isr_handler_default(void *arg)
}
}
//We only need to check here if there is a high-priority task needs to be switched.
if (HPTaskAwoken == pdTRUE) {
if (HPTaskAwoken == pdTRUE || HPTaskAwokenCallee == pdTRUE) {
portYIELD_FROM_ISR();
}
}
@ -1004,11 +1005,10 @@ esp_err_t i2c_master_read(i2c_cmd_handle_t cmd_handle, uint8_t *data, size_t dat
}
}
static void IRAM_ATTR i2c_master_cmd_begin_static(i2c_port_t i2c_num)
static void IRAM_ATTR i2c_master_cmd_begin_static(i2c_port_t i2c_num, portBASE_TYPE* HPTaskAwoken)
{
i2c_obj_t *p_i2c = p_i2c_obj[i2c_num];
portBASE_TYPE HPTaskAwoken = pdFALSE;
i2c_cmd_evt_t evt;
i2c_cmd_evt_t evt = { 0 };
if (p_i2c->cmd_link.head != NULL && p_i2c->status == I2C_STATUS_READ) {
i2c_cmd_t *cmd = &p_i2c->cmd_link.head->cmd;
i2c_hal_read_rxfifo(&(i2c_context[i2c_num].hal), cmd->data, p_i2c->rx_cnt);
@ -1020,17 +1020,19 @@ static void IRAM_ATTR i2c_master_cmd_begin_static(i2c_port_t i2c_num)
}
} else if ((p_i2c->status == I2C_STATUS_ACK_ERROR)
|| (p_i2c->status == I2C_STATUS_TIMEOUT)) {
assert(HPTaskAwoken != NULL);
evt.type = I2C_CMD_EVT_DONE;
xQueueOverwriteFromISR(p_i2c->cmd_evt_queue, &evt, &HPTaskAwoken);
xQueueOverwriteFromISR(p_i2c->cmd_evt_queue, &evt, HPTaskAwoken);
return;
} else if (p_i2c->status == I2C_STATUS_DONE) {
return;
}
if (p_i2c->cmd_link.head == NULL) {
assert(HPTaskAwoken != NULL);
p_i2c->cmd_link.cur = NULL;
evt.type = I2C_CMD_EVT_DONE;
xQueueOverwriteFromISR(p_i2c->cmd_evt_queue, &evt, &HPTaskAwoken);
xQueueOverwriteFromISR(p_i2c->cmd_evt_queue, &evt, HPTaskAwoken);
// Return to the IDLE status after cmd_eve_done signal were send out.
p_i2c->status = I2C_STATUS_IDLE;
return;
@ -1158,7 +1160,7 @@ esp_err_t i2c_master_cmd_begin(i2c_port_t i2c_num, i2c_cmd_handle_t cmd_handle,
i2c_hal_disable_intr_mask(&(i2c_context[i2c_num].hal), I2C_INTR_MASK);
i2c_hal_clr_intsts_mask(&(i2c_context[i2c_num].hal), I2C_INTR_MASK);
//start send commands, at most 32 bytes one time, isr handler will process the remaining commands.
i2c_master_cmd_begin_static(i2c_num);
i2c_master_cmd_begin_static(i2c_num, NULL);
// Wait event bits
i2c_cmd_evt_t evt;