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

This commit is contained in:
Chen Chen
2026-02-05 15:11:47 +08:00
parent caefb5741b
commit f90f05e09b
12 changed files with 385 additions and 22 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
*/
@@ -23,6 +23,13 @@ typedef struct {
mcpwm_comparator_etm_event_type_t event_type; /*!< MCPWM comparator ETM event type */
} mcpwm_cmpr_etm_event_config_t;
/**
* @brief MCPWM timer ETM event configuration
*/
typedef struct {
mcpwm_timer_etm_event_type_t event_type; /*!< MCPWM timer ETM event type */
} mcpwm_timer_etm_event_config_t;
/**
* @brief Get the ETM event for MCPWM comparator
*
@@ -38,6 +45,21 @@ typedef struct {
*/
esp_err_t mcpwm_comparator_new_etm_event(mcpwm_cmpr_handle_t cmpr, const mcpwm_cmpr_etm_event_config_t *config, esp_etm_event_handle_t *out_event);
/**
* @brief Get the ETM event for MCPWM timer
*
* @note The created ETM event object can be deleted later by calling `esp_etm_del_event`
*
* @param[in] timer MCPWM timer, allocated by `mcpwm_new_timer()`
* @param[in] config MCPWM ETM timer event configuration
* @param[out] out_event Returned ETM event handle
* @return
* - ESP_OK: Get ETM event successfully
* - ESP_ERR_INVALID_ARG: Get ETM event failed because of invalid argument
* - ESP_FAIL: Get ETM event failed because of other error
*/
esp_err_t mcpwm_timer_new_etm_event(mcpwm_timer_handle_t timer, const mcpwm_timer_etm_event_config_t *config, esp_etm_event_handle_t *out_event);
#ifdef __cplusplus
}
#endif
@@ -34,7 +34,7 @@ typedef struct {
uint32_t resolution_hz; /*!< Counter resolution in Hz
The step size of each count tick equals to (1 / resolution_hz) seconds */
mcpwm_timer_count_mode_t count_mode; /*!< Count mode */
uint32_t period_ticks; /*!< Number of count ticks within a period */
uint32_t period_ticks; /*!< Number of count ticks within a period. For up-down mode, the timer peak value is half of the period_ticks */
int intr_priority; /*!< MCPWM timer interrupt priority,
if set to 0, the driver will try to allocate an interrupt with a relative low priority (1,2,3) */
struct {
+65 -4
View File
@@ -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
*/
@@ -13,7 +13,13 @@ typedef struct {
mcpwm_cmpr_handle_t cmpr;
} mcpwm_comparator_etm_event_t;
static esp_err_t mcpwm_del_etm_event(esp_etm_event_t *event)
typedef struct {
esp_etm_event_t base;
mcpwm_timer_handle_t timer;
mcpwm_timer_etm_event_type_t event_type;
} mcpwm_timer_etm_event_t;
static esp_err_t mcpwm_del_comparator_etm_event(esp_etm_event_t *event)
{
mcpwm_comparator_etm_event_t *etm_event = __containerof(event, mcpwm_comparator_etm_event_t, base);
mcpwm_cmpr_handle_t cmpr = etm_event->cmpr;
@@ -39,11 +45,27 @@ static esp_err_t mcpwm_del_etm_event(esp_etm_event_t *event)
return ESP_OK;
}
static esp_err_t mcpwm_del_timer_etm_event(esp_etm_event_t *event)
{
mcpwm_timer_etm_event_t *etm_event = __containerof(event, mcpwm_timer_etm_event_t, base);
mcpwm_timer_handle_t timer = etm_event->timer;
mcpwm_group_t *group = timer->group;
mcpwm_hal_context_t *hal = &group->hal;
int timer_id = timer->timer_id;
portENTER_CRITICAL(&group->spinlock);
mcpwm_ll_etm_enable_timer_event(hal->dev, timer_id, etm_event->event_type, false);
portEXIT_CRITICAL(&group->spinlock);
free(etm_event);
return ESP_OK;
}
esp_err_t mcpwm_comparator_new_etm_event(mcpwm_cmpr_handle_t cmpr, const mcpwm_cmpr_etm_event_config_t *config, esp_etm_event_handle_t *out_event)
{
esp_err_t ret = ESP_OK;
mcpwm_comparator_etm_event_t *event = NULL;
ESP_RETURN_ON_FALSE(cmpr && config && out_event, ESP_ERR_INVALID_ARG, TAG, "invalid argument");
ESP_RETURN_ON_FALSE(config->event_type < MCPWM_CMPR_ETM_EVENT_MAX, ESP_ERR_INVALID_ARG, TAG, "invalid event type");
event = heap_caps_calloc(1, sizeof(mcpwm_comparator_etm_event_t), MCPWM_MEM_ALLOC_CAPS);
ESP_RETURN_ON_FALSE(event, ESP_ERR_NO_MEM, TAG, "no memory for ETM event");
@@ -78,14 +100,53 @@ esp_err_t mcpwm_comparator_new_etm_event(mcpwm_cmpr_handle_t cmpr, const mcpwm_c
event->cmpr = cmpr;
event->base.event_id = event_id;
event->base.trig_periph = ETM_TRIG_PERIPH_MCPWM;
event->base.del = mcpwm_del_etm_event;
event->base.del = mcpwm_del_comparator_etm_event;
*out_event = &event->base;
return ESP_OK;
err:
if (event) {
mcpwm_del_etm_event(&event->base);
mcpwm_del_comparator_etm_event(&event->base);
}
return ret;
}
esp_err_t mcpwm_timer_new_etm_event(mcpwm_timer_handle_t timer, const mcpwm_timer_etm_event_config_t *config, esp_etm_event_handle_t *out_event)
{
esp_err_t ret = ESP_OK;
mcpwm_timer_etm_event_t *event = NULL;
ESP_RETURN_ON_FALSE(timer && config && out_event, ESP_ERR_INVALID_ARG, TAG, "invalid argument");
ESP_RETURN_ON_FALSE(config->event_type < MCPWM_TIMER_ETM_EVENT_MAX, ESP_ERR_INVALID_ARG, TAG, "invalid event type");
event = heap_caps_calloc(1, sizeof(mcpwm_timer_etm_event_t), MCPWM_MEM_ALLOC_CAPS);
ESP_RETURN_ON_FALSE(event, ESP_ERR_NO_MEM, TAG, "no memory for ETM event");
mcpwm_group_t *group = timer->group;
mcpwm_hal_context_t *hal = &group->hal;
int group_id = group->group_id;
int timer_id = timer->timer_id;
uint32_t event_id = 0;
portENTER_CRITICAL(&group->spinlock);
mcpwm_ll_etm_enable_timer_event(hal->dev, timer_id, config->event_type, true);
portEXIT_CRITICAL(&group->spinlock);
event_id = MCPWM_LL_TIMER_ETM_EVENT_TABLE(group_id, timer_id, config->event_type);
event->event_type = config->event_type;
ESP_GOTO_ON_FALSE(event_id != 0, ESP_ERR_NOT_SUPPORTED, err, TAG, "not supported event type");
ESP_LOGD(TAG, "MCPWM (%d) timer (%d) event_id (%"PRId32")", group_id, timer_id, event_id);
// fill the ETM event object
event->timer = timer;
event->base.event_id = event_id;
event->base.trig_periph = ETM_TRIG_PERIPH_MCPWM;
event->base.del = mcpwm_del_timer_etm_event;
*out_event = &event->base;
return ESP_OK;
err:
if (event) {
mcpwm_del_timer_etm_event(&event->base);
}
return ret;
}
@@ -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));
}
@@ -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
*/
@@ -10,6 +10,7 @@
#include <stdbool.h>
#include "soc/soc_caps.h"
#include "soc/mcpwm_struct.h"
#include "soc/mcpwm_reg.h"
#include "soc/clk_tree_defs.h"
#include "soc/pcr_struct.h"
#include "hal/mcpwm_types.h"
@@ -69,9 +70,16 @@ extern "C" {
#define MCPWM_LL_GEN_ACTION_TO_REG_CAL(action) ((uint8_t[]) {0, 1, 2, 3}[(action)])
#define MCPWM_LL_BRAKE_MODE_TO_REG_VAL(mode) ((uint8_t[]) {0, 1}[(mode)])
// MCPWM ETM timer event table
#define MCPWM_LL_TIMER_ETM_EVENT_TABLE(group, timer_id, event) \
(uint32_t[1][MCPWM_TIMER_ETM_EVENT_MAX]){{ \
[MCPWM_TIMER_ETM_EVENT_TEZ] = MCPWM0_EVT_TIMER0_TEZ + timer_id, \
[MCPWM_TIMER_ETM_EVENT_TEP] = MCPWM0_EVT_TIMER0_TEP + timer_id, \
}}[group][event]
// MCPWM ETM comparator event table
#define MCPWM_LL_ETM_COMPARATOR_EVENT_TABLE(group, oper_id, cmpr_id, event) \
(uint32_t[2][MCPWM_CMPR_ETM_EVENT_MAX]){ \
(uint32_t[1][MCPWM_CMPR_ETM_EVENT_MAX]){ \
{ \
[MCPWM_CMPR_ETM_EVENT_EQUAL] = MCPWM0_EVT_OP0_TEA + oper_id + 3 * cmpr_id, \
}, \
@@ -79,7 +87,7 @@ extern "C" {
// MCPWM ETM event comparator event table
#define MCPWM_LL_ETM_EVENT_COMPARATOR_EVENT_TABLE(group, oper_id, cmpr_id, event) \
(uint32_t[2][MCPWM_CMPR_ETM_EVENT_MAX]){ \
(uint32_t[1][MCPWM_CMPR_ETM_EVENT_MAX]){ \
{ \
[MCPWM_CMPR_ETM_EVENT_EQUAL] = MCPWM0_EVT_OP0_TEE1 + oper_id + 3 * cmpr_id, \
}, \
@@ -1699,6 +1707,29 @@ static inline void mcpwm_ll_etm_enable_evt_comparator_event(mcpwm_dev_t *mcpwm,
}
}
/**
* @brief Enable timer ETM event
*
* @param mcpwm Peripheral instance address
* @param timer_id Timer ID, index from 0 to 2
* @param event_type Timer ETM event type (TEZ or TEP)
* @param en True: enable ETM module, False: disable ETM module
*/
static inline void mcpwm_ll_etm_enable_timer_event(mcpwm_dev_t *mcpwm, int timer_id, mcpwm_timer_etm_event_type_t event_type, bool en)
{
uint32_t bit_offset;
if (event_type == MCPWM_TIMER_ETM_EVENT_TEZ) {
bit_offset = timer_id + MCPWM_EVT_TIMER0_TEZ_EN_S;
} else { // MCPWM_TIMER_ETM_EVENT_TEP
bit_offset = timer_id + MCPWM_EVT_TIMER0_TEP_EN_S;
}
if (en) {
mcpwm->evt_en.val |= 1 << bit_offset;
} else {
mcpwm->evt_en.val &= ~(1 << bit_offset);
}
}
#ifdef __cplusplus
}
#endif
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -17,6 +17,7 @@
#include <stdbool.h>
#include "soc/soc_caps.h"
#include "soc/mcpwm_struct.h"
#include "soc/mcpwm_reg.h"
#include "soc/clk_tree_defs.h"
#include "soc/pcr_struct.h"
#include "hal/mcpwm_types.h"
@@ -75,6 +76,13 @@ extern "C" {
#define MCPWM_LL_GEN_ACTION_TO_REG_CAL(action) ((uint8_t[]) {0, 1, 2, 3}[(action)])
#define MCPWM_LL_BRAKE_MODE_TO_REG_VAL(mode) ((uint8_t[]) {0, 1}[(mode)])
// MCPWM ETM timer event table
#define MCPWM_LL_TIMER_ETM_EVENT_TABLE(group, timer_id, event) \
(uint32_t[1][MCPWM_TIMER_ETM_EVENT_MAX]){{ \
[MCPWM_TIMER_ETM_EVENT_TEZ] = MCPWM_EVT_TIMER0_TEZ + timer_id, \
[MCPWM_TIMER_ETM_EVENT_TEP] = MCPWM_EVT_TIMER0_TEP + timer_id, \
}}[group][event]
// MCPWM ETM comparator event table
#define MCPWM_LL_ETM_COMPARATOR_EVENT_TABLE(group, oper_id, cmpr_id, event) \
(uint32_t [1][MCPWM_CMPR_ETM_EVENT_MAX]){{ \
@@ -1659,6 +1667,29 @@ static inline void mcpwm_ll_etm_enable_comparator_event(mcpwm_dev_t *mcpwm, int
}
}
/**
* @brief Enable timer ETM event
*
* @param mcpwm Peripheral instance address
* @param timer_id Timer ID, index from 0 to 2
* @param event_type Timer ETM event type (TEZ or TEP)
* @param en True: enable ETM module, False: disable ETM module
*/
static inline void mcpwm_ll_etm_enable_timer_event(mcpwm_dev_t *mcpwm, int timer_id, mcpwm_timer_etm_event_type_t event_type, bool en)
{
uint32_t bit_offset;
if (event_type == MCPWM_TIMER_ETM_EVENT_TEZ) {
bit_offset = timer_id + MCPWM_EVT_TIMER0_TEZ_EN_S;
} else { // MCPWM_TIMER_ETM_EVENT_TEP
bit_offset = timer_id + MCPWM_EVT_TIMER0_TEP_EN_S;
}
if (en) {
mcpwm->evt_en.val |= 1 << bit_offset;
} else {
mcpwm->evt_en.val &= ~(1 << bit_offset);
}
}
#ifdef __cplusplus
}
#endif
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -15,6 +15,7 @@
#include <stdbool.h>
#include "soc/soc_caps.h"
#include "soc/mcpwm_struct.h"
#include "soc/mcpwm_reg.h"
#include "soc/clk_tree_defs.h"
#include "soc/pcr_struct.h"
#include "hal/mcpwm_types.h"
@@ -73,6 +74,13 @@ extern "C" {
#define MCPWM_LL_GEN_ACTION_TO_REG_CAL(action) ((uint8_t[]) {0, 1, 2, 3}[(action)])
#define MCPWM_LL_BRAKE_MODE_TO_REG_VAL(mode) ((uint8_t[]) {0, 1}[(mode)])
// MCPWM ETM timer event table
#define MCPWM_LL_TIMER_ETM_EVENT_TABLE(group, timer_id, event) \
(uint32_t[1][MCPWM_TIMER_ETM_EVENT_MAX]){{ \
[MCPWM_TIMER_ETM_EVENT_TEZ] = MCPWM_EVT_TIMER0_TEZ + timer_id, \
[MCPWM_TIMER_ETM_EVENT_TEP] = MCPWM_EVT_TIMER0_TEP + timer_id, \
}}[group][event]
// MCPWM ETM comparator event table
#define MCPWM_LL_ETM_COMPARATOR_EVENT_TABLE(group, oper_id, cmpr_id, event) \
(uint32_t [1][MCPWM_CMPR_ETM_EVENT_MAX]){{ \
@@ -1657,6 +1665,29 @@ static inline void mcpwm_ll_etm_enable_comparator_event(mcpwm_dev_t *mcpwm, int
}
}
/**
* @brief Enable timer ETM event
*
* @param mcpwm Peripheral instance address
* @param timer_id Timer ID, index from 0 to 2
* @param event_type Timer ETM event type (TEZ or TEP)
* @param en True: enable ETM module, False: disable ETM module
*/
static inline void mcpwm_ll_etm_enable_timer_event(mcpwm_dev_t *mcpwm, int timer_id, mcpwm_timer_etm_event_type_t event_type, bool en)
{
uint32_t bit_offset;
if (event_type == MCPWM_TIMER_ETM_EVENT_TEZ) {
bit_offset = timer_id + MCPWM_EVT_TIMER0_TEZ_EN_S;
} else { // MCPWM_TIMER_ETM_EVENT_TEP
bit_offset = timer_id + MCPWM_EVT_TIMER0_TEP_EN_S;
}
if (en) {
mcpwm->evt_en.val |= 1 << bit_offset;
} else {
mcpwm->evt_en.val &= ~(1 << bit_offset);
}
}
#ifdef __cplusplus
}
#endif
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2025-2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -10,6 +10,7 @@
#include <stdbool.h>
#include "soc/soc_caps.h"
#include "soc/mcpwm_struct.h"
#include "soc/mcpwm_reg.h"
#include "soc/clk_tree_defs.h"
#include "soc/pcr_struct.h"
#include "hal/mcpwm_types.h"
@@ -69,12 +70,28 @@ extern "C" {
#define MCPWM_LL_GEN_ACTION_TO_REG_CAL(action) ((uint8_t[]) {0, 1, 2, 3}[(action)])
#define MCPWM_LL_BRAKE_MODE_TO_REG_VAL(mode) ((uint8_t[]) {0, 1}[(mode)])
// MCPWM ETM timer event table
#define MCPWM_LL_TIMER_ETM_EVENT_TABLE(group, timer_id, event) \
(uint32_t[2][MCPWM_TIMER_ETM_EVENT_MAX]){ \
{ \
[MCPWM_TIMER_ETM_EVENT_TEZ] = MCPWM0_EVT_TIMER0_TEZ + timer_id, \
[MCPWM_TIMER_ETM_EVENT_TEP] = MCPWM0_EVT_TIMER0_TEP + timer_id, \
}, \
{ \
[MCPWM_TIMER_ETM_EVENT_TEZ] = MCPWM1_EVT_TIMER0_TEZ + timer_id, \
[MCPWM_TIMER_ETM_EVENT_TEP] = MCPWM1_EVT_TIMER0_TEP + timer_id, \
}, \
}[group][event]
// MCPWM ETM comparator event table
#define MCPWM_LL_ETM_COMPARATOR_EVENT_TABLE(group, oper_id, cmpr_id, event) \
(uint32_t[2][MCPWM_CMPR_ETM_EVENT_MAX]){ \
{ \
[MCPWM_CMPR_ETM_EVENT_EQUAL] = MCPWM0_EVT_OP0_TEA + oper_id + 3 * cmpr_id, \
}, \
{ \
[MCPWM_CMPR_ETM_EVENT_EQUAL] = MCPWM1_EVT_OP0_TEA + oper_id + 3 * cmpr_id, \
}, \
}[group][event]
// MCPWM ETM event comparator event table
@@ -82,7 +99,10 @@ extern "C" {
(uint32_t[2][MCPWM_CMPR_ETM_EVENT_MAX]){ \
{ \
[MCPWM_CMPR_ETM_EVENT_EQUAL] = MCPWM0_EVT_OP0_TEE1 + oper_id + 3 * cmpr_id, \
}, \
}, \
{ \
[MCPWM_CMPR_ETM_EVENT_EQUAL] = MCPWM1_EVT_OP0_TEE1 + oper_id + 3 * cmpr_id, \
}, \
}[group][event]
/**
@@ -1717,6 +1737,29 @@ static inline void mcpwm_ll_etm_enable_evt_comparator_event(mcpwm_dev_t *mcpwm,
}
}
/**
* @brief Enable timer ETM event
*
* @param mcpwm Peripheral instance address
* @param timer_id Timer ID, index from 0 to 2
* @param event_type Timer ETM event type (TEZ or TEP)
* @param en True: enable ETM module, False: disable ETM module
*/
static inline void mcpwm_ll_etm_enable_timer_event(mcpwm_dev_t *mcpwm, int timer_id, mcpwm_timer_etm_event_type_t event_type, bool en)
{
uint32_t bit_offset;
if (event_type == MCPWM_TIMER_ETM_EVENT_TEZ) {
bit_offset = timer_id + MCPWM_EVT_TIMER0_TEZ_EN_S;
} else { // MCPWM_TIMER_ETM_EVENT_TEP
bit_offset = timer_id + MCPWM_EVT_TIMER0_TEP_EN_S;
}
if (en) {
mcpwm->evt_en.val |= 1 << bit_offset;
} else {
mcpwm->evt_en.val &= ~(1 << bit_offset);
}
}
#ifdef __cplusplus
}
#endif
@@ -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
*/
@@ -18,6 +18,7 @@
#include <stdio.h>
#include "soc/soc_caps.h"
#include "soc/mcpwm_struct.h"
#include "soc/mcpwm_reg.h"
#include "soc/clk_tree_defs.h"
#include "soc/hp_sys_clkrst_struct.h"
#include "hal/mcpwm_types.h"
@@ -77,6 +78,18 @@ extern "C" {
#define MCPWM_LL_GEN_ACTION_TO_REG_CAL(action) ((uint8_t[]) {0, 1, 2, 3}[(action)])
#define MCPWM_LL_BRAKE_MODE_TO_REG_VAL(mode) ((uint8_t[]) {0, 1}[(mode)])
#define MCPWM_LL_TIMER_ETM_EVENT_TABLE(group, timer_id, event) \
(uint32_t[2][MCPWM_TIMER_ETM_EVENT_MAX]){ \
{ \
[MCPWM_TIMER_ETM_EVENT_TEZ] = MCPWM0_EVT_TIMER0_TEZ + timer_id, \
[MCPWM_TIMER_ETM_EVENT_TEP] = MCPWM0_EVT_TIMER0_TEP + timer_id, \
}, \
{ \
[MCPWM_TIMER_ETM_EVENT_TEZ] = MCPWM1_EVT_TIMER0_TEZ + timer_id, \
[MCPWM_TIMER_ETM_EVENT_TEP] = MCPWM1_EVT_TIMER0_TEP + timer_id, \
}, \
}[group][event]
// MCPWM ETM comparator event table
#define MCPWM_LL_ETM_COMPARATOR_EVENT_TABLE(group, oper_id, cmpr_id, event) \
(uint32_t[2][MCPWM_CMPR_ETM_EVENT_MAX]){ \
@@ -1764,6 +1777,29 @@ static inline void mcpwm_ll_etm_enable_evt_comparator_event(mcpwm_dev_t *mcpwm,
}
}
/**
* @brief Enable timer ETM event
*
* @param mcpwm Peripheral instance address
* @param timer_id Timer ID, index from 0 to 2
* @param event_type Timer ETM event type (TEZ or TEP)
* @param en True: enable ETM module, False: disable ETM module
*/
static inline void mcpwm_ll_etm_enable_timer_event(mcpwm_dev_t *mcpwm, int timer_id, mcpwm_timer_etm_event_type_t event_type, bool en)
{
uint32_t bit_offset;
if (event_type == MCPWM_TIMER_ETM_EVENT_TEZ) {
bit_offset = timer_id + MCPWM_EVT_TIMER0_TEZ_EN_S; // TEZ events start at bit 3
} else { // MCPWM_TIMER_ETM_EVENT_TEP
bit_offset = timer_id + MCPWM_EVT_TIMER0_TEP_EN_S; // TEP events start at bit 6
}
if (en) {
mcpwm->evt_en.val |= 1 << bit_offset;
} else {
mcpwm->evt_en.val &= ~(1 << bit_offset);
}
}
#ifdef __cplusplus
}
#endif
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2015-2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -105,6 +105,15 @@ typedef enum {
MCPWM_CAP_EDGE_NEG, /*!< Capture on the negative edge */
} mcpwm_capture_edge_t;
/**
* @brief MCPWM timer specific events that supported by the ETM module
*/
typedef enum {
MCPWM_TIMER_ETM_EVENT_TEZ, /*!< The timer reaches zero */
MCPWM_TIMER_ETM_EVENT_TEP, /*!< The timer reaches peak */
MCPWM_TIMER_ETM_EVENT_MAX, /*!< Maximum number of timer events */
} mcpwm_timer_etm_event_type_t;
/**
* @brief MCPWM comparator specific events that supported by the ETM module
*/
+2 -2
View File
@@ -960,9 +960,9 @@ If you don't want to process the captured value in the capture event callback fu
ETM Event and Task
^^^^^^^^^^^^^^^^^^
MCPWM comparator is able to generate events that can interact with the :doc:`ETM </api-reference/peripherals/etm>` module. The supported events are listed in the :cpp:type:`mcpwm_comparator_etm_event_type_t`. You can call :cpp:func:`mcpwm_comparator_new_etm_event` to get the corresponding ETM event handle.
MCPWM timer and comparator can generate events that can be connected to the :doc:`ETM </api-reference/peripherals/etm>` module. The event types for the timer and comparator are listed in :cpp:type:`mcpwm_timer_etm_event_type_t` and :cpp:type:`mcpwm_comparator_etm_event_type_t` respectively. You can get the ETM event handle by calling :cpp:func:`mcpwm_timer_new_etm_event` or :cpp:func:`mcpwm_comparator_new_etm_event`.
For how to connect the event and task to an ETM channel, please refer to the :doc:`ETM </api-reference/peripherals/etm>` documentation.
For how to connect the MCPWM events to an ETM channel, please refer to the :doc:`ETM </api-reference/peripherals/etm>` documentation.
.. _mcpwm-power-management:
@@ -960,9 +960,9 @@ MCPWM 捕获通道支持在信号上检测到有效边沿时发送通知。须
ETM 事件与任务
^^^^^^^^^^^^^^^^^^
MCPWM 比较器可以产生事件,这些事件可以连接到 :doc:`ETM </api-reference/peripherals/etm>` 模块。:cpp:type:`mcpwm_comparator_etm_event_type_t` 中列出了 MCPWM 比较器能够产生的事件类型。用户可以通过调用 :cpp:func:`mcpwm_comparator_new_etm_event` 来获得相应事件的 ETM event 句柄。
MCPWM 的定时器和比较器可以产生事件,这些事件可以连接到 :doc:`ETM </api-reference/peripherals/etm>` 模块。:cpp:type:`mcpwm_timer_etm_event_type_t`:cpp:type:`mcpwm_comparator_etm_event_type_t`分别列出了 MCPWM 定时器和比较器能够产生的事件类型。用户可以通过调用 :cpp:func:`mcpwm_timer_new_etm_event` :cpp:func:`mcpwm_comparator_new_etm_event` 来获得相应事件的 ETM event 句柄。
关于如何将 MCPWM 比较器事件连接到 ETM 通道中,请参阅 :doc:`ETM </api-reference/peripherals/etm>` 文档。
关于如何将 MCPWM 事件连接到 ETM 通道中,请参阅 :doc:`ETM </api-reference/peripherals/etm>` 文档。
.. _mcpwm-power-management: