diff --git a/components/driver/i2s/i2s_common.c b/components/driver/i2s/i2s_common.c index 166098803b..c9ade79d54 100644 --- a/components/driver/i2s/i2s_common.c +++ b/components/driver/i2s/i2s_common.c @@ -375,34 +375,39 @@ uint32_t i2s_get_buf_size(i2s_chan_handle_t handle, uint32_t data_bit_width, uin esp_err_t i2s_free_dma_desc(i2s_chan_handle_t handle) { I2S_NULL_POINTER_CHECK(TAG, handle); - if (!handle->dma.desc) { - return ESP_OK; - } - for (int i = 0; i < handle->dma.desc_num; i++) { - if (handle->dma.bufs[i]) { - free(handle->dma.bufs[i]); - } - if (handle->dma.desc[i]) { - free(handle->dma.desc[i]); - } - } - if (handle->dma.bufs) { - free(handle->dma.bufs); - } + handle->dma.buf_size = 0; + if (handle->dma.desc) { + for (int i = 0; i < handle->dma.desc_num; i++) { + if (handle->dma.desc[i]) { + free(handle->dma.desc[i]); + handle->dma.desc[i] = NULL; + } + } free(handle->dma.desc); } handle->dma.desc = NULL; + if (handle->dma.bufs) { + for (int i = 0; i < handle->dma.desc_num; i++) { + if (handle->dma.bufs[i]) { + free(handle->dma.bufs[i]); + handle->dma.bufs[i] = NULL; + } + } + free(handle->dma.bufs); + handle->dma.bufs = NULL; + } + return ESP_OK; } -esp_err_t i2s_alloc_dma_desc(i2s_chan_handle_t handle, uint32_t num, uint32_t bufsize) +esp_err_t i2s_alloc_dma_desc(i2s_chan_handle_t handle, uint32_t bufsize) { I2S_NULL_POINTER_CHECK(TAG, handle); esp_err_t ret = ESP_OK; ESP_RETURN_ON_FALSE(bufsize <= I2S_DMA_BUFFER_MAX_SIZE, ESP_ERR_INVALID_ARG, TAG, "dma buffer can't be bigger than %d", I2S_DMA_BUFFER_MAX_SIZE); - handle->dma.desc_num = num; + uint32_t num = handle->dma.desc_num; handle->dma.buf_size = bufsize; /* Descriptors must be in the internal RAM */ diff --git a/components/driver/i2s/i2s_pdm.c b/components/driver/i2s/i2s_pdm.c index 41601044d2..1ed6aea7e7 100644 --- a/components/driver/i2s/i2s_pdm.c +++ b/components/driver/i2s/i2s_pdm.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -44,7 +44,8 @@ static esp_err_t i2s_pdm_tx_calculate_clock(i2s_chan_handle_t handle, const i2s_ clk_info->mclk_div = clk_info->sclk / clk_info->mclk; /* Check if the configuration is correct. Use float for check in case the mclk division might be carried up in the fine division calculation */ - ESP_RETURN_ON_FALSE(clk_info->sclk / (float)clk_info->mclk > 1.99, ESP_ERR_INVALID_ARG, TAG, "sample rate is too large"); + ESP_RETURN_ON_FALSE((float)clk_info->sclk > clk_info->mclk * 1.99, ESP_ERR_INVALID_ARG, TAG, "sample rate is too large"); + ESP_RETURN_ON_FALSE(clk_info->mclk_div < 256, ESP_ERR_INVALID_ARG, TAG, "sample rate is too small"); /* Set up sampling configuration */ i2s_ll_tx_set_pdm_fpfs(handle->controller->hal.dev, pdm_tx_clk->up_sample_fp, pdm_tx_clk->up_sample_fs); i2s_ll_tx_set_pdm_over_sample_ratio(handle->controller->hal.dev, over_sample_ratio); @@ -89,9 +90,8 @@ static esp_err_t i2s_pdm_tx_set_slot(i2s_chan_handle_t handle, const i2s_pdm_tx_ uint32_t buf_size = i2s_get_buf_size(handle, slot_cfg->data_bit_width, handle->dma.frame_num); /* The DMA buffer need to re-allocate if the buffer size changed */ if (handle->dma.buf_size != buf_size) { - handle->dma.buf_size = buf_size; ESP_RETURN_ON_ERROR(i2s_free_dma_desc(handle), TAG, "failed to free the old dma descriptor"); - ESP_RETURN_ON_ERROR(i2s_alloc_dma_desc(handle, handle->dma.desc_num, buf_size), + ESP_RETURN_ON_ERROR(i2s_alloc_dma_desc(handle, buf_size), TAG, "allocate memory for dma descriptor failed"); } /* Share bck and ws signal in full-duplex mode */ @@ -333,7 +333,8 @@ static esp_err_t i2s_pdm_rx_calculate_clock(i2s_chan_handle_t handle, const i2s_ clk_info->mclk_div = clk_info->sclk / clk_info->mclk; /* Check if the configuration is correct. Use float for check in case the mclk division might be carried up in the fine division calculation */ - ESP_RETURN_ON_FALSE(clk_info->sclk / (float)clk_info->mclk > 1.99, ESP_ERR_INVALID_ARG, TAG, "sample rate is too large"); + ESP_RETURN_ON_FALSE((float)clk_info->sclk > clk_info->mclk * 1.99, ESP_ERR_INVALID_ARG, TAG, "sample rate is too large"); + ESP_RETURN_ON_FALSE(clk_info->mclk_div < I2S_LL_CLK_FRAC_DIV_N_MAX, ESP_ERR_INVALID_ARG, TAG, "sample rate is too small"); /* Set down-sampling configuration */ i2s_ll_rx_set_pdm_dsr(handle->controller->hal.dev, pdm_rx_clk->dn_sample_mode); return ESP_OK; @@ -370,9 +371,8 @@ static esp_err_t i2s_pdm_rx_set_slot(i2s_chan_handle_t handle, const i2s_pdm_rx_ uint32_t buf_size = i2s_get_buf_size(handle, slot_cfg->data_bit_width, handle->dma.frame_num); /* The DMA buffer need to re-allocate if the buffer size changed */ if (handle->dma.buf_size != buf_size) { - handle->dma.buf_size = buf_size; ESP_RETURN_ON_ERROR(i2s_free_dma_desc(handle), TAG, "failed to free the old dma descriptor"); - ESP_RETURN_ON_ERROR(i2s_alloc_dma_desc(handle, handle->dma.desc_num, buf_size), + ESP_RETURN_ON_ERROR(i2s_alloc_dma_desc(handle, buf_size), TAG, "allocate memory for dma descriptor failed"); } /* Share bck and ws signal in full-duplex mode */ diff --git a/components/driver/i2s/i2s_private.h b/components/driver/i2s/i2s_private.h index f650c2a6f3..028117ee3d 100644 --- a/components/driver/i2s/i2s_private.h +++ b/components/driver/i2s/i2s_private.h @@ -150,7 +150,6 @@ esp_err_t i2s_free_dma_desc(i2s_chan_handle_t handle); * @brief Allocate memory for I2S DMA descriptor and DMA buffer * * @param handle I2S channel handle - * @param num Number of DMA descriptors * @param bufsize The DMA buffer size * * @return @@ -158,7 +157,7 @@ esp_err_t i2s_free_dma_desc(i2s_chan_handle_t handle); * - ESP_ERR_INVALID_ARG NULL pointer or bufsize is too big * - ESP_ERR_NO_MEM No memory for DMA descriptor and DMA buffer */ -esp_err_t i2s_alloc_dma_desc(i2s_chan_handle_t handle, uint32_t num, uint32_t bufsize); +esp_err_t i2s_alloc_dma_desc(i2s_chan_handle_t handle, uint32_t bufsize); /** * @brief Get DMA buffer size diff --git a/components/driver/i2s/i2s_std.c b/components/driver/i2s/i2s_std.c index 896d3eff83..1b0709f7dd 100644 --- a/components/driver/i2s/i2s_std.c +++ b/components/driver/i2s/i2s_std.c @@ -49,7 +49,8 @@ static esp_err_t i2s_std_calculate_clock(i2s_chan_handle_t handle, const i2s_std clk_info->mclk_div = clk_info->sclk / clk_info->mclk; /* Check if the configuration is correct. Use float for check in case the mclk division might be carried up in the fine division calculation */ - ESP_RETURN_ON_FALSE(clk_info->sclk / (float)clk_info->mclk > 1.99, ESP_ERR_INVALID_ARG, TAG, "sample rate or mclk_multiple is too large for the current clock source"); + ESP_RETURN_ON_FALSE((float)clk_info->sclk > clk_info->mclk * 1.99, ESP_ERR_INVALID_ARG, TAG, "sample rate is too large"); + ESP_RETURN_ON_FALSE(clk_info->mclk_div < I2S_LL_CLK_FRAC_DIV_N_MAX, ESP_ERR_INVALID_ARG, TAG, "sample rate is too small"); return ESP_OK; } @@ -94,9 +95,8 @@ static esp_err_t i2s_std_set_slot(i2s_chan_handle_t handle, const i2s_std_slot_c uint32_t buf_size = i2s_get_buf_size(handle, slot_cfg->data_bit_width, handle->dma.frame_num); /* The DMA buffer need to re-allocate if the buffer size changed */ if (handle->dma.buf_size != buf_size) { - handle->dma.buf_size = buf_size; ESP_RETURN_ON_ERROR(i2s_free_dma_desc(handle), TAG, "failed to free the old dma descriptor"); - ESP_RETURN_ON_ERROR(i2s_alloc_dma_desc(handle, handle->dma.desc_num, buf_size), + ESP_RETURN_ON_ERROR(i2s_alloc_dma_desc(handle, buf_size), TAG, "allocate memory for dma descriptor failed"); } bool is_slave = handle->role == I2S_ROLE_SLAVE; diff --git a/components/driver/i2s/i2s_tdm.c b/components/driver/i2s/i2s_tdm.c index 573e1e915c..4a0c06a71c 100644 --- a/components/driver/i2s/i2s_tdm.c +++ b/components/driver/i2s/i2s_tdm.c @@ -60,7 +60,8 @@ static esp_err_t i2s_tdm_calculate_clock(i2s_chan_handle_t handle, const i2s_tdm clk_info->mclk_div = clk_info->sclk / clk_info->mclk; /* Check if the configuration is correct. Use float for check in case the mclk division might be carried up in the fine division calculation */ - ESP_RETURN_ON_FALSE(clk_info->sclk / (float)clk_info->mclk > 1.99, ESP_ERR_INVALID_ARG, TAG, "sample rate or mclk_multiple is too large for the current clock source"); + ESP_RETURN_ON_FALSE((float)clk_info->sclk > clk_info->mclk * 1.99, ESP_ERR_INVALID_ARG, TAG, "sample rate is too large"); + ESP_RETURN_ON_FALSE(clk_info->mclk_div < I2S_LL_CLK_FRAC_DIV_N_MAX, ESP_ERR_INVALID_ARG, TAG, "sample rate is too small"); return ESP_OK; } @@ -107,9 +108,8 @@ static esp_err_t i2s_tdm_set_slot(i2s_chan_handle_t handle, const i2s_tdm_slot_c uint32_t buf_size = i2s_get_buf_size(handle, slot_cfg->data_bit_width, handle->dma.frame_num); /* The DMA buffer need to re-allocate if the buffer size changed */ if (handle->dma.buf_size != buf_size) { - handle->dma.buf_size = buf_size; ESP_RETURN_ON_ERROR(i2s_free_dma_desc(handle), TAG, "failed to free the old dma descriptor"); - ESP_RETURN_ON_ERROR(i2s_alloc_dma_desc(handle, handle->dma.desc_num, buf_size), + ESP_RETURN_ON_ERROR(i2s_alloc_dma_desc(handle, buf_size), TAG, "allocate memory for dma descriptor failed"); } bool is_slave = handle->role == I2S_ROLE_SLAVE; diff --git a/components/hal/esp32/include/hal/i2s_ll.h b/components/hal/esp32/include/hal/i2s_ll.h index 552cde83c8..8ee2725fc8 100644 --- a/components/hal/esp32/include/hal/i2s_ll.h +++ b/components/hal/esp32/include/hal/i2s_ll.h @@ -30,6 +30,8 @@ extern "C" { #define I2S_LL_AD_BCK_FACTOR (2) #define I2S_LL_PDM_BCK_FACTOR (64) +#define I2S_LL_CLK_FRAC_DIV_N_MAX 256 // I2S_MCLK = I2S_SRC_CLK / (N + b/a), the N register is 8 bit-width + #define I2S_LL_MCLK_DIVIDER_BIT_WIDTH (6) #define I2S_LL_MCLK_DIVIDER_MAX ((1 << I2S_LL_MCLK_DIVIDER_BIT_WIDTH) - 1) diff --git a/components/hal/esp32c3/include/hal/i2s_ll.h b/components/hal/esp32c3/include/hal/i2s_ll.h index d056b140ef..4ecc51c7ea 100644 --- a/components/hal/esp32c3/include/hal/i2s_ll.h +++ b/components/hal/esp32c3/include/hal/i2s_ll.h @@ -29,6 +29,8 @@ extern "C" { #define I2S_LL_TDM_CH_MASK (0xffff) #define I2S_LL_PDM_BCK_FACTOR (64) +#define I2S_LL_CLK_FRAC_DIV_N_MAX 256 // I2S_MCLK = I2S_SRC_CLK / (N + b/a), the N register is 8 bit-width + #define I2S_LL_MCLK_DIVIDER_BIT_WIDTH (9) #define I2S_LL_MCLK_DIVIDER_MAX ((1 << I2S_LL_MCLK_DIVIDER_BIT_WIDTH) - 1) #define I2S_LL_SLOT_FRAME_BIT_MAX 128 // Up-to 128 bits in one frame, determined by MAX(half_sample_bits) * 2 diff --git a/components/hal/esp32c6/include/hal/i2s_ll.h b/components/hal/esp32c6/include/hal/i2s_ll.h index 9bd862c163..b324668fe7 100644 --- a/components/hal/esp32c6/include/hal/i2s_ll.h +++ b/components/hal/esp32c6/include/hal/i2s_ll.h @@ -30,6 +30,8 @@ extern "C" { #define I2S_LL_TDM_CH_MASK (0xffff) #define I2S_LL_PDM_BCK_FACTOR (64) +#define I2S_LL_CLK_FRAC_DIV_N_MAX 256 // I2S_MCLK = I2S_SRC_CLK / (N + b/a), the N register is 8 bit-width + #define I2S_LL_MCLK_DIVIDER_BIT_WIDTH (9) #define I2S_LL_MCLK_DIVIDER_MAX ((1 << I2S_LL_MCLK_DIVIDER_BIT_WIDTH) - 1) #define I2S_LL_SLOT_FRAME_BIT_MAX 128 // Up-to 128 bits in one frame, determined by MAX(half_sample_bits) * 2 diff --git a/components/hal/esp32h2/include/hal/i2s_ll.h b/components/hal/esp32h2/include/hal/i2s_ll.h index 2d3c97c152..e2530a47fc 100644 --- a/components/hal/esp32h2/include/hal/i2s_ll.h +++ b/components/hal/esp32h2/include/hal/i2s_ll.h @@ -30,6 +30,8 @@ extern "C" { #define I2S_LL_TDM_CH_MASK (0xffff) #define I2S_LL_PDM_BCK_FACTOR (64) +#define I2S_LL_CLK_FRAC_DIV_N_MAX 256 // I2S_MCLK = I2S_SRC_CLK / (N + b/a), the N register is 8 bit-width + #define I2S_LL_MCLK_DIVIDER_BIT_WIDTH (9) #define I2S_LL_MCLK_DIVIDER_MAX ((1 << I2S_LL_MCLK_DIVIDER_BIT_WIDTH) - 1) #define I2S_LL_SLOT_FRAME_BIT_MAX 512 // Up-to 512 bits in one frame, determined by MAX(half_sample_bits) * 2 diff --git a/components/hal/esp32s2/include/hal/i2s_ll.h b/components/hal/esp32s2/include/hal/i2s_ll.h index eb12347cb0..0205c89010 100644 --- a/components/hal/esp32s2/include/hal/i2s_ll.h +++ b/components/hal/esp32s2/include/hal/i2s_ll.h @@ -30,6 +30,8 @@ extern "C" { #define I2S_LL_BCK_MAX_PRESCALE (64) +#define I2S_LL_CLK_FRAC_DIV_N_MAX 256 // I2S_MCLK = I2S_SRC_CLK / (N + b/a), the N register is 8 bit-width + #define I2S_LL_MCLK_DIVIDER_BIT_WIDTH (6) #define I2S_LL_MCLK_DIVIDER_MAX ((1 << I2S_LL_MCLK_DIVIDER_BIT_WIDTH) - 1) diff --git a/components/hal/esp32s3/include/hal/i2s_ll.h b/components/hal/esp32s3/include/hal/i2s_ll.h index f5fab4c40b..6a51da4613 100644 --- a/components/hal/esp32s3/include/hal/i2s_ll.h +++ b/components/hal/esp32s3/include/hal/i2s_ll.h @@ -30,6 +30,8 @@ extern "C" { #define I2S_LL_TDM_CH_MASK (0xffff) #define I2S_LL_PDM_BCK_FACTOR (64) +#define I2S_LL_CLK_FRAC_DIV_N_MAX 256 // I2S_MCLK = I2S_SRC_CLK / (N + b/a), the N register is 8 bit-width + #define I2S_LL_MCLK_DIVIDER_BIT_WIDTH (9) #define I2S_LL_MCLK_DIVIDER_MAX ((1 << I2S_LL_MCLK_DIVIDER_BIT_WIDTH) - 1) #define I2S_LL_SLOT_FRAME_BIT_MAX 128 // Up-to 128 bits in one frame, determined by MAX(half_sample_bits) * 2