mirror of
https://github.com/espressif/esp-idf.git
synced 2025-07-30 02:37:19 +02:00
Merge branch 'bugfix/check_i2s_intr_alloc_failure_v5.3' into 'release/v5.3'
fix(i2s): check gdma callback register state and add missed port2 on p4 (v5.3) See merge request espressif/esp-idf!31426
This commit is contained in:
@ -348,14 +348,22 @@ static esp_err_t i2s_dma_intr_init(i2s_port_t i2s_num, int intr_flag)
|
||||
gdma_trigger_t trig = {.periph = GDMA_TRIG_PERIPH_I2S};
|
||||
|
||||
switch (i2s_num) {
|
||||
#if SOC_I2S_NUM > 2
|
||||
case I2S_NUM_2:
|
||||
trig.instance_id = SOC_GDMA_TRIG_PERIPH_I2S2;
|
||||
break;
|
||||
#endif
|
||||
#if SOC_I2S_NUM > 1
|
||||
case I2S_NUM_1:
|
||||
trig.instance_id = SOC_GDMA_TRIG_PERIPH_I2S1;
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
case I2S_NUM_0:
|
||||
trig.instance_id = SOC_GDMA_TRIG_PERIPH_I2S0;
|
||||
break;
|
||||
default:
|
||||
ESP_LOGE(TAG, "Unsupported I2S port number");
|
||||
return ESP_ERR_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
/* Set GDMA config */
|
||||
|
@ -696,6 +696,7 @@ static void IRAM_ATTR i2s_dma_tx_callback(void *arg)
|
||||
*/
|
||||
esp_err_t i2s_init_dma_intr(i2s_chan_handle_t handle, int intr_flag)
|
||||
{
|
||||
esp_err_t ret = ESP_OK;
|
||||
i2s_port_t port_id = handle->controller->id;
|
||||
ESP_RETURN_ON_FALSE((port_id >= 0) && (port_id < SOC_I2S_NUM), ESP_ERR_INVALID_ARG, TAG, "invalid handle");
|
||||
#if SOC_GDMA_SUPPORTED
|
||||
@ -703,14 +704,22 @@ esp_err_t i2s_init_dma_intr(i2s_chan_handle_t handle, int intr_flag)
|
||||
gdma_trigger_t trig = {.periph = GDMA_TRIG_PERIPH_I2S};
|
||||
|
||||
switch (port_id) {
|
||||
#if SOC_I2S_NUM > 2
|
||||
case I2S_NUM_2:
|
||||
trig.instance_id = SOC_GDMA_TRIG_PERIPH_I2S2;
|
||||
break;
|
||||
#endif
|
||||
#if SOC_I2S_NUM > 1
|
||||
case I2S_NUM_1:
|
||||
trig.instance_id = SOC_GDMA_TRIG_PERIPH_I2S1;
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
case I2S_NUM_0:
|
||||
trig.instance_id = SOC_GDMA_TRIG_PERIPH_I2S0;
|
||||
break;
|
||||
default:
|
||||
ESP_LOGE(TAG, "Unsupported I2S port number");
|
||||
return ESP_ERR_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
/* Set GDMA config */
|
||||
@ -719,18 +728,18 @@ esp_err_t i2s_init_dma_intr(i2s_chan_handle_t handle, int intr_flag)
|
||||
dma_cfg.direction = GDMA_CHANNEL_DIRECTION_TX;
|
||||
/* Register a new GDMA tx channel */
|
||||
ESP_RETURN_ON_ERROR(gdma_new_channel(&dma_cfg, &handle->dma.dma_chan), TAG, "Register tx dma channel error");
|
||||
ESP_RETURN_ON_ERROR(gdma_connect(handle->dma.dma_chan, trig), TAG, "Connect tx dma channel error");
|
||||
ESP_GOTO_ON_ERROR(gdma_connect(handle->dma.dma_chan, trig), err1, TAG, "Connect tx dma channel error");
|
||||
gdma_tx_event_callbacks_t cb = {.on_trans_eof = i2s_dma_tx_callback};
|
||||
/* Set callback function for GDMA, the interrupt is triggered by GDMA, then the GDMA ISR will call the callback function */
|
||||
gdma_register_tx_event_callbacks(handle->dma.dma_chan, &cb, handle);
|
||||
ESP_GOTO_ON_ERROR(gdma_register_tx_event_callbacks(handle->dma.dma_chan, &cb, handle), err2, TAG, "Register tx callback failed");
|
||||
} else {
|
||||
dma_cfg.direction = GDMA_CHANNEL_DIRECTION_RX;
|
||||
/* Register a new GDMA rx channel */
|
||||
ESP_RETURN_ON_ERROR(gdma_new_channel(&dma_cfg, &handle->dma.dma_chan), TAG, "Register rx dma channel error");
|
||||
ESP_RETURN_ON_ERROR(gdma_connect(handle->dma.dma_chan, trig), TAG, "Connect rx dma channel error");
|
||||
ESP_GOTO_ON_ERROR(gdma_connect(handle->dma.dma_chan, trig), err1, TAG, "Connect rx dma channel error");
|
||||
gdma_rx_event_callbacks_t cb = {.on_recv_eof = i2s_dma_rx_callback};
|
||||
/* Set callback function for GDMA, the interrupt is triggered by GDMA, then the GDMA ISR will call the callback function */
|
||||
gdma_register_rx_event_callbacks(handle->dma.dma_chan, &cb, handle);
|
||||
ESP_GOTO_ON_ERROR(gdma_register_rx_event_callbacks(handle->dma.dma_chan, &cb, handle), err2, TAG, "Register rx callback failed");
|
||||
}
|
||||
#else
|
||||
intr_flag |= handle->intr_prio_flags;
|
||||
@ -747,7 +756,15 @@ esp_err_t i2s_init_dma_intr(i2s_chan_handle_t handle, int intr_flag)
|
||||
/* Start DMA */
|
||||
i2s_ll_enable_dma(handle->controller->hal.dev, true);
|
||||
#endif // SOC_GDMA_SUPPORTED
|
||||
return ESP_OK;
|
||||
return ret;
|
||||
#if SOC_GDMA_SUPPORTED
|
||||
err2:
|
||||
gdma_disconnect(handle->dma.dma_chan);
|
||||
err1:
|
||||
gdma_del_channel(handle->dma.dma_chan);
|
||||
handle->dma.dma_chan = NULL;
|
||||
return ret;
|
||||
#endif
|
||||
}
|
||||
|
||||
static uint64_t s_i2s_get_pair_chan_gpio_mask(i2s_chan_handle_t handle)
|
||||
|
@ -22,6 +22,9 @@ typedef enum {
|
||||
I2S_NUM_0 = 0, /*!< I2S controller port 0 */
|
||||
#if SOC_I2S_NUM > 1
|
||||
I2S_NUM_1 = 1, /*!< I2S controller port 1 */
|
||||
#endif
|
||||
#if SOC_I2S_NUM > 2
|
||||
I2S_NUM_2 = 2, /*!< I2S controller port 2 */
|
||||
#endif
|
||||
I2S_NUM_AUTO, /*!< Select whichever port is available */
|
||||
} i2s_port_t;
|
||||
|
@ -190,7 +190,21 @@ TEST_CASE("I2S_basic_channel_allocation_reconfig_deleting_test", "[i2s]")
|
||||
TEST_ESP_OK(i2s_channel_enable(tx_handle));
|
||||
TEST_ESP_OK(i2s_channel_disable(tx_handle));
|
||||
TEST_ESP_OK(i2s_del_channel(tx_handle));
|
||||
TEST_ASSERT(i2s_channel_get_info(tx_handle, &chan_info) == ESP_ERR_NOT_FOUND);
|
||||
TEST_ESP_ERR(ESP_ERR_NOT_FOUND, i2s_channel_get_info(tx_handle, &chan_info));
|
||||
|
||||
/* Exhaust test */
|
||||
std_cfg.gpio_cfg.mclk = -1;
|
||||
i2s_chan_handle_t tx_ex[SOC_I2S_NUM] = {};
|
||||
for (int i = 0; i < SOC_I2S_NUM; i++) {
|
||||
TEST_ESP_OK(i2s_new_channel(&chan_cfg, &tx_ex[i], NULL));
|
||||
TEST_ESP_OK(i2s_channel_init_std_mode(tx_ex[i], &std_cfg));
|
||||
TEST_ESP_OK(i2s_channel_enable(tx_ex[i]));
|
||||
}
|
||||
TEST_ESP_ERR(ESP_ERR_NOT_FOUND, i2s_new_channel(&chan_cfg, &tx_handle, NULL));
|
||||
for (int i = 0; i < SOC_I2S_NUM; i++) {
|
||||
TEST_ESP_OK(i2s_channel_disable(tx_ex[i]));
|
||||
TEST_ESP_OK(i2s_del_channel(tx_ex[i]));
|
||||
}
|
||||
|
||||
/* Duplex channel basic test */
|
||||
chan_cfg.id = I2S_NUM_0; // Specify port id to I2S port 0
|
||||
@ -208,7 +222,7 @@ TEST_CASE("I2S_basic_channel_allocation_reconfig_deleting_test", "[i2s]")
|
||||
|
||||
/* Hold the occupation */
|
||||
TEST_ESP_OK(i2s_platform_acquire_occupation(I2S_NUM_0, "test_i2s"));
|
||||
TEST_ASSERT(i2s_new_channel(&chan_cfg, &tx_handle, &rx_handle) == ESP_ERR_NOT_FOUND);
|
||||
TEST_ESP_ERR(ESP_ERR_NOT_FOUND, i2s_new_channel(&chan_cfg, &tx_handle, &rx_handle));
|
||||
TEST_ESP_OK(i2s_platform_release_occupation(I2S_NUM_0));
|
||||
TEST_ESP_OK(i2s_new_channel(&chan_cfg, &tx_handle, &rx_handle));
|
||||
TEST_ESP_OK(i2s_del_channel(tx_handle));
|
||||
|
Reference in New Issue
Block a user