From cb62457f6dcb3077b38a74cfaffe19f5f23e4a00 Mon Sep 17 00:00:00 2001 From: Armando Date: Wed, 20 Jul 2022 16:15:39 +0800 Subject: [PATCH] adc: fix esp32 continuous mode sampling freq issue --- components/hal/adc_hal.c | 22 +++++++++++++------ components/hal/i2s_hal.c | 2 +- components/hal/include/hal/i2s_hal.h | 10 +++++++++ components/soc/esp32/include/soc/soc_caps.h | 2 +- .../adc/dma_read/main/adc_dma_example_main.c | 2 +- 5 files changed, 28 insertions(+), 10 deletions(-) diff --git a/components/hal/adc_hal.c b/components/hal/adc_hal.c index 42855524ca..3eeeae828b 100644 --- a/components/hal/adc_hal.c +++ b/components/hal/adc_hal.c @@ -14,6 +14,7 @@ #if CONFIG_IDF_TARGET_ESP32 //ADC utilises I2S0 DMA on ESP32 +#include "hal/i2s_hal.h" #include "hal/i2s_ll.h" #include "hal/i2s_types.h" #include "soc/i2s_struct.h" @@ -232,14 +233,21 @@ static void adc_hal_digi_sample_freq_config(adc_hal_context_t *hal, uint32_t fre adc_ll_digi_clk_sel(0); //use APB #else i2s_ll_rx_clk_set_src(hal->dev, I2S_CLK_D2CLK); /*!< Clock from PLL_D2_CLK(160M)*/ - uint32_t bck = I2S_BASE_CLK / (ADC_LL_CLKM_DIV_NUM_DEFAULT + ADC_LL_CLKM_DIV_B_DEFAULT / ADC_LL_CLKM_DIV_A_DEFAULT) / 2 / freq; - i2s_ll_mclk_div_t clk = { - .mclk_div = ADC_LL_CLKM_DIV_NUM_DEFAULT, - .a = ADC_LL_CLKM_DIV_A_DEFAULT, - .b = ADC_LL_CLKM_DIV_B_DEFAULT, + uint32_t bclk_div = 16; + uint32_t bclk = freq * 2; + uint32_t mclk = bclk * bclk_div; + uint32_t mclk_div = I2S_BASE_CLK / mclk; + i2s_hal_clock_cfg_t i2s_hal_clk_cfg = { + .sclk = I2S_BASE_CLK, + .bclk = bclk, + .bclk_div = bclk_div, + .mclk = mclk , + .mclk_div = mclk_div, }; - i2s_ll_rx_set_clk(hal->dev, &clk); - i2s_ll_rx_set_bck_div_num(hal->dev, bck); + i2s_ll_mclk_div_t mclk_set = {}; + i2s_hal_mclk_div_decimal_cal(&i2s_hal_clk_cfg, &mclk_set); + i2s_ll_rx_set_clk(hal->dev, &mclk_set); + i2s_ll_rx_set_bck_div_num(hal->dev, i2s_hal_clk_cfg.bclk_div); #endif } diff --git a/components/hal/i2s_hal.c b/components/hal/i2s_hal.c index 142971993d..2faf735690 100644 --- a/components/hal/i2s_hal.c +++ b/components/hal/i2s_hal.c @@ -19,7 +19,7 @@ * @param clk_cfg I2S clock configuration(input) * @param cal Point to `i2s_ll_mclk_div_t` structure(output). */ -static void i2s_hal_mclk_div_decimal_cal(i2s_hal_clock_cfg_t *clk_cfg, i2s_ll_mclk_div_t *cal) +void i2s_hal_mclk_div_decimal_cal(i2s_hal_clock_cfg_t *clk_cfg, i2s_ll_mclk_div_t *cal) { int ma = 0; int mb = 0; diff --git a/components/hal/include/hal/i2s_hal.h b/components/hal/include/hal/i2s_hal.h index 037970fa2b..0e75b80143 100644 --- a/components/hal/include/hal/i2s_hal.h +++ b/components/hal/include/hal/i2s_hal.h @@ -125,6 +125,16 @@ void i2s_hal_init(i2s_hal_context_t *hal, int i2s_num); */ void i2s_hal_set_clock_src(i2s_hal_context_t *hal, i2s_clock_src_t sel); +/** + * @brief Calculate the closest sample rate clock configuration. + * clock relationship: + * Fmclk = bck_div*fbck = fsclk/(mclk_div+b/a) + * + * @param clk_cfg I2S clock configuration(input) + * @param cal Point to `i2s_ll_mclk_div_t` structure(output). + */ +void i2s_hal_mclk_div_decimal_cal(i2s_hal_clock_cfg_t *clk_cfg, i2s_ll_mclk_div_t *cal); + /** * @brief Set Tx channel style * diff --git a/components/soc/esp32/include/soc/soc_caps.h b/components/soc/esp32/include/soc/soc_caps.h index 1225d9a1ea..b151a00984 100644 --- a/components/soc/esp32/include/soc/soc_caps.h +++ b/components/soc/esp32/include/soc/soc_caps.h @@ -94,7 +94,7 @@ #define SOC_ADC_DIGI_DATA_BYTES_PER_CONV (4) /*!< F_sample = F_digi_con / 2 / interval. F_digi_con = 5M for now. 30 <= interva <= 4095 */ #define SOC_ADC_SAMPLE_FREQ_THRES_HIGH (2*1000*1000) -#define SOC_ADC_SAMPLE_FREQ_THRES_LOW (2000) +#define SOC_ADC_SAMPLE_FREQ_THRES_LOW (20*1000) /*!< RTC */ #define SOC_ADC_MAX_BITWIDTH (12) diff --git a/examples/peripherals/adc/dma_read/main/adc_dma_example_main.c b/examples/peripherals/adc/dma_read/main/adc_dma_example_main.c index 6704fa70c7..f73095ff1e 100644 --- a/examples/peripherals/adc/dma_read/main/adc_dma_example_main.c +++ b/examples/peripherals/adc/dma_read/main/adc_dma_example_main.c @@ -69,7 +69,7 @@ static void continuous_adc_init(uint16_t adc1_chan_mask, uint16_t adc2_chan_mask adc_digi_configuration_t dig_cfg = { .conv_limit_en = ADC_CONV_LIMIT_EN, .conv_limit_num = 250, - .sample_freq_hz = 10 * 1000, + .sample_freq_hz = 20 * 1000, .conv_mode = ADC_CONV_MODE, .format = ADC_OUTPUT_TYPE, };