diff --git a/components/esp_adc/test_apps/adc/main/CMakeLists.txt b/components/esp_adc/test_apps/adc/main/CMakeLists.txt index e7eed57470a..13f17da2289 100644 --- a/components/esp_adc/test_apps/adc/main/CMakeLists.txt +++ b/components/esp_adc/test_apps/adc/main/CMakeLists.txt @@ -11,5 +11,5 @@ set(srcs "test_app_main.c" # the component can be registered as WHOLE_ARCHIVE idf_component_register(SRCS ${srcs} PRIV_REQUIRES esp_driver_gptimer esp_driver_gpio esp_wifi nvs_flash esp_adc test_utils efuse - esp_driver_tsens + esp_driver_tsens esp_timer WHOLE_ARCHIVE) diff --git a/components/esp_adc/test_apps/adc/main/test_adc_performance.c b/components/esp_adc/test_apps/adc/main/test_adc_performance.c index a5867aa9c13..c504c1c02d7 100644 --- a/components/esp_adc/test_apps/adc/main/test_adc_performance.c +++ b/components/esp_adc/test_apps/adc/main/test_adc_performance.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -19,6 +19,7 @@ #include "esp_adc/adc_filter.h" #include "test_common_adc.h" #include "idf_performance.h" +#include "esp_timer.h" __attribute__((unused)) static const char *TAG = "TEST_ADC"; @@ -295,6 +296,92 @@ TEST_CASE("ADC1 continuous std deviation performance, with filter", "[adc_contin TEST_PERFORMANCE_LESS_THAN(ADC_CONTINUOUS_STD_ATTEN3_FILTER_64, "%.2f", std); } #endif //#if SOC_ADC_DIG_IIR_FILTER_SUPPORTED + +/*--------------------------------------------------------------- + ADC Continuous Sample Count Test +---------------------------------------------------------------*/ +static void test_adc_continuous_sample_freq(uint32_t sample_freq_hz) +{ + adc_continuous_handle_t handle = NULL; + uint8_t result[256] = {0}; + uint32_t ret_num = 0; + esp_err_t ret; + int64_t samples = 0; + int64_t current_us; + int64_t previous_us; + TaskHandle_t task_handle = xTaskGetCurrentTaskHandle(); + + printf("\n\nTesting ADC continuous with sample frequency: %"PRIu32" Hz\n", sample_freq_hz); + + adc_continuous_handle_cfg_t adc_config = { + .max_store_buf_size = 1024, + .conv_frame_size = 256, + }; + TEST_ESP_OK(adc_continuous_new_handle(&adc_config, &handle)); + + adc_continuous_config_t dig_cfg = { + .sample_freq_hz = sample_freq_hz, + .conv_mode = ADC_CONV_SINGLE_UNIT_1, + }; + adc_digi_pattern_config_t adc_pattern[SOC_ADC_PATT_LEN_MAX] = {0}; + adc_pattern[0].atten = ADC_ATTEN_DB_0; + adc_pattern[0].channel = TEST_STD_ADC1_CHANNEL0; + adc_pattern[0].unit = ADC_UNIT_1; + adc_pattern[0].bit_width = SOC_ADC_DIGI_MAX_BITWIDTH; + dig_cfg.adc_pattern = adc_pattern; + dig_cfg.pattern_num = 1; + + TEST_ESP_OK(adc_continuous_config(handle, &dig_cfg)); + + adc_continuous_evt_cbs_t cbs = { + .on_conv_done = s_conv_done_cb, + }; + TEST_ESP_OK(adc_continuous_register_event_callbacks(handle, &cbs, &task_handle)); + TEST_ESP_OK(adc_continuous_start(handle)); + + for (int test_round = 0; test_round < 2; test_round++) { + samples = 0; + previous_us = esp_timer_get_time(); + + while (samples < sample_freq_hz) { + ulTaskNotifyTake(pdTRUE, portMAX_DELAY); + + while (1) { + ret = adc_continuous_read(handle, result, 256, &ret_num, 0); + if (ret == ESP_OK) { + samples += (ret_num / SOC_ADC_DIGI_RESULT_BYTES); + if (samples >= sample_freq_hz) { + current_us = esp_timer_get_time(); + int64_t samples_per_second = samples * 1000000 / (current_us - previous_us); + printf("samples = %lld, time = %lld us, samples_per_second = %lld (target: %"PRIu32" Hz)\n", + samples, (current_us - previous_us), samples_per_second, sample_freq_hz); + + uint32_t tolerance = sample_freq_hz / 1000; + if (test_round != 0) { + //For first read, ADC is not stable, the count is not accurate, so ignore it + TEST_ASSERT_INT_WITHIN(tolerance, sample_freq_hz, samples_per_second); + } + break; + } + } else if (ret == ESP_ERR_TIMEOUT) { + break; + } + } + } + } + + TEST_ESP_OK(adc_continuous_stop(handle)); + TEST_ESP_OK(adc_continuous_deinit(handle)); +} + +TEST_CASE("ADC continuous sample frequency test", "[adc_continuous][performance]") +{ + // Test minimum frequency + test_adc_continuous_sample_freq(SOC_ADC_SAMPLE_FREQ_THRES_LOW); + // Test maximum frequency + test_adc_continuous_sample_freq(SOC_ADC_SAMPLE_FREQ_THRES_HIGH); +} + #endif //#if SOC_ADC_DMA_SUPPORTED #if CONFIG_IDF_TARGET_ESP32 || SOC_ADC_CALIBRATION_V1_SUPPORTED diff --git a/components/esp_hal_ana_conv/adc_hal.c b/components/esp_hal_ana_conv/adc_hal.c index 717eceb0889..9842fc7b1d6 100644 --- a/components/esp_hal_ana_conv/adc_hal.c +++ b/components/esp_hal_ana_conv/adc_hal.c @@ -118,7 +118,9 @@ 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 !SOC_IS(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; + uint64_t clkm_div_denom = ((uint64_t)(ADC_LL_CLKM_DIV_NUM_DEFAULT + 1) * ADC_LL_CLKM_DIV_B_DEFAULT) + ADC_LL_CLKM_DIV_A_DEFAULT; + uint32_t interval = (uint32_t)(((uint64_t)clk_src_freq_hz * ADC_LL_CLKM_DIV_B_DEFAULT) / + (clkm_div_denom * 2 * sample_freq_hz)); //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/esp_hal_ana_conv/adc_oneshot_hal.c b/components/esp_hal_ana_conv/adc_oneshot_hal.c index 3648d1ace5e..6fdad1e98e6 100644 --- a/components/esp_hal_ana_conv/adc_oneshot_hal.c +++ b/components/esp_hal_ana_conv/adc_oneshot_hal.c @@ -66,7 +66,7 @@ void adc_oneshot_hal_setup(adc_oneshot_hal_ctx_t *hal, adc_channel_t chan) #if SOC_ADC_DIG_CTRL_SUPPORTED && !SOC_ADC_RTC_CTRL_SUPPORTED adc_ll_digi_clk_sel(hal->clk_src); - adc_ll_digi_controller_clk_div(ADC_LL_CLKM_DIV_NUM_DEFAULT, ADC_LL_CLKM_DIV_A_DEFAULT, ADC_LL_CLKM_DIV_B_DEFAULT); + adc_ll_digi_controller_clk_div(ADC_LL_CLKM_DIV_NUM_DEFAULT, ADC_LL_CLKM_DIV_B_DEFAULT, ADC_LL_CLKM_DIV_A_DEFAULT); adc_ll_digi_set_clk_div(ADC_LL_DIGI_SAR_CLK_DIV_DEFAULT); #else #if SOC_LP_ADC_SUPPORTED diff --git a/components/esp_hal_ana_conv/esp32c5/include/hal/adc_ll.h b/components/esp_hal_ana_conv/esp32c5/include/hal/adc_ll.h index e159e2d5b1d..dfa6dcc4c90 100644 --- a/components/esp_hal_ana_conv/esp32c5/include/hal/adc_ll.h +++ b/components/esp_hal_ana_conv/esp32c5/include/hal/adc_ll.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2024-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -147,7 +147,7 @@ __attribute__((always_inline)) static inline void adc_ll_digi_set_clk_div(uint32_t div) { /* ADC clock divided from digital controller clock clk */ - HAL_FORCE_MODIFY_U32_REG_FIELD(APB_SARADC.saradc_ctrl, saradc_saradc_sar_clk_div, div); + HAL_FORCE_MODIFY_U32_REG_FIELD(PCR.sar_clk_div, sar1_clk_div_num, div); } /** diff --git a/components/esp_hal_ana_conv/esp32c61/include/hal/adc_ll.h b/components/esp_hal_ana_conv/esp32c61/include/hal/adc_ll.h index b09049549d6..adec147480a 100644 --- a/components/esp_hal_ana_conv/esp32c61/include/hal/adc_ll.h +++ b/components/esp_hal_ana_conv/esp32c61/include/hal/adc_ll.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2024-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -147,7 +147,7 @@ __attribute__((always_inline)) static inline void adc_ll_digi_set_clk_div(uint32_t div) { /* ADC clock divided from digital controller clock clk */ - HAL_FORCE_MODIFY_U32_REG_FIELD(ADC.saradc_ctrl, saradc_sar_clk_div, div); + HAL_FORCE_MODIFY_U32_REG_FIELD(PCR.sar_clk_div, sar1_clk_div_num, div); } /** diff --git a/components/esp_hal_ana_conv/esp32h2/include/hal/adc_ll.h b/components/esp_hal_ana_conv/esp32h2/include/hal/adc_ll.h index 29c8db0d1cb..c619ffc6d16 100644 --- a/components/esp_hal_ana_conv/esp32h2/include/hal/adc_ll.h +++ b/components/esp_hal_ana_conv/esp32h2/include/hal/adc_ll.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2023-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -56,11 +56,11 @@ extern "C" { #define ADC_LL_FSM_START_WAIT_DEFAULT (5) #define ADC_LL_FSM_STANDBY_WAIT_DEFAULT (100) #define ADC_LL_SAMPLE_CYCLE_DEFAULT (2) -#define ADC_LL_DIGI_SAR_CLK_DIV_DEFAULT (2) +#define ADC_LL_DIGI_SAR_CLK_DIV_DEFAULT (1) -#define ADC_LL_CLKM_DIV_NUM_DEFAULT 19 -#define ADC_LL_CLKM_DIV_B_DEFAULT 1 -#define ADC_LL_CLKM_DIV_A_DEFAULT 0 +#define ADC_LL_CLKM_DIV_NUM_DEFAULT 18 +#define ADC_LL_CLKM_DIV_B_DEFAULT 5 +#define ADC_LL_CLKM_DIV_A_DEFAULT 1 #define ADC_LL_DEFAULT_CONV_LIMIT_EN 0 #define ADC_LL_DEFAULT_CONV_LIMIT_NUM 255 @@ -147,7 +147,7 @@ __attribute__((always_inline)) static inline void adc_ll_digi_set_clk_div(uint32_t div) { /* ADC clock divided from digital controller clock clk */ - HAL_FORCE_MODIFY_U32_REG_FIELD(APB_SARADC.saradc_ctrl, saradc_saradc_sar_clk_div, div); + HAL_FORCE_MODIFY_U32_REG_FIELD(PCR.sar_clk_div, sar1_clk_div_num, div); } /**