feat(esp_trace): add usb-serial-jtag as a transport channel

This commit is contained in:
Erhan Kurubas
2026-02-03 14:11:43 +01:00
parent 6e5d4e73be
commit 05010137f8
14 changed files with 621 additions and 6 deletions
+10 -1
View File
@@ -14,13 +14,22 @@ if(CONFIG_ESP_TRACE_ENABLE)
if(CONFIG_ESP_TRACE_TRANSPORT_APPTRACE)
list(APPEND srcs "adapters/transport/adapter_transport_apptrace.c")
endif()
if(CONFIG_ESP_TRACE_TRANSPORT_USB_SERIAL_JTAG)
list(APPEND srcs "adapters/transport/adapter_transport_usb_serial_jtag.c")
endif()
endif()
set(includes
"include"
)
set(priv_requires "esp_driver_gptimer")
set(priv_requires
"esp_driver_gptimer"
"esp_hal_usb"
"esp_driver_usb_serial_jtag"
"esp_timer"
)
set(priv_includes "")
set(requires "app_trace")
+26
View File
@@ -34,6 +34,16 @@ menu "ESP Trace Configuration"
config ESP_TRACE_TRANSPORT_APPTRACE
bool "ESP-IDF apptrace"
config ESP_TRACE_TRANSPORT_USB_SERIAL_JTAG
bool "USB Serial JTAG"
depends on SOC_USB_SERIAL_JTAG_SUPPORTED && !ESP_CONSOLE_USB_SERIAL_JTAG_ENABLED
help
Use USB Serial JTAG peripheral as trace transport.
Note: This option is not available when USB Serial JTAG is used as
primary or secondary console (ESP_CONSOLE_USB_SERIAL_JTAG or
ESP_CONSOLE_SECONDARY_USB_SERIAL_JTAG).
config ESP_TRACE_TRANSPORT_EXTERNAL
bool "External transport from component registry"
depends on !ESP_TRACE_LIB_NONE
@@ -48,6 +58,7 @@ menu "ESP Trace Configuration"
config ESP_TRACE_TRANSPORT_NAME
string
default "apptrace" if ESP_TRACE_TRANSPORT_APPTRACE
default "usb_serial_jtag" if ESP_TRACE_TRANSPORT_USB_SERIAL_JTAG
default "ext" if ESP_TRACE_TRANSPORT_EXTERNAL
default "none" if ESP_TRACE_TRANSPORT_NONE
@@ -59,6 +70,21 @@ menu "ESP Trace Configuration"
rsource "$IDF_PATH/components/app_trace/Kconfig.apptrace"
menu "USB Serial JTAG Trace Configuration"
depends on ESP_TRACE_TRANSPORT_USB_SERIAL_JTAG
config ESP_TRACE_USJ_TX_BUFFER_SIZE
int "TX buffer size"
default 2048
range 256 32768
help
Size of the TX ring buffer for USB Serial JTAG trace transport.
Larger buffer allows more trace data to be queued before blocking.
Note: Buffer size must be a power of 2.
endmenu
choice ESP_TRACE_TIMESTAMP_SOURCE
depends on ESP_TRACE_ENABLE
prompt "Trace timestamp source"
@@ -0,0 +1,361 @@
/*
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
/**
* @brief USB-Serial-JTAG transport adapter for esp_trace
*
* This implementation uses LL (Low-Level) functions directly instead of the
* high-level USB-Serial-JTAG driver to avoid FreeRTOS primitives, which would
* cause deadlocks when tracing FreeRTOS operations with SystemView.
*
* Locking: This transport does not implement its own lock. The encoder (e.g. sysview)
* is responsible for serializing access using esp_trace_lock_init(), esp_trace_lock_take(),
* and esp_trace_lock_give(). All transport operations (read, write, flush_nolock) are
* invoked while the encoder holds the lock, so no transport-level locking is required.
*/
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
#include <stddef.h>
#include <stdint.h>
#include "sdkconfig.h"
#include "esp_err.h"
#include "esp_log.h"
#include "esp_cpu.h"
#include "esp_attr.h"
#include "esp_rom_caps.h"
#include "esp_heap_caps.h"
#include "esp_private/periph_ctrl.h"
#include "hal/usb_serial_jtag_ll.h"
#include "soc/usb_serial_jtag_struct.h"
#include "driver/usb_serial_jtag.h"
#include "esp_trace_registry.h"
#include "esp_trace_port_transport.h"
#include "esp_trace_types.h"
#include "esp_trace_util.h"
static const char *TAG = "usj_transport";
/* Transport context */
typedef struct {
int inited; ///< Initialization flag (bitmask per core)
esp_trace_rb_t tx_ring; ///< TX ring buffer
esp_trace_rb_t rx_ring; ///< RX ring buffer
/* Flush configuration */
uint32_t flush_tmo; ///< Flush timeout in microseconds
uint32_t flush_thresh; ///< Flush threshold in bytes
} usj_ctx_t;
#define USJ_FLUSH_TIMEOUT_US (1000000) // 1 second
#define USJ_FLUSH_THRESH_BYTES (0) // 0 bytes
/* USB Serial JTAG hardware FIFO size (RX and TX) is 64 bytes (USB FS bulk endpoint max packet size) */
#define USJ_HW_FIFO_SIZE (64)
#define USJ_RX_BUFFER_SIZE USJ_HW_FIFO_SIZE
/* ----------------------- HW FIFO Helpers ----------------------- */
static uint32_t usj_write_fifo(usj_ctx_t *ctx, esp_trace_rb_t *rb)
{
if (!usb_serial_jtag_ll_txfifo_writable()) {
/* FIFO is full, no blocking */
return 0;
}
const uint8_t *ptr;
uint32_t to_send = esp_trace_rb_peek_contiguous(rb, &ptr);
if (to_send == 0) {
return 0;
}
uint32_t written = usb_serial_jtag_ll_write_txfifo(ptr, to_send);
esp_trace_rb_consume(rb, written);
/* Flush to send data or zero-byte packet to end USB transfer */
usb_serial_jtag_ll_txfifo_flush();
return written;
}
static void usj_read_rx_fifo(usj_ctx_t *ctx)
{
uint8_t tmp[USJ_HW_FIFO_SIZE];
while (usb_serial_jtag_ll_rxfifo_data_available()) {
uint32_t n = usb_serial_jtag_ll_read_rxfifo(tmp, sizeof(tmp));
if (n == 0) {
break;
}
esp_trace_rb_put(&ctx->rx_ring, tmp, n);
}
}
/* ----------------------- Transport Functions ----------------------- */
_Static_assert((CONFIG_ESP_TRACE_USJ_TX_BUFFER_SIZE & (CONFIG_ESP_TRACE_USJ_TX_BUFFER_SIZE - 1)) == 0,
"CONFIG_ESP_TRACE_USJ_TX_BUFFER_SIZE must be a power of 2");
static esp_err_t usj_init(esp_trace_transport_t *tp, const void *tp_cfg)
{
(void)tp_cfg;
if (!tp) {
return ESP_ERR_INVALID_ARG;
}
/* Create context if not already done */
if (!tp->ctx) {
usj_ctx_t *ctx = heap_caps_calloc(1, sizeof(*ctx), MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT);
if (!ctx) {
return ESP_ERR_NO_MEM;
}
tp->ctx = ctx;
}
usj_ctx_t *ctx = (usj_ctx_t *)tp->ctx;
int core_id = esp_cpu_get_core_id();
/* Only do main setup on core 0 */
if (core_id == 0) {
/* Set default flush configuration */
ctx->flush_tmo = USJ_FLUSH_TIMEOUT_US;
ctx->flush_thresh = USJ_FLUSH_THRESH_BYTES;
/* Enable USB-Serial-JTAG peripheral module clock */
PERIPH_RCC_ATOMIC() {
usb_serial_jtag_ll_enable_bus_clock(true);
}
/* Configure USB PHY */
#if USB_SERIAL_JTAG_LL_EXT_PHY_SUPPORTED
usb_serial_jtag_ll_phy_enable_external(false); /* Use internal PHY */
usb_serial_jtag_ll_phy_enable_pad(true); /* Enable USB PHY pads */
#else
usb_serial_jtag_ll_phy_set_defaults(); /* Set default PHY values */
#endif
/* Disable RX and TX interrupts */
usb_serial_jtag_ll_disable_intr_mask(USB_SERIAL_JTAG_INTR_SERIAL_IN_EMPTY
| USB_SERIAL_JTAG_INTR_SERIAL_OUT_RECV_PKT);
/* Initialize TX ring buffer */
esp_err_t ret = esp_trace_rb_init(&ctx->tx_ring, CONFIG_ESP_TRACE_USJ_TX_BUFFER_SIZE);
if (ret != ESP_OK) {
ESP_LOGE(TAG, "Failed to initialize TX ring buffer");
goto err_ctx;
}
/* Initialize RX ring buffer to capture host commands */
ret = esp_trace_rb_init(&ctx->rx_ring, USJ_RX_BUFFER_SIZE);
if (ret != ESP_OK) {
ESP_LOGE(TAG, "Failed to initialize RX ring buffer");
goto err_tx_ring;
}
#if ESP_ROM_HAS_ETS_PRINTF_BUG
/* Make sure no printf output is sent to USB-Serial-JTAG */
extern bool g_usb_print;
g_usb_print = false;
#endif
}
ctx->inited |= (1 << core_id);
return ESP_OK;
err_tx_ring:
heap_caps_free(ctx->tx_ring.buffer);
err_ctx:
heap_caps_free(ctx);
tp->ctx = NULL;
return ESP_FAIL;
}
static esp_err_t usj_read(esp_trace_transport_t *tp, void *data, size_t *size, uint32_t tmo)
{
usj_ctx_t *ctx = (usj_ctx_t *)tp->ctx;
if (!data || !size || *size == 0) {
return ESP_ERR_INVALID_ARG;
}
uint8_t *buf = data;
uint32_t req_size = *size;
uint32_t total_read = 0;
esp_trace_tmo_t timeout;
esp_trace_tmo_init(&timeout, tmo);
/* First read any pending RX data from the RX ring buffer */
total_read = esp_trace_rb_get(&ctx->rx_ring, buf, req_size);
while (total_read < req_size) {
/* Try to read from HW RX FIFO directly */
if (usb_serial_jtag_ll_rxfifo_data_available()) {
uint32_t to_read = req_size - total_read;
uint32_t read = usb_serial_jtag_ll_read_rxfifo(buf + total_read, to_read);
total_read += read;
continue;
}
if (esp_trace_tmo_check(&timeout) != ESP_OK) {
break;
}
esp_rom_delay_us(100);
}
*size = total_read;
return (total_read > 0) ? ESP_OK : ESP_ERR_TIMEOUT;
}
static esp_err_t usj_write(esp_trace_transport_t *tp, const void *data, size_t size, uint32_t tmo)
{
(void)tmo; /* Write is non-blocking via ring buffer */
usj_ctx_t *ctx = (usj_ctx_t *)tp->ctx;
esp_trace_rb_t *rb = &ctx->tx_ring;
if (!data || size == 0) {
return ESP_ERR_INVALID_ARG;
}
/* Read any new RX data into the RX ring buffer to avoid losing host commands in case of heavy trace output */
usj_read_rx_fifo(ctx);
/* Add data to TX ring buffer */
esp_trace_rb_put(rb, (const uint8_t *)data, size);
/* Try to flush some data to HW FIFO immediately (non-blocking) */
while (esp_trace_rb_data_len(rb) > 0) {
if (usj_write_fifo(ctx, rb) == 0) {
break; /* FIFO full, will be drained on next write or flush */
}
}
return ESP_OK;
}
static esp_err_t usj_down_buffer_config(esp_trace_transport_t *tp, uint8_t *buf, uint32_t size)
{
(void)tp;
(void)buf;
(void)size;
/* No action needed - data was already read in get function */
return ESP_OK;
}
static esp_err_t usj_flush_nolock(esp_trace_transport_t *tp)
{
usj_ctx_t *ctx = (usj_ctx_t *)tp->ctx;
esp_trace_rb_t *rb = &ctx->tx_ring;
uint32_t pending = esp_trace_rb_data_len(rb);
if (pending < ctx->flush_thresh) {
return ESP_OK;
}
esp_trace_tmo_t timeout;
esp_trace_tmo_init(&timeout, ctx->flush_tmo);
/* Drain ring buffer to HW FIFO */
while (esp_trace_rb_data_len(rb) > 0) {
usj_write_fifo(ctx, rb);
if (esp_trace_tmo_check(&timeout) != ESP_OK) {
return ESP_ERR_TIMEOUT;
}
esp_rom_delay_us(100);
}
return ESP_OK;
}
static bool usj_is_host_connected(esp_trace_transport_t *tp)
{
(void)tp;
return usb_serial_jtag_is_connected();
}
static esp_trace_link_types_t usj_get_link_type(esp_trace_transport_t *tp)
{
(void)tp;
return ESP_TRACE_LINK_USB_SERIAL_JTAG;
}
static esp_err_t usj_set_config(esp_trace_transport_t *tp, esp_trace_transport_cfg_key_t key, const void *value)
{
if (!value) {
return ESP_ERR_INVALID_ARG;
}
usj_ctx_t *ctx = (usj_ctx_t *)tp->ctx;
if (!ctx) {
return ESP_ERR_INVALID_STATE;
}
switch (key) {
case ESP_TRACE_TRANSPORT_CFG_HEADER_SIZE:
/* USB-Serial-JTAG doesn't need header size configuration */
return ESP_OK;
case ESP_TRACE_TRANSPORT_CFG_FLUSH_TMO:
ctx->flush_tmo = *(const uint32_t *)value;
return ESP_OK;
case ESP_TRACE_TRANSPORT_CFG_FLUSH_THRESH:
ctx->flush_thresh = *(const uint32_t *)value;
return ESP_OK;
default:
ESP_LOGE(TAG, "Key %d is not supported", key);
return ESP_ERR_NOT_SUPPORTED;
}
}
static esp_err_t usj_get_config(esp_trace_transport_t *tp, esp_trace_transport_cfg_key_t key, void *value)
{
if (!value) {
return ESP_ERR_INVALID_ARG;
}
usj_ctx_t *ctx = (usj_ctx_t *)tp->ctx;
if (!ctx) {
return ESP_ERR_INVALID_STATE;
}
switch (key) {
case ESP_TRACE_TRANSPORT_CFG_FLUSH_TMO:
*(uint32_t *)value = ctx->flush_tmo;
return ESP_OK;
case ESP_TRACE_TRANSPORT_CFG_FLUSH_THRESH:
*(uint32_t *)value = ctx->flush_thresh;
return ESP_OK;
default:
ESP_LOGE(TAG, "Key %d is not supported", key);
return ESP_ERR_NOT_SUPPORTED;
}
}
static void usj_panic_handler(esp_trace_transport_t *tp, const void *info)
{
(void)info;
usj_flush_nolock(tp);
}
/* ----------------------- Transport Registration ----------------------- */
static const esp_trace_transport_vtable_t s_usb_serial_jtag_vt = {
.init = usj_init,
.set_config = usj_set_config,
.get_config = usj_get_config,
.read = usj_read,
.write = usj_write,
.flush_nolock = usj_flush_nolock,
.down_buffer_config = usj_down_buffer_config,
.is_host_connected = usj_is_host_connected,
.get_link_type = usj_get_link_type,
.panic_handler = usj_panic_handler,
};
ESP_TRACE_REGISTER_TRANSPORT("usb_serial_jtag", &s_usb_serial_jtag_vt);
@@ -18,6 +18,7 @@ typedef enum {
ESP_TRACE_LINK_UNKNOWN = 0,
ESP_TRACE_LINK_DEBUG_PROBE,
ESP_TRACE_LINK_UART,
ESP_TRACE_LINK_USB_SERIAL_JTAG,
} esp_trace_link_types_t;
/* Timeout constants for trace operations */
+82 -1
View File
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2025-2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -118,6 +118,87 @@ esp_err_t esp_trace_lock_take(esp_trace_lock_t *lock, uint32_t tmo_us);
*/
esp_err_t esp_trace_lock_give(esp_trace_lock_t *lock);
///////////////////////////////////////////////////////////////////////////////
//////////////////////////////// RING BUFFER //////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
#include <stdbool.h>
/**
* @brief Power-of-2 ring buffer for trace transports
*
* Lightweight, FreeRTOS-free ring buffer suitable for use in trace hot paths
* (ISR-safe contexts, critical sections). Size must be a power of 2.
*
*/
typedef struct {
uint8_t *buffer; ///< Heap-allocated data buffer
uint32_t max_size; ///< Buffer capacity (must be power of 2)
volatile uint32_t count; ///< Bytes currently stored
volatile uint32_t head; ///< Write index
volatile uint32_t tail; ///< Read index
} esp_trace_rb_t;
/**
* @brief Initialize ring buffer (allocates internal memory)
*
* @param rb Pointer to ring buffer structure
* @param size Buffer size in bytes (must be power of 2)
* @return ESP_OK on success, ESP_ERR_NO_MEM on allocation failure
*/
esp_err_t esp_trace_rb_init(esp_trace_rb_t *rb, uint32_t size);
/**
* @brief Get number of bytes currently stored in the ring buffer
*/
static inline uint32_t esp_trace_rb_data_len(const esp_trace_rb_t *rb)
{
return rb->count;
}
/**
* @brief Write data into the ring buffer (overwrites oldest data if full)
*
* @param rb Ring buffer
* @param data Source data
* @param len Number of bytes to write
* @return ESP_OK always (data is always accepted; oldest data may be dropped)
*/
esp_err_t esp_trace_rb_put(esp_trace_rb_t *rb, const uint8_t *data, uint32_t len);
/**
* @brief Read and consume data from the ring buffer
*
* @param rb Ring buffer
* @param data Destination buffer
* @param len Maximum number of bytes to read
* @return Number of bytes actually read
*/
uint32_t esp_trace_rb_get(esp_trace_rb_t *rb, uint8_t *data, uint32_t len);
/**
* @brief Peek at contiguous readable data without consuming
*
* Returns a pointer to the contiguous block of data starting at the tail.
* When the readable region wraps around the end of the buffer, only the
* first contiguous portion is returned. Call again after consume() for the rest.
*
* @param rb Ring buffer
* @param[out] data Set to point at the contiguous data (valid until next put/consume)
* @return Number of contiguous bytes available (0 if empty)
*/
uint32_t esp_trace_rb_peek_contiguous(const esp_trace_rb_t *rb, const uint8_t **data);
/**
* @brief Consume (discard) bytes from the read side of the ring buffer
*
* Typically called after esp_trace_rb_peek_contiguous() + processing.
*
* @param rb Ring buffer
* @param len Number of bytes to consume (must be <= esp_trace_rb_data_len())
*/
void esp_trace_rb_consume(esp_trace_rb_t *rb, uint32_t len);
#ifdef __cplusplus
}
#endif
+2
View File
@@ -8,6 +8,8 @@ entries:
port_utils (noflash)
if ESP_TRACE_TRANSPORT_APPTRACE:
adapter_transport_apptrace (noflash)
if ESP_TRACE_TRANSPORT_USB_SERIAL_JTAG:
adapter_transport_usb_serial_jtag (noflash)
[mapping:esp_trace_driver]
archive: libesp_driver_gptimer.a
+104 -1
View File
@@ -1,15 +1,17 @@
/*
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2025-2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <stdint.h>
#include <string.h>
#include "sdkconfig.h"
#include "esp_timer.h"
#include "esp_clk_tree.h"
#include "esp_cpu.h"
#include "esp_private/esp_clk.h"
#include "esp_err.h"
#include "esp_heap_caps.h"
#include "freertos/FreeRTOS.h"
#include "freertos/semphr.h"
@@ -152,3 +154,104 @@ esp_err_t esp_trace_lock_give(esp_trace_lock_t *lock)
portEXIT_CRITICAL(&lock->mux);
return ESP_OK;
}
///////////////////////////////////////////////////////////////////////////////
//////////////////////////////// RING BUFFER //////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
#ifndef MIN
#define MIN(a, b) ((a) < (b) ? (a) : (b))
#endif
static inline uint32_t rb_mask(const esp_trace_rb_t *rb)
{
return rb->max_size - 1;
}
static inline void rb_advance_tail(esp_trace_rb_t *rb, uint32_t n)
{
rb->tail = (rb->tail + n) & rb_mask(rb);
rb->count -= n;
}
static inline void rb_advance_head(esp_trace_rb_t *rb, uint32_t n)
{
rb->head = (rb->head + n) & rb_mask(rb);
rb->count += n;
}
esp_err_t esp_trace_rb_init(esp_trace_rb_t *rb, uint32_t size)
{
rb->buffer = heap_caps_malloc(size, MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT);
if (!rb->buffer) {
return ESP_ERR_NO_MEM;
}
rb->max_size = size;
rb->count = 0;
rb->head = 0;
rb->tail = 0;
return ESP_OK;
}
esp_err_t esp_trace_rb_put(esp_trace_rb_t *rb, const uint8_t *data, uint32_t len)
{
/* Drop oldest data if needed to make room */
uint32_t free_len = rb->max_size - rb->count;
if (len > free_len) {
rb_advance_tail(rb, len - free_len);
}
uint32_t head = rb->head;
uint32_t space_to_end = rb->max_size - head;
if (len <= space_to_end) {
memcpy(&rb->buffer[head], data, len);
} else {
memcpy(&rb->buffer[head], data, space_to_end);
memcpy(&rb->buffer[0], &data[space_to_end], len - space_to_end);
}
rb_advance_head(rb, len);
return ESP_OK;
}
uint32_t esp_trace_rb_get(esp_trace_rb_t *rb, uint8_t *data, uint32_t len)
{
uint32_t available = rb->count;
if (available == 0 || len == 0) {
return 0;
}
uint32_t to_read = MIN(len, available);
uint32_t tail = rb->tail;
uint32_t cont = rb->max_size - tail;
if (to_read <= cont) {
memcpy(data, &rb->buffer[tail], to_read);
} else {
memcpy(data, &rb->buffer[tail], cont);
memcpy(&data[cont], &rb->buffer[0], to_read - cont);
}
rb_advance_tail(rb, to_read);
return to_read;
}
uint32_t esp_trace_rb_peek_contiguous(const esp_trace_rb_t *rb, const uint8_t **data)
{
uint32_t used = rb->count;
if (used == 0) {
*data = NULL;
return 0;
}
*data = &rb->buffer[rb->tail];
uint32_t contiguous = rb->max_size - rb->tail;
return MIN(used, contiguous);
}
void esp_trace_rb_consume(esp_trace_rb_t *rb, uint32_t len)
{
rb_advance_tail(rb, len);
}
@@ -15,11 +15,9 @@
#include <stdlib.h>
#include <inttypes.h>
#include "esp_log.h"
#include "esp_app_trace.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "driver/gptimer.h"
#include "soc/uart_pins.h"
#include "esp_trace.h"
static const char *TAG = "example";
@@ -127,6 +125,9 @@ static void example_task(void *p)
}
}
#if CONFIG_ESP_TRACE_TRANSPORT_APPTRACE
#include "soc/uart_pins.h"
#include "esp_app_trace.h"
esp_trace_open_params_t esp_trace_get_user_params(void)
{
static esp_apptrace_config_t app_trace_config = APPTRACE_CONFIG_DEFAULT();
@@ -145,6 +146,19 @@ esp_trace_open_params_t esp_trace_get_user_params(void)
};
return trace_params;
}
#elif CONFIG_ESP_TRACE_TRANSPORT_USB_SERIAL_JTAG
esp_trace_open_params_t esp_trace_get_user_params(void)
{
esp_trace_open_params_t trace_params = {
.core_cfg = NULL,
.encoder_name = "sysview",
.encoder_cfg = NULL,
.transport_name = "usb_serial_jtag",
.transport_cfg = NULL,
};
return trace_params;
}
#endif
void app_main(void)
{
@@ -10,6 +10,7 @@ import pytest
import serial
from pytest_embedded_idf import IdfDut
from pytest_embedded_idf.utils import idf_parametrize
from pytest_embedded_idf.utils import soc_filtered_targets
if typing.TYPE_CHECKING:
from conftest import OpenOCD
@@ -166,3 +167,15 @@ def test_sysview_tracing_uart(dut: IdfDut) -> None:
@idf_parametrize('target', ['esp32c2'], indirect=['target'])
def test_sysview_tracing_uart_c2(dut: IdfDut) -> None:
_test_sysview_tracing_uart(dut)
@pytest.mark.usb_serial_jtag
@idf_parametrize('target', soc_filtered_targets('SOC_USB_SERIAL_JTAG_SUPPORTED == 1'), indirect=['target'])
@pytest.mark.parametrize('config', [pytest.param('sysview_usj')], indirect=True)
def test_sysview_tracing_usj_serial(dut: IdfDut) -> None:
time.sleep(1) # wait for USJ port to be ready
usj_port = '/dev/serial_ports/ttyACM-esp32'
ser = serial.Serial(usj_port, baudrate=1000000, timeout=10)
trace_log = [os.path.join(dut.logdir, 'sys_log_usj.svdat')] # pylint: disable=protected-access
_capture_sysview_trace(ser, trace_log[0])
_validate_trace_data(trace_log, dut.target, is_uart=True)
@@ -1 +1,2 @@
CONFIG_ESP_TRACE_TRANSPORT_APPTRACE=y
CONFIG_APPTRACE_DEST_JTAG=y
@@ -1,4 +1,5 @@
CONFIG_ESP_CONSOLE_NONE=y
CONFIG_ESP_TRACE_TRANSPORT_APPTRACE=y
CONFIG_APPTRACE_DEST_UART=y
CONFIG_APPTRACE_DEST_UART_NUM=0
CONFIG_APPTRACE_UART_BAUDRATE=1000000
@@ -1,5 +1,6 @@
CONFIG_IDF_TARGET="esp32c2"
CONFIG_ESP_CONSOLE_NONE=y
CONFIG_ESP_TRACE_TRANSPORT_APPTRACE=y
CONFIG_APPTRACE_DEST_UART=y
CONFIG_APPTRACE_UART_BAUDRATE=74880
CONFIG_XTAL_FREQ_26=y
@@ -0,0 +1,3 @@
CONFIG_ESP_CONSOLE_SECONDARY_NONE=y
CONFIG_ESP_TRACE_TRANSPORT_USB_SERIAL_JTAG=y
CONFIG_USE_CUSTOM_EVENT_ID=y
@@ -3,7 +3,6 @@ CONFIG_FREERTOS_HZ=1000
# Enable FreeRTOS SystemView Tracing by default
CONFIG_ESP_TRACE_ENABLE=y
CONFIG_ESP_TRACE_LIB_EXTERNAL=y
CONFIG_ESP_TRACE_TRANSPORT_APPTRACE=y
CONFIG_ESP_TRACE_TS_SOURCE_ESP_TIMER=y
CONFIG_SEGGER_SYSVIEW_EVT_OVERFLOW_ENABLE=y
CONFIG_SEGGER_SYSVIEW_EVT_ISR_ENTER_ENABLE=y