From 37b956a2453688ddefb04bfd689135ac0bad8618 Mon Sep 17 00:00:00 2001 From: Marc CAPDEVILLE Date: Tue, 24 Dec 2024 18:52:51 +0100 Subject: [PATCH 1/8] fix(esp_hw_support): avoid l32r dangerous relocation error Whithout this patch, compilling for ESP32s3 with power management enabled lead to a 'dangerous relocation error' in sleep_modes.c at esp_wake_stub_entry function. Normally, literals variable are embeded just before the entry point of the function, but esp_wake_stub_entry is at start of rtc_ram. So add a jump over at the start of the function, and place the literals before code. --- components/esp_hw_support/CMakeLists.txt | 3 +++ components/esp_hw_support/sleep_modes.c | 6 ++++++ 2 files changed, 9 insertions(+) diff --git a/components/esp_hw_support/CMakeLists.txt b/components/esp_hw_support/CMakeLists.txt index 75f844aaf4b..3303944c843 100644 --- a/components/esp_hw_support/CMakeLists.txt +++ b/components/esp_hw_support/CMakeLists.txt @@ -144,6 +144,9 @@ if(NOT non_os_build) if(CONFIG_SOC_GPIO_CLOCKOUT_BY_GPIO_MATRIX OR CONFIG_SOC_GPIO_CLOCKOUT_BY_IO_MUX) list(APPEND srcs "esp_clock_output.c") endif() + if(CONFIG_SOC_PM_SUPPORT_DEEPSLEEP_CHECK_STUB_ONLY) + set_source_files_properties(sleep_modes.c PROPERTIES COMPILE_OPTIONS -mtext-section-literals) + endif() else() if(ESP_TEE_BUILD) list(APPEND srcs "esp_clk.c" "hw_random.c") diff --git a/components/esp_hw_support/sleep_modes.c b/components/esp_hw_support/sleep_modes.c index 9b3c64f0670..cd91fcd1695 100644 --- a/components/esp_hw_support/sleep_modes.c +++ b/components/esp_hw_support/sleep_modes.c @@ -329,6 +329,12 @@ static void __attribute__((section(".rtc.entry.text"))) esp_wake_stub_entry(void { #define _SYM2STR(s) # s #define SYM2STR(s) _SYM2STR(s) + goto __after_literal; + __asm__ __volatile__ ( + ".literal_position \n" + ".align 4 \n" + ); +__after_literal: #ifdef __riscv __asm__ __volatile__ ( From 09c3d3cc518d41ea452eb63e318c9051931ef9be Mon Sep 17 00:00:00 2001 From: Marc CAPDEVILLE Date: Tue, 24 Dec 2024 19:21:09 +0100 Subject: [PATCH 2/8] fix(i2s_hal): Set correct divisor calculation It seams that hal_utils_calc_clk_div_frac_accurate() do not get as accurate sampling frequency as the hal_utils_calc_clk_div_frac_fast(). This is needed if you want accurate non standard sampling frequencies (ex : 52800Hz) --- components/hal/i2s_hal.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/components/hal/i2s_hal.c b/components/hal/i2s_hal.c index c445af2761b..4c4daf6223b 100644 --- a/components/hal/i2s_hal.c +++ b/components/hal/i2s_hal.c @@ -10,6 +10,7 @@ #include "soc/soc.h" #include "hal/assert.h" #include "hal/i2s_hal.h" +#include "hal/log.h" #if SOC_I2S_HW_VERSION_2 && (SOC_I2S_SUPPORTS_PDM_TX || SOC_I2S_SUPPORTS_PDM_RX_HP_FILTER) /* PDM tx high pass filter cut-off frequency and coefficients list @@ -58,7 +59,7 @@ void i2s_hal_calc_mclk_precise_division(uint32_t sclk, uint32_t mclk, hal_utils_ .min_integ = 1, .max_fract = I2S_LL_CLK_FRAC_DIV_AB_MAX, }; - hal_utils_calc_clk_div_frac_accurate(&i2s_clk_info, mclk_div); + hal_utils_calc_clk_div_frac_fast(&i2s_clk_info, mclk_div); } void i2s_hal_init(i2s_hal_context_t *hal, int port_id) @@ -114,6 +115,8 @@ void i2s_hal_set_tx_clock(i2s_hal_context_t *hal, const i2s_hal_clock_info_t *cl i2s_hal_calc_mclk_precise_division(clk_info->sclk, clk_info->mclk, &mclk_div); i2s_ll_tx_set_mclk(hal->dev, &mclk_div); i2s_ll_tx_set_bck_div_num(hal->dev, clk_info->bclk_div); + HAL_EARLY_LOGD("I2S_HAL","src_clk = %ld, div = %ld + %ld/%ld, bdiv = %d, Fs = %ld",clk_info->sclk, mclk_div.integer, mclk_div.numerator, mclk_div.denominator, clk_info->bclk_div, + (int32_t)((((int64_t)clk_info->sclk*mclk_div.denominator) / ((mclk_div.integer*mclk_div.denominator + mclk_div.numerator)*clk_info->bclk_div)+64)/128) ); } else { i2s_ll_tx_clk_set_src(hal->dev, clk_src); } From b819c0934286110627e92fe92ce571c3aa02fd2c Mon Sep 17 00:00:00 2001 From: Marc CAPDEVILLE Date: Tue, 24 Dec 2024 19:25:59 +0100 Subject: [PATCH 3/8] feat(esp_driver_i2s): add CONFIG_I2S_FORCE_FRAC_DIVISOR option This configuration option is added to desactivate work around for PDM TX clock on V2 HW. If you needed accurate sampling frequencies, say no. --- components/esp_driver_i2s/Kconfig | 7 +++++++ components/esp_driver_i2s/i2s_pdm.c | 4 +++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/components/esp_driver_i2s/Kconfig b/components/esp_driver_i2s/Kconfig index 72628d820e3..574d80942ef 100644 --- a/components/esp_driver_i2s/Kconfig +++ b/components/esp_driver_i2s/Kconfig @@ -7,6 +7,13 @@ menu "ESP-Driver:I2S Configurations" Ensure the I2S interrupt is IRAM-Safe by allowing the interrupt handler to be executable when the cache is disabled (e.g. SPI Flash write). + config I2S_FORCE_FRAC_DIVISOR + bool "Force fractional divisor for PDM mode on v2 HW" + default y + help + Force fractional part of clock divisor to known value. + This seems to help reducing noise. + config I2S_ENABLE_DEBUG_LOG bool "Enable I2S debug log" default n diff --git a/components/esp_driver_i2s/i2s_pdm.c b/components/esp_driver_i2s/i2s_pdm.c index 82cb7f29e9b..5a1bb111745 100644 --- a/components/esp_driver_i2s/i2s_pdm.c +++ b/components/esp_driver_i2s/i2s_pdm.c @@ -89,10 +89,12 @@ static esp_err_t i2s_pdm_tx_set_clock(i2s_chan_handle_t handle, const i2s_pdm_tx I2S_CLOCK_SRC_ATOMIC() { i2s_hal_set_tx_clock(&handle->controller->hal, &clk_info, clk_cfg->clk_src); } -#if SOC_I2S_HW_VERSION_2 +#if SOC_I2S_HW_VERSION_2 && I2S_FORCE_FRAC_DIVISOR /* Work around for PDM TX clock, overwrite the raw division directly to reduce the noise * This set of coefficients is a special division to reduce the background noise in PDM TX mode */ i2s_ll_tx_set_raw_clk_div(handle->controller->hal.dev, clk_info.mclk_div, 1, 1, 0, 0); +#else +#warning "I2S PDM clock workaround disabled" #endif portEXIT_CRITICAL(&g_i2s.spinlock); From 87009d0a93e6912583c94d58f7c4d4cac086f430 Mon Sep 17 00:00:00 2001 From: Marc CAPDEVILLE Date: Tue, 24 Dec 2024 19:33:38 +0100 Subject: [PATCH 4/8] feat(esp_driver_i2s): Add I2S_CLK_SRC_PLL_D2 source option Add I2S_CLK_SRC_PLL_D2 = SOC_MOD_CLK_PLL_D2 clock source to i2s driver. --- components/hal/esp32s3/include/hal/i2s_ll.h | 6 ++++++ components/soc/esp32s3/include/soc/clk_tree_defs.h | 1 + 2 files changed, 7 insertions(+) diff --git a/components/hal/esp32s3/include/hal/i2s_ll.h b/components/hal/esp32s3/include/hal/i2s_ll.h index 97d7aacec78..80a88eb3ad9 100644 --- a/components/hal/esp32s3/include/hal/i2s_ll.h +++ b/components/hal/esp32s3/include/hal/i2s_ll.h @@ -232,6 +232,9 @@ static inline void i2s_ll_tx_clk_set_src(i2s_dev_t *hw, i2s_clock_src_t src) case I2S_CLK_SRC_XTAL: hw->tx_clkm_conf.tx_clk_sel = 0; break; + case I2S_CLK_SRC_PLL_D2: + hw->tx_clkm_conf.tx_clk_sel = 1; + break; case I2S_CLK_SRC_PLL_160M: hw->tx_clkm_conf.tx_clk_sel = 2; break; @@ -257,6 +260,9 @@ static inline void i2s_ll_rx_clk_set_src(i2s_dev_t *hw, i2s_clock_src_t src) case I2S_CLK_SRC_XTAL: hw->rx_clkm_conf.rx_clk_sel = 0; break; + case I2S_CLK_SRC_PLL_D2: + hw->rx_clkm_conf.rx_clk_sel = 1; + break; case I2S_CLK_SRC_PLL_160M: hw->rx_clkm_conf.rx_clk_sel = 2; break; diff --git a/components/soc/esp32s3/include/soc/clk_tree_defs.h b/components/soc/esp32s3/include/soc/clk_tree_defs.h index 4f3bea99858..21d00438d94 100644 --- a/components/soc/esp32s3/include/soc/clk_tree_defs.h +++ b/components/soc/esp32s3/include/soc/clk_tree_defs.h @@ -301,6 +301,7 @@ typedef enum { */ typedef enum { I2S_CLK_SRC_DEFAULT = SOC_MOD_CLK_PLL_F160M, /*!< Select PLL_F160M as the default source clock */ + I2S_CLK_SRC_PLL_D2 = SOC_MOD_CLK_PLL_D2, /*!< Select PLL_D2 as the source clock */ I2S_CLK_SRC_PLL_160M = SOC_MOD_CLK_PLL_F160M, /*!< Select PLL_F160M as the source clock */ I2S_CLK_SRC_XTAL = SOC_MOD_CLK_XTAL, /*!< Select XTAL as the source clock */ I2S_CLK_SRC_EXTERNAL = -1, /*!< Select external clock as source clock */ From c9a69a9c99d60b732b84e1fc7ebc58a2da3ed4ad Mon Sep 17 00:00:00 2001 From: Marc CAPDEVILLE Date: Sun, 7 Jan 2024 02:48:22 +0100 Subject: [PATCH 5/8] feat(esp_adc): Allow disableing ringbuffer Whith this, you could specify a zero size ringbuffer in adc_continuous_handle_cfg_t.max_store_buffer_size. This is useful for direct dma buffer access to avoid useless recopy of data. --- components/esp_adc/adc_continuous.c | 86 +++++++++++++++++------------ 1 file changed, 51 insertions(+), 35 deletions(-) diff --git a/components/esp_adc/adc_continuous.c b/components/esp_adc/adc_continuous.c index 1a92568ff53..833609628f1 100644 --- a/components/esp_adc/adc_continuous.c +++ b/components/esp_adc/adc_continuous.c @@ -63,7 +63,7 @@ static IRAM_ATTR bool adc_dma_intr(adc_continuous_ctx_t *adc_digi_ctx) { BaseType_t taskAwoken = 0; bool need_yield = false; - BaseType_t ret; + BaseType_t ret = 0; adc_hal_dma_desc_status_t status = false; uint8_t *finished_buffer = NULL; uint32_t finished_size = 0; @@ -80,8 +80,10 @@ static IRAM_ATTR bool adc_dma_intr(adc_continuous_ctx_t *adc_digi_ctx) } #endif - ret = xRingbufferSendFromISR(adc_digi_ctx->ringbuf_hdl, finished_buffer, finished_size, &taskAwoken); - need_yield |= (taskAwoken == pdTRUE); + if (adc_digi_ctx->ringbuf_hdl) { + ret = xRingbufferSendFromISR(adc_digi_ctx->ringbuf_hdl, finished_buffer, finished_size, &taskAwoken); + need_yield |= (taskAwoken == pdTRUE); + } if (adc_digi_ctx->cbs.on_conv_done) { adc_continuous_evt_data_t edata = { @@ -93,30 +95,32 @@ static IRAM_ATTR bool adc_dma_intr(adc_continuous_ctx_t *adc_digi_ctx) } } - if (ret == pdFALSE) { - if (adc_digi_ctx->flags.flush_pool) { - size_t actual_size = 0; - uint8_t *old_data = xRingbufferReceiveUpToFromISR(adc_digi_ctx->ringbuf_hdl, &actual_size, adc_digi_ctx->ringbuf_size); - /** - * Replace by ringbuffer reset API when this API is ready. - * Now we do manual reset. - * For old_data == NULL condition (equals to the future ringbuffer reset fail condition), we don't care this time data, - * as this only happens when the ringbuffer size is small, new data will be filled in soon. - */ - if (old_data) { - vRingbufferReturnItemFromISR(adc_digi_ctx->ringbuf_hdl, old_data, &taskAwoken); - xRingbufferSendFromISR(adc_digi_ctx->ringbuf_hdl, finished_buffer, finished_size, &taskAwoken); - if (taskAwoken == pdTRUE) { - need_yield |= true; + if (adc_digi_ctx->ringbuf_hdl) { + if (ret == pdFALSE) { + if (adc_digi_ctx->flags.flush_pool) { + size_t actual_size = 0; + uint8_t *old_data = xRingbufferReceiveUpToFromISR(adc_digi_ctx->ringbuf_hdl, &actual_size, adc_digi_ctx->ringbuf_size); + /** + * Replace by ringbuffer reset API when this API is ready. + * Now we do manual reset. + * For old_data == NULL condition (equals to the future ringbuffer reset fail condition), we don't care this time data, + * as this only happens when the ringbuffer size is small, new data will be filled in soon. + */ + if (old_data) { + vRingbufferReturnItemFromISR(adc_digi_ctx->ringbuf_hdl, old_data, &taskAwoken); + xRingbufferSendFromISR(adc_digi_ctx->ringbuf_hdl, finished_buffer, finished_size, &taskAwoken); + if (taskAwoken == pdTRUE) { + need_yield |= true; + } } } - } - //ringbuffer overflow happens before - if (adc_digi_ctx->cbs.on_pool_ovf) { - adc_continuous_evt_data_t edata = {}; - if (adc_digi_ctx->cbs.on_pool_ovf(adc_digi_ctx, &edata, adc_digi_ctx->user_data)) { - need_yield |= true; + //ringbuffer overflow happens before + if (adc_digi_ctx->cbs.on_pool_ovf) { + adc_continuous_evt_data_t edata = {}; + if (adc_digi_ctx->cbs.on_pool_ovf(adc_digi_ctx, &edata, adc_digi_ctx->user_data)) { + need_yield |= true; + } } } } @@ -179,18 +183,22 @@ esp_err_t adc_continuous_new_handle(const adc_continuous_handle_cfg_t *hdl_confi //ringbuffer storage/struct buffer adc_ctx->ringbuf_size = hdl_config->max_store_buf_size; - adc_ctx->ringbuf_storage = heap_caps_calloc(1, hdl_config->max_store_buf_size, MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT); - adc_ctx->ringbuf_struct = heap_caps_calloc(1, sizeof(StaticRingbuffer_t), MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT); - if (!adc_ctx->ringbuf_storage || !adc_ctx->ringbuf_struct) { - ret = ESP_ERR_NO_MEM; - goto cleanup; - } + if (hdl_config->max_store_buf_size) { + adc_ctx->ringbuf_storage = heap_caps_calloc(1, hdl_config->max_store_buf_size, MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT); + adc_ctx->ringbuf_struct = heap_caps_calloc(1, sizeof(StaticRingbuffer_t), MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT); + if (!adc_ctx->ringbuf_storage || !adc_ctx->ringbuf_struct) { + ret = ESP_ERR_NO_MEM; + goto cleanup; + } - //ringbuffer - adc_ctx->ringbuf_hdl = xRingbufferCreateStatic(hdl_config->max_store_buf_size, RINGBUF_TYPE_BYTEBUF, adc_ctx->ringbuf_storage, adc_ctx->ringbuf_struct); - if (!adc_ctx->ringbuf_hdl) { - ret = ESP_ERR_NO_MEM; - goto cleanup; + //ringbuffer + adc_ctx->ringbuf_hdl = xRingbufferCreateStatic(hdl_config->max_store_buf_size, RINGBUF_TYPE_BYTEBUF, adc_ctx->ringbuf_storage, adc_ctx->ringbuf_struct); + if (!adc_ctx->ringbuf_hdl) { + ret = ESP_ERR_NO_MEM; + goto cleanup; + } + } else { + adc_ctx->ringbuf_hdl = NULL; } //malloc internal buffer used by DMA @@ -389,6 +397,10 @@ esp_err_t adc_continuous_read(adc_continuous_handle_t handle, uint8_t *buf, uint uint8_t *data = NULL; size_t size = 0; + if (!handle->ringbuf_hdl) { + *out_length = 0; + return ret; + } ticks_to_wait = timeout_ms / portTICK_PERIOD_MS; if (timeout_ms == ADC_MAX_DELAY) { ticks_to_wait = portMAX_DELAY; @@ -562,6 +574,10 @@ esp_err_t adc_continuous_flush_pool(adc_continuous_handle_t handle) size_t actual_size = 0; uint8_t *old_data = NULL; + if (!handle->ringbuf_hdl) { + return ESP_OK; + } + while ((old_data = xRingbufferReceiveUpTo(handle->ringbuf_hdl, &actual_size, 0, handle->ringbuf_size))) { vRingbufferReturnItem(handle->ringbuf_hdl, old_data); } From c8cef56c641d5e03b4ee1decc705e441b9a300d5 Mon Sep 17 00:00:00 2001 From: Marc CAPDEVILLE Date: Tue, 9 Jan 2024 15:45:09 +0100 Subject: [PATCH 6/8] fix(adc_hal): Fix rounding clock parameters This is to achieve good rounded clock value. --- components/hal/adc_hal.c | 2 +- components/hal/esp32s3/include/hal/adc_ll.h | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/components/hal/adc_hal.c b/components/hal/adc_hal.c index e71c70f1de0..27a72ecd59f 100644 --- a/components/hal/adc_hal.c +++ b/components/hal/adc_hal.c @@ -119,7 +119,7 @@ static adc_ll_digi_convert_mode_t get_convert_mode(adc_digi_convert_mode_t conve static void adc_hal_digi_sample_freq_config(adc_hal_dma_ctx_t *hal, adc_continuous_clk_src_t clk_src, uint32_t clk_src_freq_hz, uint32_t sample_freq_hz) { #if !CONFIG_IDF_TARGET_ESP32 - uint32_t interval = clk_src_freq_hz / (ADC_LL_CLKM_DIV_NUM_DEFAULT + ADC_LL_CLKM_DIV_A_DEFAULT / ADC_LL_CLKM_DIV_B_DEFAULT + 1) / 2 / sample_freq_hz; + uint32_t interval = (((long long)clk_src_freq_hz<<10) / (((long long)ADC_LL_CLKM_DIV_NUM_DEFAULT<<10) + ((long long)ADC_LL_CLKM_DIV_B_DEFAULT<<10) / ADC_LL_CLKM_DIV_A_DEFAULT) /sample_freq_hz +1) /2; //set sample interval adc_ll_digi_set_trigger_interval(interval); //Here we set the clock divider factor to make the digital clock to 5M Hz diff --git a/components/hal/esp32s3/include/hal/adc_ll.h b/components/hal/esp32s3/include/hal/adc_ll.h index ec8180c0486..1d1324aa2f7 100644 --- a/components/hal/esp32s3/include/hal/adc_ll.h +++ b/components/hal/esp32s3/include/hal/adc_ll.h @@ -57,8 +57,8 @@ extern "C" { #define ADC_LL_DIGI_SAR_CLK_DIV_DEFAULT (1) #define ADC_LL_CLKM_DIV_NUM_DEFAULT 15 -#define ADC_LL_CLKM_DIV_B_DEFAULT 1 -#define ADC_LL_CLKM_DIV_A_DEFAULT 0 +#define ADC_LL_CLKM_DIV_B_DEFAULT 5 +#define ADC_LL_CLKM_DIV_A_DEFAULT 33 #define ADC_LL_DEFAULT_CONV_LIMIT_EN 0 #define ADC_LL_DEFAULT_CONV_LIMIT_NUM 10 From 14fbba835d027155c2e41222c1feee2fa618094a Mon Sep 17 00:00:00 2001 From: Marc CAPDEVILLE Date: Wed, 25 Dec 2024 14:58:23 +0100 Subject: [PATCH 7/8] feat(adc_hal): option to calc precise clk divisor --- components/esp_adc/Kconfig | 15 +++++++++++++++ components/hal/adc_hal.c | 23 +++++++++++++++++++++++ 2 files changed, 38 insertions(+) diff --git a/components/esp_adc/Kconfig b/components/esp_adc/Kconfig index 0bdf4dd73ea..e8d712bc75f 100644 --- a/components/esp_adc/Kconfig +++ b/components/esp_adc/Kconfig @@ -77,6 +77,21 @@ menu "ADC and ADC Calibration" If you stick to this, you can enable this option to force use ADC2 under above conditions. For more details, you can search for errata on espressif website. + config ADC_DIGI_CLK_DIV_DEFAULT + bool "Use default adc clk divisor" + depends on !IDF_TARGET_ESP32 + default y + help + Force use of default digital controller clk divisors. + + config ADC_SARADC_TARGET_CLK + int "Set SARADC target clock frequency" + depends on !ADC_DIGI_CLK_DIV_DEFAULT + default 5280000 + help + The SARADC clock frequency will be set to the nearest integer multiple of sample freq. + The fractional divisor parameters will be calculated at runtime. + config ADC_ENABLE_DEBUG_LOG bool "Enable ADC debug log" default n diff --git a/components/hal/adc_hal.c b/components/hal/adc_hal.c index 27a72ecd59f..e6f003a9eaa 100644 --- a/components/hal/adc_hal.c +++ b/components/hal/adc_hal.c @@ -8,8 +8,10 @@ #include "sdkconfig.h" #include "hal/adc_hal.h" #include "hal/assert.h" +#include "hal/hal_utils.h" #include "soc/lldesc.h" #include "soc/soc_caps.h" +#include "hal/log.h" #if CONFIG_IDF_TARGET_ESP32 //ADC utilises I2S0 DMA on ESP32 @@ -119,11 +121,32 @@ static adc_ll_digi_convert_mode_t get_convert_mode(adc_digi_convert_mode_t conve static void adc_hal_digi_sample_freq_config(adc_hal_dma_ctx_t *hal, adc_continuous_clk_src_t clk_src, uint32_t clk_src_freq_hz, uint32_t sample_freq_hz) { #if !CONFIG_IDF_TARGET_ESP32 +#if CONFIG_ADC_DIGI_CLK_DIV_DEFAULT uint32_t interval = (((long long)clk_src_freq_hz<<10) / (((long long)ADC_LL_CLKM_DIV_NUM_DEFAULT<<10) + ((long long)ADC_LL_CLKM_DIV_B_DEFAULT<<10) / ADC_LL_CLKM_DIV_A_DEFAULT) /sample_freq_hz +1) /2; //set sample interval adc_ll_digi_set_trigger_interval(interval); //Here we set the clock divider factor to make the digital clock to 5M Hz adc_ll_digi_controller_clk_div(ADC_LL_CLKM_DIV_NUM_DEFAULT, ADC_LL_CLKM_DIV_B_DEFAULT, ADC_LL_CLKM_DIV_A_DEFAULT); +#else + uint32_t interval; + hal_utils_clk_info_t digi_clk_info = { + .src_freq_hz = clk_src_freq_hz, + .exp_freq_hz = (CONFIG_ADC_SARADC_TARGET_CLK/sample_freq_hz)*sample_freq_hz, + .max_integ = APB_SARADC_CLKM_DIV_NUM, + .min_integ = 1, + .max_fract = APB_SARADC_CLKM_DIV_A, + }; + hal_utils_clk_div_t clk_div; + hal_utils_calc_clk_div_frac_fast(&digi_clk_info, &clk_div); + interval = (((long long)clk_src_freq_hz<<10) / (((long long)(clk_div.integer)<<10) + ((long long)(clk_div.numerator)<<10) / clk_div.denominator ) / sample_freq_hz +1) /2; + + HAL_EARLY_LOGD("ADC_HAL","sclk = %ld, Div = %ld + %ld/%ld, Interval = %ld, Fs = %ld", clk_src_freq_hz, clk_div.integer, clk_div.numerator, clk_div.denominator, interval, (int32_t)(((int64_t)clk_src_freq_hz*clk_div.denominator / ((clk_div.integer*clk_div.denominator + clk_div.numerator) * interval ) +1) /2)); + + //set sample interval + adc_ll_digi_set_trigger_interval(interval); + //Here we set the clock divider factor to make the digital clock to CONFIG_ADC_SARADC_TARGET_CLK Hz + adc_ll_digi_controller_clk_div(clk_div.integer-1, clk_div.denominator, clk_div.numerator); +#endif adc_ll_digi_clk_sel(clk_src); #else i2s_ll_rx_clk_set_src(adc_hal_i2s_dev, I2S_CLK_SRC_DEFAULT); /*!< Clock from PLL_D2_CLK(160M)*/ From c0c6921efa6fb4284a2ce3ec85e148f73595e42b Mon Sep 17 00:00:00 2001 From: Marc CAPDEVILLE Date: Wed, 25 Dec 2024 15:02:15 +0100 Subject: [PATCH 8/8] feat(esp_adc): option to set number of DMA buffers Add a configuration option to set the number of DMA buffers used by adc_continuous driver --- components/esp_adc/Kconfig | 6 ++++++ components/esp_adc/adc_continuous.c | 4 ++++ 2 files changed, 10 insertions(+) diff --git a/components/esp_adc/Kconfig b/components/esp_adc/Kconfig index e8d712bc75f..74f84dbb265 100644 --- a/components/esp_adc/Kconfig +++ b/components/esp_adc/Kconfig @@ -92,6 +92,12 @@ menu "ADC and ADC Calibration" The SARADC clock frequency will be set to the nearest integer multiple of sample freq. The fractional divisor parameters will be calculated at runtime. + config ADC_CONTINUOUS_NUM_DMA + int "Set the number of DMA buffers" + default 5 + help + Configure the number of DMA buffers used by adc + config ADC_ENABLE_DEBUG_LOG bool "Enable ADC debug log" default n diff --git a/components/esp_adc/adc_continuous.c b/components/esp_adc/adc_continuous.c index 833609628f1..1d7e64713c6 100644 --- a/components/esp_adc/adc_continuous.c +++ b/components/esp_adc/adc_continuous.c @@ -53,7 +53,11 @@ extern portMUX_TYPE rtc_spinlock; //TODO: Will be placed in the appropriate posi #define ADC_ENTER_CRITICAL() portENTER_CRITICAL(&rtc_spinlock) #define ADC_EXIT_CRITICAL() portEXIT_CRITICAL(&rtc_spinlock) +#ifndef CONFIG_ADC_CONTINUOUS_NUM_DMA #define INTERNAL_BUF_NUM 5 +#else +#define INTERNAL_BUF_NUM CONFIG_ADC_CONTINUOUS_NUM_DMA +#endif /*--------------------------------------------------------------- ADC Continuous Read Mode (via DMA)