feat(mcpwm): ETM support mcpwm timer TEZ/TEP events

This commit is contained in:
Chen Chen
2026-02-05 18:08:51 +08:00
parent a483acbf8f
commit 346a021d3d
13 changed files with 417 additions and 23 deletions
@@ -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
*/
@@ -9,6 +9,7 @@
#include "unity.h"
#include "unity_test_utils.h"
#include "esp_attr.h"
#include "hal/mcpwm_ll.h"
#include "driver/gptimer_etm.h"
#include "driver/gptimer.h"
#include "driver/gpio.h"
@@ -18,9 +19,11 @@ TEST_CASE("mcpwm_comparator_etm_event", "[mcpwm][etm]")
{
// MCPWM cmpra -------------------------------------> ETM channel A ---> GPTimer start
// MCPWM cmprb / evt_cmpra (if support evt_cmpr) ---> ETM channel B ---> GPTimer stop
// Use the last MCPWM group (e.g. group_id=1 when MCPWM_LL_GROUP_NUM==2) to test multi-group chips
const int mcpwm_group_id = MCPWM_LL_GET(GROUP_NUM) - 1;
mcpwm_timer_config_t timer_config = {
.group_id = 0,
.group_id = mcpwm_group_id,
.clk_src = MCPWM_TIMER_CLK_SRC_DEFAULT,
.resolution_hz = 1 * 1000 * 1000,
.count_mode = MCPWM_TIMER_COUNT_MODE_UP,
@@ -30,7 +33,7 @@ TEST_CASE("mcpwm_comparator_etm_event", "[mcpwm][etm]")
TEST_ESP_OK(mcpwm_new_timer(&timer_config, &timer));
mcpwm_operator_config_t operator_config = {
.group_id = 0,
.group_id = mcpwm_group_id,
};
mcpwm_oper_handle_t oper = NULL;
TEST_ESP_OK(mcpwm_new_operator(&operator_config, &oper));
@@ -151,3 +154,99 @@ TEST_CASE("mcpwm_comparator_etm_event", "[mcpwm][etm]")
TEST_ESP_OK(mcpwm_del_operator(oper));
TEST_ESP_OK(mcpwm_del_timer(timer));
}
TEST_CASE("mcpwm_timer_etm_event", "[mcpwm][etm]")
{
// MCPWM timer TEP (timer equals peak) ---> ETM channel A ---> GPTimer start
// MCPWM timer TEZ (timer equals zero) ---> ETM channel B ---> GPTimer stop
// Using UP_DOWN count mode, the timer counts: 0 -> peak -> 0 -> peak -> ...
// GPTimer starts at TEP and stops at TEZ, so it measures the time from peak to 0
// Use the last MCPWM group (e.g. group_id=1 when MCPWM_LL_GROUP_NUM==2) to test multi-group chips
const int mcpwm_group_id = MCPWM_LL_GET(GROUP_NUM) - 1;
printf("create mcpwm timer\r\n");
const uint32_t timer_resolution = 1 * 1000 * 1000; // 1MHz, 1 tick = 1us
const uint32_t period_ticks = 10000; // For UP_DOWN mode, peak = period_ticks / 2 = 5000
mcpwm_timer_config_t timer_config = {
.group_id = mcpwm_group_id,
.clk_src = MCPWM_TIMER_CLK_SRC_DEFAULT,
.resolution_hz = timer_resolution,
.count_mode = MCPWM_TIMER_COUNT_MODE_UP_DOWN,
.period_ticks = period_ticks,
};
mcpwm_timer_handle_t mcpwm_timer = NULL;
TEST_ESP_OK(mcpwm_new_timer(&timer_config, &mcpwm_timer));
TEST_ESP_OK(mcpwm_timer_enable(mcpwm_timer));
printf("create mcpwm timer etm event\r\n");
esp_etm_event_handle_t mcpwm_timer_event_tez = NULL;
esp_etm_event_handle_t mcpwm_timer_event_tep = NULL;
mcpwm_timer_etm_event_config_t timer_etm_event_config = {
.event_type = MCPWM_TIMER_ETM_EVENT_TEZ,
};
TEST_ESP_OK(mcpwm_timer_new_etm_event(mcpwm_timer, &timer_etm_event_config, &mcpwm_timer_event_tez));
timer_etm_event_config.event_type = MCPWM_TIMER_ETM_EVENT_TEP;
TEST_ESP_OK(mcpwm_timer_new_etm_event(mcpwm_timer, &timer_etm_event_config, &mcpwm_timer_event_tep));
printf("create gptimer\r\n");
gptimer_handle_t gptimer = NULL;
gptimer_config_t gptimer_config = {
.clk_src = GPTIMER_CLK_SRC_DEFAULT,
.direction = GPTIMER_COUNT_UP,
.resolution_hz = timer_resolution, // Same resolution as MCPWM timer
};
TEST_ESP_OK(gptimer_new_timer(&gptimer_config, &gptimer));
printf("create gptimer etm task\r\n");
esp_etm_task_handle_t gptimer_task_start = NULL;
esp_etm_task_handle_t gptimer_task_stop = NULL;
gptimer_etm_task_config_t gptimer_etm_task_conf = {
.task_type = GPTIMER_ETM_TASK_START_COUNT,
};
TEST_ESP_OK(gptimer_new_etm_task(gptimer, &gptimer_etm_task_conf, &gptimer_task_start));
gptimer_etm_task_conf.task_type = GPTIMER_ETM_TASK_STOP_COUNT;
TEST_ESP_OK(gptimer_new_etm_task(gptimer, &gptimer_etm_task_conf, &gptimer_task_stop));
TEST_ESP_OK(gptimer_enable(gptimer));
printf("create and connect etm channels\r\n");
esp_etm_channel_config_t etm_config = {};
esp_etm_channel_handle_t etm_channel_a = NULL;
esp_etm_channel_handle_t etm_channel_b = NULL;
TEST_ESP_OK(esp_etm_new_channel(&etm_config, &etm_channel_a));
TEST_ESP_OK(esp_etm_new_channel(&etm_config, &etm_channel_b));
// TEP -> start gptimer, TEZ -> stop gptimer
TEST_ESP_OK(esp_etm_channel_connect(etm_channel_a, mcpwm_timer_event_tep, gptimer_task_start));
TEST_ESP_OK(esp_etm_channel_connect(etm_channel_b, mcpwm_timer_event_tez, gptimer_task_stop));
TEST_ESP_OK(esp_etm_channel_enable(etm_channel_a));
TEST_ESP_OK(esp_etm_channel_enable(etm_channel_b));
printf("start mcpwm timer and let it run for multiple periods\r\n");
TEST_ESP_OK(mcpwm_timer_start_stop(mcpwm_timer, MCPWM_TIMER_START_NO_STOP));
esp_rom_delay_us(100 * 1000); // Let it run for 100ms
TEST_ESP_OK(mcpwm_timer_start_stop(mcpwm_timer, MCPWM_TIMER_STOP_EMPTY));
printf("verify gptimer count value\r\n");
uint64_t gptimer_count = 0;
TEST_ESP_OK(gptimer_get_raw_count(gptimer, &gptimer_count));
printf("gptimer_count: %"PRIu64"\r\n", gptimer_count);
// In UP_DOWN mode with period_ticks=10000:
// - One full cycle (0->peak->0) takes 10000 ticks
// - Peak value is period_ticks/2 = 5000
// - GPTimer accumulates: 10 cycles * 5000 ticks = 50000 ticks
const uint32_t expected_count = (100 * 1000 / period_ticks) * (period_ticks / 2);
TEST_ASSERT_UINT_WITHIN(500, expected_count, gptimer_count);
printf("cleanup\r\n");
TEST_ESP_OK(gptimer_disable(gptimer));
TEST_ESP_OK(gptimer_del_timer(gptimer));
TEST_ESP_OK(esp_etm_channel_disable(etm_channel_a));
TEST_ESP_OK(esp_etm_channel_disable(etm_channel_b));
TEST_ESP_OK(esp_etm_del_task(gptimer_task_start));
TEST_ESP_OK(esp_etm_del_task(gptimer_task_stop));
TEST_ESP_OK(esp_etm_del_event(mcpwm_timer_event_tez));
TEST_ESP_OK(esp_etm_del_event(mcpwm_timer_event_tep));
TEST_ESP_OK(esp_etm_del_channel(etm_channel_a));
TEST_ESP_OK(esp_etm_del_channel(etm_channel_b));
TEST_ESP_OK(mcpwm_timer_disable(mcpwm_timer));
TEST_ESP_OK(mcpwm_del_timer(mcpwm_timer));
}