fix(i2s): fix the auto port failure when use simplex on ESP32

This commit is contained in:
laokaiyao
2025-11-28 11:40:11 +08:00
parent f42b153669
commit e21942222b
5 changed files with 151 additions and 7 deletions
+36
View File
@@ -370,6 +370,40 @@ err:
return ret;
}
#if SOC_I2S_HW_VERSION_1
esp_err_t i2s_channel_change_port(i2s_chan_handle_t handle, int id)
{
I2S_NULL_POINTER_CHECK(TAG, handle);
ESP_RETURN_ON_FALSE(id >= 0 && id < SOC_I2S_NUM, ESP_ERR_INVALID_ARG, TAG, "invalid I2S port id");
if (id == handle->controller->id) {
return ESP_OK;
}
i2s_controller_t *i2s_obj = i2s_acquire_controller_obj(id);
if (!i2s_obj || !i2s_take_available_channel(i2s_obj, handle->dir)) {
return ESP_ERR_NOT_FOUND;
}
i2s_controller_t *old_i2s_obj = handle->controller;
portENTER_CRITICAL(&g_i2s.spinlock);
if (handle->dir == I2S_DIR_TX) {
i2s_obj->tx_chan = handle;
i2s_obj->chan_occupancy |= I2S_DIR_TX;
old_i2s_obj->tx_chan = NULL;
old_i2s_obj->full_duplex = false;
old_i2s_obj->chan_occupancy &= ~I2S_DIR_TX;
} else {
i2s_obj->rx_chan = handle;
i2s_obj->chan_occupancy |= I2S_DIR_RX;
old_i2s_obj->rx_chan = NULL;
old_i2s_obj->full_duplex = false;
old_i2s_obj->chan_occupancy &= ~I2S_DIR_RX;
}
handle->controller = i2s_obj;
portEXIT_CRITICAL(&g_i2s.spinlock);
return ESP_OK;
}
#endif
#ifndef __cplusplus
/* To make sure the i2s_event_callbacks_t is same size as i2s_event_callbacks_internal_t */
_Static_assert(sizeof(i2s_event_callbacks_t) == sizeof(i2s_event_callbacks_internal_t), "Invalid size of i2s_event_callbacks_t structure");
@@ -983,6 +1017,7 @@ esp_err_t i2s_new_channel(const i2s_chan_config_t *chan_cfg, i2s_chan_handle_t *
ESP_GOTO_ON_ERROR(i2s_register_channel(i2s_obj, I2S_DIR_TX, chan_cfg->dma_desc_num),
err, TAG, "register I2S tx channel failed");
i2s_obj->tx_chan->role = chan_cfg->role;
i2s_obj->tx_chan->is_port_auto = id == I2S_NUM_AUTO;
i2s_obj->tx_chan->intr_prio_flags = chan_cfg->intr_priority ? BIT(chan_cfg->intr_priority) : ESP_INTR_FLAG_LOWMED;
i2s_obj->tx_chan->dma.auto_clear_after_cb = chan_cfg->auto_clear_after_cb;
i2s_obj->tx_chan->dma.auto_clear_before_cb = chan_cfg->auto_clear_before_cb;
@@ -998,6 +1033,7 @@ esp_err_t i2s_new_channel(const i2s_chan_config_t *chan_cfg, i2s_chan_handle_t *
ESP_GOTO_ON_ERROR(i2s_register_channel(i2s_obj, I2S_DIR_RX, chan_cfg->dma_desc_num),
err, TAG, "register I2S rx channel failed");
i2s_obj->rx_chan->role = chan_cfg->role;
i2s_obj->rx_chan->is_port_auto = id == I2S_NUM_AUTO;
i2s_obj->rx_chan->intr_prio_flags = chan_cfg->intr_priority ? BIT(chan_cfg->intr_priority) : ESP_INTR_FLAG_LOWMED;
i2s_obj->rx_chan->dma.desc_num = chan_cfg->dma_desc_num;
i2s_obj->rx_chan->dma.frame_num = chan_cfg->dma_frame_num;