Skip to content

Commit cfea4f7

Browse files
committed
Merge branch 'bugfix/fix_i2s_24b_buf_size_calc_v5.3' into 'release/v5.3'
fix(i2s): fixed some issues in I2S driver (v5.3) See merge request espressif/esp-idf!35769
2 parents fbdf9d9 + fdc8275 commit cfea4f7

File tree

30 files changed

+104
-27
lines changed

30 files changed

+104
-27
lines changed

components/esp_driver_i2s/i2s_common.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -350,7 +350,11 @@ esp_err_t i2s_channel_register_event_callback(i2s_chan_handle_t handle, const i2
350350
uint32_t i2s_get_buf_size(i2s_chan_handle_t handle, uint32_t data_bit_width, uint32_t dma_frame_num)
351351
{
352352
uint32_t active_chan = handle->active_slot;
353+
#if CONFIG_IDF_TARGET_ESP32
353354
uint32_t bytes_per_sample = ((data_bit_width + 15) / 16) * 2;
355+
#else
356+
uint32_t bytes_per_sample = (data_bit_width + 7) / 8;
357+
#endif // CONFIG_IDF_TARGET_ESP32
354358
uint32_t bytes_per_frame = bytes_per_sample * active_chan;
355359
uint32_t bufsize = dma_frame_num * bytes_per_frame;
356360
#if SOC_CACHE_INTERNAL_MEM_VIA_L1CACHE

components/esp_driver_i2s/i2s_pdm.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -44,8 +44,8 @@ static esp_err_t i2s_pdm_tx_calculate_clock(i2s_chan_handle_t handle, const i2s_
4444
clk_info->sclk = i2s_get_source_clk_freq(clk_cfg->clk_src, clk_info->mclk);
4545
clk_info->mclk_div = clk_info->sclk / clk_info->mclk;
4646

47-
/* Check if the configuration is correct */
48-
ESP_RETURN_ON_FALSE(clk_info->mclk_div, ESP_ERR_INVALID_ARG, TAG, "sample rate is too large");
47+
/* Check if the configuration is correct. Use float for check in case the mclk division might be carried up in the fine division calculation */
48+
ESP_RETURN_ON_FALSE(clk_info->sclk / (float)clk_info->mclk > 1.99, ESP_ERR_INVALID_ARG, TAG, "sample rate is too large");
4949
/* Set up sampling configuration */
5050
i2s_ll_tx_set_pdm_fpfs(handle->controller->hal.dev, pdm_tx_clk->up_sample_fp, pdm_tx_clk->up_sample_fs);
5151
i2s_ll_tx_set_pdm_over_sample_ratio(handle->controller->hal.dev, over_sample_ratio);
@@ -342,8 +342,8 @@ static esp_err_t i2s_pdm_rx_calculate_clock(i2s_chan_handle_t handle, const i2s_
342342
clk_info->sclk = i2s_get_source_clk_freq(clk_cfg->clk_src, clk_info->mclk);
343343
clk_info->mclk_div = clk_info->sclk / clk_info->mclk;
344344

345-
/* Check if the configuration is correct */
346-
ESP_RETURN_ON_FALSE(clk_info->mclk_div, ESP_ERR_INVALID_ARG, TAG, "sample rate is too large");
345+
/* Check if the configuration is correct. Use float for check in case the mclk division might be carried up in the fine division calculation */
346+
ESP_RETURN_ON_FALSE(clk_info->sclk / (float)clk_info->mclk > 1.99, ESP_ERR_INVALID_ARG, TAG, "sample rate is too large");
347347
/* Set down-sampling configuration */
348348
i2s_ll_rx_set_pdm_dsr(handle->controller->hal.dev, pdm_rx_clk->dn_sample_mode);
349349
return ESP_OK;

components/esp_driver_i2s/i2s_std.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,13 +51,15 @@ static esp_err_t i2s_std_calculate_clock(i2s_chan_handle_t handle, const i2s_std
5151
#if SOC_I2S_HW_VERSION_2
5252
clk_info->sclk = clk_cfg->clk_src == I2S_CLK_SRC_EXTERNAL ?
5353
clk_cfg->ext_clk_freq_hz : i2s_get_source_clk_freq(clk_cfg->clk_src, clk_info->mclk);
54+
float min_mclk_div = clk_cfg->clk_src == I2S_CLK_SRC_EXTERNAL ? 0.99 : 1.99;
5455
#else
5556
clk_info->sclk = i2s_get_source_clk_freq(clk_cfg->clk_src, clk_info->mclk);
57+
float min_mclk_div = 1.99;
5658
#endif
5759
clk_info->mclk_div = clk_info->sclk / clk_info->mclk;
5860

59-
/* Check if the configuration is correct */
60-
ESP_RETURN_ON_FALSE(clk_info->mclk_div, ESP_ERR_INVALID_ARG, TAG, "sample rate is too large for the current clock source");
61+
/* Check if the configuration is correct. Use float for check in case the mclk division might be carried up in the fine division calculation */
62+
ESP_RETURN_ON_FALSE(clk_info->sclk / (float)clk_info->mclk > min_mclk_div, ESP_ERR_INVALID_ARG, TAG, "sample rate or mclk_multiple is too large for the current clock source");
6163

6264
return ESP_OK;
6365
}

components/esp_driver_i2s/i2s_tdm.c

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -61,10 +61,11 @@ static esp_err_t i2s_tdm_calculate_clock(i2s_chan_handle_t handle, const i2s_tdm
6161
}
6262
clk_info->sclk = clk_cfg->clk_src == I2S_CLK_SRC_EXTERNAL ?
6363
clk_cfg->ext_clk_freq_hz : i2s_get_source_clk_freq(clk_cfg->clk_src, clk_info->mclk);
64+
float min_mclk_div = clk_cfg->clk_src == I2S_CLK_SRC_EXTERNAL ? 0.99 : 1.99;
6465
clk_info->mclk_div = clk_info->sclk / clk_info->mclk;
6566

66-
/* Check if the configuration is correct */
67-
ESP_RETURN_ON_FALSE(clk_info->mclk_div, ESP_ERR_INVALID_ARG, TAG, "sample rate is too large for the current clock source");
67+
/* Check if the configuration is correct. Use float for check in case the mclk division might be carried up in the fine division calculation */
68+
ESP_RETURN_ON_FALSE(clk_info->sclk / (float)clk_info->mclk > min_mclk_div, ESP_ERR_INVALID_ARG, TAG, "sample rate or mclk_multiple is too large for the current clock source");
6869

6970
return ESP_OK;
7071
}
@@ -104,8 +105,12 @@ static esp_err_t i2s_tdm_set_slot(i2s_chan_handle_t handle, const i2s_tdm_slot_c
104105
handle->active_slot = slot_cfg->slot_mode == I2S_SLOT_MODE_MONO ? 1 : __builtin_popcount(slot_cfg->slot_mask);
105106
uint32_t max_slot_num = 32 - __builtin_clz(slot_cfg->slot_mask);
106107
handle->total_slot = slot_cfg->total_slot < max_slot_num ? max_slot_num : slot_cfg->total_slot;
107-
handle->total_slot = handle->total_slot < 2 ? 2 : handle->total_slot; // At least two slots in a frame
108-
108+
// At least two slots in a frame if not using PCM short format
109+
handle->total_slot = ((handle->total_slot < 2) && (slot_cfg->ws_width != 1)) ? 2 : handle->total_slot;
110+
uint32_t slot_bits = slot_cfg->slot_bit_width == I2S_SLOT_BIT_WIDTH_AUTO ? slot_cfg->data_bit_width : slot_cfg->slot_bit_width;
111+
ESP_RETURN_ON_FALSE(handle->total_slot * slot_bits <= I2S_LL_SLOT_FRAME_BIT_MAX, ESP_ERR_INVALID_ARG, TAG,
112+
"total slots(%"PRIu32") * slot_bit_width(%"PRIu32") exceeds the maximum %d",
113+
handle->total_slot, slot_bits, (int)I2S_LL_SLOT_FRAME_BIT_MAX);
109114
uint32_t buf_size = i2s_get_buf_size(handle, slot_cfg->data_bit_width, handle->dma.frame_num);
110115
/* The DMA buffer need to re-allocate if the buffer size changed */
111116
if (handle->dma.buf_size != buf_size) {

components/esp_driver_i2s/test_apps/i2s/main/test_i2s.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -904,7 +904,11 @@ TEST_CASE("I2S_package_lost_test", "[i2s]")
904904
TEST_ESP_OK(i2s_channel_register_event_callback(rx_handle, &cbs, &count));
905905

906906
uint32_t test_freq[] = {16000, 32000, 48000, 64000, 96000, 128000, 144000};
907+
#if CONFIG_IDF_TARGET_ESP32P4
908+
uint32_t test_num = 4;
909+
#else
907910
uint32_t test_num = sizeof(test_freq) / sizeof(uint32_t);
911+
#endif // CONFIG_IDF_TARGET_ESP32P4
908912
uint8_t *data = (uint8_t *)calloc(TEST_RECV_BUF_LEN, sizeof(uint8_t));
909913
size_t bytes_read = 0;
910914
int i;

components/esp_driver_i2s/test_apps/i2s_multi_dev/main/test_i2s_multi_dev.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -330,6 +330,13 @@ static void test_i2s_external_clk_src(bool is_master, bool is_external)
330330
std_cfg.clk_cfg.clk_src = I2S_CLK_SRC_EXTERNAL;
331331
std_cfg.clk_cfg.ext_clk_freq_hz = 22579200;
332332
}
333+
#if CONFIG_IDF_TARGET_ESP32P4
334+
else {
335+
// Use APLL instead.
336+
// Because the default clock source is not sufficient for 22.58M MCLK
337+
std_cfg.clk_cfg.clk_src = I2S_CLK_SRC_APLL;
338+
}
339+
#endif
333340
TEST_ESP_OK(i2s_channel_init_std_mode(tx_handle, &std_cfg));
334341
TEST_ESP_OK(i2s_channel_init_std_mode(rx_handle, &std_cfg));
335342

components/hal/esp32c3/include/hal/i2s_ll.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ extern "C" {
3333

3434
#define I2S_LL_CLK_FRAC_DIV_N_MAX 256 // I2S_MCLK = I2S_SRC_CLK / (N + b/a), the N register is 8 bit-width
3535
#define I2S_LL_CLK_FRAC_DIV_AB_MAX 512 // I2S_MCLK = I2S_SRC_CLK / (N + b/a), the a/b register is 9 bit-width
36+
#define I2S_LL_SLOT_FRAME_BIT_MAX 128 // Up-to 128 bits in one frame, determined by MAX(half_sample_bits) * 2
3637

3738
#define I2S_LL_PLL_F160M_CLK_FREQ (160 * 1000000) // PLL_F160M_CLK: 160MHz
3839
#define I2S_LL_DEFAULT_CLK_FREQ I2S_LL_PLL_F160M_CLK_FREQ // The default PLL clock frequency while using I2S_CLK_SRC_DEFAULT

components/hal/esp32c6/include/hal/i2s_ll.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ extern "C" {
3333

3434
#define I2S_LL_CLK_FRAC_DIV_N_MAX 256 // I2S_MCLK = I2S_SRC_CLK / (N + b/a), the N register is 8 bit-width
3535
#define I2S_LL_CLK_FRAC_DIV_AB_MAX 512 // I2S_MCLK = I2S_SRC_CLK / (N + b/a), the a/b register is 9 bit-width
36+
#define I2S_LL_SLOT_FRAME_BIT_MAX 128 // Up-to 128 bits in one frame, determined by MAX(half_sample_bits) * 2
3637

3738
#define I2S_LL_PLL_F160M_CLK_FREQ (160 * 1000000) // PLL_F160M_CLK: 160MHz
3839
#define I2S_LL_DEFAULT_CLK_FREQ I2S_LL_PLL_F160M_CLK_FREQ // The default PLL clock frequency while using I2S_CLK_SRC_DEFAULT

components/hal/esp32h2/include/hal/i2s_ll.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@ extern "C" {
3333

3434
#define I2S_LL_CLK_FRAC_DIV_N_MAX 256 // I2S_MCLK = I2S_SRC_CLK / (N + b/a), the N register is 8 bit-width
3535
#define I2S_LL_CLK_FRAC_DIV_AB_MAX 512 // I2S_MCLK = I2S_SRC_CLK / (N + b/a), the a/b register is 9 bit-width
36+
/* Add SOC_I2S_TDM_FULL_DATA_WIDTH in the soc_caps to indicate there is no limitation to support full data width (i.e., 16 slots * 32 bits) */
37+
#define I2S_LL_SLOT_FRAME_BIT_MAX 512 // Up-to 512 bits in one frame, determined by MAX(half_sample_bits) * 2
3638

3739
#define I2S_LL_PLL_F96M_CLK_FREQ (96 * 1000000) // PLL_F96M_CLK: 96MHz
3840
#define I2S_LL_PLL_F64M_CLK_FREQ (64 * 1000000) // PLL_F64M_CLK: 64MHz

components/hal/esp32p4/include/hal/i2s_ll.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@ extern "C" {
3434

3535
#define I2S_LL_CLK_FRAC_DIV_N_MAX 256 // I2S_MCLK = I2S_SRC_CLK / (N + b/a), the N register is 8 bit-width
3636
#define I2S_LL_CLK_FRAC_DIV_AB_MAX 512 // I2S_MCLK = I2S_SRC_CLK / (N + b/a), the a/b register is 9 bit-width
37+
/* Add SOC_I2S_TDM_FULL_DATA_WIDTH in the soc_caps to indicate there is no limitation to support full data width (i.e., 16 slots * 32 bits) */
38+
#define I2S_LL_SLOT_FRAME_BIT_MAX 512 // Up-to 512 bits in one frame, determined by MAX(half_sample_bits) * 2
3739

3840
#define I2S_LL_XTAL_CLK_FREQ (40 * 1000000) // XTAL_CLK: 40MHz
3941
#define I2S_LL_DEFAULT_CLK_FREQ I2S_LL_XTAL_CLK_FREQ // No PLL clock source on P4, use XTAL as default

0 commit comments

Comments
 (0)