feat(esp_riscv_trace): add ESP32-C5 support

This commit is contained in:
Erhan Kurubas
2026-07-30 16:17:32 +03:00
parent 81f6360e4d
commit 1a59c3e769
12 changed files with 302 additions and 7 deletions

View File

@@ -0,0 +1,254 @@
/*
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include <stdint.h>
#include <stdbool.h>
#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
*--------------------------------------------------------------------------*/
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

View File

@@ -20,7 +20,7 @@ menu "RISC-V Trace Encoder Configurations"
default ESP_RISCV_TRACE_BUFFER_IN_INTERNAL
help
Where the driver allocates the trace buffer. The encoder writes the buffer over
its AHB master, which can reach both internal and external PSRAM.
its AHB master. PSRAM is only offered on targets whose encoder can reach it.
Internal RAM is fastest and always usable. PSRAM frees internal RAM and allows
much larger buffers, but is slower (higher risk of FIFO overflow at high trace
@@ -30,7 +30,7 @@ menu "RISC-V Trace Encoder Configurations"
bool "Internal RAM"
config ESP_RISCV_TRACE_BUFFER_IN_EXTERNAL
bool "External RAM (PSRAM)"
depends on SPIRAM
depends on SPIRAM && SOC_RISCV_TRACE_MEM_SUPPORT_PSRAM
endchoice
config ESP_RISCV_TRACE_BUFFER_MEM

View File

@@ -42,7 +42,9 @@ The trace buffer must be reachable by the trace encoder AHB master. Driver
allocated buffers are placed in internal RAM or PSRAM according to
configuration, and are cache-line aligned when that memory is reached through a
data cache. Caller-provided buffers are validated for reachable memory and
cache-line alignment.
cache-line alignment. PSRAM placement is only available on targets whose
encoder can reach external RAM (`SOC_RISCV_TRACE_MEM_SUPPORT_PSRAM`); on other
targets the buffer is always internal.
In loop memory mode, wrapped buffers need periodic resynchronization packets to
remain decodable after the original start sync has been overwritten.

View File

@@ -3,6 +3,6 @@
components/esp_riscv_trace/test_apps:
disable:
- if: SOC_RISCV_TRACE_SUPPORTED != 1
- if: CONFIG_NAME == "psram" and SOC_SPIRAM_SUPPORTED != 1
- if: CONFIG_NAME == "psram" and SOC_RISCV_TRACE_MEM_SUPPORT_PSRAM != 1
depends_components:
- esp_riscv_trace

View File

@@ -1,5 +1,5 @@
| Supported Targets | ESP32-P4 | ESP32-S31 |
| ----------------- | -------- | --------- |
| Supported Targets | ESP32-C5 | ESP32-P4 | ESP32-S31 |
| ----------------- | -------- | -------- | --------- |
# RISC-V Trace Basic Test App

View File

@@ -16,7 +16,9 @@ def test_riscv_trace(dut: Dut) -> None:
@pytest.mark.generic
@pytest.mark.parametrize('config', ['psram'], indirect=True)
@idf_parametrize(
'target', soc_filtered_targets('SOC_RISCV_TRACE_SUPPORTED == 1 and SOC_SPIRAM_SUPPORTED == 1'), indirect=['target']
'target',
soc_filtered_targets('SOC_RISCV_TRACE_SUPPORTED == 1 and SOC_RISCV_TRACE_MEM_SUPPORT_PSRAM == 1'),
indirect=['target'],
)
def test_riscv_trace_psram(dut: Dut) -> None:
dut.run_all_single_board_cases()

View File

@@ -307,6 +307,10 @@ config SOC_SPI_EXTERNAL_NOR_FLASH_SUPPORTED
bool
default y
config SOC_RISCV_TRACE_SUPPORTED
bool
default y
config SOC_XTAL_SUPPORT_40M
bool
default y
@@ -1618,3 +1622,19 @@ config SOC_LP_CORE_HW_AUTO_CLRWAKEUPCAUSE
config SOC_LP_CORE_LP_UART_WAKEUP_KEEP_TRIGGERED
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

View File

@@ -100,6 +100,7 @@
#define SOC_PHY_SUPPORTED 1
#define SOC_BITSCRAMBLER_SUPPORTED 1
#define SOC_SPI_EXTERNAL_NOR_FLASH_SUPPORTED 1
#define SOC_RISCV_TRACE_SUPPORTED 1
/*-------------------------- XTAL CAPS ---------------------------------------*/
#define SOC_XTAL_SUPPORT_40M 1
@@ -645,3 +646,9 @@
#define SOC_LP_CORE_SUPPORT_I2C (1) /*!< LP Core supports I2C */
#define SOC_LP_CORE_HW_AUTO_CLRWAKEUPCAUSE (1) /*!< LP core requests sleep, PMU clears both HP and LP wakeup causes */
#define SOC_LP_CORE_LP_UART_WAKEUP_KEEP_TRIGGERED (1) /*!< LP UART wakeup source is kept triggered */
/*-------------------------- 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) */

View File

@@ -1954,3 +1954,7 @@ config SOC_RISCV_TRACE_FILTER_SUPPORTED
config SOC_RISCV_TRACE_PRIV_WIDTH
int
default 1
config SOC_RISCV_TRACE_MEM_SUPPORT_PSRAM
bool
default y

View File

@@ -747,3 +747,4 @@
#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) */
#define SOC_RISCV_TRACE_MEM_SUPPORT_PSRAM (1) /*!< Encoder AHB master can reach external PSRAM */

View File

@@ -1874,3 +1874,7 @@ config SOC_RISCV_TRACE_FILTER_SUPPORTED
config SOC_RISCV_TRACE_PRIV_WIDTH
int
default 2
config SOC_RISCV_TRACE_MEM_SUPPORT_PSRAM
bool
default y

View File

@@ -697,3 +697,4 @@
#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 (2U) /*!< Bits in the privilege field (privilege_width_p) */
#define SOC_RISCV_TRACE_MEM_SUPPORT_PSRAM (1) /*!< Encoder AHB master can reach external PSRAM */