diff --git a/components/esp_driver_cordic/cordic.c b/components/esp_driver_cordic/cordic.c index 293961efec3..3cd0f0084fb 100644 --- a/components/esp_driver_cordic/cordic.c +++ b/components/esp_driver_cordic/cordic.c @@ -25,7 +25,7 @@ ESP_LOG_ATTR_TAG(TAG, "cordic"); -// Per result; generous margin over the maximum 15 CORDIC iterations. +// Per result; generous margin over the maximum 24 CORDIC iterations. #define CORDIC_ONESHOT_CALCULATE_MAX_RETRIES (1024) typedef struct cordic_platform_t { @@ -130,8 +130,7 @@ esp_err_t cordic_calculate_polling(cordic_engine_handle_t engine, const cordic_c calc_cfg->iq_format >= ESP_CORDIC_IQ_SIZE_MAX || calc_cfg->scale_exp < cordic_hal_algorithm_allowable_scale[calc_cfg->function][0] || calc_cfg->scale_exp > cordic_hal_algorithm_allowable_scale[calc_cfg->function][1] || - calc_cfg->iteration_count == 0 || - calc_cfg->iteration_count > CORDIC_LL_PRECISION_MAX) { + !cordic_ll_iteration_count_valid(calc_cfg->function, calc_cfg->iteration_count)) { return ESP_ERR_INVALID_ARG; } bool is_two_args = (calc_cfg->function == ESP_CORDIC_FUNC_PHASE || calc_cfg->function == ESP_CORDIC_FUNC_MODULUS); @@ -153,7 +152,7 @@ esp_err_t cordic_calculate_polling(cordic_engine_handle_t engine, const cordic_c cordic_ll_set_calculate_config(engine->hal.dev, calc_cfg->function, CORDIC_LL_MODE_REG, - calc_cfg->iteration_count - 1, + calc_cfg->iteration_count, calc_cfg->scale_exp, is_two_args ? 2 : 1, 2, diff --git a/components/esp_driver_cordic/include/driver/cordic.h b/components/esp_driver_cordic/include/driver/cordic.h index 224d0bd3a1d..cbe7d658ea6 100644 --- a/components/esp_driver_cordic/include/driver/cordic.h +++ b/components/esp_driver_cordic/include/driver/cordic.h @@ -28,7 +28,7 @@ typedef struct { typedef struct { cordic_func_t function; /*!< CORDIC calculation function type (e.g., cosine, sine, arctan) */ cordic_iq_format_t iq_format; /*!< IQ data format */ - uint16_t iteration_count; /*!< Internal CORDIC iteration count */ + uint16_t iteration_count; /*!< Iterations: 4, 8, 12, 16, 20 or 24. Square root allows only 4, 8 or 12 */ uint16_t scale_exp; /*!< Input scaling exponent n, effective scaling is 2^n (range depends on function type) */ } cordic_calculate_config_t; diff --git a/components/esp_driver_cordic/test_apps/cordic_driver_ut/main/CMakeLists.txt b/components/esp_driver_cordic/test_apps/cordic_driver_ut/main/CMakeLists.txt index ee528a712c0..9a128858011 100644 --- a/components/esp_driver_cordic/test_apps/cordic_driver_ut/main/CMakeLists.txt +++ b/components/esp_driver_cordic/test_apps/cordic_driver_ut/main/CMakeLists.txt @@ -1,9 +1,12 @@ set(srcs "test_app_main.c") if(CONFIG_SOC_CORDIC_SUPPORTED) - list(APPEND srcs "test_cordic_common.c" "test_cordic_q15.c" "test_cordic_q31.c") + list(APPEND srcs "test_cordic_common.cpp" "test_cordic_q15.cpp" "test_cordic_q31.cpp") + if(CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP) + list(APPEND srcs "test_cordic_sleep.cpp") + endif() endif() idf_component_register(SRCS ${srcs} - PRIV_REQUIRES unity esp_driver_cordic esp_driver_gptimer spi_flash + PRIV_REQUIRES unity esp_driver_cordic esp_driver_gptimer spi_flash esp_hw_support WHOLE_ARCHIVE) diff --git a/components/esp_driver_cordic/test_apps/cordic_driver_ut/main/test_cordic_common.c b/components/esp_driver_cordic/test_apps/cordic_driver_ut/main/test_cordic_common.cpp similarity index 97% rename from components/esp_driver_cordic/test_apps/cordic_driver_ut/main/test_cordic_common.c rename to components/esp_driver_cordic/test_apps/cordic_driver_ut/main/test_cordic_common.cpp index 6831dd3cee6..4fac53ee67e 100644 --- a/components/esp_driver_cordic/test_apps/cordic_driver_ut/main/test_cordic_common.c +++ b/components/esp_driver_cordic/test_apps/cordic_driver_ut/main/test_cordic_common.cpp @@ -13,6 +13,7 @@ TEST_CASE("cordic acquire-release test", "[cordic]") cordic_engine_handle_t engine2 = NULL; cordic_engine_config_t engine_config = { .clock_source = CORDIC_CLK_SRC_DEFAULT, + .instance_id = 0, }; TEST_ESP_OK(cordic_acquire_engine(&engine_config, &engine)); @@ -39,6 +40,7 @@ TEST_CASE("new/delete must not mix with acquire/release", "[cordic]") cordic_engine_handle_t other = NULL; cordic_engine_config_t engine_config = { .clock_source = CORDIC_CLK_SRC_DEFAULT, + .instance_id = 0, }; #pragma GCC diagnostic push diff --git a/components/esp_driver_cordic/test_apps/cordic_driver_ut/main/test_cordic_q15.c b/components/esp_driver_cordic/test_apps/cordic_driver_ut/main/test_cordic_q15.cpp similarity index 97% rename from components/esp_driver_cordic/test_apps/cordic_driver_ut/main/test_cordic_q15.c rename to components/esp_driver_cordic/test_apps/cordic_driver_ut/main/test_cordic_q15.cpp index 0b94c6def66..7ca92671408 100644 --- a/components/esp_driver_cordic/test_apps/cordic_driver_ut/main/test_cordic_q15.c +++ b/components/esp_driver_cordic/test_apps/cordic_driver_ut/main/test_cordic_q15.cpp @@ -35,13 +35,14 @@ TEST_CASE("test cosine and sine q15", "[cordic]") cordic_engine_handle_t engine = NULL; cordic_engine_config_t engine_config = { .clock_source = CORDIC_CLK_SRC_DEFAULT, + .instance_id = 0, }; TEST_ESP_OK(cordic_acquire_engine(&engine_config, &engine)); cordic_calculate_config_t calc_config = { .function = ESP_CORDIC_FUNC_COS, .iq_format = ESP_CORDIC_FORMAT_Q15, - .iteration_count = 4, + .iteration_count = 8, .scale_exp = 0, }; @@ -105,13 +106,14 @@ TEST_CASE("test phase and module q15", "[cordic]") cordic_engine_handle_t engine = NULL; cordic_engine_config_t engine_config = { .clock_source = CORDIC_CLK_SRC_DEFAULT, + .instance_id = 0, }; TEST_ESP_OK(cordic_acquire_engine(&engine_config, &engine)); cordic_calculate_config_t calc_config = { .function = ESP_CORDIC_FUNC_PHASE, .iq_format = ESP_CORDIC_FORMAT_Q15, - .iteration_count = 4, + .iteration_count = 12, .scale_exp = 0, }; @@ -180,13 +182,14 @@ TEST_CASE("test arctan q15", "[cordic]") cordic_engine_handle_t engine = NULL; cordic_engine_config_t engine_config = { .clock_source = CORDIC_CLK_SRC_DEFAULT, + .instance_id = 0, }; TEST_ESP_OK(cordic_acquire_engine(&engine_config, &engine)); cordic_calculate_config_t calc_config = { .function = ESP_CORDIC_FUNC_ARCTAN, .iq_format = ESP_CORDIC_FORMAT_Q15, - .iteration_count = 4, + .iteration_count = 12, .scale_exp = 0, }; @@ -244,13 +247,14 @@ TEST_CASE("test hyperbolic cosine and sine q15", "[cordic]") cordic_engine_handle_t engine = NULL; cordic_engine_config_t engine_config = { .clock_source = CORDIC_CLK_SRC_DEFAULT, + .instance_id = 0, }; TEST_ESP_OK(cordic_acquire_engine(&engine_config, &engine)); cordic_calculate_config_t calc_config = { .function = ESP_CORDIC_FUNC_COSH, .iq_format = ESP_CORDIC_FORMAT_Q15, - .iteration_count = 4, + .iteration_count = 16, .scale_exp = 1, }; @@ -316,13 +320,14 @@ TEST_CASE("test arctanh q15", "[cordic]") cordic_engine_handle_t engine = NULL; cordic_engine_config_t engine_config = { .clock_source = CORDIC_CLK_SRC_DEFAULT, + .instance_id = 0, }; TEST_ESP_OK(cordic_acquire_engine(&engine_config, &engine)); cordic_calculate_config_t calc_config = { .function = ESP_CORDIC_FUNC_ARCHTANH, .iq_format = ESP_CORDIC_FORMAT_Q15, - .iteration_count = 4, + .iteration_count = 16, .scale_exp = 1, }; @@ -384,13 +389,14 @@ TEST_CASE("test natural logarithm q15", "[cordic]") cordic_engine_handle_t engine = NULL; cordic_engine_config_t engine_config = { .clock_source = CORDIC_CLK_SRC_DEFAULT, + .instance_id = 0, }; TEST_ESP_OK(cordic_acquire_engine(&engine_config, &engine)); cordic_calculate_config_t calc_config = { .function = ESP_CORDIC_FUNC_LOGE, .iq_format = ESP_CORDIC_FORMAT_Q15, - .iteration_count = 4, + .iteration_count = 16, .scale_exp = 1, }; @@ -457,13 +463,14 @@ TEST_CASE("test square root q15", "[cordic]") cordic_engine_handle_t engine = NULL; cordic_engine_config_t engine_config = { .clock_source = CORDIC_CLK_SRC_DEFAULT, + .instance_id = 0, }; TEST_ESP_OK(cordic_acquire_engine(&engine_config, &engine)); cordic_calculate_config_t calc_config = { .function = ESP_CORDIC_FUNC_SQUARE_ROOT, .iq_format = ESP_CORDIC_FORMAT_Q15, - .iteration_count = 4, + .iteration_count = 8, .scale_exp = 0, }; @@ -523,13 +530,14 @@ TEST_CASE("test arctan scale 2 q15", "[cordic]") cordic_engine_handle_t engine = NULL; cordic_engine_config_t engine_config = { .clock_source = CORDIC_CLK_SRC_DEFAULT, + .instance_id = 0, }; TEST_ESP_OK(cordic_acquire_engine(&engine_config, &engine)); cordic_calculate_config_t calc_config = { .function = ESP_CORDIC_FUNC_ARCTAN, .iq_format = ESP_CORDIC_FORMAT_Q15, - .iteration_count = 4, + .iteration_count = 16, .scale_exp = 2, // Scale = 2: hardware input is (x) * 2^(-2) = x / 4 }; @@ -602,6 +610,7 @@ TEST_CASE("test cordic performance should quicker than software iqmath", "[cordi cordic_engine_handle_t engine = NULL; cordic_engine_config_t engine_config = { .clock_source = CORDIC_CLK_SRC_DEFAULT, + .instance_id = 0, }; TEST_ESP_OK(cordic_acquire_engine(&engine_config, &engine)); @@ -687,7 +696,7 @@ static void concurrent_calculate_task(void *arg) cordic_calculate_config_t calc_config = { .function = ESP_CORDIC_FUNC_COS, .iq_format = ESP_CORDIC_FORMAT_Q15, - .iteration_count = 4, + .iteration_count = 8, .scale_exp = 0, }; cordic_input_buffer_desc_t input_buffer = { @@ -722,6 +731,7 @@ TEST_CASE("cordic results stay correct when shared by multiple tasks", "[cordic] cordic_engine_handle_t engine = NULL; cordic_engine_config_t engine_config = { .clock_source = CORDIC_CLK_SRC_DEFAULT, + .instance_id = 0, }; TEST_ESP_OK(cordic_acquire_engine(&engine_config, &engine)); @@ -827,15 +837,21 @@ TEST_CASE("cordic can calculation in ISR", "[cordic]") cordic_engine_config_t engine_config = { .clock_source = CORDIC_CLK_SRC_DEFAULT, + .instance_id = 0, }; TEST_ESP_OK(cordic_acquire_engine(&engine_config, &isr_test_ctx.engine_handle)); //-------------GPTimer Init & Config---------------// gptimer_handle_t timer = NULL; gptimer_config_t timer_config = { - .resolution_hz = 1 * 1000 * 1000, .clk_src = GPTIMER_CLK_SRC_DEFAULT, .direction = GPTIMER_COUNT_UP, + .resolution_hz = 1 * 1000 * 1000, + .intr_priority = 0, + .flags = { + .intr_shared = 0, + .allow_pd = 0, + }, }; TEST_ESP_OK(gptimer_new_timer(&timer_config, &timer)); @@ -843,8 +859,11 @@ TEST_CASE("cordic can calculation in ISR", "[cordic]") .on_alarm = s_alarm_callback, }; gptimer_alarm_config_t alarm_config = { - .reload_count = 0, .alarm_count = 100000, // 100ms + .reload_count = 0, + .flags = { + .auto_reload_on_alarm = 0, + }, }; TEST_ESP_OK(gptimer_set_alarm_action(timer, &alarm_config)); TEST_ESP_OK(gptimer_register_event_callbacks(timer, &cbs, &isr_test_ctx)); diff --git a/components/esp_driver_cordic/test_apps/cordic_driver_ut/main/test_cordic_q31.c b/components/esp_driver_cordic/test_apps/cordic_driver_ut/main/test_cordic_q31.cpp similarity index 98% rename from components/esp_driver_cordic/test_apps/cordic_driver_ut/main/test_cordic_q31.c rename to components/esp_driver_cordic/test_apps/cordic_driver_ut/main/test_cordic_q31.cpp index f6e8bfc8e73..d971cec42d0 100644 --- a/components/esp_driver_cordic/test_apps/cordic_driver_ut/main/test_cordic_q31.c +++ b/components/esp_driver_cordic/test_apps/cordic_driver_ut/main/test_cordic_q31.cpp @@ -23,13 +23,14 @@ TEST_CASE("test cosine and sine q31", "[cordic]") cordic_engine_handle_t engine = NULL; cordic_engine_config_t engine_config = { .clock_source = CORDIC_CLK_SRC_DEFAULT, + .instance_id = 0, }; TEST_ESP_OK(cordic_acquire_engine(&engine_config, &engine)); cordic_calculate_config_t calc_config = { .function = ESP_CORDIC_FUNC_COS, .iq_format = ESP_CORDIC_FORMAT_Q31, - .iteration_count = 4, + .iteration_count = 16, .scale_exp = 0, }; @@ -84,13 +85,14 @@ TEST_CASE("test phase and module q31", "[cordic]") cordic_engine_handle_t engine = NULL; cordic_engine_config_t engine_config = { .clock_source = CORDIC_CLK_SRC_DEFAULT, + .instance_id = 0, }; TEST_ESP_OK(cordic_acquire_engine(&engine_config, &engine)); cordic_calculate_config_t calc_config = { .function = ESP_CORDIC_FUNC_PHASE, .iq_format = ESP_CORDIC_FORMAT_Q31, - .iteration_count = 4, + .iteration_count = 16, .scale_exp = 0, }; @@ -158,13 +160,14 @@ TEST_CASE("test arctan q31", "[cordic]") cordic_engine_handle_t engine = NULL; cordic_engine_config_t engine_config = { .clock_source = CORDIC_CLK_SRC_DEFAULT, + .instance_id = 0, }; TEST_ESP_OK(cordic_acquire_engine(&engine_config, &engine)); cordic_calculate_config_t calc_config = { .function = ESP_CORDIC_FUNC_ARCTAN, .iq_format = ESP_CORDIC_FORMAT_Q31, - .iteration_count = 4, + .iteration_count = 16, .scale_exp = 0, }; @@ -221,13 +224,14 @@ TEST_CASE("test hyperbolic cosine and sine q31", "[cordic]") cordic_engine_handle_t engine = NULL; cordic_engine_config_t engine_config = { .clock_source = CORDIC_CLK_SRC_DEFAULT, + .instance_id = 0, }; TEST_ESP_OK(cordic_acquire_engine(&engine_config, &engine)); cordic_calculate_config_t calc_config = { .function = ESP_CORDIC_FUNC_COSH, .iq_format = ESP_CORDIC_FORMAT_Q31, - .iteration_count = 4, + .iteration_count = 20, .scale_exp = 1, }; @@ -287,13 +291,14 @@ TEST_CASE("test arctanh q31", "[cordic]") cordic_engine_handle_t engine = NULL; cordic_engine_config_t engine_config = { .clock_source = CORDIC_CLK_SRC_DEFAULT, + .instance_id = 0, }; TEST_ESP_OK(cordic_acquire_engine(&engine_config, &engine)); cordic_calculate_config_t calc_config = { .function = ESP_CORDIC_FUNC_ARCHTANH, .iq_format = ESP_CORDIC_FORMAT_Q31, - .iteration_count = 4, + .iteration_count = 20, .scale_exp = 1, }; @@ -351,13 +356,14 @@ TEST_CASE("test natural logarithm q31", "[cordic]") cordic_engine_handle_t engine = NULL; cordic_engine_config_t engine_config = { .clock_source = CORDIC_CLK_SRC_DEFAULT, + .instance_id = 0, }; TEST_ESP_OK(cordic_acquire_engine(&engine_config, &engine)); cordic_calculate_config_t calc_config = { .function = ESP_CORDIC_FUNC_LOGE, .iq_format = ESP_CORDIC_FORMAT_Q31, - .iteration_count = 4, + .iteration_count = 16, .scale_exp = 1, }; @@ -424,13 +430,14 @@ TEST_CASE("test square root q31", "[cordic]") cordic_engine_handle_t engine = NULL; cordic_engine_config_t engine_config = { .clock_source = CORDIC_CLK_SRC_DEFAULT, + .instance_id = 0, }; TEST_ESP_OK(cordic_acquire_engine(&engine_config, &engine)); cordic_calculate_config_t calc_config = { .function = ESP_CORDIC_FUNC_SQUARE_ROOT, .iq_format = ESP_CORDIC_FORMAT_Q31, - .iteration_count = 4, + .iteration_count = 12, .scale_exp = 0, }; @@ -488,13 +495,14 @@ TEST_CASE("test arctan scale 2 q31", "[cordic]") cordic_engine_handle_t engine = NULL; cordic_engine_config_t engine_config = { .clock_source = CORDIC_CLK_SRC_DEFAULT, + .instance_id = 0, }; TEST_ESP_OK(cordic_acquire_engine(&engine_config, &engine)); cordic_calculate_config_t calc_config = { .function = ESP_CORDIC_FUNC_ARCTAN, .iq_format = ESP_CORDIC_FORMAT_Q31, - .iteration_count = 4, + .iteration_count = 16, .scale_exp = 2, // Scale = 2: hardware input is (x) * 2^(-2) = x / 4 }; @@ -568,13 +576,14 @@ TEST_CASE("test reconfig from cos q15 to log q31", "[cordic]") // Step 1: Create engine with COS function and Q15 format cordic_engine_config_t engine_config = { .clock_source = CORDIC_CLK_SRC_DEFAULT, + .instance_id = 0, }; TEST_ESP_OK(cordic_acquire_engine(&engine_config, &engine)); cordic_calculate_config_t calc_config_cos = { .function = ESP_CORDIC_FUNC_COS, .iq_format = ESP_CORDIC_FORMAT_Q15, - .iteration_count = 4, + .iteration_count = 8, .scale_exp = 0, }; @@ -621,7 +630,7 @@ TEST_CASE("test reconfig from cos q15 to log q31", "[cordic]") cordic_calculate_config_t calc_config_log = { .function = ESP_CORDIC_FUNC_LOGE, .iq_format = ESP_CORDIC_FORMAT_Q31, - .iteration_count = 4, + .iteration_count = 16, .scale_exp = 1, }; diff --git a/components/esp_driver_cordic/test_apps/cordic_driver_ut/main/test_cordic_sleep.cpp b/components/esp_driver_cordic/test_apps/cordic_driver_ut/main/test_cordic_sleep.cpp new file mode 100644 index 00000000000..da49c7f9fb6 --- /dev/null +++ b/components/esp_driver_cordic/test_apps/cordic_driver_ut/main/test_cordic_sleep.cpp @@ -0,0 +1,77 @@ +/* + * SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: CC0-1.0 + */ + +#include +#include "sdkconfig.h" +#include "unity.h" +#include "driver/cordic.h" +#include "esp_sleep.h" +#include "esp_private/sleep_cpu.h" +#include "esp_private/esp_sleep_internal.h" +#include "esp_private/esp_pmu.h" + +/* q1.15 residual at 12 iterations is 2^-11. */ +#define CORDIC_SLEEP_TOLERANCE 0.01f + +static void cordic_check_cos0(cordic_engine_handle_t engine) +{ + cordic_calculate_config_t calc_config = { + .function = ESP_CORDIC_FUNC_COS, + .iq_format = ESP_CORDIC_FORMAT_Q15, + .iteration_count = 12, + .scale_exp = 0, + }; + uint32_t arg = 0; + uint32_t res_cos = 0; + uint32_t res_sin = 0; + cordic_input_buffer_desc_t input_buffer = { + .p_data_arg1 = &arg, + .p_data_arg2 = NULL, + }; + cordic_output_buffer_desc_t output_buffer = { + .p_data_res1 = &res_cos, + .p_data_res2 = &res_sin, + }; + + TEST_ESP_OK(cordic_calculate_polling(engine, &calc_config, &input_buffer, &output_buffer, 1)); + + float hw_cos = cordic_convert_fixed_to_float(res_cos, ESP_CORDIC_FORMAT_Q15); + float hw_sin = cordic_convert_fixed_to_float(res_sin, ESP_CORDIC_FORMAT_Q15); + printf("cos(0)=%f sin(0)=%f\n", hw_cos, hw_sin); + TEST_ASSERT_FLOAT_WITHIN(CORDIC_SLEEP_TOLERANCE, 1.0f, hw_cos); + TEST_ASSERT_FLOAT_WITHIN(CORDIC_SLEEP_TOLERANCE, 0.0f, hw_sin); +} + +TEST_CASE("cordic works after top domain light sleep", "[cordic]") +{ + cordic_engine_handle_t engine = NULL; + cordic_engine_config_t engine_config = { + .clock_source = CORDIC_CLK_SRC_DEFAULT, + .instance_id = 0, + }; + TEST_ESP_OK(cordic_acquire_engine(&engine_config, &engine)); + + cordic_check_cos0(engine); + + esp_sleep_context_t sleep_ctx; + esp_sleep_set_sleep_context(&sleep_ctx); +#if CONFIG_PM_ESP_SLEEP_POWER_DOWN_CPU + TEST_ESP_OK(sleep_cpu_configure(true)); +#endif + printf("go to light sleep for 1 second\r\n"); + TEST_ESP_OK(esp_sleep_enable_timer_wakeup(1 * 1000 * 1000)); + TEST_ESP_OK(esp_light_sleep_start()); +#if CONFIG_PM_ESP_SLEEP_POWER_DOWN_CPU + TEST_ESP_OK(sleep_cpu_configure(false)); +#endif + + TEST_ASSERT_EQUAL(0, sleep_ctx.sleep_request_result); + TEST_ASSERT_EQUAL(PMU_SLEEP_PD_TOP, sleep_ctx.sleep_flags & PMU_SLEEP_PD_TOP); + esp_sleep_set_sleep_context(NULL); + + cordic_check_cos0(engine); + TEST_ESP_OK(cordic_release_engine(engine)); +} diff --git a/components/esp_driver_cordic/test_apps/cordic_driver_ut/sdkconfig.defaults b/components/esp_driver_cordic/test_apps/cordic_driver_ut/sdkconfig.defaults index fa8ac618b94..96018375af6 100644 --- a/components/esp_driver_cordic/test_apps/cordic_driver_ut/sdkconfig.defaults +++ b/components/esp_driver_cordic/test_apps/cordic_driver_ut/sdkconfig.defaults @@ -1,2 +1,3 @@ CONFIG_FREERTOS_HZ=1000 CONFIG_ESP_TASK_WDT_EN=n +CONFIG_ESP_SLEEP_DEBUG=y diff --git a/components/esp_hal_cordic/esp32s31/include/hal/cordic_ll.h b/components/esp_hal_cordic/esp32s31/include/hal/cordic_ll.h index ba9c84907fc..eecc5d25f20 100644 --- a/components/esp_hal_cordic/esp32s31/include/hal/cordic_ll.h +++ b/components/esp_hal_cordic/esp32s31/include/hal/cordic_ll.h @@ -16,7 +16,9 @@ #include "soc/hp_sys_clkrst_struct.h" #define CORDIC_LL_GET_HW() (&CORDIC) -#define CORDIC_LL_PRECISION_MAX 0xF +#define CORDIC_LL_ITERATION_MIN 4 /*!< Smallest iteration count. CORDIC_PRES steps by 4 */ +#define CORDIC_LL_ITERATION_MAX 24 /*!< Largest iteration count (CORDIC_PRES = 5) */ +#define CORDIC_LL_SQRT_ITERATION_MAX 12 /*!< Square root only supports CORDIC_PRES 0..2 */ #define CORDIC_LL_INST_NUM 1U /*!< Number of CORDIC hardware instances on this chip */ #ifdef __cplusplus @@ -107,13 +109,26 @@ static inline void cordic_ll_set_clock_div(uint32_t integer, uint32_t numerator, HAL_FORCE_MODIFY_U32_REG_FIELD(HP_SYS_CLKRST.cordic_ctrl1, reg_cordic_clk_div_denonimator, denominator); } +/** + * @brief Iteration count is legal for this function + * + * Counts are 4, 8, 12, 16, 20, 24. Square root stops at 12. + */ +static inline bool cordic_ll_iteration_count_valid(cordic_func_t function, uint16_t iteration_count) +{ + uint16_t max_iter = (function == ESP_CORDIC_FUNC_SQUARE_ROOT) ? CORDIC_LL_SQRT_ITERATION_MAX : CORDIC_LL_ITERATION_MAX; + return iteration_count >= CORDIC_LL_ITERATION_MIN && + iteration_count <= max_iter && + (iteration_count % CORDIC_LL_ITERATION_MIN) == 0; +} + /** * @brief Program the calculation configuration fields of csr_cfg with one RMW * * @param hw Pointer to the CORDIC hardware register structure * @param function Function type to calculate * @param mode Data transfer mode (register or DMA) - * @param precision Iteration count programmed into press (already decremented by the caller) + * @param precision Iteration count. Mapped to CORDIC_PRES: 4, 8, 12, 16, 20, 24 * @param scale Input scale exponent * @param arg_num Number of input arguments (1 or 2) * @param res_num Number of result outputs (1 or 2) @@ -170,7 +185,7 @@ static inline void cordic_ll_set_calculate_config(cordic_dev_t *hw, } csr.work_mode = mode; - csr.press = precision; + csr.press = (precision / CORDIC_LL_ITERATION_MIN) - 1; csr.scale = scale; csr.arg_num = arg_num - 1; csr.res_num = res_num - 1; diff --git a/docs/en/api-reference/peripherals/cordic.rst b/docs/en/api-reference/peripherals/cordic.rst index 0b0641dda78..b88a7d5bbdd 100644 --- a/docs/en/api-reference/peripherals/cordic.rst +++ b/docs/en/api-reference/peripherals/cordic.rst @@ -138,7 +138,7 @@ Input and output data format is selected via :cpp:member:`cordic_calculate_confi Precision --------- -The number of iterations (precision) is set via :cpp:member:`cordic_calculate_config_t::iteration_count`. Supported values are given below. +The number of iterations (precision) is set via :cpp:member:`cordic_calculate_config_t::iteration_count`. Legal values are 4, 8, 12, 16, 20 and 24. Square root accepts only 4, 8 and 12. Any other value makes the calculation return ``ESP_ERR_INVALID_ARG``. Supported values and their residuals are given below. **Phase, Modulus, Arctan functions** @@ -225,7 +225,7 @@ Use the engine to perform a calculation: cordic_calculate_config_t calc_config = { .function = ESP_CORDIC_FUNC_COS, // Select function .iq_format = ESP_CORDIC_FORMAT_Q15, // Input/output data format - .iteration_count = 4, // Iteration count (precision) + .iteration_count = 4, // 4, 8, 12, 16, 20 or 24 iterations .scale_exp = 0, // Input scale exponent n (effective scale 2^n) }; diff --git a/docs/zh_CN/api-reference/peripherals/cordic.rst b/docs/zh_CN/api-reference/peripherals/cordic.rst index bde1d77c5e8..486bc214063 100644 --- a/docs/zh_CN/api-reference/peripherals/cordic.rst +++ b/docs/zh_CN/api-reference/peripherals/cordic.rst @@ -138,7 +138,7 @@ CORDIC 驱动 通过 :cpp:member:`cordic_calculate_config_t::iq_format` 参数 精度 ---- -CORDIC 驱动通过 :cpp:member:`cordic_calculate_config_t::iteration_count` 参数来设置计算的迭代周期(精度),其支持的精度如下所示。 +CORDIC 驱动通过 :cpp:member:`cordic_calculate_config_t::iteration_count` 设置迭代次数。合法取值为 4、8、12、16、20、24。开方只允许 4、8、12。其他取值会使本次计算返回 ``ESP_ERR_INVALID_ARG``。各档位的残差如下所示。 **Phase, Modulus, arctan 函数** @@ -225,7 +225,7 @@ CORDIC 驱动通过 :cpp:member:`cordic_calculate_config_t::iteration_count` 参 cordic_calculate_config_t calc_config = { .function = ESP_CORDIC_FUNC_COS, // 选择计算的函数 .iq_format = ESP_CORDIC_FORMAT_Q15, // 选择输入和输出数据的格式 - .iteration_count = 4, // 选择计算的迭代周期(精度) + .iteration_count = 4, // 迭代次数:4、8、12、16、20 或 24 .scale_exp = 0, // 输入缩放指数 n,有效缩放为 2^n };