mirror of
https://github.com/espressif/esp-idf.git
synced 2026-04-27 11:03:11 +00:00
feat(mcpwm): ETM support mcpwm timer TEZ/TEP events
This commit is contained in:
@@ -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 {
|
||||
|
||||
@@ -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
|
||||
*/
|
||||
|
||||
@@ -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:
|
||||
|
||||
|
||||
Reference in New Issue
Block a user