From 64d913f86b47096c6acf1e12db2d0368a9a25733 Mon Sep 17 00:00:00 2001 From: Erhan Kurubas Date: Thu, 30 Jul 2026 21:05:19 +0300 Subject: [PATCH 1/3] feat(riscv_trace): add trace support for ESP32-C61 --- .../esp32c61/include/hal/riscv_trace_ll.h | 261 ++++++++++++++++++ .../esp_riscv_trace/test_apps/basic/README.md | 4 +- .../esp32c61/include/soc/Kconfig.soc_caps.in | 20 ++ .../soc/esp32c61/include/soc/soc_caps.h | 7 + 4 files changed, 290 insertions(+), 2 deletions(-) create mode 100644 components/esp_hal_debug_assist/esp32c61/include/hal/riscv_trace_ll.h diff --git a/components/esp_hal_debug_assist/esp32c61/include/hal/riscv_trace_ll.h b/components/esp_hal_debug_assist/esp32c61/include/hal/riscv_trace_ll.h new file mode 100644 index 00000000000..9b1c1aac905 --- /dev/null +++ b/components/esp_hal_debug_assist/esp32c61/include/hal/riscv_trace_ll.h @@ -0,0 +1,261 @@ +/* + * SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#include +#include + +#include "soc/trace_reg.h" +#include "soc/trace_struct.h" +#include "soc/pcr_struct.h" +#include "hal/assert.h" +#include "hal/riscv_trace_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** @brief Return the register block for the given core. */ +static inline trace_dev_t *riscv_trace_ll_get_hw(int core) +{ + HAL_ASSERT(core == 0); + (void)core; + return &TRACE; +} + +/*--------------------------------------------------------------------------- + * Clock and reset + *--------------------------------------------------------------------------*/ + +/** @brief Enable or disable the TRACE clock. */ +static inline void riscv_trace_ll_enable_bus_clock(bool enable) +{ + PCR.trace_conf.trace_clk_en = enable; +} + +/** @brief Assert and release the reset of the encoder. */ +static inline void riscv_trace_ll_reset_register(int core) +{ + (void)core; + PCR.trace_conf.trace_rst_en = 1; + PCR.trace_conf.trace_rst_en = 0; +} + +/** @brief Enable the per-module register clock gate. */ +static inline void riscv_trace_ll_enable_module_clock(trace_dev_t *hw, bool enable) +{ + hw->clock_gate.clk_en = enable; +} + +/*--------------------------------------------------------------------------- + * Memory configuration + *--------------------------------------------------------------------------*/ + +static inline void riscv_trace_ll_set_mem_start_addr(trace_dev_t *hw, uint32_t addr) +{ + hw->mem_start_addr.mem_start_addr = addr; +} + +static inline void riscv_trace_ll_set_mem_end_addr(trace_dev_t *hw, uint32_t addr) +{ + hw->mem_end_addr.mem_end_addr = addr; +} + +static inline uint32_t riscv_trace_ll_get_mem_current_addr(trace_dev_t *hw) +{ + return hw->mem_current_addr.mem_current_addr; +} + +/** @brief Reload the current address from the start address. */ +static inline void riscv_trace_ll_update_mem_current_addr(trace_dev_t *hw) +{ + hw->mem_addr_update.mem_current_addr_update = 1; +} + +/*--------------------------------------------------------------------------- + * Status + *--------------------------------------------------------------------------*/ + +static inline uint32_t riscv_trace_ll_get_fifo_status(trace_dev_t *hw) +{ + return hw->fifo_status.val; +} + +/*--------------------------------------------------------------------------- + * Trigger, loop mode and restart + *--------------------------------------------------------------------------*/ + +static inline void riscv_trace_ll_trigger_on(trace_dev_t *hw) +{ + hw->trigger.trigger_on = 1; +} + +static inline void riscv_trace_ll_trigger_off(trace_dev_t *hw) +{ + hw->trigger.trigger_off = 1; +} + +static inline void riscv_trace_ll_set_mem_loop(trace_dev_t *hw, bool loop) +{ + hw->trigger.mem_loop = loop; +} + +static inline void riscv_trace_ll_set_restart_ena(trace_dev_t *hw, bool enable) +{ + hw->trigger.restart_ena = enable; +} + +/*--------------------------------------------------------------------------- + * Encoder options (config register) + *--------------------------------------------------------------------------*/ + +static inline void riscv_trace_ll_set_full_address(trace_dev_t *hw, bool full) +{ + hw->config.full_address = full; +} + +static inline void riscv_trace_ll_set_stall_ena(trace_dev_t *hw, bool enable) +{ + hw->config.stall_ena = enable; +} + +static inline void riscv_trace_ll_set_halt_ena(trace_dev_t *hw, bool enable) +{ + hw->config.halt_ena = enable; +} + +static inline void riscv_trace_ll_set_reset_ena(trace_dev_t *hw, bool enable) +{ + hw->config.reset_ena = enable; +} + +static inline void riscv_trace_ll_set_dm_trigger_ena(trace_dev_t *hw, bool enable) +{ + hw->config.dm_trigger_ena = enable; +} + +/*--------------------------------------------------------------------------- + * Resynchronization + *--------------------------------------------------------------------------*/ + +/** @brief Whether the resync counter can represent the given mode. */ +static inline bool riscv_trace_ll_resync_mode_is_supported(uint32_t mode) +{ + return mode == RISCV_TRACE_RESYNC_DISABLED || mode == RISCV_TRACE_RESYNC_PACKET || + mode == RISCV_TRACE_RESYNC_CYCLE; +} + +static inline void riscv_trace_ll_set_resync_mode(trace_dev_t *hw, uint32_t mode) +{ + hw->resync_prolonged.resync_mode = mode; +} + +static inline void riscv_trace_ll_set_resync_threshold(trace_dev_t *hw, uint32_t threshold) +{ + hw->resync_prolonged.resync_prolonged = threshold; +} + +/*--------------------------------------------------------------------------- + * AHB configuration + *--------------------------------------------------------------------------*/ + +static inline void riscv_trace_ll_set_ahb_burst(trace_dev_t *hw, uint32_t hburst) +{ + hw->ahb_config.hburst = hburst; +} + +static inline void riscv_trace_ll_set_ahb_max_incr(trace_dev_t *hw, uint32_t max_incr) +{ + hw->ahb_config.max_incr = max_incr; +} + +/*--------------------------------------------------------------------------- + * Interrupts + *--------------------------------------------------------------------------*/ + +static inline void riscv_trace_ll_set_intr_ena(trace_dev_t *hw, uint32_t mask) +{ + hw->intr_ena.val = mask; +} + +static inline uint32_t riscv_trace_ll_get_intr_raw(trace_dev_t *hw) +{ + return hw->intr_raw.val; +} + +static inline void riscv_trace_ll_clear_intr(trace_dev_t *hw, uint32_t mask) +{ + hw->intr_clr.val = mask; +} + +/*--------------------------------------------------------------------------- + * Filter unit + *--------------------------------------------------------------------------*/ + +static inline void riscv_trace_ll_set_filter_en(trace_dev_t *hw, bool enable) +{ + hw->filter_control.filter_en = enable; +} + +static inline void riscv_trace_ll_set_filter_control(trace_dev_t *hw, bool match_comp, + bool match_privilege, bool match_ecause, + bool match_interrupt) +{ + hw->filter_control.match_comp = match_comp; + hw->filter_control.match_privilege = match_privilege; + hw->filter_control.match_ecause = match_ecause; + hw->filter_control.match_interrupt = match_interrupt; +} + +static inline bool riscv_trace_ll_priv_is_supported(uint32_t priv) +{ + return priv == RISCV_TRACE_PRIV_USER || priv == RISCV_TRACE_PRIV_MACHINE; +} + +static inline void riscv_trace_ll_set_filter_match_control(trace_dev_t *hw, uint32_t priv_choice, + bool intr_value, uint32_t ecause_choice) +{ + // This target has no supervisor mode, so the selector is 1 bit: 0 = user, 1 = machine. + hw->filter_match_control.match_choice_privilege = (priv_choice == RISCV_TRACE_PRIV_MACHINE); + hw->filter_match_control.match_value_interrupt = intr_value; + hw->filter_match_control.match_choice_ecause = ecause_choice; +} + +static inline void riscv_trace_ll_set_p_comparator(trace_dev_t *hw, uint32_t input, + uint32_t function, bool notify) +{ + hw->filter_comparator_control.p_input = input; + hw->filter_comparator_control.p_function = function; + hw->filter_comparator_control.p_notify = notify; +} + +static inline void riscv_trace_ll_set_s_comparator(trace_dev_t *hw, uint32_t input, + uint32_t function, bool notify) +{ + hw->filter_comparator_control.s_input = input; + hw->filter_comparator_control.s_function = function; + hw->filter_comparator_control.s_notify = notify; +} + +static inline void riscv_trace_ll_set_match_mode(trace_dev_t *hw, uint32_t mode) +{ + hw->filter_comparator_control.match_mode = mode; +} + +static inline void riscv_trace_ll_set_p_match_value(trace_dev_t *hw, uint32_t value) +{ + hw->filter_p_comparator_match.p_match = value; +} + +static inline void riscv_trace_ll_set_s_match_value(trace_dev_t *hw, uint32_t value) +{ + hw->filter_s_comparator_match.s_match = value; +} + +#ifdef __cplusplus +} +#endif diff --git a/components/esp_riscv_trace/test_apps/basic/README.md b/components/esp_riscv_trace/test_apps/basic/README.md index 5a882fdee32..dbbdc939d58 100644 --- a/components/esp_riscv_trace/test_apps/basic/README.md +++ b/components/esp_riscv_trace/test_apps/basic/README.md @@ -1,5 +1,5 @@ -| Supported Targets | ESP32-C5 | ESP32-C6 | ESP32-H2 | ESP32-P4 | ESP32-S31 | -| ----------------- | -------- | -------- | -------- | -------- | --------- | +| Supported Targets | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-P4 | ESP32-S31 | +| ----------------- | -------- | -------- | --------- | -------- | -------- | --------- | # RISC-V Trace Basic Test App diff --git a/components/soc/esp32c61/include/soc/Kconfig.soc_caps.in b/components/soc/esp32c61/include/soc/Kconfig.soc_caps.in index 1beff414086..fce473d8223 100644 --- a/components/soc/esp32c61/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32c61/include/soc/Kconfig.soc_caps.in @@ -119,6 +119,10 @@ config SOC_APM_SUPPORTED bool default y +config SOC_RISCV_TRACE_SUPPORTED + bool + default y + config SOC_PMU_SUPPORTED bool default y @@ -1234,3 +1238,19 @@ config SOC_PHY_CALIBRATION_CLOCK_IS_INDEPENDENT config SOC_DEBUG_HAVE_OCD_STUB_BINS bool default y + +config SOC_RISCV_TRACE_HAS_CONFIG_REG + bool + default y + +config SOC_RISCV_TRACE_AHB_CONFIGURABLE + bool + default y + +config SOC_RISCV_TRACE_FILTER_SUPPORTED + bool + default y + +config SOC_RISCV_TRACE_PRIV_WIDTH + int + default 1 diff --git a/components/soc/esp32c61/include/soc/soc_caps.h b/components/soc/esp32c61/include/soc/soc_caps.h index 109892d7961..3d38ba7d85d 100644 --- a/components/soc/esp32c61/include/soc/soc_caps.h +++ b/components/soc/esp32c61/include/soc/soc_caps.h @@ -52,6 +52,7 @@ #define SOC_SECURE_BOOT_SUPPORTED 1 #define SOC_BOD_SUPPORTED 1 #define SOC_APM_SUPPORTED 1 /*!< Support for APM peripheral */ +#define SOC_RISCV_TRACE_SUPPORTED 1 #define SOC_PMU_SUPPORTED 1 #define SOC_PMU_PVT_SUPPORTED 1 #define SOC_RTC_TIMER_SUPPORTED 1 @@ -499,5 +500,11 @@ /*------------------------------------- DEBUG CAPS -------------------------------------*/ #define SOC_DEBUG_HAVE_OCD_STUB_BINS (1) +/*-------------------------- RISC-V TRACE CAPS ------------------------------*/ +#define SOC_RISCV_TRACE_HAS_CONFIG_REG (1) /*!< Has the encoder config register */ +#define SOC_RISCV_TRACE_AHB_CONFIGURABLE (1) /*!< AHB write master is configurable */ +#define SOC_RISCV_TRACE_FILTER_SUPPORTED (1) /*!< Has the filter unit */ +#define SOC_RISCV_TRACE_PRIV_WIDTH (1U) /*!< Bits in the privilege field (privilege_width_p) */ + /*------------------------------------- No Reset CAPS -------------------------------------*/ // \#define SOC_CAPS_NO_RESET_BY_ANA_BOD (1) //TODO: [ESP32C61] IDF-9254 From cde1da8fe6d836a7ade6979fd17b39198ba424c4 Mon Sep 17 00:00:00 2001 From: Erhan Kurubas Date: Thu, 30 Jul 2026 21:41:35 +0300 Subject: [PATCH 2/3] feat(riscv_trace): add trace support for ESP32-H4 --- .../esp32h4/include/hal/riscv_trace_ll.h | 271 ++++++++++++++++++ .../esp_riscv_trace/test_apps/basic/README.md | 4 +- .../esp32h4/include/soc/Kconfig.soc_caps.in | 20 ++ components/soc/esp32h4/include/soc/soc_caps.h | 7 + 4 files changed, 300 insertions(+), 2 deletions(-) create mode 100644 components/esp_hal_debug_assist/esp32h4/include/hal/riscv_trace_ll.h diff --git a/components/esp_hal_debug_assist/esp32h4/include/hal/riscv_trace_ll.h b/components/esp_hal_debug_assist/esp32h4/include/hal/riscv_trace_ll.h new file mode 100644 index 00000000000..5320f038d88 --- /dev/null +++ b/components/esp_hal_debug_assist/esp32h4/include/hal/riscv_trace_ll.h @@ -0,0 +1,271 @@ +/* + * SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#include +#include + +#include "soc/trace_reg.h" +#include "soc/trace_struct.h" +#include "soc/pcr_struct.h" +#include "hal/assert.h" +#include "hal/riscv_trace_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** @brief Return the register block for the given core. */ +static inline trace_dev_t *riscv_trace_ll_get_hw(int core) +{ + HAL_ASSERT(core == 0 || core == 1); + return core == 0 ? &TRACE0 : &TRACE1; +} + +/*--------------------------------------------------------------------------- + * Clock and reset + *--------------------------------------------------------------------------*/ + +static inline void _riscv_trace_ll_enable_bus_clock(bool enable) +{ + PCR.trace_conf.trace_clk_en = enable; + PCR.trace_conf.trace1_clk_en = enable; +} +#define riscv_trace_ll_enable_bus_clock(...) do { \ + (void)__DECLARE_RCC_ATOMIC_ENV; \ + _riscv_trace_ll_enable_bus_clock(__VA_ARGS__); \ +} while (0) + +static inline void _riscv_trace_ll_reset_register(int core) +{ + if (core == 0) { + PCR.trace_conf.trace_rst_en = 1; + PCR.trace_conf.trace_rst_en = 0; + } else { + PCR.trace_conf.trace1_rst_en = 1; + PCR.trace_conf.trace1_rst_en = 0; + } +} +#define riscv_trace_ll_reset_register(...) do { \ + (void)__DECLARE_RCC_ATOMIC_ENV; \ + _riscv_trace_ll_reset_register(__VA_ARGS__); \ +} while (0) + +/** @brief Enable the per-module register clock gate. */ +static inline void riscv_trace_ll_enable_module_clock(trace_dev_t *hw, bool enable) +{ + hw->clock_gate.clk_en = enable; +} + +/*--------------------------------------------------------------------------- + * Memory configuration + *--------------------------------------------------------------------------*/ + +static inline void riscv_trace_ll_set_mem_start_addr(trace_dev_t *hw, uint32_t addr) +{ + hw->mem_start_addr.mem_start_addr = addr; +} + +static inline void riscv_trace_ll_set_mem_end_addr(trace_dev_t *hw, uint32_t addr) +{ + hw->mem_end_addr.mem_end_addr = addr; +} + +static inline uint32_t riscv_trace_ll_get_mem_current_addr(trace_dev_t *hw) +{ + return hw->mem_current_addr.mem_current_addr; +} + +/** @brief Reload the current address from the start address. */ +static inline void riscv_trace_ll_update_mem_current_addr(trace_dev_t *hw) +{ + hw->mem_addr_update.mem_current_addr_update = 1; +} + +/*--------------------------------------------------------------------------- + * Status + *--------------------------------------------------------------------------*/ + +static inline uint32_t riscv_trace_ll_get_fifo_status(trace_dev_t *hw) +{ + return hw->fifo_status.val; +} + +/*--------------------------------------------------------------------------- + * Trigger, loop mode and restart + *--------------------------------------------------------------------------*/ + +static inline void riscv_trace_ll_trigger_on(trace_dev_t *hw) +{ + hw->trigger.trigger_on = 1; +} + +static inline void riscv_trace_ll_trigger_off(trace_dev_t *hw) +{ + hw->trigger.trigger_off = 1; +} + +static inline void riscv_trace_ll_set_mem_loop(trace_dev_t *hw, bool loop) +{ + hw->trigger.mem_loop = loop; +} + +static inline void riscv_trace_ll_set_restart_ena(trace_dev_t *hw, bool enable) +{ + hw->trigger.restart_ena = enable; +} + +/*--------------------------------------------------------------------------- + * Encoder options (config register) + *--------------------------------------------------------------------------*/ + +static inline void riscv_trace_ll_set_full_address(trace_dev_t *hw, bool full) +{ + hw->config.full_address = full; +} + +static inline void riscv_trace_ll_set_stall_ena(trace_dev_t *hw, bool enable) +{ + hw->config.stall_ena = enable; +} + +static inline void riscv_trace_ll_set_halt_ena(trace_dev_t *hw, bool enable) +{ + hw->config.halt_ena = enable; +} + +static inline void riscv_trace_ll_set_reset_ena(trace_dev_t *hw, bool enable) +{ + hw->config.reset_ena = enable; +} + +static inline void riscv_trace_ll_set_dm_trigger_ena(trace_dev_t *hw, bool enable) +{ + hw->config.dm_trigger_ena = enable; +} + +/*--------------------------------------------------------------------------- + * Resynchronization + *--------------------------------------------------------------------------*/ + +/** @brief Whether the resync counter can represent the given mode. */ +static inline bool riscv_trace_ll_resync_mode_is_supported(uint32_t mode) +{ + return mode == RISCV_TRACE_RESYNC_DISABLED || mode == RISCV_TRACE_RESYNC_PACKET || + mode == RISCV_TRACE_RESYNC_CYCLE; +} + +static inline void riscv_trace_ll_set_resync_mode(trace_dev_t *hw, uint32_t mode) +{ + hw->resync_prolonged.resync_mode = mode; +} + +static inline void riscv_trace_ll_set_resync_threshold(trace_dev_t *hw, uint32_t threshold) +{ + hw->resync_prolonged.resync_prolonged = threshold; +} + +/*--------------------------------------------------------------------------- + * AHB configuration + *--------------------------------------------------------------------------*/ + +static inline void riscv_trace_ll_set_ahb_burst(trace_dev_t *hw, uint32_t hburst) +{ + hw->ahb_config.hburst = hburst; +} + +static inline void riscv_trace_ll_set_ahb_max_incr(trace_dev_t *hw, uint32_t max_incr) +{ + hw->ahb_config.max_incr = max_incr; +} + +/*--------------------------------------------------------------------------- + * Interrupts + *--------------------------------------------------------------------------*/ + +static inline void riscv_trace_ll_set_intr_ena(trace_dev_t *hw, uint32_t mask) +{ + hw->intr_ena.val = mask; +} + +static inline uint32_t riscv_trace_ll_get_intr_raw(trace_dev_t *hw) +{ + return hw->intr_raw.val; +} + +static inline void riscv_trace_ll_clear_intr(trace_dev_t *hw, uint32_t mask) +{ + hw->intr_clr.val = mask; +} + +/*--------------------------------------------------------------------------- + * Filter unit + *--------------------------------------------------------------------------*/ + +static inline void riscv_trace_ll_set_filter_en(trace_dev_t *hw, bool enable) +{ + hw->filter_control.filter_en = enable; +} + +static inline void riscv_trace_ll_set_filter_control(trace_dev_t *hw, bool match_comp, + bool match_privilege, bool match_ecause, + bool match_interrupt) +{ + hw->filter_control.match_comp = match_comp; + hw->filter_control.match_privilege = match_privilege; + hw->filter_control.match_ecause = match_ecause; + hw->filter_control.match_interrupt = match_interrupt; +} + +static inline bool riscv_trace_ll_priv_is_supported(uint32_t priv) +{ + return priv == RISCV_TRACE_PRIV_USER || priv == RISCV_TRACE_PRIV_MACHINE; +} + +static inline void riscv_trace_ll_set_filter_match_control(trace_dev_t *hw, uint32_t priv_choice, + bool intr_value, uint32_t ecause_choice) +{ + // This target has no supervisor mode, so the selector is 1 bit: 0 = user, 1 = machine. + hw->filter_match_control.match_choice_privilege = (priv_choice == RISCV_TRACE_PRIV_MACHINE); + hw->filter_match_control.match_value_interrupt = intr_value; + hw->filter_match_control.match_choice_ecause = ecause_choice; +} + +static inline void riscv_trace_ll_set_p_comparator(trace_dev_t *hw, uint32_t input, + uint32_t function, bool notify) +{ + hw->filter_comparator_control.p_input = input; + hw->filter_comparator_control.p_function = function; + hw->filter_comparator_control.p_notify = notify; +} + +static inline void riscv_trace_ll_set_s_comparator(trace_dev_t *hw, uint32_t input, + uint32_t function, bool notify) +{ + hw->filter_comparator_control.s_input = input; + hw->filter_comparator_control.s_function = function; + hw->filter_comparator_control.s_notify = notify; +} + +static inline void riscv_trace_ll_set_match_mode(trace_dev_t *hw, uint32_t mode) +{ + hw->filter_comparator_control.match_mode = mode; +} + +static inline void riscv_trace_ll_set_p_match_value(trace_dev_t *hw, uint32_t value) +{ + hw->filter_p_comparator_match.p_match = value; +} + +static inline void riscv_trace_ll_set_s_match_value(trace_dev_t *hw, uint32_t value) +{ + hw->filter_s_comparator_match.s_match = value; +} + +#ifdef __cplusplus +} +#endif diff --git a/components/esp_riscv_trace/test_apps/basic/README.md b/components/esp_riscv_trace/test_apps/basic/README.md index dbbdc939d58..6d2d5a419b8 100644 --- a/components/esp_riscv_trace/test_apps/basic/README.md +++ b/components/esp_riscv_trace/test_apps/basic/README.md @@ -1,5 +1,5 @@ -| Supported Targets | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-P4 | ESP32-S31 | -| ----------------- | -------- | -------- | --------- | -------- | -------- | --------- | +| Supported Targets | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-H4 | ESP32-P4 | ESP32-S31 | +| ----------------- | -------- | -------- | --------- | -------- | -------- | -------- | --------- | # RISC-V Trace Basic Test App diff --git a/components/soc/esp32h4/include/soc/Kconfig.soc_caps.in b/components/soc/esp32h4/include/soc/Kconfig.soc_caps.in index b0cc245ba92..cea61e11929 100644 --- a/components/soc/esp32h4/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32h4/include/soc/Kconfig.soc_caps.in @@ -171,6 +171,10 @@ config SOC_BOD_SUPPORTED bool default y +config SOC_RISCV_TRACE_SUPPORTED + bool + default y + config SOC_PMU_SUPPORTED bool default y @@ -1379,6 +1383,22 @@ config SOC_DEBUG_HAVE_OCD_STUB_BINS bool default y +config SOC_RISCV_TRACE_HAS_CONFIG_REG + bool + default y + +config SOC_RISCV_TRACE_AHB_CONFIGURABLE + bool + default y + +config SOC_RISCV_TRACE_FILTER_SUPPORTED + bool + default y + +config SOC_RISCV_TRACE_PRIV_WIDTH + int + default 1 + config SOC_ASRC_SUPPORTED bool default y diff --git a/components/soc/esp32h4/include/soc/soc_caps.h b/components/soc/esp32h4/include/soc/soc_caps.h index ceabc961fce..6b02b7a7853 100644 --- a/components/soc/esp32h4/include/soc/soc_caps.h +++ b/components/soc/esp32h4/include/soc/soc_caps.h @@ -76,6 +76,7 @@ #define SOC_SECURE_BOOT_SUPPORTED 0 #define SOC_BOD_SUPPORTED 1 // #define SOC_APM_SUPPORTED 1 // TODO: [ESP32H4] IDF-12256 +#define SOC_RISCV_TRACE_SUPPORTED 1 #define SOC_PMU_SUPPORTED 1 // TODO: [ESP32H4] IDF-12286 #define SOC_PAU_SUPPORTED 1 #define SOC_RTC_TIMER_SUPPORTED 1 @@ -568,5 +569,11 @@ /*------------------------------------- DEBUG CAPS -------------------------------------*/ #define SOC_DEBUG_HAVE_OCD_STUB_BINS (1) +/*-------------------------- RISC-V TRACE CAPS ------------------------------*/ +#define SOC_RISCV_TRACE_HAS_CONFIG_REG (1) /*!< Has the encoder config register */ +#define SOC_RISCV_TRACE_AHB_CONFIGURABLE (1) /*!< AHB write master is configurable */ +#define SOC_RISCV_TRACE_FILTER_SUPPORTED (1) /*!< Has the filter unit */ +#define SOC_RISCV_TRACE_PRIV_WIDTH (1U) /*!< Bits in the privilege field (privilege_width_p) */ + /*---------------------------------- ASRC CAPS ----------------------------------*/ #define SOC_ASRC_SUPPORTED (1) From 114807c98160228218d0ea3e478b51009f3b03b1 Mon Sep 17 00:00:00 2001 From: Erhan Kurubas Date: Thu, 30 Jul 2026 22:17:25 +0300 Subject: [PATCH 3/3] feat(riscv_trace): add trace support for ESP32-H21 --- .../esp32h21/include/hal/riscv_trace_ll.h | 163 ++++++++++++++++++ .../esp_riscv_trace/test_apps/basic/README.md | 4 +- .../esp32h21/include/soc/Kconfig.soc_caps.in | 8 + .../soc/esp32h21/include/soc/soc_caps.h | 4 + 4 files changed, 177 insertions(+), 2 deletions(-) create mode 100644 components/esp_hal_debug_assist/esp32h21/include/hal/riscv_trace_ll.h diff --git a/components/esp_hal_debug_assist/esp32h21/include/hal/riscv_trace_ll.h b/components/esp_hal_debug_assist/esp32h21/include/hal/riscv_trace_ll.h new file mode 100644 index 00000000000..cd301883be0 --- /dev/null +++ b/components/esp_hal_debug_assist/esp32h21/include/hal/riscv_trace_ll.h @@ -0,0 +1,163 @@ +/* + * SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/* + * ESP32-H21 has a v1.0-spec trace encoder: no filter unit, no encoder config + * register (delta/full address, stall, halt, reset, debug trigger) and no AHB + * config register, so the LL only exposes the base register set. Its resync + * mode field is 1 bit with a different encoding than the v2.0 targets, handled + * in riscv_trace_ll_set_resync_mode() below. + */ + +#pragma once + +#include +#include + +#include "soc/trace_reg.h" +#include "soc/trace_struct.h" +#include "soc/pcr_struct.h" +#include "hal/assert.h" +#include "hal/riscv_trace_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** @brief Return the register block for the given core. */ +static inline trace_dev_t *riscv_trace_ll_get_hw(int core) +{ + HAL_ASSERT(core == 0); + (void)core; + return &TRACE; +} + +/*--------------------------------------------------------------------------- + * Clock and reset + *--------------------------------------------------------------------------*/ + +/** @brief Enable or disable the TRACE clock. */ +static inline void riscv_trace_ll_enable_bus_clock(bool enable) +{ + PCR.trace_conf.trace_clk_en = enable; +} + +/** @brief Assert and release the reset of the encoder. */ +static inline void riscv_trace_ll_reset_register(int core) +{ + (void)core; + PCR.trace_conf.trace_rst_en = 1; + PCR.trace_conf.trace_rst_en = 0; +} + +/** @brief Enable the per-module register clock gate. */ +static inline void riscv_trace_ll_enable_module_clock(trace_dev_t *hw, bool enable) +{ + hw->clock_gate.clk_en = enable; +} + +/*--------------------------------------------------------------------------- + * Memory configuration + *--------------------------------------------------------------------------*/ + +static inline void riscv_trace_ll_set_mem_start_addr(trace_dev_t *hw, uint32_t addr) +{ + hw->mem_start_addr.mem_start_addr = addr; +} + +static inline void riscv_trace_ll_set_mem_end_addr(trace_dev_t *hw, uint32_t addr) +{ + hw->mem_end_addr.mem_end_addr = addr; +} + +static inline uint32_t riscv_trace_ll_get_mem_current_addr(trace_dev_t *hw) +{ + return hw->mem_current_addr.mem_current_addr; +} + +/** @brief Reload the current address from the start address. */ +static inline void riscv_trace_ll_update_mem_current_addr(trace_dev_t *hw) +{ + hw->mem_addr_update.mem_current_addr_update = 1; +} + +/*--------------------------------------------------------------------------- + * Status + *--------------------------------------------------------------------------*/ + +static inline uint32_t riscv_trace_ll_get_fifo_status(trace_dev_t *hw) +{ + return hw->fifo_status.val; +} + +/*--------------------------------------------------------------------------- + * Trigger, loop mode and restart + *--------------------------------------------------------------------------*/ + +static inline void riscv_trace_ll_trigger_on(trace_dev_t *hw) +{ + hw->trigger.trigger_on = 1; +} + +static inline void riscv_trace_ll_trigger_off(trace_dev_t *hw) +{ + hw->trigger.trigger_off = 1; +} + +static inline void riscv_trace_ll_set_mem_loop(trace_dev_t *hw, bool loop) +{ + hw->trigger.mem_loop = loop; +} + +static inline void riscv_trace_ll_set_restart_ena(trace_dev_t *hw, bool enable) +{ + hw->trigger.restart_ena = enable; +} + +/*--------------------------------------------------------------------------- + * Resynchronization + *--------------------------------------------------------------------------*/ + +/** @brief Whether the resync counter can represent the given mode. */ +static inline bool riscv_trace_ll_resync_mode_is_supported(uint32_t mode) +{ + // 1-bit field: this encoder always counts and has no "disabled" mode. + return mode == RISCV_TRACE_RESYNC_PACKET || mode == RISCV_TRACE_RESYNC_CYCLE; +} + +static inline void riscv_trace_ll_set_resync_mode(trace_dev_t *hw, uint32_t mode) +{ + // 1-bit field: 0 = count by cycle, 1 = count by packet. + hw->resync_prolonged.resync_mode = (mode == RISCV_TRACE_RESYNC_PACKET); +} + +static inline void riscv_trace_ll_set_resync_threshold(trace_dev_t *hw, uint32_t threshold) +{ + hw->resync_prolonged.resync_prolonged = threshold; +} + +/*--------------------------------------------------------------------------- + * Interrupts + *--------------------------------------------------------------------------*/ + +static inline void riscv_trace_ll_set_intr_ena(trace_dev_t *hw, uint32_t mask) +{ + hw->intr_ena.val = mask; +} + +static inline uint32_t riscv_trace_ll_get_intr_raw(trace_dev_t *hw) +{ + return hw->intr_raw.val; +} + +static inline void riscv_trace_ll_clear_intr(trace_dev_t *hw, uint32_t mask) +{ + hw->intr_clr.val = mask; +} + +#ifdef __cplusplus +} +#endif diff --git a/components/esp_riscv_trace/test_apps/basic/README.md b/components/esp_riscv_trace/test_apps/basic/README.md index 6d2d5a419b8..52f194e67f6 100644 --- a/components/esp_riscv_trace/test_apps/basic/README.md +++ b/components/esp_riscv_trace/test_apps/basic/README.md @@ -1,5 +1,5 @@ -| Supported Targets | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-H4 | ESP32-P4 | ESP32-S31 | -| ----------------- | -------- | -------- | --------- | -------- | -------- | -------- | --------- | +| Supported Targets | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-H21 | ESP32-H4 | ESP32-P4 | ESP32-S31 | +| ----------------- | -------- | -------- | --------- | -------- | --------- | -------- | -------- | --------- | # RISC-V Trace Basic Test App diff --git a/components/soc/esp32h21/include/soc/Kconfig.soc_caps.in b/components/soc/esp32h21/include/soc/Kconfig.soc_caps.in index da21f9c0f22..b798b9856d5 100644 --- a/components/soc/esp32h21/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32h21/include/soc/Kconfig.soc_caps.in @@ -143,6 +143,10 @@ config SOC_BOD_SUPPORTED bool default y +config SOC_RISCV_TRACE_SUPPORTED + bool + default y + config SOC_PMU_SUPPORTED bool default y @@ -1150,3 +1154,7 @@ config SOC_BLE_PERIODIC_ADV_WITH_RESPONSE config SOC_DEBUG_HAVE_OCD_STUB_BINS bool default y + +config SOC_RISCV_TRACE_PRIV_WIDTH + int + default 1 diff --git a/components/soc/esp32h21/include/soc/soc_caps.h b/components/soc/esp32h21/include/soc/soc_caps.h index 5789cdc4d45..42ebbd065b5 100644 --- a/components/soc/esp32h21/include/soc/soc_caps.h +++ b/components/soc/esp32h21/include/soc/soc_caps.h @@ -61,6 +61,7 @@ #define SOC_SECURE_BOOT_SUPPORTED 1 #define SOC_BOD_SUPPORTED 1 // #define SOC_APM_SUPPORTED 1 //TODO: [ESP32H21] IDF-11494 +#define SOC_RISCV_TRACE_SUPPORTED 1 #define SOC_PMU_SUPPORTED 1 #define SOC_RTC_TIMER_SUPPORTED 1 #define SOC_LP_AON_SUPPORTED 1 @@ -498,3 +499,6 @@ /*------------------------------------- DEBUG CAPS -------------------------------------*/ #define SOC_DEBUG_HAVE_OCD_STUB_BINS (1) + +/*-------------------------- RISC-V TRACE CAPS ------------------------------*/ +#define SOC_RISCV_TRACE_PRIV_WIDTH (1U) /*!< Bits in the privilege field (privilege_width_p) */