From ab818887057a284400b0ea92b61638d9dc9c6df9 Mon Sep 17 00:00:00 2001 From: laokaiyao Date: Wed, 22 May 2024 16:21:15 +0800 Subject: [PATCH 1/2] fix(i2s): add check to gdma callback register --- components/esp_driver_i2s/i2s_common.c | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/components/esp_driver_i2s/i2s_common.c b/components/esp_driver_i2s/i2s_common.c index 7bd6cddd6d..43a6958017 100644 --- a/components/esp_driver_i2s/i2s_common.c +++ b/components/esp_driver_i2s/i2s_common.c @@ -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 @@ -719,18 +720,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 +748,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) From cd4c71e20f7d676ba22c320d546f64ee18635f75 Mon Sep 17 00:00:00 2001 From: laokaiyao Date: Wed, 22 May 2024 16:23:06 +0800 Subject: [PATCH 2/2] fix(i2s): add the missed port2 for p4 --- components/driver/deprecated/i2s_legacy.c | 10 +++++++++- components/esp_driver_i2s/i2s_common.c | 10 +++++++++- .../esp_driver_i2s/include/driver/i2s_types.h | 3 +++ .../test_apps/i2s/main/test_i2s.c | 18 ++++++++++++++++-- 4 files changed, 37 insertions(+), 4 deletions(-) diff --git a/components/driver/deprecated/i2s_legacy.c b/components/driver/deprecated/i2s_legacy.c index d36b2e2945..a7d26760a7 100644 --- a/components/driver/deprecated/i2s_legacy.c +++ b/components/driver/deprecated/i2s_legacy.c @@ -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 */ diff --git a/components/esp_driver_i2s/i2s_common.c b/components/esp_driver_i2s/i2s_common.c index 43a6958017..7520bb23cc 100644 --- a/components/esp_driver_i2s/i2s_common.c +++ b/components/esp_driver_i2s/i2s_common.c @@ -704,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 */ diff --git a/components/esp_driver_i2s/include/driver/i2s_types.h b/components/esp_driver_i2s/include/driver/i2s_types.h index 2135124389..9f103f0718 100644 --- a/components/esp_driver_i2s/include/driver/i2s_types.h +++ b/components/esp_driver_i2s/include/driver/i2s_types.h @@ -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; diff --git a/components/esp_driver_i2s/test_apps/i2s/main/test_i2s.c b/components/esp_driver_i2s/test_apps/i2s/main/test_i2s.c index 5cb9489b5d..93aca31233 100644 --- a/components/esp_driver_i2s/test_apps/i2s/main/test_i2s.c +++ b/components/esp_driver_i2s/test_apps/i2s/main/test_i2s.c @@ -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));