mirror of
https://github.com/espressif/esp-idf.git
synced 2026-08-18 06:35:35 +03:00
Merge branch 'fix/adc_clk_div_error_v6.0' into 'release/v6.0'
Fix ADC continuous sample frequency and clock divide error on H2/C5/C61 (v6.0) See merge request espressif/esp-idf!47974
This commit is contained in:
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user