diff --git a/components/esp_driver_gpio/src/gpio_etm.c b/components/esp_driver_gpio/src/gpio_etm.c index b0a3ea61ea..d521a64e72 100644 --- a/components/esp_driver_gpio/src/gpio_etm.c +++ b/components/esp_driver_gpio/src/gpio_etm.c @@ -8,11 +8,6 @@ #include #include #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 "driver/gpio.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, ...) { -#if CONFIG_ETM_ENABLE_DEBUG_LOG - esp_log_level_set(TAG, ESP_LOG_DEBUG); -#endif esp_err_t ret = ESP_OK; int chan_id = -1; 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, ...) { -#if CONFIG_ETM_ENABLE_DEBUG_LOG - esp_log_level_set(TAG, ESP_LOG_DEBUG); -#endif esp_err_t ret = ESP_OK; int chan_id = -1; uint8_t task_mask = 0; diff --git a/components/esp_driver_sdm/src/sdm.c b/components/esp_driver_sdm/src/sdm.c index 4ea47994aa..0a233bf100 100644 --- a/components/esp_driver_sdm/src/sdm.c +++ b/components/esp_driver_sdm/src/sdm.c @@ -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; #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 = { .cbs = { .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 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 @@ -408,7 +408,7 @@ esp_err_t sdm_channel_set_pulse_density(sdm_channel_handle_t chan, int8_t densit bool valid_state = false; sdm_fsm_t expected_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)) { valid_state = true; 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); 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; } diff --git a/components/esp_driver_tsens/src/temperature_sensor_etm.c b/components/esp_driver_tsens/src/temperature_sensor_etm.c index b6059e5092..9a3f680fe6 100644 --- a/components/esp_driver_tsens/src/temperature_sensor_etm.c +++ b/components/esp_driver_tsens/src/temperature_sensor_etm.c @@ -12,11 +12,6 @@ #include "hal/temperature_sensor_ll.h" #include "driver/temperature_sensor_etm.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" #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) { -#if CONFIG_ETM_ENABLE_DEBUG_LOG - esp_log_level_set(TAG, ESP_LOG_DEBUG); -#endif esp_etm_event_t *event = NULL; esp_err_t ret = ESP_OK; 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) { -#if CONFIG_ETM_ENABLE_DEBUG_LOG - esp_log_level_set(TAG, ESP_LOG_DEBUG); -#endif esp_etm_task_t *task = NULL; esp_err_t ret = ESP_OK; ESP_GOTO_ON_FALSE(tsens && config && out_task, ESP_ERR_INVALID_ARG, err, TAG, "invalid argument"); diff --git a/components/esp_hw_support/CMakeLists.txt b/components/esp_hw_support/CMakeLists.txt index dd3a052c89..ca9622c21c 100644 --- a/components/esp_hw_support/CMakeLists.txt +++ b/components/esp_hw_support/CMakeLists.txt @@ -5,7 +5,7 @@ idf_build_get_property(non_os_build NON_OS_BUILD) if(${target} STREQUAL "linux") idf_component_register(SRCS "port/linux/esp_random.c" "port/linux/chip_info.c" - INCLUDE_DIRS "include") + INCLUDE_DIRS "include" "etm/include") return() endif() @@ -122,7 +122,7 @@ if(NOT non_os_build) endif() if(CONFIG_SOC_ETM_SUPPORTED) - list(APPEND srcs "esp_etm.c") + list(APPEND srcs "etm/esp_etm.c") endif() if(CONFIG_SOC_PAU_SUPPORTED) @@ -175,7 +175,7 @@ else() endif() 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" "power_supply/include") diff --git a/components/esp_hw_support/Kconfig b/components/esp_hw_support/Kconfig index f16ca70eb5..7d20a580f5 100644 --- a/components/esp_hw_support/Kconfig +++ b/components/esp_hw_support/Kconfig @@ -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. 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 "./etm/Kconfig.etm" menu "Main XTAL Config" orsource "./port/$IDF_TARGET/Kconfig.xtal" diff --git a/components/esp_hw_support/etm/Kconfig.etm b/components/esp_hw_support/etm/Kconfig.etm new file mode 100644 index 0000000000..935c7dda51 --- /dev/null +++ b/components/esp_hw_support/etm/Kconfig.etm @@ -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 diff --git a/components/esp_hw_support/esp_etm.c b/components/esp_hw_support/etm/esp_etm.c similarity index 70% rename from components/esp_hw_support/esp_etm.c rename to components/esp_hw_support/etm/esp_etm.c index e3507f64e2..933aeb3ff2 100644 --- a/components/esp_hw_support/esp_etm.c +++ b/components/esp_hw_support/etm/esp_etm.c @@ -5,17 +5,17 @@ */ #include +#include #include #include #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 +#define LOG_LOCAL_LEVEL ESP_LOG_VERBOSE #endif #include "freertos/FreeRTOS.h" #include "freertos/task.h" -#include "soc/soc_caps.h" #include "soc/etm_periph.h" #include "esp_log.h" #include "esp_check.h" @@ -39,34 +39,35 @@ #define ETM_RCC_ATOMIC() #endif -static const char *TAG = "etm"; +#define TAG "etm" typedef struct etm_platform_t etm_platform_t; typedef struct etm_group_t etm_group_t; typedef struct esp_etm_channel_t esp_etm_channel_t; struct etm_platform_t { - _lock_t mutex; // platform level mutex lock - etm_group_t *groups[SOC_ETM_GROUPS]; // etm group pool - int group_ref_counts[SOC_ETM_GROUPS]; // reference count used to protect group install/uninstall + _lock_t mutex; // platform level mutex lock + etm_group_t *groups[SOC_ETM_ATTR(INST_NUM)]; // etm group pool + int group_ref_counts[SOC_ETM_ATTR(INST_NUM)]; // reference count used to protect group install/uninstall }; struct etm_group_t { int group_id; // hardware group id etm_hal_context_t hal; // hardware abstraction layer context - portMUX_TYPE spinlock; // to protect per-group register level concurrent access - esp_etm_channel_t *chans[SOC_ETM_CHANNELS_PER_GROUP]; + portMUX_TYPE spinlock; // to protect per-group light weight resource access + esp_etm_channel_t *chans[SOC_ETM_ATTR(CHANS_PER_INST)]; // array of channels in the group }; typedef enum { ETM_CHAN_FSM_INIT, ETM_CHAN_FSM_ENABLE, + ETM_CHAN_FSM_WAIT, } etm_chan_fsm_t; struct esp_etm_channel_t { int chan_id; // Channel ID 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_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; int group_id = group->group_id; - esp_err_t err = sleep_retention_entries_create(etm_reg_retention_info[group_id].regdma_entry_array, - etm_reg_retention_info[group_id].array_size, - REGDMA_LINK_PRI_ETM, etm_reg_retention_info[group_id].module); + esp_err_t err = sleep_retention_entries_create(soc_etm_retention_info[group_id].regdma_entry_array, + soc_etm_retention_info[group_id].array_size, + REGDMA_LINK_PRI_ETM, soc_etm_retention_info[group_id].module); return err; } static void etm_create_retention_module(etm_group_t *group) { 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); if (sleep_retention_is_module_inited(module) && !sleep_retention_is_module_created(module)) { 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 - 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); @@ -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_reset_register(group_id); } + #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 = { .cbs = { .create = { @@ -131,11 +133,13 @@ static etm_group_t *etm_acquire_group_handle(int group_id) }, .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) { // 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 + // initialize HAL context 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]); do_deinitialize = true; s_platform.groups[group_id] = NULL; // deregister from platform + etm_hal_deinit(&group->hal); // disable the bus clock for the ETM registers ETM_RCC_ATOMIC() { etm_ll_enable_bus_clock(group_id, false); } - } - _lock_release(&s_platform.mutex); - if (do_deinitialize) { #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)) { sleep_retention_module_free(module); } if (sleep_retention_is_module_inited(module)) { sleep_retention_module_deinit(module); } -#endif +#endif // ETM_USE_RETENTION_LINK + } + _lock_release(&s_platform.mutex); + + if (do_deinitialize) { free(group); 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; 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); ESP_RETURN_ON_FALSE(group, ESP_ERR_NO_MEM, TAG, "no mem for group (%d)", i); // loop to search free channel in the group 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]) { chan_id = j; group->chans[j] = chan; + chan->chan_id = chan_id; + chan->group = group; break; } } esp_os_exit_critical(&group->spinlock); if (chan_id < 0) { etm_release_group_handle(group); - group = NULL; } else { - chan->chan_id = chan_id; - chan->group = group; 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) { -#if CONFIG_ETM_ENABLE_DEBUG_LOG - esp_log_level_set(TAG, ESP_LOG_DEBUG); -#endif esp_err_t ret = ESP_OK; 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 - 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 - chan = heap_caps_calloc(1, sizeof(esp_etm_channel_t), ETM_MEM_ALLOC_CAPS); - ESP_GOTO_ON_FALSE(chan, ESP_ERR_NO_MEM, err, TAG, "no mem for channel"); + // allocate channel memory from internal memory because it contains atomic variable + 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 - 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; int group_id = group->group_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 (config->flags.allow_pd != 0) { + if (allow_pd) { etm_create_retention_module(group); } #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); *ret_chan = chan; return ESP_OK; @@ -279,7 +287,9 @@ err: 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->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; int group_id = group->group_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_RETURN_ON_FALSE(chan, ESP_ERR_INVALID_ARG, TAG, "invalid argument"); - ESP_RETURN_ON_FALSE(chan->fsm == ETM_CHAN_FSM_INIT, ESP_ERR_INVALID_STATE, TAG, "channel is not in init state"); - etm_group_t *group = chan->group; - etm_ll_enable_channel(group->hal.regs, chan->chan_id); - chan->fsm = ETM_CHAN_FSM_ENABLE; - return ESP_OK; + if (!chan) { + 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; + // 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); + // change state to ENABLE + atomic_store(&chan->fsm, ETM_CHAN_FSM_ENABLE); + return ESP_OK; + } else { + return ESP_ERR_INVALID_STATE; + } } 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"); - ESP_RETURN_ON_FALSE(chan->fsm == ETM_CHAN_FSM_ENABLE, ESP_ERR_INVALID_STATE, TAG, "channel not in enable state"); - etm_group_t *group = chan->group; - etm_ll_disable_channel(group->hal.regs, chan->chan_id); - chan->fsm = ETM_CHAN_FSM_INIT; - return ESP_OK; + if (!chan) { + 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; + // 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); + // change state to INIT + atomic_store(&chan->fsm, ETM_CHAN_FSM_INIT); + 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_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; uint32_t event_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); chan->event = event; 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, "channel %d => task %"PRIu32, chan->chan_id, task_id); return ESP_OK; @@ -357,11 +405,11 @@ esp_err_t esp_etm_dump(FILE *out_stream) fprintf(out_stream, "===========ETM Dump Start==========\r\n"); char line[80]; 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); ESP_RETURN_ON_FALSE(group, ESP_ERR_NO_MEM, TAG, "no mem for group (%d)", i); 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; esp_os_enter_critical(&group->spinlock); 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"); 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 diff --git a/components/esp_hw_support/include/esp_etm.h b/components/esp_hw_support/etm/include/esp_etm.h similarity index 100% rename from components/esp_hw_support/include/esp_etm.h rename to components/esp_hw_support/etm/include/esp_etm.h diff --git a/components/esp_hw_support/include/esp_private/etm_interface.h b/components/esp_hw_support/etm/include/esp_private/etm_interface.h similarity index 100% rename from components/esp_hw_support/include/esp_private/etm_interface.h rename to components/esp_hw_support/etm/include/esp_private/etm_interface.h diff --git a/components/esp_hw_support/test_apps/esp_hw_support_unity_tests/main/test_etm_core.c b/components/esp_hw_support/test_apps/esp_hw_support_unity_tests/main/test_etm_core.c index 4c2f850efd..7454ef2fb7 100644 --- a/components/esp_hw_support/test_apps/esp_hw_support_unity_tests/main/test_etm_core.c +++ b/components/esp_hw_support/test_apps/esp_hw_support_unity_tests/main/test_etm_core.c @@ -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 */ @@ -10,16 +10,15 @@ #include "freertos/task.h" #include "unity.h" #include "esp_etm.h" -#include "soc/soc_caps.h" -#include "esp_attr.h" +#include "soc/etm_periph.h" TEST_CASE("etm_channel_install_uninstall", "[etm]") { 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 = {}; - for (int i = 0; i < SOC_ETM_GROUPS; i++) { - for (int j = 0; j < SOC_ETM_CHANNELS_PER_GROUP; j++) { + for (int i = 0; i < SOC_ETM_ATTR(INST_NUM); i++) { + 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_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_OK(esp_etm_channel_disable(etm_chans[0][0])); - for (int i = 0; i < SOC_ETM_GROUPS; i++) { - for (int j = 0; j < SOC_ETM_CHANNELS_PER_GROUP; j++) { + for (int i = 0; i < SOC_ETM_ATTR(INST_NUM); i++) { + for (int j = 0; j < SOC_ETM_ATTR(CHANS_PER_INST); j++) { TEST_ESP_OK(esp_etm_del_channel(etm_chans[i][j])); } } diff --git a/components/soc/esp32c5/etm_periph.c b/components/soc/esp32c5/etm_periph.c index 0084a78164..ea6b2ab7c4 100644 --- a/components/soc/esp32c5/etm_periph.c +++ b/components/soc/esp32c5/etm_periph.c @@ -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 */ @@ -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] = { .module = SLEEP_RETENTION_MODULE_ETM0, .regdma_entry_array = etm_regdma_entries, diff --git a/components/soc/esp32c5/include/soc/Kconfig.soc_caps.in b/components/soc/esp32c5/include/soc/Kconfig.soc_caps.in index 54daa898b7..6f1b35c349 100644 --- a/components/soc/esp32c5/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32c5/include/soc/Kconfig.soc_caps.in @@ -523,18 +523,6 @@ config SOC_GDMA_SUPPORT_WEIGHTED_ARBITRATION bool 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 int default 1 @@ -651,6 +639,10 @@ config SOC_SDM_SUPPORT_SLEEP_RETENTION bool default y +config SOC_ETM_SUPPORT_SLEEP_RETENTION + bool + default y + config SOC_ANA_CMPR_NUM int default 1 diff --git a/components/soc/esp32c5/include/soc/soc_caps.h b/components/soc/esp32c5/include/soc/soc_caps.h index 3a7065a0c4..b668b44f73 100644 --- a/components/soc/esp32c5/include/soc/soc_caps.h +++ b/components/soc/esp32c5/include/soc/soc_caps.h @@ -204,11 +204,6 @@ #define SOC_AHB_GDMA_SUPPORT_PSRAM 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 ---------------------------------------*/ // ESP32-C5 has 1 GPIO peripheral #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_SDM_SUPPORT_SLEEP_RETENTION 1 +#define SOC_ETM_SUPPORT_SLEEP_RETENTION 1 /*------------------------- Analog Comparator CAPS ---------------------------*/ #define SOC_ANA_CMPR_NUM (1U) diff --git a/components/soc/esp32c5/include/soc/soc_caps_full.h b/components/soc/esp32c5/include/soc/soc_caps_full.h index 63d2d2eec5..d9ce210e7d 100644 --- a/components/soc/esp32c5/include/soc/soc_caps_full.h +++ b/components/soc/esp32c5/include/soc/soc_caps_full.h @@ -23,3 +23,7 @@ /*--------------------------- 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 diff --git a/components/soc/esp32c6/etm_periph.c b/components/soc/esp32c6/etm_periph.c index 0084a78164..ea6b2ab7c4 100644 --- a/components/soc/esp32c6/etm_periph.c +++ b/components/soc/esp32c6/etm_periph.c @@ -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 */ @@ -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] = { .module = SLEEP_RETENTION_MODULE_ETM0, .regdma_entry_array = etm_regdma_entries, diff --git a/components/soc/esp32c6/include/soc/Kconfig.soc_caps.in b/components/soc/esp32c6/include/soc/Kconfig.soc_caps.in index 7e7068ed44..ac19a476db 100644 --- a/components/soc/esp32c6/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32c6/include/soc/Kconfig.soc_caps.in @@ -459,18 +459,6 @@ config SOC_GDMA_SUPPORT_SLEEP_RETENTION bool 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 int default 1 @@ -583,6 +571,10 @@ config SOC_SDM_SUPPORT_SLEEP_RETENTION bool default y +config SOC_ETM_SUPPORT_SLEEP_RETENTION + bool + default y + config SOC_I2C_NUM int default 2 diff --git a/components/soc/esp32c6/include/soc/soc_caps.h b/components/soc/esp32c6/include/soc/soc_caps.h index 1ef964369e..c59db3e62d 100644 --- a/components/soc/esp32c6/include/soc/soc_caps.h +++ b/components/soc/esp32c6/include/soc/soc_caps.h @@ -183,11 +183,6 @@ #define SOC_GDMA_SUPPORT_ETM 1 // Support ETM submodule #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 ---------------------------------------*/ // ESP32-C6 has 1 GPIO peripheral #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_SDM_SUPPORT_SLEEP_RETENTION 1 +#define SOC_ETM_SUPPORT_SLEEP_RETENTION 1 /*-------------------------- I2C CAPS ----------------------------------------*/ // ESP32-C6 has 1 I2C diff --git a/components/soc/esp32c6/include/soc/soc_caps_full.h b/components/soc/esp32c6/include/soc/soc_caps_full.h index 63d2d2eec5..d9ce210e7d 100644 --- a/components/soc/esp32c6/include/soc/soc_caps_full.h +++ b/components/soc/esp32c6/include/soc/soc_caps_full.h @@ -23,3 +23,7 @@ /*--------------------------- 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 diff --git a/components/soc/esp32c61/etm_periph.c b/components/soc/esp32c61/etm_periph.c index 0084a78164..ea6b2ab7c4 100644 --- a/components/soc/esp32c61/etm_periph.c +++ b/components/soc/esp32c61/etm_periph.c @@ -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 */ @@ -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] = { .module = SLEEP_RETENTION_MODULE_ETM0, .regdma_entry_array = etm_regdma_entries, diff --git a/components/soc/esp32c61/include/soc/Kconfig.soc_caps.in b/components/soc/esp32c61/include/soc/Kconfig.soc_caps.in index 725f96b6e0..5bb67cfc56 100644 --- a/components/soc/esp32c61/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32c61/include/soc/Kconfig.soc_caps.in @@ -403,14 +403,6 @@ config SOC_GDMA_SUPPORT_WEIGHTED_ARBITRATION bool 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 diff --git a/components/soc/esp32c61/include/soc/soc_caps.h b/components/soc/esp32c61/include/soc/soc_caps.h index a04929dfe7..7abf05d6a9 100644 --- a/components/soc/esp32c61/include/soc/soc_caps.h +++ b/components/soc/esp32c61/include/soc/soc_caps.h @@ -161,10 +161,7 @@ #define SOC_AHB_GDMA_SUPPORT_PSRAM 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 +#define SOC_ETM_SUPPORT_SLEEP_RETENTION 1 /*-------------------------- GPIO CAPS ---------------------------------------*/ // ESP32-C61 has 1 GPIO peripheral diff --git a/components/soc/esp32c61/include/soc/soc_caps_full.h b/components/soc/esp32c61/include/soc/soc_caps_full.h index 6ccb00bd76..0f0c3fe392 100644 --- a/components/soc/esp32c61/include/soc/soc_caps_full.h +++ b/components/soc/esp32c61/include/soc/soc_caps_full.h @@ -19,3 +19,7 @@ /*--------------------------- Watch Dog ------------------------------------------*/ #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 diff --git a/components/soc/esp32h2/etm_periph.c b/components/soc/esp32h2/etm_periph.c index 0084a78164..ea6b2ab7c4 100644 --- a/components/soc/esp32h2/etm_periph.c +++ b/components/soc/esp32h2/etm_periph.c @@ -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 */ @@ -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] = { .module = SLEEP_RETENTION_MODULE_ETM0, .regdma_entry_array = etm_regdma_entries, diff --git a/components/soc/esp32h2/include/soc/Kconfig.soc_caps.in b/components/soc/esp32h2/include/soc/Kconfig.soc_caps.in index 31ed4d660a..b7a521cf58 100644 --- a/components/soc/esp32h2/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32h2/include/soc/Kconfig.soc_caps.in @@ -479,18 +479,6 @@ config SOC_GDMA_SUPPORT_SLEEP_RETENTION bool 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 int default 1 @@ -587,6 +575,10 @@ config SOC_SDM_SUPPORT_SLEEP_RETENTION bool default y +config SOC_ETM_SUPPORT_SLEEP_RETENTION + bool + default y + config SOC_ANA_CMPR_NUM int default 1 diff --git a/components/soc/esp32h2/include/soc/soc_caps.h b/components/soc/esp32h2/include/soc/soc_caps.h index 8b2b490874..30a8fea465 100644 --- a/components/soc/esp32h2/include/soc/soc_caps.h +++ b/components/soc/esp32h2/include/soc/soc_caps.h @@ -206,11 +206,6 @@ #define SOC_GDMA_SUPPORT_ETM 1 // Support ETM submodule #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 ---------------------------------------*/ // ESP32-H2 has 1 GPIO peripheral #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_SDM_SUPPORT_SLEEP_RETENTION 1 +#define SOC_ETM_SUPPORT_SLEEP_RETENTION 1 /*------------------------- Analog Comparator CAPS ---------------------------*/ #define SOC_ANA_CMPR_NUM (1U) diff --git a/components/soc/esp32h2/include/soc/soc_caps_full.h b/components/soc/esp32h2/include/soc/soc_caps_full.h index 63d2d2eec5..d9ce210e7d 100644 --- a/components/soc/esp32h2/include/soc/soc_caps_full.h +++ b/components/soc/esp32h2/include/soc/soc_caps_full.h @@ -23,3 +23,7 @@ /*--------------------------- 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 diff --git a/components/soc/esp32h21/include/soc/Kconfig.soc_caps.in b/components/soc/esp32h21/include/soc/Kconfig.soc_caps.in index b0bda3c2bc..6d7f798d0d 100644 --- a/components/soc/esp32h21/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32h21/include/soc/Kconfig.soc_caps.in @@ -331,14 +331,6 @@ config SOC_GDMA_SUPPORT_SLEEP_RETENTION bool default y -config SOC_ETM_GROUPS - int - default 1 - -config SOC_ETM_CHANNELS_PER_GROUP - int - default 50 - config SOC_GPIO_PORT int default 1 @@ -383,6 +375,14 @@ config SOC_GPIO_SUPPORT_HOLD_SINGLE_IO_IN_DSLP bool 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 int default 7 diff --git a/components/soc/esp32h21/include/soc/soc_caps.h b/components/soc/esp32h21/include/soc/soc_caps.h index 4ce2e260e9..ce0ac6b56f 100644 --- a/components/soc/esp32h21/include/soc/soc_caps.h +++ b/components/soc/esp32h21/include/soc/soc_caps.h @@ -191,10 +191,6 @@ // #define SOC_GDMA_SUPPORT_ETM 1 // Support ETM submodule TODO: IDF-11604 #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 ---------------------------------------*/ // ESP32-H21 has 1 GPIO peripheral #define SOC_GPIO_PORT 1U @@ -235,6 +231,9 @@ // #define SOC_CLOCKOUT_HAS_SOURCE_GATE (1) // #define SOC_GPIO_CLOCKOUT_CHANNEL_NUM (3) +#define SOC_SDM_SUPPORT_SLEEP_RETENTION 1 +#define SOC_ETM_SUPPORT_SLEEP_RETENTION 1 + /*-------------------------- RTCIO CAPS --------------------------------------*/ /* No dedicated LP_IOMUX subsystem on ESP32-H21. LP functions are still supported * for hold, wake & 32kHz crystal functions - via LP_AON registers */ diff --git a/components/soc/esp32h21/include/soc/soc_caps_full.h b/components/soc/esp32h21/include/soc/soc_caps_full.h index 6ccb00bd76..d9ce210e7d 100644 --- a/components/soc/esp32h21/include/soc/soc_caps_full.h +++ b/components/soc/esp32h21/include/soc/soc_caps_full.h @@ -19,3 +19,11 @@ /*--------------------------- Watch Dog ------------------------------------------*/ #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 diff --git a/components/soc/esp32h4/etm_periph.c b/components/soc/esp32h4/etm_periph.c index 82e5ac6ffb..9f44803e7c 100644 --- a/components/soc/esp32h4/etm_periph.c +++ b/components/soc/esp32h4/etm_periph.c @@ -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] = { .module = SLEEP_RETENTION_MODULE_ETM0, .regdma_entry_array = etm_regdma_entries, diff --git a/components/soc/esp32h4/include/soc/Kconfig.soc_caps.in b/components/soc/esp32h4/include/soc/Kconfig.soc_caps.in index e2c906eba1..efd9d3a9e8 100644 --- a/components/soc/esp32h4/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32h4/include/soc/Kconfig.soc_caps.in @@ -263,18 +263,6 @@ config SOC_AHB_GDMA_SUPPORT_PSRAM bool 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 int default 1 @@ -355,6 +343,10 @@ config SOC_SDM_SUPPORT_SLEEP_RETENTION bool default y +config SOC_ETM_SUPPORT_SLEEP_RETENTION + bool + default y + config SOC_I2C_NUM int default 2 diff --git a/components/soc/esp32h4/include/soc/soc_caps.h b/components/soc/esp32h4/include/soc/soc_caps.h index a4691c82e1..adcb3c3017 100644 --- a/components/soc/esp32h4/include/soc/soc_caps.h +++ b/components/soc/esp32h4/include/soc/soc_caps.h @@ -198,11 +198,6 @@ #define SOC_GDMA_SUPPORT_SLEEP_RETENTION 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 ---------------------------------------*/ // ESP32-H4 has 1 GPIO peripheral #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_SDM_SUPPORT_SLEEP_RETENTION 1 +#define SOC_ETM_SUPPORT_SLEEP_RETENTION 1 /*-------------------------- I2C CAPS ----------------------------------------*/ // ESP32-H4 has 2 I2C diff --git a/components/soc/esp32h4/include/soc/soc_caps_full.h b/components/soc/esp32h4/include/soc/soc_caps_full.h index 63d2d2eec5..d9ce210e7d 100644 --- a/components/soc/esp32h4/include/soc/soc_caps_full.h +++ b/components/soc/esp32h4/include/soc/soc_caps_full.h @@ -23,3 +23,7 @@ /*--------------------------- 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 diff --git a/components/soc/esp32p4/etm_periph.c b/components/soc/esp32p4/etm_periph.c index 5e24359e30..88acc8cc77 100644 --- a/components/soc/esp32p4/etm_periph.c +++ b/components/soc/esp32p4/etm_periph.c @@ -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 */ @@ -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] = { .module = SLEEP_RETENTION_MODULE_ETM0, .regdma_entry_array = etm_regdma_entries, diff --git a/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in b/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in index 71a741369f..671aca30e2 100644 --- a/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in @@ -635,18 +635,6 @@ config SOC_DMA2D_RX_CHANNELS_PER_GROUP int 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 int default 1 @@ -771,6 +759,10 @@ config SOC_SDM_SUPPORT_SLEEP_RETENTION bool default y +config SOC_ETM_SUPPORT_SLEEP_RETENTION + bool + default y + config SOC_ANA_CMPR_NUM int default 2 diff --git a/components/soc/esp32p4/include/soc/soc_caps.h b/components/soc/esp32p4/include/soc/soc_caps.h index 3650733055..59519b23da 100644 --- a/components/soc/esp32p4/include/soc/soc_caps.h +++ b/components/soc/esp32p4/include/soc/soc_caps.h @@ -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_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 ---------------------------------------*/ // ESP32-P4 has 1 GPIO peripheral #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_SDM_SUPPORT_SLEEP_RETENTION 1 +#define SOC_ETM_SUPPORT_SLEEP_RETENTION 1 /*------------------------- Analog Comparator CAPS ---------------------------*/ #define SOC_ANA_CMPR_NUM (2) diff --git a/components/soc/esp32p4/include/soc/soc_caps_full.h b/components/soc/esp32p4/include/soc/soc_caps_full.h index c1cdc3b38c..44735d0ac2 100644 --- a/components/soc/esp32p4/include/soc/soc_caps_full.h +++ b/components/soc/esp32p4/include/soc/soc_caps_full.h @@ -23,3 +23,7 @@ /*--------------------------- SDM (Sigma-Delta Modulator) ------------------------*/ #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 + +/*--------------------------- 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 diff --git a/components/soc/include/soc/etm_periph.h b/components/soc/include/soc/etm_periph.h index f7168ff717..7b64aba527 100644 --- a/components/soc/include/soc/etm_periph.h +++ b/components/soc/include/soc/etm_periph.h @@ -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 */ #pragma once -#include "soc/soc_caps.h" +#include +#include "soc/soc_caps_full.h" #include "soc/regdma.h" -#if SOC_ETM_SUPPORT_SLEEP_RETENTION +#if SOC_HAS(PAU) #include "soc/retention_periph_defs.h" #endif +// helper macros to access module attributes +#define SOC_ETM_ATTR(_attr) SOC_MODULE_ATTR(ETM, _attr) + #ifdef __cplusplus extern "C" { #endif -#if SOC_ETM_SUPPORT_SLEEP_RETENTION -typedef struct { - periph_retention_module_t module; - const regdma_entries_config_t *regdma_entry_array; - uint32_t array_size; -} etm_reg_retention_info_t; +#if SOC_HAS(PAU) -extern const etm_reg_retention_info_t etm_reg_retention_info[SOC_ETM_GROUPS]; -#endif // SOC_ETM_SUPPORT_SLEEP_RETENTION +typedef struct { + 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 } diff --git a/docs/docs_not_updated/esp32h4.txt b/docs/docs_not_updated/esp32h4.txt index 47566d3f39..ea29f01fc1 100644 --- a/docs/docs_not_updated/esp32h4.txt +++ b/docs/docs_not_updated/esp32h4.txt @@ -146,7 +146,6 @@ api-reference/peripherals/usb_host.rst api-reference/peripherals/camera_driver.rst api-reference/peripherals/adc_oneshot.rst api-reference/peripherals/twai.rst -api-reference/peripherals/etm.rst api-reference/peripherals/sdspi_share.rst api-reference/peripherals/ana_cmpr.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_optional_feature.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/lcd/i80_lcd.rst api-reference/peripherals/lcd/index.rst diff --git a/docs/doxygen/Doxyfile b/docs/doxygen/Doxyfile index b4b575fb29..6c0db67ea3 100644 --- a/docs/doxygen/Doxyfile +++ b/docs/doxygen/Doxyfile @@ -165,12 +165,12 @@ INPUT = \ $(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_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_async_memcpy.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_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_types.h \ $(PROJECT_PATH)/components/esp_hw_support/include/esp_mac.h \ diff --git a/docs/en/api-reference/peripherals/etm.rst b/docs/en/api-reference/peripherals/etm.rst index 411e1d1d13..89f16d411e 100644 --- a/docs/en/api-reference/peripherals/etm.rst +++ b/docs/en/api-reference/peripherals/etm.rst @@ -148,11 +148,11 @@ When power management is enabled, i.e., :ref:`CONFIG_PM_ENABLE` is on, the syste 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. - -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. +- 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`. +- No functions are allowed to run within the ISR environment. .. _etm-kconfig-options: diff --git a/docs/zh_CN/api-reference/peripherals/etm.rst b/docs/zh_CN/api-reference/peripherals/etm.rst index 1d2e9350a7..0f6127a356 100644 --- a/docs/zh_CN/api-reference/peripherals/etm.rst +++ b/docs/zh_CN/api-reference/peripherals/etm.rst @@ -148,11 +148,11 @@ ETM 通道分析 线程安全 ^^^^^^^^^^^^^ -ETM 驱动程序会确保工厂函数 :cpp:func:`esp_etm_new_channel` 和 :cpp:func:`gpio_new_etm_task` 的线程安全。使用时,可以直接从不同的 RTOS 任务中调用此类函数,无需额外锁保护。 +ETM 核心驱动程序具备线程安全性。 -在 ISR 环境中,不支持运行任何函数。 - -其他以 :cpp:type:`esp_etm_channel_handle_t`、:cpp:type:`esp_etm_task_handle_t` 和 :cpp:type:`esp_etm_event_handle_t` 作为首个位置参数的函数,则非线程安全,应避免从不同任务中调用此类函数。 +- 工厂函数(如 :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` 错误。 +- 所有 ETM API 均不允许在中断服务程序(ISR)环境下调用。 .. _etm-kconfig-options: diff --git a/tools/mocks/esp_hw_support/include/esp_etm.h b/tools/mocks/esp_hw_support/include/esp_etm.h deleted file mode 100644 index 38963482db..0000000000 --- a/tools/mocks/esp_hw_support/include/esp_etm.h +++ /dev/null @@ -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 diff --git a/tools/mocks/esp_timer/CMakeLists.txt b/tools/mocks/esp_timer/CMakeLists.txt index 39fe5a78f4..163d85338d 100644 --- a/tools/mocks/esp_timer/CMakeLists.txt +++ b/tools/mocks/esp_timer/CMakeLists.txt @@ -3,11 +3,12 @@ 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_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 - "${original_esp_timer_dir}/include" - "${CMAKE_CURRENT_SOURCE_DIR}/../esp_hw_support/include") - -idf_component_mock(INCLUDE_DIRS ${include_dirs} - REQUIRES esp_common - MOCK_HEADER_FILES ${original_esp_timer_dir}/include/esp_timer.h) +idf_component_mock(INCLUDE_DIRS "${original_esp_timer_dir}/include" + "${original_esp_hw_support_dir}/etm/include" + REQUIRES esp_common + MOCK_HEADER_FILES ${original_esp_timer_dir}/include/esp_timer.h)