diff --git a/components/esp_driver_mcpwm/test_apps/mcpwm/main/CMakeLists.txt b/components/esp_driver_mcpwm/test_apps/mcpwm/main/CMakeLists.txt index 232f3c1e9ef..17d91c59e17 100644 --- a/components/esp_driver_mcpwm/test_apps/mcpwm/main/CMakeLists.txt +++ b/components/esp_driver_mcpwm/test_apps/mcpwm/main/CMakeLists.txt @@ -24,5 +24,5 @@ endif() # In order for the cases defined by `TEST_CASE` to be linked into the final elf, # the component can be registered as WHOLE_ARCHIVE idf_component_register(SRCS ${srcs} - PRIV_REQUIRES unity esp_driver_mcpwm esp_driver_gpio esp_driver_gptimer esp_psram + PRIV_REQUIRES unity esp_driver_mcpwm esp_driver_gpio esp_driver_gptimer esp_psram esp_timer esp_rom WHOLE_ARCHIVE) diff --git a/components/esp_driver_mcpwm/test_apps/mcpwm/main/test_mcpwm_timer.c b/components/esp_driver_mcpwm/test_apps/mcpwm/main/test_mcpwm_timer.c index ac2a74541db..15b19759d96 100644 --- a/components/esp_driver_mcpwm/test_apps/mcpwm/main/test_mcpwm_timer.c +++ b/components/esp_driver_mcpwm/test_apps/mcpwm/main/test_mcpwm_timer.c @@ -7,6 +7,8 @@ #include "freertos/task.h" #include "freertos/event_groups.h" #include "unity.h" +#include "esp_timer.h" +#include "esp_rom_sys.h" #include "hal/mcpwm_ll.h" #include "driver/mcpwm_timer.h" #include "esp_private/mcpwm.h" @@ -88,6 +90,72 @@ TEST_CASE("mcpwm_timer_start_stop", "[mcpwm]") } } +TEST_CASE("mcpwm_timer_various_clk_src", "[mcpwm]") +{ + mcpwm_timer_clock_source_t clk_srcs[] = SOC_MCPWM_TIMER_CLKS; + const int num_timers = MCPWM_LL_GET(TIMERS_PER_GROUP) * MCPWM_LL_GET(GROUP_NUM); + const uint32_t resolution_test_duration_us = 5000; + + for (size_t clk_src_idx = 0; clk_src_idx < sizeof(clk_srcs) / sizeof(clk_srcs[0]); clk_src_idx++) { + mcpwm_timer_clock_source_t clk_src = clk_srcs[clk_src_idx]; + const uint32_t tolerance_percent = (soc_module_clk_t)clk_src == SOC_MOD_CLK_RC_FAST ? 10 : 1; + mcpwm_timer_config_t config = { + .clk_src = clk_src, + .resolution_hz = 1000000, // 1MHz + .period_ticks = 12000, + .count_mode = MCPWM_TIMER_COUNT_MODE_UP_DOWN, + }; + + printf("create MCPWM timers with clock source: %d\r\n", clk_src); + mcpwm_timer_handle_t timers[num_timers]; + for (int group_id = 0; group_id < MCPWM_LL_GET(GROUP_NUM); group_id++) { + config.group_id = group_id; + for (int timer_id = 0; timer_id < MCPWM_LL_GET(TIMERS_PER_GROUP); timer_id++) { + int timer_index = group_id * MCPWM_LL_GET(TIMERS_PER_GROUP) + timer_id; + TEST_ESP_OK(mcpwm_new_timer(&config, &timers[timer_index])); + } + } + + printf("enable timers\r\n"); + for (int i = 0; i < num_timers; i++) { + TEST_ESP_OK(mcpwm_timer_enable(timers[i])); + } + + printf("check timer resolution\r\n"); + for (int i = 0; i < num_timers; i++) { + TEST_ESP_OK(mcpwm_timer_start_stop(timers[i], MCPWM_TIMER_START_NO_STOP)); + + uint32_t start_count = 0; + uint32_t end_count = 0; + mcpwm_timer_direction_t direction; + TEST_ESP_OK(mcpwm_timer_get_phase(timers[i], &start_count, &direction)); + int64_t start_time_us = esp_timer_get_time(); + + esp_rom_delay_us(resolution_test_duration_us); + + TEST_ESP_OK(mcpwm_timer_get_phase(timers[i], &end_count, &direction)); + int64_t elapsed_time_us = esp_timer_get_time() - start_time_us; + uint32_t expected_ticks = (uint64_t)config.resolution_hz * elapsed_time_us / 1000000; + uint32_t actual_ticks = end_count - start_count; + uint32_t tolerance_ticks = expected_ticks * tolerance_percent / 100; + + TEST_ASSERT_EQUAL(MCPWM_TIMER_DIRECTION_UP, direction); + TEST_ASSERT_UINT32_WITHIN(tolerance_ticks, expected_ticks, actual_ticks); + + // make sure the timer has stopped + TEST_ESP_OK(mcpwm_timer_start_stop(timers[i], MCPWM_TIMER_STOP_EMPTY)); + vTaskDelay(pdMS_TO_TICKS(10)); + check_mcpwm_timer_phase(&timers[i], 1, 0, MCPWM_TIMER_DIRECTION_UP); + } + + printf("disable and delete timers\r\n"); + for (int i = 0; i < num_timers; i++) { + TEST_ESP_OK(mcpwm_timer_disable(timers[i])); + TEST_ESP_OK(mcpwm_del_timer(timers[i])); + } + } +} + #define TEST_MCPWM_TIMER_EVENT_BIT_FULL (1 << 0) #define TEST_MCPWM_TIMER_EVENT_BIT_EMPTY (1 << 1) #define TEST_MCPWM_TIMER_EVENT_BIT_STOP (1 << 2) diff --git a/components/esp_hal_mcpwm/esp32c6/include/hal/mcpwm_ll.h b/components/esp_hal_mcpwm/esp32c6/include/hal/mcpwm_ll.h index 000d5f1124f..1272163769e 100644 --- a/components/esp_hal_mcpwm/esp32c6/include/hal/mcpwm_ll.h +++ b/components/esp_hal_mcpwm/esp32c6/include/hal/mcpwm_ll.h @@ -145,6 +145,9 @@ static inline void mcpwm_ll_group_set_clock_source(int group_id, soc_module_clk_ case SOC_MOD_CLK_XTAL: PCR.pwm_clk_conf.pwm_clkm_sel = 2; break; + case SOC_MOD_CLK_RC_FAST: + PCR.pwm_clk_conf.pwm_clkm_sel = 3; + break; default: HAL_ASSERT(false); break; diff --git a/components/esp_hal_mcpwm/esp32h2/include/hal/mcpwm_ll.h b/components/esp_hal_mcpwm/esp32h2/include/hal/mcpwm_ll.h index dabc8fc77c9..05c873d8e02 100644 --- a/components/esp_hal_mcpwm/esp32h2/include/hal/mcpwm_ll.h +++ b/components/esp_hal_mcpwm/esp32h2/include/hal/mcpwm_ll.h @@ -140,6 +140,9 @@ static inline void mcpwm_ll_group_set_clock_source(int group_id, soc_module_clk_ case SOC_MOD_CLK_XTAL: PCR.pwm_clk_conf.pwm_clkm_sel = 0; break; + case SOC_MOD_CLK_RC_FAST: + PCR.pwm_clk_conf.pwm_clkm_sel = 1; + break; case SOC_MOD_CLK_PLL_F96M: PCR.pwm_clk_conf.pwm_clkm_sel = 2; break; diff --git a/components/esp_hal_mcpwm/esp32s31/include/hal/mcpwm_ll.h b/components/esp_hal_mcpwm/esp32s31/include/hal/mcpwm_ll.h index 1189b5b934f..22c829c5543 100644 --- a/components/esp_hal_mcpwm/esp32s31/include/hal/mcpwm_ll.h +++ b/components/esp_hal_mcpwm/esp32s31/include/hal/mcpwm_ll.h @@ -181,7 +181,7 @@ static inline void mcpwm_ll_group_set_clock_source(int group_id, soc_module_clk_ case SOC_MOD_CLK_XTAL: clk_id = 0; break; - case SOC_MOD_CLK_PLL_F20M: + case SOC_MOD_CLK_RC_FAST: clk_id = 1; break; case SOC_MOD_CLK_PLL_F160M: diff --git a/components/soc/esp32c5/include/soc/clk_tree_defs.h b/components/soc/esp32c5/include/soc/clk_tree_defs.h index 461f3934c2e..4c0f66038de 100644 --- a/components/soc/esp32c5/include/soc/clk_tree_defs.h +++ b/components/soc/esp32c5/include/soc/clk_tree_defs.h @@ -284,13 +284,14 @@ typedef enum { /** * @brief Array initializer for all supported clock sources of MCPWM Timer */ -#define SOC_MCPWM_TIMER_CLKS {SOC_MOD_CLK_PLL_F160M, SOC_MOD_CLK_XTAL} +#define SOC_MCPWM_TIMER_CLKS {SOC_MOD_CLK_PLL_F160M, SOC_MOD_CLK_RC_FAST, SOC_MOD_CLK_XTAL} /** * @brief Type of MCPWM timer clock source */ typedef enum { MCPWM_TIMER_CLK_SRC_PLL160M = SOC_MOD_CLK_PLL_F160M, /*!< Select PLL_F160M as the source clock */ + MCPWM_TIMER_CLK_SRC_RC_FAST = SOC_MOD_CLK_RC_FAST, /*!< Select RC_FAST as the source clock */ MCPWM_TIMER_CLK_SRC_XTAL = SOC_MOD_CLK_XTAL, /*!< Select XTAL as the source clock */ MCPWM_TIMER_CLK_SRC_DEFAULT = SOC_MOD_CLK_PLL_F160M, /*!< Select PLL_F160M as the default clock choice */ } soc_periph_mcpwm_timer_clk_src_t; @@ -298,13 +299,14 @@ typedef enum { /** * @brief Array initializer for all supported clock sources of MCPWM Capture Timer */ -#define SOC_MCPWM_CAPTURE_CLKS {SOC_MOD_CLK_PLL_F160M, SOC_MOD_CLK_XTAL} +#define SOC_MCPWM_CAPTURE_CLKS {SOC_MOD_CLK_PLL_F160M, SOC_MOD_CLK_RC_FAST, SOC_MOD_CLK_XTAL} /** * @brief Type of MCPWM capture clock source */ typedef enum { MCPWM_CAPTURE_CLK_SRC_PLL160M = SOC_MOD_CLK_PLL_F160M, /*!< Select PLL_F160M as the source clock */ + MCPWM_CAPTURE_CLK_SRC_RC_FAST = SOC_MOD_CLK_RC_FAST, /*!< Select RC_FAST as the source clock */ MCPWM_CAPTURE_CLK_SRC_XTAL = SOC_MOD_CLK_XTAL, /*!< Select XTAL as the source clock */ MCPWM_CAPTURE_CLK_SRC_DEFAULT = SOC_MOD_CLK_PLL_F160M, /*!< Select PLL_F160M as the default clock choice */ } soc_periph_mcpwm_capture_clk_src_t; @@ -312,13 +314,14 @@ typedef enum { /** * @brief Array initializer for all supported clock sources of MCPWM Carrier */ -#define SOC_MCPWM_CARRIER_CLKS {SOC_MOD_CLK_PLL_F160M, SOC_MOD_CLK_XTAL} +#define SOC_MCPWM_CARRIER_CLKS {SOC_MOD_CLK_PLL_F160M, SOC_MOD_CLK_RC_FAST, SOC_MOD_CLK_XTAL} /** * @brief Type of MCPWM carrier clock source */ typedef enum { MCPWM_CARRIER_CLK_SRC_PLL160M = SOC_MOD_CLK_PLL_F160M, /*!< Select PLL_F160M as the source clock */ + MCPWM_CARRIER_CLK_SRC_RC_FAST = SOC_MOD_CLK_RC_FAST, /*!< Select RC_FAST as the source clock */ MCPWM_CARRIER_CLK_SRC_XTAL = SOC_MOD_CLK_XTAL, /*!< Select XTAL as the source clock */ MCPWM_CARRIER_CLK_SRC_DEFAULT = SOC_MOD_CLK_PLL_F160M, /*!< Select PLL_F160M as the default clock choice */ } soc_periph_mcpwm_carrier_clk_src_t; diff --git a/components/soc/esp32c6/include/soc/clk_tree_defs.h b/components/soc/esp32c6/include/soc/clk_tree_defs.h index 5562f89fc91..6af2724f372 100644 --- a/components/soc/esp32c6/include/soc/clk_tree_defs.h +++ b/components/soc/esp32c6/include/soc/clk_tree_defs.h @@ -281,13 +281,14 @@ typedef enum { /** * @brief Array initializer for all supported clock sources of MCPWM Timer */ -#define SOC_MCPWM_TIMER_CLKS {SOC_MOD_CLK_PLL_F160M, SOC_MOD_CLK_XTAL} +#define SOC_MCPWM_TIMER_CLKS {SOC_MOD_CLK_PLL_F160M, SOC_MOD_CLK_RC_FAST, SOC_MOD_CLK_XTAL} /** * @brief Type of MCPWM timer clock source */ typedef enum { MCPWM_TIMER_CLK_SRC_PLL160M = SOC_MOD_CLK_PLL_F160M, /*!< Select PLL_F160M as the source clock */ + MCPWM_TIMER_CLK_SRC_RC_FAST = SOC_MOD_CLK_RC_FAST, /*!< Select RC_FAST as the source clock */ MCPWM_TIMER_CLK_SRC_XTAL = SOC_MOD_CLK_XTAL, /*!< Select XTAL as the source clock */ MCPWM_TIMER_CLK_SRC_DEFAULT = SOC_MOD_CLK_PLL_F160M, /*!< Select PLL_F160M as the default clock choice */ } soc_periph_mcpwm_timer_clk_src_t; @@ -295,13 +296,14 @@ typedef enum { /** * @brief Array initializer for all supported clock sources of MCPWM Capture Timer */ -#define SOC_MCPWM_CAPTURE_CLKS {SOC_MOD_CLK_PLL_F160M, SOC_MOD_CLK_XTAL} +#define SOC_MCPWM_CAPTURE_CLKS {SOC_MOD_CLK_PLL_F160M, SOC_MOD_CLK_RC_FAST, SOC_MOD_CLK_XTAL} /** * @brief Type of MCPWM capture clock source */ typedef enum { MCPWM_CAPTURE_CLK_SRC_PLL160M = SOC_MOD_CLK_PLL_F160M, /*!< Select PLL_F160M as the source clock */ + MCPWM_CAPTURE_CLK_SRC_RC_FAST = SOC_MOD_CLK_RC_FAST, /*!< Select RC_FAST as the source clock */ MCPWM_CAPTURE_CLK_SRC_XTAL = SOC_MOD_CLK_XTAL, /*!< Select XTAL as the source clock */ MCPWM_CAPTURE_CLK_SRC_DEFAULT = SOC_MOD_CLK_PLL_F160M, /*!< Select PLL_F160M as the default clock choice */ } soc_periph_mcpwm_capture_clk_src_t; @@ -309,13 +311,14 @@ typedef enum { /** * @brief Array initializer for all supported clock sources of MCPWM Carrier */ -#define SOC_MCPWM_CARRIER_CLKS {SOC_MOD_CLK_PLL_F160M, SOC_MOD_CLK_XTAL} +#define SOC_MCPWM_CARRIER_CLKS {SOC_MOD_CLK_PLL_F160M, SOC_MOD_CLK_RC_FAST, SOC_MOD_CLK_XTAL} /** * @brief Type of MCPWM carrier clock source */ typedef enum { MCPWM_CARRIER_CLK_SRC_PLL160M = SOC_MOD_CLK_PLL_F160M, /*!< Select PLL_F160M as the source clock */ + MCPWM_CARRIER_CLK_SRC_RC_FAST = SOC_MOD_CLK_RC_FAST, /*!< Select RC_FAST as the source clock */ MCPWM_CARRIER_CLK_SRC_XTAL = SOC_MOD_CLK_XTAL, /*!< Select XTAL as the source clock */ MCPWM_CARRIER_CLK_SRC_DEFAULT = SOC_MOD_CLK_PLL_F160M, /*!< Select PLL_F160M as the default clock choice */ } soc_periph_mcpwm_carrier_clk_src_t; diff --git a/components/soc/esp32h2/include/soc/clk_tree_defs.h b/components/soc/esp32h2/include/soc/clk_tree_defs.h index cf5cf9f0320..05248dd7280 100644 --- a/components/soc/esp32h2/include/soc/clk_tree_defs.h +++ b/components/soc/esp32h2/include/soc/clk_tree_defs.h @@ -275,13 +275,14 @@ typedef enum { /** * @brief Array initializer for all supported clock sources of MCPWM Timer */ -#define SOC_MCPWM_TIMER_CLKS {SOC_MOD_CLK_PLL_F96M, SOC_MOD_CLK_XTAL} +#define SOC_MCPWM_TIMER_CLKS {SOC_MOD_CLK_PLL_F96M, SOC_MOD_CLK_RC_FAST, SOC_MOD_CLK_XTAL} /** * @brief Type of MCPWM timer clock source */ typedef enum { MCPWM_TIMER_CLK_SRC_PLL96M = SOC_MOD_CLK_PLL_F96M, /*!< Select PLL_F96M as the source clock */ + MCPWM_TIMER_CLK_SRC_RC_FAST = SOC_MOD_CLK_RC_FAST, /*!< Select RC_FAST as the source clock */ MCPWM_TIMER_CLK_SRC_XTAL = SOC_MOD_CLK_XTAL, /*!< Select XTAL as the source clock */ MCPWM_TIMER_CLK_SRC_DEFAULT = SOC_MOD_CLK_PLL_F96M, /*!< Select PLL_F96M as the default clock choice */ } soc_periph_mcpwm_timer_clk_src_t; @@ -289,13 +290,14 @@ typedef enum { /** * @brief Array initializer for all supported clock sources of MCPWM Capture Timer */ -#define SOC_MCPWM_CAPTURE_CLKS {SOC_MOD_CLK_PLL_F96M, SOC_MOD_CLK_XTAL} +#define SOC_MCPWM_CAPTURE_CLKS {SOC_MOD_CLK_PLL_F96M, SOC_MOD_CLK_RC_FAST, SOC_MOD_CLK_XTAL} /** * @brief Type of MCPWM capture clock source */ typedef enum { MCPWM_CAPTURE_CLK_SRC_PLL96M = SOC_MOD_CLK_PLL_F96M, /*!< Select PLL_F96M as the source clock */ + MCPWM_CAPTURE_CLK_SRC_RC_FAST = SOC_MOD_CLK_RC_FAST, /*!< Select RC_FAST as the source clock */ MCPWM_CAPTURE_CLK_SRC_XTAL = SOC_MOD_CLK_XTAL, /*!< Select XTAL as the source clock */ MCPWM_CAPTURE_CLK_SRC_DEFAULT = SOC_MOD_CLK_PLL_F96M, /*!< Select PLL_F96M as the default clock choice */ } soc_periph_mcpwm_capture_clk_src_t; @@ -303,13 +305,14 @@ typedef enum { /** * @brief Array initializer for all supported clock sources of MCPWM Carrier */ -#define SOC_MCPWM_CARRIER_CLKS {SOC_MOD_CLK_PLL_F96M, SOC_MOD_CLK_XTAL} +#define SOC_MCPWM_CARRIER_CLKS {SOC_MOD_CLK_PLL_F96M, SOC_MOD_CLK_RC_FAST, SOC_MOD_CLK_XTAL} /** * @brief Type of MCPWM carrier clock source */ typedef enum { MCPWM_CARRIER_CLK_SRC_PLL96M = SOC_MOD_CLK_PLL_F96M, /*!< Select PLL_F96M as the source clock */ + MCPWM_CARRIER_CLK_SRC_RC_FAST = SOC_MOD_CLK_RC_FAST, /*!< Select RC_FAST as the source clock */ MCPWM_CARRIER_CLK_SRC_XTAL = SOC_MOD_CLK_XTAL, /*!< Select XTAL as the source clock */ MCPWM_CARRIER_CLK_SRC_DEFAULT = SOC_MOD_CLK_PLL_F96M, /*!< Select PLL_F96M as the default clock choice */ } soc_periph_mcpwm_carrier_clk_src_t; diff --git a/components/soc/esp32p4/include/soc/clk_tree_defs.h b/components/soc/esp32p4/include/soc/clk_tree_defs.h index 25c529d1ad2..767e3c06212 100644 --- a/components/soc/esp32p4/include/soc/clk_tree_defs.h +++ b/components/soc/esp32p4/include/soc/clk_tree_defs.h @@ -308,13 +308,14 @@ typedef enum { /** * @brief Array initializer for all supported clock sources of MCPWM Timer */ -#define SOC_MCPWM_TIMER_CLKS {SOC_MOD_CLK_PLL_F160M, SOC_MOD_CLK_XTAL} +#define SOC_MCPWM_TIMER_CLKS {SOC_MOD_CLK_PLL_F160M, SOC_MOD_CLK_RC_FAST, SOC_MOD_CLK_XTAL} /** * @brief Type of MCPWM timer clock source */ typedef enum { MCPWM_TIMER_CLK_SRC_PLL160M = SOC_MOD_CLK_PLL_F160M, /*!< Select PLL_F160M as the source clock */ + MCPWM_TIMER_CLK_SRC_RC_FAST = SOC_MOD_CLK_RC_FAST, /*!< Select RC_FAST as the source clock */ MCPWM_TIMER_CLK_SRC_XTAL = SOC_MOD_CLK_XTAL, /*!< Select XTAL as the source clock */ MCPWM_TIMER_CLK_SRC_DEFAULT = SOC_MOD_CLK_PLL_F160M, /*!< Select PLL_F160M as the default choice */ } soc_periph_mcpwm_timer_clk_src_t; @@ -322,13 +323,14 @@ typedef enum { /** * @brief Array initializer for all supported clock sources of MCPWM Capture Timer */ -#define SOC_MCPWM_CAPTURE_CLKS {SOC_MOD_CLK_PLL_F160M, SOC_MOD_CLK_XTAL} +#define SOC_MCPWM_CAPTURE_CLKS {SOC_MOD_CLK_PLL_F160M, SOC_MOD_CLK_RC_FAST, SOC_MOD_CLK_XTAL} /** * @brief Type of MCPWM capture clock source */ typedef enum { MCPWM_CAPTURE_CLK_SRC_PLL160M = SOC_MOD_CLK_PLL_F160M, /*!< Select PLL_F160M as the source clock */ + MCPWM_CAPTURE_CLK_SRC_RC_FAST = SOC_MOD_CLK_RC_FAST, /*!< Select RC_FAST as the source clock */ MCPWM_CAPTURE_CLK_SRC_XTAL = SOC_MOD_CLK_XTAL, /*!< Select XTAL as the source clock */ MCPWM_CAPTURE_CLK_SRC_DEFAULT = SOC_MOD_CLK_PLL_F160M, /*!< Select PLL_F160M as the default choice */ } soc_periph_mcpwm_capture_clk_src_t; @@ -336,13 +338,14 @@ typedef enum { /** * @brief Array initializer for all supported clock sources of MCPWM Carrier */ -#define SOC_MCPWM_CARRIER_CLKS {SOC_MOD_CLK_PLL_F160M, SOC_MOD_CLK_XTAL} +#define SOC_MCPWM_CARRIER_CLKS {SOC_MOD_CLK_PLL_F160M, SOC_MOD_CLK_RC_FAST, SOC_MOD_CLK_XTAL} /** * @brief Type of MCPWM carrier clock source */ typedef enum { MCPWM_CARRIER_CLK_SRC_PLL160M = SOC_MOD_CLK_PLL_F160M, /*!< Select PLL_F160M as the source clock */ + MCPWM_CARRIER_CLK_SRC_RC_FAST = SOC_MOD_CLK_RC_FAST, /*!< Select RC_FAST as the source clock */ MCPWM_CARRIER_CLK_SRC_XTAL = SOC_MOD_CLK_XTAL, /*!< Select XTAL as the source clock */ MCPWM_CARRIER_CLK_SRC_DEFAULT = SOC_MOD_CLK_PLL_F160M, /*!< Select PLL_F160M as the default choice */ } soc_periph_mcpwm_carrier_clk_src_t;