Merge branch 'refactor/etm_driver_soc_caps' into 'master'

refactor(etm): clean up soc macros && enhance thread safety

Closes IDF-13634

See merge request espressif/esp-idf!41201
This commit is contained in:
morris
2025-08-21 10:19:19 +08:00
44 changed files with 250 additions and 283 deletions

View File

@@ -8,11 +8,6 @@
#include <string.h> #include <string.h>
#include <sys/cdefs.h> #include <sys/cdefs.h>
#include "sdkconfig.h" #include "sdkconfig.h"
#if CONFIG_ETM_ENABLE_DEBUG_LOG
// The local log level must be defined before including esp_log.h
// Set the maximum log level for this source file
#define LOG_LOCAL_LEVEL ESP_LOG_DEBUG
#endif
#include "freertos/FreeRTOS.h" #include "freertos/FreeRTOS.h"
#include "driver/gpio.h" #include "driver/gpio.h"
#include "driver/gpio_etm.h" #include "driver/gpio_etm.h"
@@ -151,9 +146,6 @@ static esp_err_t gpio_del_etm_task(esp_etm_task_t *task)
esp_err_t gpio_new_etm_event(const gpio_etm_event_config_t *config, esp_etm_event_handle_t *ret_event, ...) esp_err_t gpio_new_etm_event(const gpio_etm_event_config_t *config, esp_etm_event_handle_t *ret_event, ...)
{ {
#if CONFIG_ETM_ENABLE_DEBUG_LOG
esp_log_level_set(TAG, ESP_LOG_DEBUG);
#endif
esp_err_t ret = ESP_OK; esp_err_t ret = ESP_OK;
int chan_id = -1; int chan_id = -1;
uint8_t event_mask = 0; uint8_t event_mask = 0;
@@ -243,9 +235,6 @@ err:
esp_err_t gpio_new_etm_task(const gpio_etm_task_config_t *config, esp_etm_task_handle_t *ret_task, ...) esp_err_t gpio_new_etm_task(const gpio_etm_task_config_t *config, esp_etm_task_handle_t *ret_task, ...)
{ {
#if CONFIG_ETM_ENABLE_DEBUG_LOG
esp_log_level_set(TAG, ESP_LOG_DEBUG);
#endif
esp_err_t ret = ESP_OK; esp_err_t ret = ESP_OK;
int chan_id = -1; int chan_id = -1;
uint8_t task_mask = 0; uint8_t task_mask = 0;

View File

@@ -126,7 +126,7 @@ static sdm_group_t *sdm_acquire_group_handle(int group_id, sdm_clock_source_t cl
group->clk_src = clk_src; group->clk_src = clk_src;
#if SDM_USE_RETENTION_LINK #if SDM_USE_RETENTION_LINK
sleep_retention_module_t module = soc_sdm_retention_infos[group->group_id].module; sleep_retention_module_t module = soc_sdm_retention_infos[group_id].module;
sleep_retention_module_init_param_t init_param = { sleep_retention_module_init_param_t init_param = {
.cbs = { .cbs = {
.create = { .create = {
@@ -138,7 +138,7 @@ static sdm_group_t *sdm_acquire_group_handle(int group_id, sdm_clock_source_t cl
}; };
// retention module init must be called BEFORE the hal init // retention module init must be called BEFORE the hal init
if (sleep_retention_module_init(module, &init_param) != ESP_OK) { if (sleep_retention_module_init(module, &init_param) != ESP_OK) {
ESP_LOGW(TAG, "init sleep retention failed on SDM Group%d, power domain may be turned off during sleep", group->group_id); ESP_LOGW(TAG, "init sleep retention failed on SDM Group%d, power domain may be turned off during sleep", group_id);
} }
#endif // SDM_USE_RETENTION_LINK #endif // SDM_USE_RETENTION_LINK
@@ -408,7 +408,7 @@ esp_err_t sdm_channel_set_pulse_density(sdm_channel_handle_t chan, int8_t densit
bool valid_state = false; bool valid_state = false;
sdm_fsm_t expected_fsm = SDM_FSM_INIT; sdm_fsm_t expected_fsm = SDM_FSM_INIT;
sdm_fsm_t restore_fsm = SDM_FSM_INIT; sdm_fsm_t restore_fsm = SDM_FSM_INIT;
// check if the channel is in INIT state, if so, change it to WAIT state // this function can be called only when the channel is in init or enable state
if (atomic_compare_exchange_strong(&chan->fsm, &expected_fsm, SDM_FSM_WAIT)) { if (atomic_compare_exchange_strong(&chan->fsm, &expected_fsm, SDM_FSM_WAIT)) {
valid_state = true; valid_state = true;
restore_fsm = SDM_FSM_INIT; restore_fsm = SDM_FSM_INIT;
@@ -430,7 +430,8 @@ esp_err_t sdm_channel_set_pulse_density(sdm_channel_handle_t chan, int8_t densit
sdm_ll_set_pulse_density(group->hal.dev, chan_id, density); sdm_ll_set_pulse_density(group->hal.dev, chan_id, density);
portEXIT_CRITICAL_SAFE(&chan->spinlock); portEXIT_CRITICAL_SAFE(&chan->spinlock);
atomic_store(&chan->fsm, restore_fsm); // restore the state // restore the state
atomic_store(&chan->fsm, restore_fsm);
return ESP_OK; return ESP_OK;
} }

View File

@@ -12,11 +12,6 @@
#include "hal/temperature_sensor_ll.h" #include "hal/temperature_sensor_ll.h"
#include "driver/temperature_sensor_etm.h" #include "driver/temperature_sensor_etm.h"
#include "esp_heap_caps.h" #include "esp_heap_caps.h"
#if CONFIG_ETM_ENABLE_DEBUG_LOG
// The local log level must be defined before including esp_log.h
// Set the maximum log level for this source file
#define LOG_LOCAL_LEVEL ESP_LOG_DEBUG
#endif
#include "esp_log.h" #include "esp_log.h"
#define ETM_MEM_ALLOC_CAPS MALLOC_CAP_DEFAULT #define ETM_MEM_ALLOC_CAPS MALLOC_CAP_DEFAULT
@@ -37,9 +32,6 @@ static esp_err_t temperature_sensor_del_etm_task(esp_etm_task_t *task)
esp_err_t temperature_sensor_new_etm_event(temperature_sensor_handle_t tsens, const temperature_sensor_etm_event_config_t *config, esp_etm_event_handle_t *out_event) esp_err_t temperature_sensor_new_etm_event(temperature_sensor_handle_t tsens, const temperature_sensor_etm_event_config_t *config, esp_etm_event_handle_t *out_event)
{ {
#if CONFIG_ETM_ENABLE_DEBUG_LOG
esp_log_level_set(TAG, ESP_LOG_DEBUG);
#endif
esp_etm_event_t *event = NULL; esp_etm_event_t *event = NULL;
esp_err_t ret = ESP_OK; esp_err_t ret = ESP_OK;
ESP_GOTO_ON_FALSE(tsens && config && out_event, ESP_ERR_INVALID_ARG, err, TAG, "invalid argument"); ESP_GOTO_ON_FALSE(tsens && config && out_event, ESP_ERR_INVALID_ARG, err, TAG, "invalid argument");
@@ -67,9 +59,6 @@ err:
esp_err_t temperature_sensor_new_etm_task(temperature_sensor_handle_t tsens, const temperature_sensor_etm_task_config_t *config, esp_etm_task_handle_t *out_task) esp_err_t temperature_sensor_new_etm_task(temperature_sensor_handle_t tsens, const temperature_sensor_etm_task_config_t *config, esp_etm_task_handle_t *out_task)
{ {
#if CONFIG_ETM_ENABLE_DEBUG_LOG
esp_log_level_set(TAG, ESP_LOG_DEBUG);
#endif
esp_etm_task_t *task = NULL; esp_etm_task_t *task = NULL;
esp_err_t ret = ESP_OK; esp_err_t ret = ESP_OK;
ESP_GOTO_ON_FALSE(tsens && config && out_task, ESP_ERR_INVALID_ARG, err, TAG, "invalid argument"); ESP_GOTO_ON_FALSE(tsens && config && out_task, ESP_ERR_INVALID_ARG, err, TAG, "invalid argument");

View File

@@ -5,7 +5,7 @@ idf_build_get_property(non_os_build NON_OS_BUILD)
if(${target} STREQUAL "linux") if(${target} STREQUAL "linux")
idf_component_register(SRCS "port/linux/esp_random.c" idf_component_register(SRCS "port/linux/esp_random.c"
"port/linux/chip_info.c" "port/linux/chip_info.c"
INCLUDE_DIRS "include") INCLUDE_DIRS "include" "etm/include")
return() return()
endif() endif()
@@ -122,7 +122,7 @@ if(NOT non_os_build)
endif() endif()
if(CONFIG_SOC_ETM_SUPPORTED) if(CONFIG_SOC_ETM_SUPPORTED)
list(APPEND srcs "esp_etm.c") list(APPEND srcs "etm/esp_etm.c")
endif() endif()
if(CONFIG_SOC_PAU_SUPPORTED) if(CONFIG_SOC_PAU_SUPPORTED)
@@ -175,7 +175,7 @@ else()
endif() endif()
set(public_include_dirs "include" "include/soc" set(public_include_dirs "include" "include/soc"
"dma/include" "ldo/include" "debug_probe/include" "dma/include" "ldo/include" "debug_probe/include" "etm/include"
"mspi_timing_tuning/include" "mspi_timing_tuning/tuning_scheme_impl/include" "mspi_timing_tuning/include" "mspi_timing_tuning/tuning_scheme_impl/include"
"power_supply/include") "power_supply/include")

View File

@@ -238,17 +238,8 @@ menu "Hardware Settings"
so that these functions can be IRAM-safe and able to be called in the other IRAM interrupt context. so that these functions can be IRAM-safe and able to be called in the other IRAM interrupt context.
endmenu endmenu
menu "ETM Configuration"
depends on SOC_ETM_SUPPORTED
config ETM_ENABLE_DEBUG_LOG
bool "Enable debug log"
default n
help
whether to enable the debug log message for ETM core driver.
Note that, this option only controls the ETM related driver log, won't affect other drivers.
endmenu # ETM Configuration
rsource "./dma/Kconfig.dma" rsource "./dma/Kconfig.dma"
rsource "./etm/Kconfig.etm"
menu "Main XTAL Config" menu "Main XTAL Config"
orsource "./port/$IDF_TARGET/Kconfig.xtal" orsource "./port/$IDF_TARGET/Kconfig.xtal"

View File

@@ -0,0 +1,12 @@
menu "Event Task Matrix (ETM) Configurations"
depends on SOC_ETM_SUPPORTED
config ETM_ENABLE_DEBUG_LOG
bool "Force enable debug log"
default n
help
If enabled, ETM driver will:
1. ignore the global logging settings
2. compile all log messages into the binary
3. set the runtime log level to VERBOSE
Please enable this option by caution, as it will increase the binary size.
endmenu # ETM Configuration

View File

@@ -5,17 +5,17 @@
*/ */
#include <stdlib.h> #include <stdlib.h>
#include <stdatomic.h>
#include <sys/cdefs.h> #include <sys/cdefs.h>
#include <sys/lock.h> #include <sys/lock.h>
#include "sdkconfig.h" #include "sdkconfig.h"
#if CONFIG_ETM_ENABLE_DEBUG_LOG #if CONFIG_ETM_ENABLE_DEBUG_LOG
// The local log level must be defined before including esp_log.h // The local log level must be defined before including esp_log.h
// Set the maximum log level for this source file // Set the maximum log level for this source file
#define LOG_LOCAL_LEVEL ESP_LOG_DEBUG #define LOG_LOCAL_LEVEL ESP_LOG_VERBOSE
#endif #endif
#include "freertos/FreeRTOS.h" #include "freertos/FreeRTOS.h"
#include "freertos/task.h" #include "freertos/task.h"
#include "soc/soc_caps.h"
#include "soc/etm_periph.h" #include "soc/etm_periph.h"
#include "esp_log.h" #include "esp_log.h"
#include "esp_check.h" #include "esp_check.h"
@@ -39,7 +39,7 @@
#define ETM_RCC_ATOMIC() #define ETM_RCC_ATOMIC()
#endif #endif
static const char *TAG = "etm"; #define TAG "etm"
typedef struct etm_platform_t etm_platform_t; typedef struct etm_platform_t etm_platform_t;
typedef struct etm_group_t etm_group_t; typedef struct etm_group_t etm_group_t;
@@ -47,26 +47,27 @@ typedef struct esp_etm_channel_t esp_etm_channel_t;
struct etm_platform_t { struct etm_platform_t {
_lock_t mutex; // platform level mutex lock _lock_t mutex; // platform level mutex lock
etm_group_t *groups[SOC_ETM_GROUPS]; // etm group pool etm_group_t *groups[SOC_ETM_ATTR(INST_NUM)]; // etm group pool
int group_ref_counts[SOC_ETM_GROUPS]; // reference count used to protect group install/uninstall int group_ref_counts[SOC_ETM_ATTR(INST_NUM)]; // reference count used to protect group install/uninstall
}; };
struct etm_group_t { struct etm_group_t {
int group_id; // hardware group id int group_id; // hardware group id
etm_hal_context_t hal; // hardware abstraction layer context etm_hal_context_t hal; // hardware abstraction layer context
portMUX_TYPE spinlock; // to protect per-group register level concurrent access portMUX_TYPE spinlock; // to protect per-group light weight resource access
esp_etm_channel_t *chans[SOC_ETM_CHANNELS_PER_GROUP]; esp_etm_channel_t *chans[SOC_ETM_ATTR(CHANS_PER_INST)]; // array of channels in the group
}; };
typedef enum { typedef enum {
ETM_CHAN_FSM_INIT, ETM_CHAN_FSM_INIT,
ETM_CHAN_FSM_ENABLE, ETM_CHAN_FSM_ENABLE,
ETM_CHAN_FSM_WAIT,
} etm_chan_fsm_t; } etm_chan_fsm_t;
struct esp_etm_channel_t { struct esp_etm_channel_t {
int chan_id; // Channel ID int chan_id; // Channel ID
etm_group_t *group; // which group this channel belongs to etm_group_t *group; // which group this channel belongs to
etm_chan_fsm_t fsm; // record ETM channel's driver state _Atomic etm_chan_fsm_t fsm; // record ETM channel's driver state
esp_etm_event_handle_t event; // which event is connect to the channel esp_etm_event_handle_t event; // which event is connect to the channel
esp_etm_task_handle_t task; // which task is connect to the channel esp_etm_task_handle_t task; // which task is connect to the channel
}; };
@@ -79,21 +80,21 @@ static esp_err_t etm_create_sleep_retention_link_cb(void *arg)
{ {
etm_group_t *group = (etm_group_t *)arg; etm_group_t *group = (etm_group_t *)arg;
int group_id = group->group_id; int group_id = group->group_id;
esp_err_t err = sleep_retention_entries_create(etm_reg_retention_info[group_id].regdma_entry_array, esp_err_t err = sleep_retention_entries_create(soc_etm_retention_info[group_id].regdma_entry_array,
etm_reg_retention_info[group_id].array_size, soc_etm_retention_info[group_id].array_size,
REGDMA_LINK_PRI_ETM, etm_reg_retention_info[group_id].module); REGDMA_LINK_PRI_ETM, soc_etm_retention_info[group_id].module);
return err; return err;
} }
static void etm_create_retention_module(etm_group_t *group) static void etm_create_retention_module(etm_group_t *group)
{ {
int group_id = group->group_id; int group_id = group->group_id;
sleep_retention_module_t module = etm_reg_retention_info[group_id].module; sleep_retention_module_t module = soc_etm_retention_info[group_id].module;
_lock_acquire(&s_platform.mutex); _lock_acquire(&s_platform.mutex);
if (sleep_retention_is_module_inited(module) && !sleep_retention_is_module_created(module)) { if (sleep_retention_is_module_inited(module) && !sleep_retention_is_module_created(module)) {
if (sleep_retention_module_allocate(module) != ESP_OK) { if (sleep_retention_module_allocate(module) != ESP_OK) {
// even though the sleep retention module create failed, ETM driver should still work, so just warning here // even though the sleep retention module create failed, ETM driver should still work, so just warning here
ESP_LOGW(TAG, "create retention link failed %d, power domain won't be turned off during sleep", group_id); ESP_LOGW(TAG, "create retention link failed on ETM Group%d, power domain won't be turned off during sleep", group_id);
} }
} }
_lock_release(&s_platform.mutex); _lock_release(&s_platform.mutex);
@@ -120,8 +121,9 @@ static etm_group_t *etm_acquire_group_handle(int group_id)
etm_ll_enable_bus_clock(group_id, true); etm_ll_enable_bus_clock(group_id, true);
etm_ll_reset_register(group_id); etm_ll_reset_register(group_id);
} }
#if ETM_USE_RETENTION_LINK #if ETM_USE_RETENTION_LINK
sleep_retention_module_t module = etm_reg_retention_info[group_id].module; sleep_retention_module_t module = soc_etm_retention_info[group_id].module;
sleep_retention_module_init_param_t init_param = { sleep_retention_module_init_param_t init_param = {
.cbs = { .cbs = {
.create = { .create = {
@@ -131,11 +133,13 @@ static etm_group_t *etm_acquire_group_handle(int group_id)
}, },
.depends = RETENTION_MODULE_BITMAP_INIT(CLOCK_SYSTEM) .depends = RETENTION_MODULE_BITMAP_INIT(CLOCK_SYSTEM)
}; };
// retention module init must be called BEFORE the hal init
if (sleep_retention_module_init(module, &init_param) != ESP_OK) { if (sleep_retention_module_init(module, &init_param) != ESP_OK) {
// even though the sleep retention module init failed, ETM driver may still work, so just warning here // even though the sleep retention module init failed, ETM driver may still work, so just warning here
ESP_LOGW(TAG, "init sleep retention failed %d, power domain may be turned off during sleep", group_id); ESP_LOGW(TAG, "init sleep retention failed on ETM Group%d, power domain may be turned off during sleep", group_id);
} }
#endif // ETM_USE_RETENTION_LINK #endif // ETM_USE_RETENTION_LINK
// initialize HAL context // initialize HAL context
etm_hal_init(&group->hal); etm_hal_init(&group->hal);
} }
@@ -166,23 +170,25 @@ static void etm_release_group_handle(etm_group_t *group)
assert(s_platform.groups[group_id]); assert(s_platform.groups[group_id]);
do_deinitialize = true; do_deinitialize = true;
s_platform.groups[group_id] = NULL; // deregister from platform s_platform.groups[group_id] = NULL; // deregister from platform
etm_hal_deinit(&group->hal);
// disable the bus clock for the ETM registers // disable the bus clock for the ETM registers
ETM_RCC_ATOMIC() { ETM_RCC_ATOMIC() {
etm_ll_enable_bus_clock(group_id, false); etm_ll_enable_bus_clock(group_id, false);
} }
}
_lock_release(&s_platform.mutex);
if (do_deinitialize) {
#if ETM_USE_RETENTION_LINK #if ETM_USE_RETENTION_LINK
sleep_retention_module_t module = etm_reg_retention_info[group_id].module; sleep_retention_module_t module = soc_etm_retention_info[group_id].module;
if (sleep_retention_is_module_created(module)) { if (sleep_retention_is_module_created(module)) {
sleep_retention_module_free(module); sleep_retention_module_free(module);
} }
if (sleep_retention_is_module_inited(module)) { if (sleep_retention_is_module_inited(module)) {
sleep_retention_module_deinit(module); sleep_retention_module_deinit(module);
} }
#endif #endif // ETM_USE_RETENTION_LINK
}
_lock_release(&s_platform.mutex);
if (do_deinitialize) {
free(group); free(group);
ESP_LOGD(TAG, "del group (%d)", group_id); ESP_LOGD(TAG, "del group (%d)", group_id);
} }
@@ -192,25 +198,24 @@ static esp_err_t etm_chan_register_to_group(esp_etm_channel_t *chan)
{ {
etm_group_t *group = NULL; etm_group_t *group = NULL;
int chan_id = -1; int chan_id = -1;
for (int i = 0; i < SOC_ETM_GROUPS; i++) { for (int i = 0; i < SOC_ETM_ATTR(INST_NUM); i++) {
group = etm_acquire_group_handle(i); group = etm_acquire_group_handle(i);
ESP_RETURN_ON_FALSE(group, ESP_ERR_NO_MEM, TAG, "no mem for group (%d)", i); ESP_RETURN_ON_FALSE(group, ESP_ERR_NO_MEM, TAG, "no mem for group (%d)", i);
// loop to search free channel in the group // loop to search free channel in the group
esp_os_enter_critical(&group->spinlock); esp_os_enter_critical(&group->spinlock);
for (int j = 0; j < SOC_ETM_CHANNELS_PER_GROUP; j++) { for (int j = 0; j < SOC_ETM_ATTR(CHANS_PER_INST); j++) {
if (!group->chans[j]) { if (!group->chans[j]) {
chan_id = j; chan_id = j;
group->chans[j] = chan; group->chans[j] = chan;
chan->chan_id = chan_id;
chan->group = group;
break; break;
} }
} }
esp_os_exit_critical(&group->spinlock); esp_os_exit_critical(&group->spinlock);
if (chan_id < 0) { if (chan_id < 0) {
etm_release_group_handle(group); etm_release_group_handle(group);
group = NULL;
} else { } else {
chan->chan_id = chan_id;
chan->group = group;
break; break;
} }
} }
@@ -240,31 +245,34 @@ static esp_err_t etm_chan_destroy(esp_etm_channel_t *chan)
esp_err_t esp_etm_new_channel(const esp_etm_channel_config_t *config, esp_etm_channel_handle_t *ret_chan) esp_err_t esp_etm_new_channel(const esp_etm_channel_config_t *config, esp_etm_channel_handle_t *ret_chan)
{ {
#if CONFIG_ETM_ENABLE_DEBUG_LOG
esp_log_level_set(TAG, ESP_LOG_DEBUG);
#endif
esp_err_t ret = ESP_OK; esp_err_t ret = ESP_OK;
esp_etm_channel_t *chan = NULL; esp_etm_channel_t *chan = NULL;
ESP_GOTO_ON_FALSE(config && ret_chan, ESP_ERR_INVALID_ARG, err, TAG, "invalid args"); ESP_RETURN_ON_FALSE(config && ret_chan, ESP_ERR_INVALID_ARG, TAG, "invalid args");
[[maybe_unused]] bool allow_pd = config->flags.allow_pd == 1;
#if !SOC_ETM_SUPPORT_SLEEP_RETENTION #if !SOC_ETM_SUPPORT_SLEEP_RETENTION
ESP_RETURN_ON_FALSE(config->flags.allow_pd == 0, ESP_ERR_NOT_SUPPORTED, TAG, "not able to power down in light sleep"); ESP_RETURN_ON_FALSE(allow_pd == 0, ESP_ERR_NOT_SUPPORTED, TAG, "not able to power down in light sleep");
#endif // SOC_ETM_SUPPORT_SLEEP_RETENTION #endif // SOC_ETM_SUPPORT_SLEEP_RETENTION
chan = heap_caps_calloc(1, sizeof(esp_etm_channel_t), ETM_MEM_ALLOC_CAPS); // allocate channel memory from internal memory because it contains atomic variable
ESP_GOTO_ON_FALSE(chan, ESP_ERR_NO_MEM, err, TAG, "no mem for channel"); chan = heap_caps_calloc(1, sizeof(esp_etm_channel_t), MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT);
ESP_RETURN_ON_FALSE(chan, ESP_ERR_NO_MEM, TAG, "no mem for channel");
// register channel to the group, one group can have multiple channels // register channel to the group, one group can have multiple channels
ESP_GOTO_ON_ERROR(etm_chan_register_to_group(chan), err, TAG, "register channel failed"); ESP_GOTO_ON_ERROR(etm_chan_register_to_group(chan), err, TAG, "register channel to group failed");
etm_group_t *group = chan->group; etm_group_t *group = chan->group;
int group_id = group->group_id; int group_id = group->group_id;
int chan_id = chan->chan_id; int chan_id = chan->chan_id;
// set the initial state to INIT
atomic_init(&chan->fsm, ETM_CHAN_FSM_INIT);
#if ETM_USE_RETENTION_LINK #if ETM_USE_RETENTION_LINK
if (config->flags.allow_pd != 0) { if (allow_pd) {
etm_create_retention_module(group); etm_create_retention_module(group);
} }
#endif // ETM_USE_RETENTION_LINK #endif // ETM_USE_RETENTION_LINK
chan->fsm = ETM_CHAN_FSM_INIT;
ESP_LOGD(TAG, "new etm channel (%d,%d) at %p", group_id, chan_id, chan); ESP_LOGD(TAG, "new etm channel (%d,%d) at %p", group_id, chan_id, chan);
*ret_chan = chan; *ret_chan = chan;
return ESP_OK; return ESP_OK;
@@ -279,7 +287,9 @@ err:
esp_err_t esp_etm_del_channel(esp_etm_channel_handle_t chan) esp_err_t esp_etm_del_channel(esp_etm_channel_handle_t chan)
{ {
ESP_RETURN_ON_FALSE(chan, ESP_ERR_INVALID_ARG, TAG, "invalid args"); ESP_RETURN_ON_FALSE(chan, ESP_ERR_INVALID_ARG, TAG, "invalid args");
ESP_RETURN_ON_FALSE(chan->fsm == ETM_CHAN_FSM_INIT, ESP_ERR_INVALID_STATE, TAG, "channel is not in init state"); etm_chan_fsm_t expected_fsm = ETM_CHAN_FSM_INIT;
ESP_RETURN_ON_FALSE(atomic_compare_exchange_strong(&chan->fsm, &expected_fsm, ETM_CHAN_FSM_WAIT),
ESP_ERR_INVALID_STATE, TAG, "channel not in init state");
etm_group_t *group = chan->group; etm_group_t *group = chan->group;
int group_id = group->group_id; int group_id = group->group_id;
int chan_id = chan->chan_id; int chan_id = chan->chan_id;
@@ -296,27 +306,63 @@ esp_err_t esp_etm_del_channel(esp_etm_channel_handle_t chan)
esp_err_t esp_etm_channel_enable(esp_etm_channel_handle_t chan) esp_err_t esp_etm_channel_enable(esp_etm_channel_handle_t chan)
{ {
ESP_RETURN_ON_FALSE(chan, ESP_ERR_INVALID_ARG, TAG, "invalid argument"); if (!chan) {
ESP_RETURN_ON_FALSE(chan->fsm == ETM_CHAN_FSM_INIT, ESP_ERR_INVALID_STATE, TAG, "channel is not in init state"); return ESP_ERR_INVALID_ARG;
}
etm_chan_fsm_t expected_fsm = ETM_CHAN_FSM_INIT;
if (atomic_compare_exchange_strong(&chan->fsm, &expected_fsm, ETM_CHAN_FSM_WAIT)) {
etm_group_t *group = chan->group; etm_group_t *group = chan->group;
// no race condition here even without a lock, because the underlying register is write only and each channel has its own position
etm_ll_enable_channel(group->hal.regs, chan->chan_id); etm_ll_enable_channel(group->hal.regs, chan->chan_id);
chan->fsm = ETM_CHAN_FSM_ENABLE; // change state to ENABLE
atomic_store(&chan->fsm, ETM_CHAN_FSM_ENABLE);
return ESP_OK; return ESP_OK;
} else {
return ESP_ERR_INVALID_STATE;
}
} }
esp_err_t esp_etm_channel_disable(esp_etm_channel_handle_t chan) esp_err_t esp_etm_channel_disable(esp_etm_channel_handle_t chan)
{ {
ESP_RETURN_ON_FALSE(chan, ESP_ERR_INVALID_ARG, TAG, "invalid argument"); if (!chan) {
ESP_RETURN_ON_FALSE(chan->fsm == ETM_CHAN_FSM_ENABLE, ESP_ERR_INVALID_STATE, TAG, "channel not in enable state"); return ESP_ERR_INVALID_ARG;
}
etm_chan_fsm_t expected_fsm = ETM_CHAN_FSM_ENABLE;
if (atomic_compare_exchange_strong(&chan->fsm, &expected_fsm, ETM_CHAN_FSM_WAIT)) {
etm_group_t *group = chan->group; etm_group_t *group = chan->group;
// no race condition here even without a lock, because the underlying register is write only and each channel has its own position
etm_ll_disable_channel(group->hal.regs, chan->chan_id); etm_ll_disable_channel(group->hal.regs, chan->chan_id);
chan->fsm = ETM_CHAN_FSM_INIT; // change state to INIT
atomic_store(&chan->fsm, ETM_CHAN_FSM_INIT);
return ESP_OK; return ESP_OK;
} else {
return ESP_ERR_INVALID_STATE;
}
} }
esp_err_t esp_etm_channel_connect(esp_etm_channel_handle_t chan, esp_etm_event_handle_t event, esp_etm_task_handle_t task) esp_err_t esp_etm_channel_connect(esp_etm_channel_handle_t chan, esp_etm_event_handle_t event, esp_etm_task_handle_t task)
{ {
ESP_RETURN_ON_FALSE(chan, ESP_ERR_INVALID_ARG, TAG, "invalid argument"); if (!chan) {
return ESP_ERR_INVALID_ARG;
}
bool valid_state = false;
etm_chan_fsm_t expected_fsm = ETM_CHAN_FSM_INIT;
etm_chan_fsm_t restore_fsm = ETM_CHAN_FSM_INIT;
// this function can be called only when the channel is in init or enable state
if (atomic_compare_exchange_strong(&chan->fsm, &expected_fsm, ETM_CHAN_FSM_WAIT)) {
valid_state = true;
restore_fsm = ETM_CHAN_FSM_INIT;
} else {
expected_fsm = ETM_CHAN_FSM_ENABLE;
if (atomic_compare_exchange_strong(&chan->fsm, &expected_fsm, ETM_CHAN_FSM_WAIT)) {
valid_state = true;
restore_fsm = ETM_CHAN_FSM_ENABLE;
}
}
if (!valid_state) {
return ESP_ERR_INVALID_STATE;
}
etm_group_t *group = chan->group; etm_group_t *group = chan->group;
uint32_t event_id = 0; uint32_t event_id = 0;
uint32_t task_id = 0; uint32_t task_id = 0;
@@ -332,6 +378,8 @@ esp_err_t esp_etm_channel_connect(esp_etm_channel_handle_t chan, esp_etm_event_h
etm_ll_channel_set_task(group->hal.regs, chan->chan_id, task_id); etm_ll_channel_set_task(group->hal.regs, chan->chan_id, task_id);
chan->event = event; chan->event = event;
chan->task = task; chan->task = task;
// restore the state
atomic_store(&chan->fsm, restore_fsm);
ESP_LOGD(TAG, "event %"PRIu32" => channel %d", event_id, chan->chan_id); ESP_LOGD(TAG, "event %"PRIu32" => channel %d", event_id, chan->chan_id);
ESP_LOGD(TAG, "channel %d => task %"PRIu32, chan->chan_id, task_id); ESP_LOGD(TAG, "channel %d => task %"PRIu32, chan->chan_id, task_id);
return ESP_OK; return ESP_OK;
@@ -357,11 +405,11 @@ esp_err_t esp_etm_dump(FILE *out_stream)
fprintf(out_stream, "===========ETM Dump Start==========\r\n"); fprintf(out_stream, "===========ETM Dump Start==========\r\n");
char line[80]; char line[80];
size_t len = sizeof(line); size_t len = sizeof(line);
for (int i = 0; i < SOC_ETM_GROUPS; i++) { for (int i = 0; i < SOC_ETM_ATTR(INST_NUM); i++) {
group = etm_acquire_group_handle(i); group = etm_acquire_group_handle(i);
ESP_RETURN_ON_FALSE(group, ESP_ERR_NO_MEM, TAG, "no mem for group (%d)", i); ESP_RETURN_ON_FALSE(group, ESP_ERR_NO_MEM, TAG, "no mem for group (%d)", i);
etm_hal_context_t *hal = &group->hal; etm_hal_context_t *hal = &group->hal;
for (int j = 0; j < SOC_ETM_CHANNELS_PER_GROUP; j++) { for (int j = 0; j < SOC_ETM_ATTR(CHANS_PER_INST); j++) {
bool print_line = true; bool print_line = true;
esp_os_enter_critical(&group->spinlock); esp_os_enter_critical(&group->spinlock);
etm_chan = group->chans[j]; etm_chan = group->chans[j];
@@ -394,3 +442,11 @@ esp_err_t esp_etm_dump(FILE *out_stream)
fprintf(out_stream, "===========ETM Dump End============\r\n"); fprintf(out_stream, "===========ETM Dump End============\r\n");
return ESP_OK; return ESP_OK;
} }
#if CONFIG_ETM_ENABLE_DEBUG_LOG
__attribute__((constructor))
static void etm_override_default_log_level(void)
{
esp_log_level_set(TAG, ESP_LOG_VERBOSE);
}
#endif

View File

@@ -1,5 +1,5 @@
/* /*
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD * SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD
* *
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
*/ */
@@ -10,16 +10,15 @@
#include "freertos/task.h" #include "freertos/task.h"
#include "unity.h" #include "unity.h"
#include "esp_etm.h" #include "esp_etm.h"
#include "soc/soc_caps.h" #include "soc/etm_periph.h"
#include "esp_attr.h"
TEST_CASE("etm_channel_install_uninstall", "[etm]") TEST_CASE("etm_channel_install_uninstall", "[etm]")
{ {
printf("install etm channels exhaustively\r\n"); printf("install etm channels exhaustively\r\n");
esp_etm_channel_handle_t etm_chans[SOC_ETM_GROUPS][SOC_ETM_CHANNELS_PER_GROUP]; esp_etm_channel_handle_t etm_chans[SOC_ETM_ATTR(INST_NUM)][SOC_ETM_ATTR(CHANS_PER_INST)];
esp_etm_channel_config_t config = {}; esp_etm_channel_config_t config = {};
for (int i = 0; i < SOC_ETM_GROUPS; i++) { for (int i = 0; i < SOC_ETM_ATTR(INST_NUM); i++) {
for (int j = 0; j < SOC_ETM_CHANNELS_PER_GROUP; j++) { for (int j = 0; j < SOC_ETM_ATTR(CHANS_PER_INST); j++) {
TEST_ESP_OK(esp_etm_new_channel(&config, &etm_chans[i][j])); TEST_ESP_OK(esp_etm_new_channel(&config, &etm_chans[i][j]));
} }
TEST_ESP_ERR(ESP_ERR_NOT_FOUND, esp_etm_new_channel(&config, &etm_chans[0][0])); TEST_ESP_ERR(ESP_ERR_NOT_FOUND, esp_etm_new_channel(&config, &etm_chans[0][0]));
@@ -31,8 +30,8 @@ TEST_CASE("etm_channel_install_uninstall", "[etm]")
TEST_ESP_ERR(ESP_ERR_INVALID_STATE, esp_etm_del_channel(etm_chans[0][0])); TEST_ESP_ERR(ESP_ERR_INVALID_STATE, esp_etm_del_channel(etm_chans[0][0]));
TEST_ESP_OK(esp_etm_channel_disable(etm_chans[0][0])); TEST_ESP_OK(esp_etm_channel_disable(etm_chans[0][0]));
for (int i = 0; i < SOC_ETM_GROUPS; i++) { for (int i = 0; i < SOC_ETM_ATTR(INST_NUM); i++) {
for (int j = 0; j < SOC_ETM_CHANNELS_PER_GROUP; j++) { for (int j = 0; j < SOC_ETM_ATTR(CHANS_PER_INST); j++) {
TEST_ESP_OK(esp_etm_del_channel(etm_chans[i][j])); TEST_ESP_OK(esp_etm_del_channel(etm_chans[i][j]));
} }
} }

View File

@@ -1,5 +1,5 @@
/* /*
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD * SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD
* *
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
*/ */
@@ -35,7 +35,7 @@ static const regdma_entries_config_t etm_regdma_entries[] = {
}, },
}; };
const etm_reg_retention_info_t etm_reg_retention_info[SOC_ETM_GROUPS] = { const soc_etm_retention_desc_t soc_etm_retention_info[1] = {
[0] = { [0] = {
.module = SLEEP_RETENTION_MODULE_ETM0, .module = SLEEP_RETENTION_MODULE_ETM0,
.regdma_entry_array = etm_regdma_entries, .regdma_entry_array = etm_regdma_entries,

View File

@@ -523,18 +523,6 @@ config SOC_GDMA_SUPPORT_WEIGHTED_ARBITRATION
bool bool
default y default y
config SOC_ETM_GROUPS
int
default 1
config SOC_ETM_CHANNELS_PER_GROUP
int
default 50
config SOC_ETM_SUPPORT_SLEEP_RETENTION
bool
default y
config SOC_GPIO_PORT config SOC_GPIO_PORT
int int
default 1 default 1
@@ -651,6 +639,10 @@ config SOC_SDM_SUPPORT_SLEEP_RETENTION
bool bool
default y default y
config SOC_ETM_SUPPORT_SLEEP_RETENTION
bool
default y
config SOC_ANA_CMPR_NUM config SOC_ANA_CMPR_NUM
int int
default 1 default 1

View File

@@ -204,11 +204,6 @@
#define SOC_AHB_GDMA_SUPPORT_PSRAM 1 #define SOC_AHB_GDMA_SUPPORT_PSRAM 1
#define SOC_GDMA_SUPPORT_WEIGHTED_ARBITRATION 1 #define SOC_GDMA_SUPPORT_WEIGHTED_ARBITRATION 1
/*-------------------------- ETM CAPS --------------------------------------*/
#define SOC_ETM_GROUPS 1U // Number of ETM groups
#define SOC_ETM_CHANNELS_PER_GROUP 50 // Number of ETM channels in the group
#define SOC_ETM_SUPPORT_SLEEP_RETENTION 1 // Support sleep retention
/*-------------------------- GPIO CAPS ---------------------------------------*/ /*-------------------------- GPIO CAPS ---------------------------------------*/
// ESP32-C5 has 1 GPIO peripheral // ESP32-C5 has 1 GPIO peripheral
#define SOC_GPIO_PORT 1U #define SOC_GPIO_PORT 1U
@@ -268,6 +263,7 @@
#define SOC_DEDIC_PERIPH_ALWAYS_ENABLE (1) /*!< The dedicated GPIO (a.k.a. fast GPIO) is featured by some customized CPU instructions, which is always enabled */ #define SOC_DEDIC_PERIPH_ALWAYS_ENABLE (1) /*!< The dedicated GPIO (a.k.a. fast GPIO) is featured by some customized CPU instructions, which is always enabled */
#define SOC_SDM_SUPPORT_SLEEP_RETENTION 1 #define SOC_SDM_SUPPORT_SLEEP_RETENTION 1
#define SOC_ETM_SUPPORT_SLEEP_RETENTION 1
/*------------------------- Analog Comparator CAPS ---------------------------*/ /*------------------------- Analog Comparator CAPS ---------------------------*/
#define SOC_ANA_CMPR_NUM (1U) #define SOC_ANA_CMPR_NUM (1U)

View File

@@ -23,3 +23,7 @@
/*--------------------------- SDM (Sigma-Delta Modulator) ------------------------*/ /*--------------------------- SDM (Sigma-Delta Modulator) ------------------------*/
#define _SOC_CAPS_SDM_INST_NUM 1 // Number of SDM instances #define _SOC_CAPS_SDM_INST_NUM 1 // Number of SDM instances
#define _SOC_CAPS_SDM_CHANS_PER_INST 4 // Number of channels in each SDM instance #define _SOC_CAPS_SDM_CHANS_PER_INST 4 // Number of channels in each SDM instance
/*--------------------------- ETM (Event Task Matrix) ----------------------------*/
#define _SOC_CAPS_ETM_INST_NUM 1 // Number of ETM instances
#define _SOC_CAPS_ETM_CHANS_PER_INST 50 // Number of channels in each ETM instance

View File

@@ -1,5 +1,5 @@
/* /*
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD * SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD
* *
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
*/ */
@@ -35,7 +35,7 @@ static const regdma_entries_config_t etm_regdma_entries[] = {
}, },
}; };
const etm_reg_retention_info_t etm_reg_retention_info[SOC_ETM_GROUPS] = { const soc_etm_retention_desc_t soc_etm_retention_info[1] = {
[0] = { [0] = {
.module = SLEEP_RETENTION_MODULE_ETM0, .module = SLEEP_RETENTION_MODULE_ETM0,
.regdma_entry_array = etm_regdma_entries, .regdma_entry_array = etm_regdma_entries,

View File

@@ -459,18 +459,6 @@ config SOC_GDMA_SUPPORT_SLEEP_RETENTION
bool bool
default y default y
config SOC_ETM_GROUPS
int
default 1
config SOC_ETM_CHANNELS_PER_GROUP
int
default 50
config SOC_ETM_SUPPORT_SLEEP_RETENTION
bool
default y
config SOC_GPIO_PORT config SOC_GPIO_PORT
int int
default 1 default 1
@@ -583,6 +571,10 @@ config SOC_SDM_SUPPORT_SLEEP_RETENTION
bool bool
default y default y
config SOC_ETM_SUPPORT_SLEEP_RETENTION
bool
default y
config SOC_I2C_NUM config SOC_I2C_NUM
int int
default 2 default 2

View File

@@ -183,11 +183,6 @@
#define SOC_GDMA_SUPPORT_ETM 1 // Support ETM submodule #define SOC_GDMA_SUPPORT_ETM 1 // Support ETM submodule
#define SOC_GDMA_SUPPORT_SLEEP_RETENTION 1 #define SOC_GDMA_SUPPORT_SLEEP_RETENTION 1
/*-------------------------- ETM CAPS --------------------------------------*/
#define SOC_ETM_GROUPS 1U // Number of ETM groups
#define SOC_ETM_CHANNELS_PER_GROUP 50 // Number of ETM channels in the group
#define SOC_ETM_SUPPORT_SLEEP_RETENTION 1 // Support sleep retention
/*-------------------------- GPIO CAPS ---------------------------------------*/ /*-------------------------- GPIO CAPS ---------------------------------------*/
// ESP32-C6 has 1 GPIO peripheral // ESP32-C6 has 1 GPIO peripheral
#define SOC_GPIO_PORT 1U #define SOC_GPIO_PORT 1U
@@ -246,6 +241,7 @@
#define SOC_DEDIC_PERIPH_ALWAYS_ENABLE (1) /*!< The dedicated GPIO (a.k.a. fast GPIO) is featured by some customized CPU instructions, which is always enabled */ #define SOC_DEDIC_PERIPH_ALWAYS_ENABLE (1) /*!< The dedicated GPIO (a.k.a. fast GPIO) is featured by some customized CPU instructions, which is always enabled */
#define SOC_SDM_SUPPORT_SLEEP_RETENTION 1 #define SOC_SDM_SUPPORT_SLEEP_RETENTION 1
#define SOC_ETM_SUPPORT_SLEEP_RETENTION 1
/*-------------------------- I2C CAPS ----------------------------------------*/ /*-------------------------- I2C CAPS ----------------------------------------*/
// ESP32-C6 has 1 I2C // ESP32-C6 has 1 I2C

View File

@@ -23,3 +23,7 @@
/*--------------------------- SDM (Sigma-Delta Modulator) ------------------------*/ /*--------------------------- SDM (Sigma-Delta Modulator) ------------------------*/
#define _SOC_CAPS_SDM_INST_NUM 1 // Number of SDM instances #define _SOC_CAPS_SDM_INST_NUM 1 // Number of SDM instances
#define _SOC_CAPS_SDM_CHANS_PER_INST 4 // Number of channels in each SDM instance #define _SOC_CAPS_SDM_CHANS_PER_INST 4 // Number of channels in each SDM instance
/*--------------------------- ETM (Event Task Matrix) ----------------------------*/
#define _SOC_CAPS_ETM_INST_NUM 1 // Number of ETM instances
#define _SOC_CAPS_ETM_CHANS_PER_INST 50 // Number of channels in each ETM instance

View File

@@ -1,5 +1,5 @@
/* /*
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD * SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD
* *
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
*/ */
@@ -35,7 +35,7 @@ static const regdma_entries_config_t etm_regdma_entries[] = {
}, },
}; };
const etm_reg_retention_info_t etm_reg_retention_info[SOC_ETM_GROUPS] = { const soc_etm_retention_desc_t soc_etm_retention_info[1] = {
[0] = { [0] = {
.module = SLEEP_RETENTION_MODULE_ETM0, .module = SLEEP_RETENTION_MODULE_ETM0,
.regdma_entry_array = etm_regdma_entries, .regdma_entry_array = etm_regdma_entries,

View File

@@ -403,14 +403,6 @@ config SOC_GDMA_SUPPORT_WEIGHTED_ARBITRATION
bool bool
default y default y
config SOC_ETM_GROUPS
int
default 1
config SOC_ETM_CHANNELS_PER_GROUP
int
default 50
config SOC_ETM_SUPPORT_SLEEP_RETENTION config SOC_ETM_SUPPORT_SLEEP_RETENTION
bool bool
default y default y

View File

@@ -161,10 +161,7 @@
#define SOC_AHB_GDMA_SUPPORT_PSRAM 1 #define SOC_AHB_GDMA_SUPPORT_PSRAM 1
#define SOC_GDMA_SUPPORT_WEIGHTED_ARBITRATION 1 #define SOC_GDMA_SUPPORT_WEIGHTED_ARBITRATION 1
/*-------------------------- ETM CAPS --------------------------------------*/ #define SOC_ETM_SUPPORT_SLEEP_RETENTION 1
#define SOC_ETM_GROUPS 1U // Number of ETM groups
#define SOC_ETM_CHANNELS_PER_GROUP 50 // Number of ETM channels in the group
#define SOC_ETM_SUPPORT_SLEEP_RETENTION 1 // Support sleep retention
/*-------------------------- GPIO CAPS ---------------------------------------*/ /*-------------------------- GPIO CAPS ---------------------------------------*/
// ESP32-C61 has 1 GPIO peripheral // ESP32-C61 has 1 GPIO peripheral

View File

@@ -19,3 +19,7 @@
/*--------------------------- Watch Dog ------------------------------------------*/ /*--------------------------- Watch Dog ------------------------------------------*/
#define _SOC_CAPS_WDT_MWDTS_PER_TIMG 1 // Number of main watchdog timers in each Timer Group #define _SOC_CAPS_WDT_MWDTS_PER_TIMG 1 // Number of main watchdog timers in each Timer Group
/*--------------------------- ETM (Event Task Matrix) ----------------------------*/
#define _SOC_CAPS_ETM_INST_NUM 1 // Number of ETM instances
#define _SOC_CAPS_ETM_CHANS_PER_INST 50 // Number of channels in each ETM instance

View File

@@ -1,5 +1,5 @@
/* /*
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD * SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD
* *
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
*/ */
@@ -35,7 +35,7 @@ static const regdma_entries_config_t etm_regdma_entries[] = {
}, },
}; };
const etm_reg_retention_info_t etm_reg_retention_info[SOC_ETM_GROUPS] = { const soc_etm_retention_desc_t soc_etm_retention_info[1] = {
[0] = { [0] = {
.module = SLEEP_RETENTION_MODULE_ETM0, .module = SLEEP_RETENTION_MODULE_ETM0,
.regdma_entry_array = etm_regdma_entries, .regdma_entry_array = etm_regdma_entries,

View File

@@ -479,18 +479,6 @@ config SOC_GDMA_SUPPORT_SLEEP_RETENTION
bool bool
default y default y
config SOC_ETM_GROUPS
int
default 1
config SOC_ETM_CHANNELS_PER_GROUP
int
default 50
config SOC_ETM_SUPPORT_SLEEP_RETENTION
bool
default y
config SOC_GPIO_PORT config SOC_GPIO_PORT
int int
default 1 default 1
@@ -587,6 +575,10 @@ config SOC_SDM_SUPPORT_SLEEP_RETENTION
bool bool
default y default y
config SOC_ETM_SUPPORT_SLEEP_RETENTION
bool
default y
config SOC_ANA_CMPR_NUM config SOC_ANA_CMPR_NUM
int int
default 1 default 1

View File

@@ -206,11 +206,6 @@
#define SOC_GDMA_SUPPORT_ETM 1 // Support ETM submodule #define SOC_GDMA_SUPPORT_ETM 1 // Support ETM submodule
#define SOC_GDMA_SUPPORT_SLEEP_RETENTION 1 #define SOC_GDMA_SUPPORT_SLEEP_RETENTION 1
/*-------------------------- ETM CAPS --------------------------------------*/
#define SOC_ETM_GROUPS 1U // Number of ETM groups
#define SOC_ETM_CHANNELS_PER_GROUP 50 // Number of ETM channels in the group
#define SOC_ETM_SUPPORT_SLEEP_RETENTION 1 // Support sleep retention
/*-------------------------- GPIO CAPS ---------------------------------------*/ /*-------------------------- GPIO CAPS ---------------------------------------*/
// ESP32-H2 has 1 GPIO peripheral // ESP32-H2 has 1 GPIO peripheral
#define SOC_GPIO_PORT 1U #define SOC_GPIO_PORT 1U
@@ -266,6 +261,7 @@
#define SOC_DEDIC_PERIPH_ALWAYS_ENABLE (1) /*!< The dedicated GPIO (a.k.a. fast GPIO) is featured by some customized CPU instructions, which is always enabled */ #define SOC_DEDIC_PERIPH_ALWAYS_ENABLE (1) /*!< The dedicated GPIO (a.k.a. fast GPIO) is featured by some customized CPU instructions, which is always enabled */
#define SOC_SDM_SUPPORT_SLEEP_RETENTION 1 #define SOC_SDM_SUPPORT_SLEEP_RETENTION 1
#define SOC_ETM_SUPPORT_SLEEP_RETENTION 1
/*------------------------- Analog Comparator CAPS ---------------------------*/ /*------------------------- Analog Comparator CAPS ---------------------------*/
#define SOC_ANA_CMPR_NUM (1U) #define SOC_ANA_CMPR_NUM (1U)

View File

@@ -23,3 +23,7 @@
/*--------------------------- SDM (Sigma-Delta Modulator) ------------------------*/ /*--------------------------- SDM (Sigma-Delta Modulator) ------------------------*/
#define _SOC_CAPS_SDM_INST_NUM 1 // Number of SDM instances #define _SOC_CAPS_SDM_INST_NUM 1 // Number of SDM instances
#define _SOC_CAPS_SDM_CHANS_PER_INST 4 // Number of channels in each SDM instance #define _SOC_CAPS_SDM_CHANS_PER_INST 4 // Number of channels in each SDM instance
/*--------------------------- ETM (Event Task Matrix) ----------------------------*/
#define _SOC_CAPS_ETM_INST_NUM 1 // Number of ETM instances
#define _SOC_CAPS_ETM_CHANS_PER_INST 50 // Number of channels in each ETM instance

View File

@@ -331,14 +331,6 @@ config SOC_GDMA_SUPPORT_SLEEP_RETENTION
bool bool
default y default y
config SOC_ETM_GROUPS
int
default 1
config SOC_ETM_CHANNELS_PER_GROUP
int
default 50
config SOC_GPIO_PORT config SOC_GPIO_PORT
int int
default 1 default 1
@@ -383,6 +375,14 @@ config SOC_GPIO_SUPPORT_HOLD_SINGLE_IO_IN_DSLP
bool bool
default y default y
config SOC_SDM_SUPPORT_SLEEP_RETENTION
bool
default y
config SOC_ETM_SUPPORT_SLEEP_RETENTION
bool
default y
config SOC_RTCIO_PIN_COUNT config SOC_RTCIO_PIN_COUNT
int int
default 7 default 7

View File

@@ -191,10 +191,6 @@
// #define SOC_GDMA_SUPPORT_ETM 1 // Support ETM submodule TODO: IDF-11604 // #define SOC_GDMA_SUPPORT_ETM 1 // Support ETM submodule TODO: IDF-11604
#define SOC_GDMA_SUPPORT_SLEEP_RETENTION 1 #define SOC_GDMA_SUPPORT_SLEEP_RETENTION 1
/*-------------------------- ETM CAPS --------------------------------------*/
#define SOC_ETM_GROUPS 1U // Number of ETM groups
#define SOC_ETM_CHANNELS_PER_GROUP 50 // Number of ETM channels in the group
/*-------------------------- GPIO CAPS ---------------------------------------*/ /*-------------------------- GPIO CAPS ---------------------------------------*/
// ESP32-H21 has 1 GPIO peripheral // ESP32-H21 has 1 GPIO peripheral
#define SOC_GPIO_PORT 1U #define SOC_GPIO_PORT 1U
@@ -235,6 +231,9 @@
// #define SOC_CLOCKOUT_HAS_SOURCE_GATE (1) // #define SOC_CLOCKOUT_HAS_SOURCE_GATE (1)
// #define SOC_GPIO_CLOCKOUT_CHANNEL_NUM (3) // #define SOC_GPIO_CLOCKOUT_CHANNEL_NUM (3)
#define SOC_SDM_SUPPORT_SLEEP_RETENTION 1
#define SOC_ETM_SUPPORT_SLEEP_RETENTION 1
/*-------------------------- RTCIO CAPS --------------------------------------*/ /*-------------------------- RTCIO CAPS --------------------------------------*/
/* No dedicated LP_IOMUX subsystem on ESP32-H21. LP functions are still supported /* No dedicated LP_IOMUX subsystem on ESP32-H21. LP functions are still supported
* for hold, wake & 32kHz crystal functions - via LP_AON registers */ * for hold, wake & 32kHz crystal functions - via LP_AON registers */

View File

@@ -19,3 +19,11 @@
/*--------------------------- Watch Dog ------------------------------------------*/ /*--------------------------- Watch Dog ------------------------------------------*/
#define _SOC_CAPS_WDT_MWDTS_PER_TIMG 1 // Number of main watchdog timers in each Timer Group #define _SOC_CAPS_WDT_MWDTS_PER_TIMG 1 // Number of main watchdog timers in each Timer Group
/*--------------------------- SDM (Sigma-Delta Modulator) ------------------------*/
#define _SOC_CAPS_SDM_INST_NUM 1 // Number of SDM instances
#define _SOC_CAPS_SDM_CHANS_PER_INST 4 // Number of channels in each SDM instance
/*--------------------------- ETM (Event Task Matrix) ----------------------------*/
#define _SOC_CAPS_ETM_INST_NUM 1 // Number of ETM instances
#define _SOC_CAPS_ETM_CHANS_PER_INST 50 // Number of channels in each ETM instance

View File

@@ -35,7 +35,7 @@ static const regdma_entries_config_t etm_regdma_entries[] = {
}, },
}; };
const etm_reg_retention_info_t etm_reg_retention_info[SOC_ETM_GROUPS] = { const soc_etm_retention_desc_t soc_etm_retention_info[1] = {
[0] = { [0] = {
.module = SLEEP_RETENTION_MODULE_ETM0, .module = SLEEP_RETENTION_MODULE_ETM0,
.regdma_entry_array = etm_regdma_entries, .regdma_entry_array = etm_regdma_entries,

View File

@@ -263,18 +263,6 @@ config SOC_AHB_GDMA_SUPPORT_PSRAM
bool bool
default y default y
config SOC_ETM_GROUPS
int
default 1
config SOC_ETM_CHANNELS_PER_GROUP
int
default 50
config SOC_ETM_SUPPORT_SLEEP_RETENTION
bool
default y
config SOC_GPIO_PORT config SOC_GPIO_PORT
int int
default 1 default 1
@@ -355,6 +343,10 @@ config SOC_SDM_SUPPORT_SLEEP_RETENTION
bool bool
default y default y
config SOC_ETM_SUPPORT_SLEEP_RETENTION
bool
default y
config SOC_I2C_NUM config SOC_I2C_NUM
int int
default 2 default 2

View File

@@ -198,11 +198,6 @@
#define SOC_GDMA_SUPPORT_SLEEP_RETENTION 1 #define SOC_GDMA_SUPPORT_SLEEP_RETENTION 1
#define SOC_AHB_GDMA_SUPPORT_PSRAM 1 #define SOC_AHB_GDMA_SUPPORT_PSRAM 1
/*-------------------------- ETM CAPS --------------------------------------*/
#define SOC_ETM_GROUPS 1U // Number of ETM groups
#define SOC_ETM_CHANNELS_PER_GROUP 50 // Number of ETM channels in the group
#define SOC_ETM_SUPPORT_SLEEP_RETENTION 1
/*-------------------------- GPIO CAPS ---------------------------------------*/ /*-------------------------- GPIO CAPS ---------------------------------------*/
// ESP32-H4 has 1 GPIO peripheral // ESP32-H4 has 1 GPIO peripheral
#define SOC_GPIO_PORT 1U #define SOC_GPIO_PORT 1U
@@ -257,6 +252,7 @@
// #define SOC_DEDIC_PERIPH_ALWAYS_ENABLE (1) /*!< The dedicated GPIO (a.k.a. fast GPIO) is featured by some customized CPU instructions, which is always enabled */ // #define SOC_DEDIC_PERIPH_ALWAYS_ENABLE (1) /*!< The dedicated GPIO (a.k.a. fast GPIO) is featured by some customized CPU instructions, which is always enabled */
#define SOC_SDM_SUPPORT_SLEEP_RETENTION 1 #define SOC_SDM_SUPPORT_SLEEP_RETENTION 1
#define SOC_ETM_SUPPORT_SLEEP_RETENTION 1
/*-------------------------- I2C CAPS ----------------------------------------*/ /*-------------------------- I2C CAPS ----------------------------------------*/
// ESP32-H4 has 2 I2C // ESP32-H4 has 2 I2C

View File

@@ -23,3 +23,7 @@
/*--------------------------- SDM (Sigma-Delta Modulator) ------------------------*/ /*--------------------------- SDM (Sigma-Delta Modulator) ------------------------*/
#define _SOC_CAPS_SDM_INST_NUM 1 // Number of SDM instances #define _SOC_CAPS_SDM_INST_NUM 1 // Number of SDM instances
#define _SOC_CAPS_SDM_CHANS_PER_INST 4 // Number of channels in each SDM instance #define _SOC_CAPS_SDM_CHANS_PER_INST 4 // Number of channels in each SDM instance
/*--------------------------- ETM (Event Task Matrix) ----------------------------*/
#define _SOC_CAPS_ETM_INST_NUM 1 // Number of ETM instances
#define _SOC_CAPS_ETM_CHANS_PER_INST 50 // Number of channels in each ETM instance

View File

@@ -1,5 +1,5 @@
/* /*
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD * SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD
* *
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
*/ */
@@ -35,7 +35,7 @@ static const regdma_entries_config_t etm_regdma_entries[] = {
}, },
}; };
const etm_reg_retention_info_t etm_reg_retention_info[SOC_ETM_GROUPS] = { const soc_etm_retention_desc_t soc_etm_retention_info[1] = {
[0] = { [0] = {
.module = SLEEP_RETENTION_MODULE_ETM0, .module = SLEEP_RETENTION_MODULE_ETM0,
.regdma_entry_array = etm_regdma_entries, .regdma_entry_array = etm_regdma_entries,

View File

@@ -635,18 +635,6 @@ config SOC_DMA2D_RX_CHANNELS_PER_GROUP
int int
default 2 default 2
config SOC_ETM_GROUPS
int
default 1
config SOC_ETM_CHANNELS_PER_GROUP
int
default 50
config SOC_ETM_SUPPORT_SLEEP_RETENTION
bool
default y
config SOC_GPIO_PORT config SOC_GPIO_PORT
int int
default 1 default 1
@@ -771,6 +759,10 @@ config SOC_SDM_SUPPORT_SLEEP_RETENTION
bool bool
default y default y
config SOC_ETM_SUPPORT_SLEEP_RETENTION
bool
default y
config SOC_ANA_CMPR_NUM config SOC_ANA_CMPR_NUM
int int
default 2 default 2

View File

@@ -234,11 +234,6 @@
#define SOC_DMA2D_TX_CHANNELS_PER_GROUP (3) // Number of 2D-DMA TX (OUT) channels in each group #define SOC_DMA2D_TX_CHANNELS_PER_GROUP (3) // Number of 2D-DMA TX (OUT) channels in each group
#define SOC_DMA2D_RX_CHANNELS_PER_GROUP (2) // Number of 2D-DMA RX (IN) channels in each group #define SOC_DMA2D_RX_CHANNELS_PER_GROUP (2) // Number of 2D-DMA RX (IN) channels in each group
/*-------------------------- ETM CAPS --------------------------------------*/
#define SOC_ETM_GROUPS 1U // Number of ETM groups
#define SOC_ETM_CHANNELS_PER_GROUP 50 // Number of ETM channels in the group
#define SOC_ETM_SUPPORT_SLEEP_RETENTION 1 // Support sleep retention
/*-------------------------- GPIO CAPS ---------------------------------------*/ /*-------------------------- GPIO CAPS ---------------------------------------*/
// ESP32-P4 has 1 GPIO peripheral // ESP32-P4 has 1 GPIO peripheral
#define SOC_GPIO_PORT 1U #define SOC_GPIO_PORT 1U
@@ -299,6 +294,7 @@
#define SOC_DEDIC_PERIPH_ALWAYS_ENABLE (1) /*!< The dedicated GPIO (a.k.a. fast GPIO) is featured by some customized CPU instructions, which is always enabled */ #define SOC_DEDIC_PERIPH_ALWAYS_ENABLE (1) /*!< The dedicated GPIO (a.k.a. fast GPIO) is featured by some customized CPU instructions, which is always enabled */
#define SOC_SDM_SUPPORT_SLEEP_RETENTION 1 #define SOC_SDM_SUPPORT_SLEEP_RETENTION 1
#define SOC_ETM_SUPPORT_SLEEP_RETENTION 1
/*------------------------- Analog Comparator CAPS ---------------------------*/ /*------------------------- Analog Comparator CAPS ---------------------------*/
#define SOC_ANA_CMPR_NUM (2) #define SOC_ANA_CMPR_NUM (2)

View File

@@ -23,3 +23,7 @@
/*--------------------------- SDM (Sigma-Delta Modulator) ------------------------*/ /*--------------------------- SDM (Sigma-Delta Modulator) ------------------------*/
#define _SOC_CAPS_SDM_INST_NUM 1 // Number of SDM instances #define _SOC_CAPS_SDM_INST_NUM 1 // Number of SDM instances
#define _SOC_CAPS_SDM_CHANS_PER_INST 8 // Number of channels in each SDM instance #define _SOC_CAPS_SDM_CHANS_PER_INST 8 // Number of channels in each SDM instance
/*--------------------------- ETM (Event Task Matrix) ----------------------------*/
#define _SOC_CAPS_ETM_INST_NUM 1 // Number of ETM instances
#define _SOC_CAPS_ETM_CHANS_PER_INST 50 // Number of channels in each ETM instance

View File

@@ -1,31 +1,37 @@
/* /*
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD * SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD
* *
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
*/ */
#pragma once #pragma once
#include "soc/soc_caps.h" #include <stdint.h>
#include "soc/soc_caps_full.h"
#include "soc/regdma.h" #include "soc/regdma.h"
#if SOC_ETM_SUPPORT_SLEEP_RETENTION #if SOC_HAS(PAU)
#include "soc/retention_periph_defs.h" #include "soc/retention_periph_defs.h"
#endif #endif
// helper macros to access module attributes
#define SOC_ETM_ATTR(_attr) SOC_MODULE_ATTR(ETM, _attr)
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
#if SOC_ETM_SUPPORT_SLEEP_RETENTION #if SOC_HAS(PAU)
typedef struct {
periph_retention_module_t module;
const regdma_entries_config_t *regdma_entry_array;
uint32_t array_size;
} etm_reg_retention_info_t;
extern const etm_reg_retention_info_t etm_reg_retention_info[SOC_ETM_GROUPS]; typedef struct {
#endif // SOC_ETM_SUPPORT_SLEEP_RETENTION periph_retention_module_t module; // ID of the ETM as a retention module
const regdma_entries_config_t *regdma_entry_array; // Array of regdma entries for retention
uint32_t array_size; // Size of the regdma_entry_array
} soc_etm_retention_desc_t;
extern const soc_etm_retention_desc_t soc_etm_retention_info[SOC_ETM_ATTR(INST_NUM)];
#endif // SOC_HAS(PAU)
#ifdef __cplusplus #ifdef __cplusplus
} }

View File

@@ -146,7 +146,6 @@ api-reference/peripherals/usb_host.rst
api-reference/peripherals/camera_driver.rst api-reference/peripherals/camera_driver.rst
api-reference/peripherals/adc_oneshot.rst api-reference/peripherals/adc_oneshot.rst
api-reference/peripherals/twai.rst api-reference/peripherals/twai.rst
api-reference/peripherals/etm.rst
api-reference/peripherals/sdspi_share.rst api-reference/peripherals/sdspi_share.rst
api-reference/peripherals/ana_cmpr.rst api-reference/peripherals/ana_cmpr.rst
api-reference/peripherals/adc_continuous.rst api-reference/peripherals/adc_continuous.rst
@@ -175,7 +174,6 @@ api-reference/peripherals/spi_flash/spi_flash_concurrency.rst
api-reference/peripherals/spi_flash/spi_flash_override_driver.rst api-reference/peripherals/spi_flash/spi_flash_override_driver.rst
api-reference/peripherals/spi_flash/spi_flash_optional_feature.rst api-reference/peripherals/spi_flash/spi_flash_optional_feature.rst
api-reference/peripherals/spi_flash/spi_flash_idf_vs_rom.rst api-reference/peripherals/spi_flash/spi_flash_idf_vs_rom.rst
api-reference/peripherals/sdm.rst
api-reference/peripherals/sdmmc_host.rst api-reference/peripherals/sdmmc_host.rst
api-reference/peripherals/lcd/i80_lcd.rst api-reference/peripherals/lcd/i80_lcd.rst
api-reference/peripherals/lcd/index.rst api-reference/peripherals/lcd/index.rst

View File

@@ -165,12 +165,12 @@ INPUT = \
$(PROJECT_PATH)/components/esp_http_server/include/esp_http_server.h \ $(PROJECT_PATH)/components/esp_http_server/include/esp_http_server.h \
$(PROJECT_PATH)/components/esp_https_ota/include/esp_https_ota.h \ $(PROJECT_PATH)/components/esp_https_ota/include/esp_https_ota.h \
$(PROJECT_PATH)/components/esp_https_server/include/esp_https_server.h \ $(PROJECT_PATH)/components/esp_https_server/include/esp_https_server.h \
$(PROJECT_PATH)/components/esp_hw_support/etm/include/esp_etm.h \
$(PROJECT_PATH)/components/esp_hw_support/include/esp_clk_tree.h \ $(PROJECT_PATH)/components/esp_hw_support/include/esp_clk_tree.h \
$(PROJECT_PATH)/components/esp_hw_support/include/esp_async_memcpy.h \ $(PROJECT_PATH)/components/esp_hw_support/include/esp_async_memcpy.h \
$(PROJECT_PATH)/components/esp_hw_support/include/esp_chip_info.h \ $(PROJECT_PATH)/components/esp_hw_support/include/esp_chip_info.h \
$(PROJECT_PATH)/components/esp_hw_support/include/esp_cpu.h \ $(PROJECT_PATH)/components/esp_hw_support/include/esp_cpu.h \
$(PROJECT_PATH)/components/esp_hw_support/include/esp_crc.h \ $(PROJECT_PATH)/components/esp_hw_support/include/esp_crc.h \
$(PROJECT_PATH)/components/esp_hw_support/include/esp_etm.h \
$(PROJECT_PATH)/components/esp_hw_support/include/esp_intr_alloc.h \ $(PROJECT_PATH)/components/esp_hw_support/include/esp_intr_alloc.h \
$(PROJECT_PATH)/components/esp_hw_support/include/esp_intr_types.h \ $(PROJECT_PATH)/components/esp_hw_support/include/esp_intr_types.h \
$(PROJECT_PATH)/components/esp_hw_support/include/esp_mac.h \ $(PROJECT_PATH)/components/esp_hw_support/include/esp_mac.h \

View File

@@ -148,11 +148,11 @@ When power management is enabled, i.e., :ref:`CONFIG_PM_ENABLE` is on, the syste
Thread Safety Thread Safety
^^^^^^^^^^^^^ ^^^^^^^^^^^^^
The factory functions like :cpp:func:`esp_etm_new_channel` and :cpp:func:`gpio_new_etm_task` are guaranteed to be thread-safe by the driver, which means, you can call them from different RTOS tasks without protection by extra locks. The ETM core driver is thread-safe.
No functions are allowed to run within the ISR environment. - Factory functions (for example, :cpp:func:`esp_etm_new_channel`, :cpp:func:`gpio_new_etm_task`, and other ``*_new_etm_*`` creators) are thread-safe and can be called from different RTOS tasks concurrently.
- Channel control APIs (for example, :cpp:func:`esp_etm_channel_connect`, :cpp:func:`esp_etm_channel_enable`, :cpp:func:`esp_etm_channel_disable`, :cpp:func:`esp_etm_del_channel`) are also thread-safe. Concurrent operations on different channels are safe. Concurrent operations on the same channel are serialized internally; if an operation is incompatible with the current channel state, it will return :c:macro:`ESP_ERR_INVALID_STATE`.
Other functions that take :cpp:type:`esp_etm_channel_handle_t`, :cpp:type:`esp_etm_task_handle_t` and :cpp:type:`esp_etm_event_handle_t` as the first positional parameter, are not treated as thread-safe, which means you should avoid calling them from multiple tasks. - No functions are allowed to run within the ISR environment.
.. _etm-kconfig-options: .. _etm-kconfig-options:

View File

@@ -148,11 +148,11 @@ ETM 通道分析
线程安全 线程安全
^^^^^^^^^^^^^ ^^^^^^^^^^^^^
ETM 驱动程序会确保工厂函数 :cpp:func:`esp_etm_new_channel` 和 :cpp:func:`gpio_new_etm_task` 的线程安全。使用时,可以直接从不同的 RTOS 任务中调用此类函数,无需额外锁保护 ETM 核心驱动程序具备线程安全性
在 ISR 环境中,不支持运行任何函数。 - 工厂函数(如 :cpp:func:`esp_etm_new_channel` :cpp:func:`gpio_new_etm_task` 以及其他 ``*_new_etm_*`` 创建函数)均为线程安全,可在不同 RTOS 任务中并发调用,无需担心资源冲突。
- 通道控制相关 API:cpp:func:`esp_etm_channel_connect` :cpp:func:`esp_etm_channel_enable` :cpp:func:`esp_etm_channel_disable` :cpp:func:`esp_etm_del_channel`)同样支持线程安全。针对不同通道的并发操作是安全的;若对同一通道进行并发操作,驱动会自动进行内部序列化。如果操作与当前通道状态不兼容,则会返回 :c:macro:`ESP_ERR_INVALID_STATE` 错误。
其他以 :cpp:type:`esp_etm_channel_handle_t`、:cpp:type:`esp_etm_task_handle_t` 和 :cpp:type:`esp_etm_event_handle_t` 作为首个位置参数的函数,则非线程安全,应避免从不同任务中调用此类函数。 - 所有 ETM API 均不允许在中断服务程序ISR环境下调用。
.. _etm-kconfig-options: .. _etm-kconfig-options:

View File

@@ -1,35 +0,0 @@
/*
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
/**
* NOTE: this is not the original header file from the esp_hw_support component.
* It is a stripped-down copy to support mocking.
*/
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief ETM channel handle
*/
typedef struct esp_etm_channel_t *esp_etm_channel_handle_t;
/**
* @brief ETM event handle
*/
typedef struct esp_etm_event_t *esp_etm_event_handle_t;
/**
* @brief ETM task handle
*/
typedef struct esp_etm_task_t *esp_etm_task_handle_t;
#ifdef __cplusplus
}
#endif

View File

@@ -3,11 +3,12 @@
message(STATUS "building ESP TIMER MOCKS") message(STATUS "building ESP TIMER MOCKS")
idf_component_get_property(original_esp_timer_dir esp_timer COMPONENT_OVERRIDEN_DIR) idf_component_get_property(original_esp_timer_dir esp_timer COMPONENT_OVERRIDEN_DIR)
idf_component_get_property(original_esp_hw_support_dir esp_hw_support COMPONENT_OVERRIDEN_DIR)
if(NOT original_esp_hw_support_dir)
idf_component_get_property(original_esp_hw_support_dir esp_hw_support COMPONENT_DIR)
endif()
set(include_dirs idf_component_mock(INCLUDE_DIRS "${original_esp_timer_dir}/include"
"${original_esp_timer_dir}/include" "${original_esp_hw_support_dir}/etm/include"
"${CMAKE_CURRENT_SOURCE_DIR}/../esp_hw_support/include")
idf_component_mock(INCLUDE_DIRS ${include_dirs}
REQUIRES esp_common REQUIRES esp_common
MOCK_HEADER_FILES ${original_esp_timer_dir}/include/esp_timer.h) MOCK_HEADER_FILES ${original_esp_timer_dir}/include/esp_timer.h)