Files
esp-idf/components/esp_riscv_trace/README.md
Erhan Kurubas 3dfd8f0154 feat(esp_riscv_trace): add ESP32-S31 support
ESP32-S31 uses the same trace encoder IP as ESP32-P4. Of the E-Trace v2.0
parameters the two targets report, only privilege_width_p differs (1 on P4,
2 on S31), and it affects both the sync packet layout and the filter's
privilege selector.

- Add the SOC_RISCV_TRACE_* caps for ESP32-S31 along with the esp32s31 LL, and
  declare TRACE0/TRACE1 in the target's trace_struct.h.
- Carry privilege_width_p as SOC_RISCV_TRACE_PRIV_WIDTH so the sync packet
  decoder can locate the address field, which starts one bit later on targets
  that implement supervisor mode.
- Use the RISC-V architectural privilege encoding (0 user, 1 supervisor,
  3 machine) in the public filter enum so the values do not change per target,
  and let each LL narrow them to its own register field.
- Add riscv_trace_ll_priv_is_supported() per target, so a privilege level the
  selector cannot represent is rejected with ESP_ERR_NOT_SUPPORTED rather than
  being silently narrowed to a different level. It lives next to the narrowing
  code so the two cannot drift apart.
- Fix trace buffer allocation on targets whose internal RAM is not reached
  through a cache. esp_cache_get_alignment() reports 0 there, which underflowed
  the size check and failed every allocation. Align base and size to the larger
  of the reported cache line and the encoder's 4-byte write granularity.
2026-08-06 13:08:26 +08:00

2.1 KiB

RISC-V Trace Encoder Driver

Overview

The esp_riscv_trace component provides the public driver API for the RISC-V trace encoder peripheral. The driver is enabled by CONFIG_ESP_RISCV_TRACE_ENABLE and creates one encoder handle per selected core during startup auto-initialization.

Applications can override the weak esp_riscv_trace_get_user_config(int core_id) function to customize the startup configuration per core (each encoder can be configured independently), or use Kconfig defaults through ESP_RISCV_TRACE_DEFAULT_CONFIG().

State Transition

stateDiagram-v2
    [*] --> created: startup auto-init
    created --> started: esp_riscv_trace_start
    started --> stopped: esp_riscv_trace_stop
    stopped --> started: esp_riscv_trace_start

esp_riscv_trace_set_filter() and esp_riscv_trace_get_buffer() are only valid while the encoder is not started. esp_riscv_trace_get_status() can be used to read a coherent status snapshot.

Concurrency

Public driver APIs are serialized per trace core with a task-level lock. They are task-context APIs and must not be called from ISR context.

The driver keeps the lifecycle state check and the corresponding HAL register operation under the same per-core lock. This prevents concurrent callers from double-starting an encoder, racing a stop against filter programming, or reading the buffer before a stop has completed its cache synchronization.

Buffer and Trace Stream Notes

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.

In loop memory mode, wrapped buffers need periodic resynchronization packets to remain decodable after the original start sync has been overwritten.

Dependencies

This driver depends on the RISC-V trace HAL (part of the hal component) and currently targets SoCs that support the RISC-V trace encoder peripheral.