mirror of
https://github.com/espressif/esp-idf.git
synced 2024-10-05 20:47:46 -04:00
Merge branch 'bugfix/i2s_dma_buf_saturation_on_p4_v5.3' into 'release/v5.3'
fix(i2s): fixed alignment of max DMA buffer length on P4 (v5.3) See merge request espressif/esp-idf!33221
This commit is contained in:
commit
d77148bb33
@ -25,6 +25,7 @@
|
||||
#include "soc/soc_caps.h"
|
||||
#include "hal/gpio_hal.h"
|
||||
#include "hal/i2s_hal.h"
|
||||
#include "hal/dma_types.h"
|
||||
#if SOC_CACHE_INTERNAL_MEM_VIA_L1CACHE
|
||||
#include "hal/cache_hal.h"
|
||||
#include "hal/cache_ll.h"
|
||||
@ -62,8 +63,12 @@
|
||||
#include "esp_memory_utils.h"
|
||||
|
||||
/* The actual max size of DMA buffer is 4095
|
||||
* Set 4092 here to align with 4-byte, so that the position of the slot data in the buffer will be relatively fixed */
|
||||
#define I2S_DMA_BUFFER_MAX_SIZE (4092)
|
||||
* Reserve several bytes for alignment, so that the position of the slot data in the buffer will be relatively fixed */
|
||||
#if SOC_CACHE_INTERNAL_MEM_VIA_L1CACHE
|
||||
#define I2S_DMA_BUFFER_MAX_SIZE DMA_DESCRIPTOR_BUFFER_MAX_SIZE_64B_ALIGNED
|
||||
#else
|
||||
#define I2S_DMA_BUFFER_MAX_SIZE DMA_DESCRIPTOR_BUFFER_MAX_SIZE_4B_ALIGNED
|
||||
#endif // SOC_CACHE_INTERNAL_MEM_VIA_L1CACHE
|
||||
|
||||
static const char *TAG = "i2s_common";
|
||||
|
||||
@ -357,7 +362,7 @@ uint32_t i2s_get_buf_size(i2s_chan_handle_t handle, uint32_t data_bit_width, uin
|
||||
for (int sign = 1; bufsize % alignment != 0; aligned_frame_num += sign) {
|
||||
bufsize = aligned_frame_num * bytes_per_frame;
|
||||
/* If the buffer size exceed the max dma size */
|
||||
if (bufsize > I2S_DMA_BUFFER_MAX_SIZE) {
|
||||
if (bufsize > I2S_DMA_BUFFER_MAX_SIZE && sign == 1) {
|
||||
sign = -1; // toggle the search sign
|
||||
aligned_frame_num = dma_frame_num; // Reset the frame num
|
||||
bufsize = aligned_frame_num * bytes_per_frame; // Reset the bufsize
|
||||
@ -368,7 +373,7 @@ uint32_t i2s_get_buf_size(i2s_chan_handle_t handle, uint32_t data_bit_width, uin
|
||||
", bufsize = %"PRIu32, bufsize / bytes_per_frame, alignment, bufsize);
|
||||
}
|
||||
#endif
|
||||
/* Limit DMA buffer size if it is out of range (DMA buffer limitation is 4092 bytes) */
|
||||
/* Limit DMA buffer size if it is out of range */
|
||||
if (bufsize > I2S_DMA_BUFFER_MAX_SIZE) {
|
||||
uint32_t frame_num = I2S_DMA_BUFFER_MAX_SIZE / bytes_per_frame;
|
||||
bufsize = frame_num * bytes_per_frame;
|
||||
|
@ -39,6 +39,9 @@ static esp_err_t i2s_std_calculate_clock(i2s_chan_handle_t handle, const i2s_std
|
||||
clk_info->bclk = rate * handle->total_slot * slot_bits;
|
||||
clk_info->mclk = rate * clk_cfg->mclk_multiple;
|
||||
clk_info->bclk_div = clk_info->mclk / clk_info->bclk;
|
||||
if (clk_info->mclk % clk_info->bclk != 0) {
|
||||
ESP_LOGW(TAG, "the current mclk multiple cannot perform integer division (slot_num: %"PRIu32", slot_bits: %"PRIu32")", handle->total_slot, slot_bits);
|
||||
}
|
||||
} else {
|
||||
/* For slave mode, mclk >= bclk * 8, so fix bclk_div to 2 first */
|
||||
clk_info->bclk_div = 8;
|
||||
|
@ -46,6 +46,9 @@ static esp_err_t i2s_tdm_calculate_clock(i2s_chan_handle_t handle, const i2s_tdm
|
||||
clk_info->mclk = clk_info->bclk * clk_info->bclk_div;
|
||||
ESP_LOGW(TAG, "the current mclk multiple is too small, adjust the mclk multiple to %"PRIu32, clk_info->mclk / rate);
|
||||
}
|
||||
if (clk_info->mclk % clk_info->bclk != 0) {
|
||||
ESP_LOGW(TAG, "the current mclk multiple cannot perform integer division (slot_num: %"PRIu32", slot_bits: %"PRIu32")", handle->total_slot, slot_bits);
|
||||
}
|
||||
} else {
|
||||
if (clk_cfg->bclk_div < 8) {
|
||||
ESP_LOGW(TAG, "the current bclk division is too small, adjust the bclk division to 8");
|
||||
|
@ -14,6 +14,7 @@
|
||||
#include "sdkconfig.h"
|
||||
#include "driver/gpio.h"
|
||||
#include "hal/gpio_hal.h"
|
||||
#include "hal/dma_types.h"
|
||||
#include "esp_err.h"
|
||||
#include "esp_attr.h"
|
||||
#include "unity.h"
|
||||
@ -866,17 +867,25 @@ TEST_CASE("I2S_package_lost_test", "[i2s]")
|
||||
{
|
||||
/* Steps of calculate appropriate parameters of I2S buffer:
|
||||
* Known by user: sample_rate = 144k, data_bit_width = 32, slot_num = 2, polling_cycle = 10 ms
|
||||
* 1. dma_buffer_size = dma_frame_num * slot_num * data_bit_width / 8 <= 4092
|
||||
* dma_frame_num <= 511, dma_frame_num is as big as possible.
|
||||
* 1. dma_buffer_size = dma_frame_num * slot_num * data_bit_width / 8 <= DMA_MAX_ALIGNED_SIZE
|
||||
* dma_frame_num <= DMA_MAX_ALIGNED_SIZE / data_bit_width / slot_num * 8, dma_frame_num is as big as possible.
|
||||
* interrupt_interval = dma_frame_num / sample_rate = 3.549 ms
|
||||
* 2. dma_desc_num > polling_cycle / interrupt_interval = cell(2.818) = 3
|
||||
* 3. recv_buffer_size > dma_desc_num * dma_buffer_size = 3 * 4092 = 12276 bytes */
|
||||
#define TEST_RECV_BUF_LEN 12276
|
||||
* 3. recv_buffer_size > dma_desc_num * dma_buffer_size = 3 * DMA_MAX_ALIGNED_SIZE */
|
||||
#if SOC_CACHE_INTERNAL_MEM_VIA_L1CACHE
|
||||
#define TEST_RECV_BUF_LEN (3 * DMA_DESCRIPTOR_BUFFER_MAX_SIZE_64B_ALIGNED)
|
||||
#else
|
||||
#define TEST_RECV_BUF_LEN (3 * DMA_DESCRIPTOR_BUFFER_MAX_SIZE_4B_ALIGNED)
|
||||
#endif
|
||||
i2s_chan_handle_t rx_handle;
|
||||
|
||||
i2s_chan_config_t chan_cfg = I2S_CHANNEL_DEFAULT_CONFIG(I2S_NUM_AUTO, I2S_ROLE_MASTER);
|
||||
chan_cfg.dma_desc_num = 3;
|
||||
#if SOC_CACHE_INTERNAL_MEM_VIA_L1CACHE
|
||||
chan_cfg.dma_frame_num = 504;
|
||||
#else
|
||||
chan_cfg.dma_frame_num = 511;
|
||||
#endif
|
||||
i2s_std_config_t std_cfg = {
|
||||
.clk_cfg = I2S_STD_CLK_DEFAULT_CONFIG(SAMPLE_RATE),
|
||||
.slot_cfg = I2S_STD_PHILIPS_SLOT_DEFAULT_CONFIG(I2S_DATA_BIT_WIDTH_32BIT, I2S_SLOT_MODE_STEREO),
|
||||
|
@ -430,3 +430,7 @@
|
||||
-
|
||||
re: "unplaced orphan section"
|
||||
hint: "Avoid creating custom sections. Please refer to the 'Linker Script Generation' article in the IDF documentation to address this. Or set option CONFIG_COMPILER_ORPHAN_SECTIONS_PLACE (not recommended)."
|
||||
|
||||
-
|
||||
re: "the current mclk multiple cannot perform integer division"
|
||||
hint: "Please adjust the mclk multiple to get the accurate sample rate.\nFor example, if you're using 24-bit slot width or enabled 3 slots, then the mclk multiple should be a multiple of 3, otherwise the sample rate will be inaccurate."
|
||||
|
Loading…
x
Reference in New Issue
Block a user