Merge branch 'test/sysview_uart' into 'master'

test(app_trace): add SystemView UART tracing tests for all targets

Closes IDF-11919, IDF-11920, IDF-11921, DOC-12212, and IDF-7660

See merge request espressif/esp-idf!41552
This commit is contained in:
Erhan Kurubas
2025-08-29 09:37:37 +02:00
29 changed files with 279 additions and 241 deletions

View File

@@ -10,8 +10,7 @@ set(srcs
"host_file_io.c")
if(CONFIG_ESP_DEBUG_STUBS_ENABLE)
list(APPEND srcs
"debug_stubs.c")
list(APPEND srcs "debug_stubs.c")
endif()
set(include_dirs "include")
@@ -19,20 +18,21 @@ set(include_dirs "include")
set(priv_include_dirs "private_include" "port/include")
if(CONFIG_APPTRACE_MEMBUFS_APPTRACE_PROTO_ENABLE)
list(APPEND srcs
"app_trace_membufs_proto.c")
list(APPEND srcs "app_trace_membufs_proto.c")
endif()
if(CONFIG_APPTRACE_DEST_JTAG)
if(CONFIG_IDF_TARGET_ARCH_XTENSA)
list(APPEND srcs
"port/xtensa/port.c")
list(APPEND srcs "port/xtensa/port_jtag.c")
endif()
if(CONFIG_IDF_TARGET_ARCH_RISCV)
list(APPEND srcs
"port/riscv/port.c")
list(APPEND srcs "port/riscv/port_jtag.c")
endif()
endif()
list(APPEND srcs
"port/port_uart.c")
if(CONFIG_APPTRACE_DEST_UART)
list(APPEND srcs "port/port_uart.c")
endif()
if(CONFIG_APPTRACE_SV_ENABLE)
list(APPEND include_dirs

View File

@@ -17,65 +17,43 @@ menu "Application Level Tracing"
endchoice
config APPTRACE_DEST_UART
bool
config APPTRACE_DEST_UART_NOUSB
bool
choice APPTRACE_DESTINATION2
prompt "Data Destination 2"
default APPTRACE_DEST_UART_NONE
help
Select destination for application trace: UART(XX) or none (to disable).
Select destination for application trace: UART or none (to disable).
config APPTRACE_DEST_UART0
bool "UART0"
config APPTRACE_DEST_UART
bool "UART"
select APPTRACE_ENABLE
select APPTRACE_DEST_UART
select APPTRACE_DEST_UART_NOUSB
depends on (ESP_CONSOLE_UART_NUM !=0)
config APPTRACE_DEST_UART1
bool "UART1"
select APPTRACE_ENABLE
select APPTRACE_DEST_UART
select APPTRACE_DEST_UART_NOUSB
depends on (ESP_CONSOLE_UART_NUM !=1)
config APPTRACE_DEST_UART2
bool "UART2"
select APPTRACE_ENABLE
select APPTRACE_DEST_UART
select APPTRACE_DEST_UART_NOUSB
depends on (ESP_CONSOLE_UART_NUM !=2) && (SOC_UART_NUM > 2)
config APPTRACE_DEST_USB_CDC
bool "USB_CDC"
select APPTRACE_ENABLE
select APPTRACE_DEST_UART
depends on !ESP_CONSOLE_USB_CDC && (IDF_TARGET_ESP32C3 || IDF_TARGET_ESP32S3) && !USB_ENABLED
config APPTRACE_DEST_UART_NONE
bool "None"
endchoice
config APPTRACE_DEST_UART_NUM
int "UART port number"
depends on APPTRACE_DEST_UART
range 0 1 if (SOC_UART_NUM <= 2)
range 0 2 if (SOC_UART_NUM <= 3)
range 0 5 if (SOC_UART_NUM <= 6)
default 1
help
UART communication port number for the apptrace destination.
See UART documentation for available port numbers.
config APPTRACE_UART_TX_GPIO
int "UART TX on GPIO<num>"
depends on APPTRACE_DEST_UART_NOUSB
depends on APPTRACE_DEST_UART
range 0 46
default 12 if IDF_TARGET_ESP32
default 12 if IDF_TARGET_ESP32C3
default 12
help
This GPIO is used for UART TX pin.
config APPTRACE_UART_RX_GPIO
int "UART RX on GPIO<num>"
depends on APPTRACE_DEST_UART_NOUSB
depends on APPTRACE_DEST_UART
range 0 46
default 13 if IDF_TARGET_ESP32
default 13 if IDF_TARGET_ESP32C3
default 13
help
This GPIO is used for UART RX pin.

View File

@@ -11,16 +11,8 @@
#include "esp_app_trace_port.h"
#include "esp_private/startup_internal.h"
#ifdef CONFIG_APPTRACE_DEST_UART0
#define ESP_APPTRACE_DEST_UART_NUM 0
#elif CONFIG_APPTRACE_DEST_UART1
#define ESP_APPTRACE_DEST_UART_NUM 1
#elif CONFIG_APPTRACE_DEST_UART2
#define ESP_APPTRACE_DEST_UART_NUM 2
#elif CONFIG_APPTRACE_DEST_USB_CDC
#define ESP_APPTRACE_DEST_UART_NUM 10
#else
#define ESP_APPTRACE_DEST_UART_NUM 0
#if CONFIG_ESP_CONSOLE_UART && CONFIG_APPTRACE_DEST_UART && (CONFIG_APPTRACE_DEST_UART_NUM == CONFIG_ESP_CONSOLE_UART_NUM)
#error "Application trace UART and console UART cannot use the same port number"
#endif
#define ESP_APPTRACE_MAX_VPRINTF_ARGS 256
@@ -39,24 +31,19 @@ static bool s_inited;
esp_err_t esp_apptrace_init(void)
{
int res;
esp_apptrace_hw_t *hw = NULL;
void *hw_data = NULL;
__attribute__((unused)) void *hw_data = NULL;
// 'esp_apptrace_init()' is called on every core, so ensure to do main initialization only once
if (esp_cpu_get_core_id() == 0) {
memset(&s_trace_channels, 0, sizeof(s_trace_channels));
hw = esp_apptrace_jtag_hw_get(&hw_data);
ESP_APPTRACE_LOGD("HW interface %p", hw);
if (hw != NULL) {
s_trace_channels[ESP_APPTRACE_DEST_JTAG].hw = hw;
s_trace_channels[ESP_APPTRACE_DEST_JTAG].hw_data = hw_data;
}
hw = esp_apptrace_uart_hw_get(ESP_APPTRACE_DEST_UART_NUM, &hw_data);
if (hw != NULL) {
s_trace_channels[ESP_APPTRACE_DEST_UART].hw = hw;
s_trace_channels[ESP_APPTRACE_DEST_UART].hw_data = hw_data;
}
#if CONFIG_APPTRACE_DEST_JTAG
s_trace_channels[ESP_APPTRACE_DEST_JTAG].hw = esp_apptrace_jtag_hw_get(&hw_data);
s_trace_channels[ESP_APPTRACE_DEST_JTAG].hw_data = hw_data;
#endif
#if CONFIG_APPTRACE_DEST_UART
s_trace_channels[ESP_APPTRACE_DEST_UART].hw = esp_apptrace_uart_hw_get(CONFIG_APPTRACE_DEST_UART_NUM, &hw_data);
s_trace_channels[ESP_APPTRACE_DEST_UART].hw_data = hw_data;
#endif
s_inited = true;
}
@@ -64,7 +51,7 @@ esp_err_t esp_apptrace_init(void)
for (int i = 0; i < sizeof(s_trace_channels) / sizeof(s_trace_channels[0]); i++) {
esp_apptrace_channel_t *ch = &s_trace_channels[i];
if (ch->hw) {
res = ch->hw->init(ch->hw_data);
int res = ch->hw->init(ch->hw_data);
if (res != ESP_OK) {
ESP_APPTRACE_LOGE("Failed to init trace channel HW interface (%d)!", res);
return res;
@@ -441,10 +428,3 @@ bool esp_apptrace_host_is_connected(esp_apptrace_dest_t dest)
return ch->hw->host_is_connected(ch->hw_data);
}
#if !CONFIG_APPTRACE_DEST_JTAG
esp_apptrace_hw_t *esp_apptrace_jtag_hw_get(void **data)
{
return NULL;
}
#endif

View File

@@ -2,12 +2,13 @@
archive: libapp_trace.a
entries:
app_trace (noflash)
port_uart (noflash)
app_trace_util (noflash)
if APPTRACE_MEMBUFS_APPTRACE_PROTO_ENABLE:
app_trace_membufs_proto (noflash)
if APPTRACE_DEST_JTAG = y:
port (noflash)
port_jtag (noflash)
if APPTRACE_DEST_UART = y:
port_uart (noflash)
if APPTRACE_SV_ENABLE = y:
SEGGER_SYSVIEW (noflash)
SEGGER_RTT_esp (noflash)

View File

@@ -14,8 +14,6 @@
#include "string.h"
#include "driver/gpio.h"
#define APPTRACE_DEST_UART (CONFIG_APPTRACE_DEST_UART0 | CONFIG_APPTRACE_DEST_UART1 | CONFIG_APPTRACE_DEST_UART2)
#define APP_TRACE_MAX_TX_BUFF_UART CONFIG_APPTRACE_UART_TX_BUFF_SIZE
#define APP_TRACE_MAX_TX_MSG_UART CONFIG_APPTRACE_UART_TX_MSG_SIZE
@@ -42,47 +40,8 @@ typedef struct {
bool circular_buff_overflow;
} esp_apptrace_uart_data_t;
#if APPTRACE_DEST_UART
static esp_err_t esp_apptrace_uart_init(esp_apptrace_uart_data_t *hw_data);
static esp_err_t esp_apptrace_uart_flush(esp_apptrace_uart_data_t *hw_data, esp_apptrace_tmo_t *tmo);
static esp_err_t esp_apptrace_uart_flush_nolock(esp_apptrace_uart_data_t *hw_data, uint32_t min_sz, esp_apptrace_tmo_t *tmo);
static uint8_t *esp_apptrace_uart_up_buffer_get(esp_apptrace_uart_data_t *hw_data, uint32_t size, esp_apptrace_tmo_t *tmo);
static esp_err_t esp_apptrace_uart_up_buffer_put(esp_apptrace_uart_data_t *hw_data, uint8_t *ptr, esp_apptrace_tmo_t *tmo);
static void esp_apptrace_uart_down_buffer_config(esp_apptrace_uart_data_t *hw_data, uint8_t *buf, uint32_t size);
static uint8_t *esp_apptrace_uart_down_buffer_get(esp_apptrace_uart_data_t *hw_data, uint32_t *size, esp_apptrace_tmo_t *tmo);
static esp_err_t esp_apptrace_uart_down_buffer_put(esp_apptrace_uart_data_t *hw_data, uint8_t *ptr, esp_apptrace_tmo_t *tmo);
static bool esp_apptrace_uart_host_is_connected(esp_apptrace_uart_data_t *hw_data);
#endif // APPTRACE_DEST_UART
const static char *TAG = "esp_apptrace_uart";
esp_apptrace_hw_t *esp_apptrace_uart_hw_get(int num, void **data)
{
ESP_LOGD(TAG, "esp_apptrace_uart_hw_get - %i", num);
#if APPTRACE_DEST_UART
static esp_apptrace_uart_data_t s_uart_hw_data = {
};
static esp_apptrace_hw_t s_uart_hw = {
.init = (esp_err_t (*)(void *))esp_apptrace_uart_init,
.get_up_buffer = (uint8_t *(*)(void *, uint32_t, esp_apptrace_tmo_t *))esp_apptrace_uart_up_buffer_get,
.put_up_buffer = (esp_err_t (*)(void *, uint8_t *, esp_apptrace_tmo_t *))esp_apptrace_uart_up_buffer_put,
.flush_up_buffer_nolock = (esp_err_t (*)(void *, uint32_t, esp_apptrace_tmo_t *))esp_apptrace_uart_flush_nolock,
.flush_up_buffer = (esp_err_t (*)(void *, esp_apptrace_tmo_t *))esp_apptrace_uart_flush,
.down_buffer_config = (void (*)(void *, uint8_t *, uint32_t))esp_apptrace_uart_down_buffer_config,
.get_down_buffer = (uint8_t *(*)(void *, uint32_t *, esp_apptrace_tmo_t *))esp_apptrace_uart_down_buffer_get,
.put_down_buffer = (esp_err_t (*)(void *, uint8_t *, esp_apptrace_tmo_t *))esp_apptrace_uart_down_buffer_put,
.host_is_connected = (bool (*)(void *))esp_apptrace_uart_host_is_connected,
};
s_uart_hw_data.port_num = num;
*data = &s_uart_hw_data;
return &s_uart_hw;
#else
return NULL;
#endif
}
#if APPTRACE_DEST_UART
static esp_err_t esp_apptrace_uart_lock(esp_apptrace_uart_data_t *hw_data, esp_apptrace_tmo_t *tmo)
{
#if CONFIG_APPTRACE_LOCK_ENABLE
@@ -348,4 +307,23 @@ static esp_err_t esp_apptrace_uart_flush(esp_apptrace_uart_data_t *hw_data, esp_
return ESP_OK;
}
#endif // APPTRACE_DEST_UART
esp_apptrace_hw_t *esp_apptrace_uart_hw_get(int num, void **data)
{
ESP_LOGD(TAG, "esp_apptrace_uart_hw_get - %i", num);
static esp_apptrace_uart_data_t s_uart_hw_data;
static esp_apptrace_hw_t s_uart_hw = {
.init = (esp_err_t (*)(void *))esp_apptrace_uart_init,
.get_up_buffer = (uint8_t *(*)(void *, uint32_t, esp_apptrace_tmo_t *))esp_apptrace_uart_up_buffer_get,
.put_up_buffer = (esp_err_t (*)(void *, uint8_t *, esp_apptrace_tmo_t *))esp_apptrace_uart_up_buffer_put,
.flush_up_buffer_nolock = (esp_err_t (*)(void *, uint32_t, esp_apptrace_tmo_t *))esp_apptrace_uart_flush_nolock,
.flush_up_buffer = (esp_err_t (*)(void *, esp_apptrace_tmo_t *))esp_apptrace_uart_flush,
.down_buffer_config = (void (*)(void *, uint8_t *, uint32_t))esp_apptrace_uart_down_buffer_config,
.get_down_buffer = (uint8_t *(*)(void *, uint32_t *, esp_apptrace_tmo_t *))esp_apptrace_uart_down_buffer_get,
.put_down_buffer = (esp_err_t (*)(void *, uint8_t *, esp_apptrace_tmo_t *))esp_apptrace_uart_down_buffer_put,
.host_is_connected = (bool (*)(void *))esp_apptrace_uart_host_is_connected,
};
s_uart_hw_data.port_num = num;
*data = &s_uart_hw_data;
return &s_uart_hw;
}

View File

@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2021-2025 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*/
@@ -40,20 +40,6 @@ typedef struct {
#define ESP_APPTRACE_RISCV_INITED(_hw_) ((_hw_)->inited & (1 << 0/*esp_cpu_get_core_id()*/))
static esp_err_t esp_apptrace_riscv_init(esp_apptrace_riscv_data_t *hw_data);
static esp_err_t esp_apptrace_riscv_flush(esp_apptrace_riscv_data_t *hw_data, esp_apptrace_tmo_t *tmo);
static esp_err_t esp_apptrace_riscv_flush_nolock(esp_apptrace_riscv_data_t *hw_data, uint32_t min_sz, esp_apptrace_tmo_t *tmo);
static uint8_t *esp_apptrace_riscv_up_buffer_get(esp_apptrace_riscv_data_t *hw_data, uint32_t size, esp_apptrace_tmo_t *tmo);
static esp_err_t esp_apptrace_riscv_up_buffer_put(esp_apptrace_riscv_data_t *hw_data, uint8_t *ptr, esp_apptrace_tmo_t *tmo);
static void esp_apptrace_riscv_down_buffer_config(esp_apptrace_riscv_data_t *hw_data, uint8_t *buf, uint32_t size);
static uint8_t *esp_apptrace_riscv_down_buffer_get(esp_apptrace_riscv_data_t *hw_data, uint32_t *size, esp_apptrace_tmo_t *tmo);
static esp_err_t esp_apptrace_riscv_down_buffer_put(esp_apptrace_riscv_data_t *hw_data, uint8_t *ptr, esp_apptrace_tmo_t *tmo);
static bool esp_apptrace_riscv_host_is_connected(esp_apptrace_riscv_data_t *hw_data);
static esp_err_t esp_apptrace_riscv_buffer_swap_start(uint32_t curr_block_id);
static esp_err_t esp_apptrace_riscv_buffer_swap(uint32_t new_block_id, uint32_t prev_block_len);
static esp_err_t esp_apptrace_riscv_buffer_swap_end(uint32_t new_block_id, uint32_t prev_block_len);
static bool esp_apptrace_riscv_host_data_pending(void);
const static char *TAG = "esp_apptrace";
#if SOC_CACHE_INTERNAL_MEM_VIA_L1CACHE
@@ -64,38 +50,6 @@ const static char *TAG = "esp_apptrace";
static APPTRACE_DRAM_ATTR esp_apptrace_riscv_ctrl_block_t s_tracing_ctrl[CONFIG_FREERTOS_NUMBER_OF_CORES];
esp_apptrace_hw_t *esp_apptrace_jtag_hw_get(void **data)
{
#if CONFIG_APPTRACE_DEST_JTAG
static esp_apptrace_membufs_proto_hw_t s_trace_proto_hw = {
.swap_start = esp_apptrace_riscv_buffer_swap_start,
.swap = esp_apptrace_riscv_buffer_swap,
.swap_end = esp_apptrace_riscv_buffer_swap_end,
.host_data_pending = esp_apptrace_riscv_host_data_pending,
};
static esp_apptrace_riscv_data_t s_trace_hw_data = {
.membufs = {
.hw = &s_trace_proto_hw,
},
};
static esp_apptrace_hw_t s_trace_hw = {
.init = (esp_err_t (*)(void *))esp_apptrace_riscv_init,
.get_up_buffer = (uint8_t *(*)(void *, uint32_t, esp_apptrace_tmo_t *))esp_apptrace_riscv_up_buffer_get,
.put_up_buffer = (esp_err_t (*)(void *, uint8_t *, esp_apptrace_tmo_t *))esp_apptrace_riscv_up_buffer_put,
.flush_up_buffer_nolock = (esp_err_t (*)(void *, uint32_t, esp_apptrace_tmo_t *))esp_apptrace_riscv_flush_nolock,
.flush_up_buffer = (esp_err_t (*)(void *, esp_apptrace_tmo_t *))esp_apptrace_riscv_flush,
.down_buffer_config = (void (*)(void *, uint8_t *, uint32_t))esp_apptrace_riscv_down_buffer_config,
.get_down_buffer = (uint8_t *(*)(void *, uint32_t *, esp_apptrace_tmo_t *))esp_apptrace_riscv_down_buffer_get,
.put_down_buffer = (esp_err_t (*)(void *, uint8_t *, esp_apptrace_tmo_t *))esp_apptrace_riscv_down_buffer_put,
.host_is_connected = (bool (*)(void *))esp_apptrace_riscv_host_is_connected,
};
*data = &s_trace_hw_data;
return &s_trace_hw;
#else
return NULL;
#endif
}
/* Advertises apptrace control block address to host.
This function can be overridden with custom implementation,
e.g. OpenOCD flasher stub use own implementation of it. */
@@ -364,3 +318,31 @@ static bool esp_apptrace_riscv_host_data_pending(void)
// ESP_APPTRACE_LOGV("%s() 0x%x", __func__, ctrl_reg);
return (ctrl_reg & ESP_APPTRACE_RISCV_HOST_DATA) ? true : false;
}
esp_apptrace_hw_t *esp_apptrace_jtag_hw_get(void **data)
{
static esp_apptrace_membufs_proto_hw_t s_trace_proto_hw = {
.swap_start = esp_apptrace_riscv_buffer_swap_start,
.swap = esp_apptrace_riscv_buffer_swap,
.swap_end = esp_apptrace_riscv_buffer_swap_end,
.host_data_pending = esp_apptrace_riscv_host_data_pending,
};
static esp_apptrace_riscv_data_t s_trace_hw_data = {
.membufs = {
.hw = &s_trace_proto_hw,
},
};
static esp_apptrace_hw_t s_trace_hw = {
.init = (esp_err_t (*)(void *))esp_apptrace_riscv_init,
.get_up_buffer = (uint8_t *(*)(void *, uint32_t, esp_apptrace_tmo_t *))esp_apptrace_riscv_up_buffer_get,
.put_up_buffer = (esp_err_t (*)(void *, uint8_t *, esp_apptrace_tmo_t *))esp_apptrace_riscv_up_buffer_put,
.flush_up_buffer_nolock = (esp_err_t (*)(void *, uint32_t, esp_apptrace_tmo_t *))esp_apptrace_riscv_flush_nolock,
.flush_up_buffer = (esp_err_t (*)(void *, esp_apptrace_tmo_t *))esp_apptrace_riscv_flush,
.down_buffer_config = (void (*)(void *, uint8_t *, uint32_t))esp_apptrace_riscv_down_buffer_config,
.get_down_buffer = (uint8_t *(*)(void *, uint32_t *, esp_apptrace_tmo_t *))esp_apptrace_riscv_down_buffer_get,
.put_down_buffer = (esp_err_t (*)(void *, uint8_t *, esp_apptrace_tmo_t *))esp_apptrace_riscv_down_buffer_put,
.host_is_connected = (bool (*)(void *))esp_apptrace_riscv_host_is_connected,
};
*data = &s_trace_hw_data;
return &s_trace_hw;
}

View File

@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*/
@@ -188,20 +188,6 @@ typedef struct {
esp_apptrace_membufs_proto_data_t membufs;
} esp_apptrace_trax_data_t;
static esp_err_t esp_apptrace_trax_init(esp_apptrace_trax_data_t *hw_data);
static esp_err_t esp_apptrace_trax_flush(esp_apptrace_trax_data_t *hw_data, esp_apptrace_tmo_t *tmo);
static esp_err_t esp_apptrace_trax_flush_nolock(esp_apptrace_trax_data_t *hw_data, uint32_t min_sz, esp_apptrace_tmo_t *tmo);
static uint8_t *esp_apptrace_trax_up_buffer_get(esp_apptrace_trax_data_t *hw_data, uint32_t size, esp_apptrace_tmo_t *tmo);
static esp_err_t esp_apptrace_trax_up_buffer_put(esp_apptrace_trax_data_t *hw_data, uint8_t *ptr, esp_apptrace_tmo_t *tmo);
static void esp_apptrace_trax_down_buffer_config(esp_apptrace_trax_data_t *hw_data, uint8_t *buf, uint32_t size);
static uint8_t *esp_apptrace_trax_down_buffer_get(esp_apptrace_trax_data_t *hw_data, uint32_t *size, esp_apptrace_tmo_t *tmo);
static esp_err_t esp_apptrace_trax_down_buffer_put(esp_apptrace_trax_data_t *hw_data, uint8_t *ptr, esp_apptrace_tmo_t *tmo);
static bool esp_apptrace_trax_host_is_connected(esp_apptrace_trax_data_t *hw_data);
static esp_err_t esp_apptrace_trax_buffer_swap_start(uint32_t curr_block_id);
static esp_err_t esp_apptrace_trax_buffer_swap(uint32_t new_block_id, uint32_t prev_block_len);
static esp_err_t esp_apptrace_trax_buffer_swap_end(uint32_t new_block_id, uint32_t prev_block_len);
static bool esp_apptrace_trax_host_data_pending(void);
const static char *TAG = "esp_apptrace";
static uint8_t * const s_trax_blocks[] = {
@@ -209,38 +195,6 @@ static uint8_t * const s_trax_blocks[] = {
(uint8_t *)TRACEMEM_BLK1_ADDR
};
esp_apptrace_hw_t *esp_apptrace_jtag_hw_get(void **data)
{
#if CONFIG_APPTRACE_DEST_JTAG
static esp_apptrace_membufs_proto_hw_t s_trax_proto_hw = {
.swap_start = esp_apptrace_trax_buffer_swap_start,
.swap = esp_apptrace_trax_buffer_swap,
.swap_end = esp_apptrace_trax_buffer_swap_end,
.host_data_pending = esp_apptrace_trax_host_data_pending,
};
static esp_apptrace_trax_data_t s_trax_hw_data = {
.membufs = {
.hw = &s_trax_proto_hw,
},
};
static esp_apptrace_hw_t s_trax_hw = {
.init = (esp_err_t (*)(void *))esp_apptrace_trax_init,
.get_up_buffer = (uint8_t *(*)(void *, uint32_t, esp_apptrace_tmo_t *))esp_apptrace_trax_up_buffer_get,
.put_up_buffer = (esp_err_t (*)(void *, uint8_t *, esp_apptrace_tmo_t *))esp_apptrace_trax_up_buffer_put,
.flush_up_buffer_nolock = (esp_err_t (*)(void *, uint32_t, esp_apptrace_tmo_t *))esp_apptrace_trax_flush_nolock,
.flush_up_buffer = (esp_err_t (*)(void *, esp_apptrace_tmo_t *))esp_apptrace_trax_flush,
.down_buffer_config = (void (*)(void *, uint8_t *, uint32_t))esp_apptrace_trax_down_buffer_config,
.get_down_buffer = (uint8_t *(*)(void *, uint32_t *, esp_apptrace_tmo_t *))esp_apptrace_trax_down_buffer_get,
.put_down_buffer = (esp_err_t (*)(void *, uint8_t *, esp_apptrace_tmo_t *))esp_apptrace_trax_down_buffer_put,
.host_is_connected = (bool (*)(void *))esp_apptrace_trax_host_is_connected,
};
*data = &s_trax_hw_data;
return &s_trax_hw;
#else
return NULL;
#endif
}
static esp_err_t esp_apptrace_trax_lock(esp_apptrace_trax_data_t *hw_data, esp_apptrace_tmo_t *tmo)
{
#if CONFIG_APPTRACE_LOCK_ENABLE
@@ -539,3 +493,31 @@ static bool esp_apptrace_trax_host_data_pending(void)
uint32_t ctrl_reg = eri_read(ESP_APPTRACE_TRAX_CTRL_REG);
return (ctrl_reg & ESP_APPTRACE_TRAX_HOST_DATA) ? true : false;
}
esp_apptrace_hw_t *esp_apptrace_jtag_hw_get(void **data)
{
static esp_apptrace_membufs_proto_hw_t s_trax_proto_hw = {
.swap_start = esp_apptrace_trax_buffer_swap_start,
.swap = esp_apptrace_trax_buffer_swap,
.swap_end = esp_apptrace_trax_buffer_swap_end,
.host_data_pending = esp_apptrace_trax_host_data_pending,
};
static esp_apptrace_trax_data_t s_trax_hw_data = {
.membufs = {
.hw = &s_trax_proto_hw,
},
};
static esp_apptrace_hw_t s_trax_hw = {
.init = (esp_err_t (*)(void *))esp_apptrace_trax_init,
.get_up_buffer = (uint8_t *(*)(void *, uint32_t, esp_apptrace_tmo_t *))esp_apptrace_trax_up_buffer_get,
.put_up_buffer = (esp_err_t (*)(void *, uint8_t *, esp_apptrace_tmo_t *))esp_apptrace_trax_up_buffer_put,
.flush_up_buffer_nolock = (esp_err_t (*)(void *, uint32_t, esp_apptrace_tmo_t *))esp_apptrace_trax_flush_nolock,
.flush_up_buffer = (esp_err_t (*)(void *, esp_apptrace_tmo_t *))esp_apptrace_trax_flush,
.down_buffer_config = (void (*)(void *, uint8_t *, uint32_t))esp_apptrace_trax_down_buffer_config,
.get_down_buffer = (uint8_t *(*)(void *, uint32_t *, esp_apptrace_tmo_t *))esp_apptrace_trax_down_buffer_get,
.put_down_buffer = (esp_err_t (*)(void *, uint8_t *, esp_apptrace_tmo_t *))esp_apptrace_trax_down_buffer_put,
.host_is_connected = (bool (*)(void *))esp_apptrace_trax_host_is_connected,
};
*data = &s_trax_hw_data;
return &s_trax_hw;
}

View File

@@ -41,7 +41,7 @@ Using of this feature depends on two components:
1. **Host side:** Application tracing is done over JTAG, so it needs OpenOCD to be set up and running on host machine. For instructions on how to set it up, please see :doc:`JTAG Debugging <../api-guides/jtag-debugging/index>` for details.
2. **Target side:** Application tracing functionality can be enabled in menuconfig. Please go to ``Component config`` > ``Application Level Tracing`` menu, which allows selecting destination for the trace data (hardware interface for transport: JTAG or/and UART). Choosing any of the destinations automatically enables the ``CONFIG_APPTRACE_ENABLE`` option. For UART interfaces, users have to define baud rate, TX and RX pins numbers, and additional UART-related parameters.
2. **Target side:** Application tracing functionality can be enabled in menuconfig. Please go to ``Component config`` > ``Application Level Tracing`` menu, which allows selecting destination for the trace data (hardware interface for transport: JTAG or/and UART). Choosing any of the destinations automatically enables the ``CONFIG_APPTRACE_ENABLE`` option. For UART interfaces, users have to define port number, baud rate, TX and RX pins numbers, and additional UART-related parameters.
.. note::

View File

@@ -81,6 +81,28 @@ Update to:
return res;
}
The UART destination configuration has been simplified:
- Removed: Individual UART selection via ``CONFIG_APPTRACE_DEST_UARTx=y``
- Added: Single UART port selection via ``CONFIG_APPTRACE_DEST_UART_NUM``
To migrate, update your sdkconfig:
Old configuration:
.. code-block:: none
CONFIG_APPTRACE_DEST_UART0=y
# or
CONFIG_APPTRACE_DEST_UART1=y
New configuration:
.. code-block:: none
CONFIG_APPTRACE_DEST_UART=y
CONFIG_APPTRACE_DEST_UART_NUM=0 # or 1, 2 depending on target
FreeRTOS
--------

View File

@@ -41,7 +41,7 @@ ESP-IDF 中提供了应用层跟踪功能,用于分析应用程序的行为。
1. **主机端:** 应用程序跟踪通过 JTAG 来完成,因此需要在主机上安装并运行 OpenOCD。详细信息请参阅 :doc:`JTAG 调试 <../api-guides/jtag-debugging/index>`
2. **目标端:** 在 menuconfig 中开启应用程序跟踪功能。前往 ``Component config`` > ``Application Level Tracing`` 菜单选择跟踪数据的传输目标具体用于传输的硬件接口JTAG 和/或 UART选择任一非 None 的目标都会自动开启 ``CONFIG_APPTRACE_ENABLE`` 这个选项。对于 UART 接口,用户必须定义波特率、TX 和 RX 管脚及其他相关参数。
2. **目标端:** 在 menuconfig 中开启应用程序跟踪功能。前往 ``Component config`` > ``Application Level Tracing`` 菜单选择跟踪数据的传输目标具体用于传输的硬件接口JTAG 和/或 UART选择任一非 None 的目标都会自动开启 ``CONFIG_APPTRACE_ENABLE`` 这个选项。对于 UART 接口,用户需要定义端口号、波特率、TX 和 RX 管脚及其他相关参数。
.. note::

View File

@@ -81,6 +81,28 @@ App 追踪
return res;
}
UART 目标配置已简化:
- 移除:通过 ``CONFIG_APPTRACE_DEST_UARTx=y`` 选择单个 UART
- 新增:通过 ``CONFIG_APPTRACE_DEST_UART_NUM`` 选择 UART 端口
迁移方法,更新你的 sdkconfig 配置:
旧配置:
.. code-block:: none
CONFIG_APPTRACE_DEST_UART0=y
# 或
CONFIG_APPTRACE_DEST_UART1=y
新配置:
.. code-block:: none
CONFIG_APPTRACE_DEST_UART=y
CONFIG_APPTRACE_DEST_UART_NUM=0 # 或 1、2具体取决于目标芯片
FreeRTOS
--------

View File

@@ -134,7 +134,7 @@ static void example_task(void *p)
void app_main(void)
{
ESP_LOGI(TAG, "Ready for OpenOCD connection");
ESP_LOGI(TAG, "Hello from sysview_tracing example!");
static example_event_data_t event_data[CONFIG_FREERTOS_NUMBER_OF_CORES];

View File

@@ -7,6 +7,7 @@ import typing
import pexpect
import pytest
import serial
from pytest_embedded_idf import IdfDut
from pytest_embedded_idf.utils import idf_parametrize
@@ -14,7 +15,7 @@ if typing.TYPE_CHECKING:
from conftest import OpenOCD
def _test_examples_sysview_tracing(openocd_dut: 'OpenOCD', dut: IdfDut) -> None:
def _test_sysview_tracing_jtag(openocd_dut: 'OpenOCD', dut: IdfDut) -> None:
# Construct trace log paths
trace_log = [
os.path.join(dut.logdir, 'sys_log0.svdat') # pylint: disable=protected-access
@@ -27,7 +28,7 @@ def _test_examples_sysview_tracing(openocd_dut: 'OpenOCD', dut: IdfDut) -> None:
gdb_logfile = os.path.join(dut.logdir, 'gdb.txt')
gdbinit_orig = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'gdbinit')
gdbinit = os.path.join(dut.logdir, 'gdbinit')
with open(gdbinit_orig, 'r') as f_r, open(gdbinit, 'w') as f_w:
with open(gdbinit_orig) as f_r, open(gdbinit, 'w') as f_w:
for line in f_r:
if line.startswith('mon esp sysview start'):
f_w.write(f'mon esp sysview start {trace_files}\n')
@@ -37,14 +38,18 @@ def _test_examples_sysview_tracing(openocd_dut: 'OpenOCD', dut: IdfDut) -> None:
def dut_expect_task_event() -> None:
dut.expect(re.compile(rb'example: Task\[0x[0-9A-Fa-f]+\]: received event \d+'), timeout=30)
dut.expect_exact('example: Ready for OpenOCD connection', timeout=5)
with openocd_dut.run() as openocd, open(gdb_logfile, 'w') as gdb_log, pexpect.spawn(
f'idf.py -B {dut.app.binary_path} gdb --batch -x {gdbinit}',
timeout=60,
logfile=gdb_log,
encoding='utf-8',
codec_errors='ignore',
) as p:
dut.expect_exact('example: Hello from sysview_tracing example!', timeout=5)
with (
openocd_dut.run() as openocd,
open(gdb_logfile, 'w') as gdb_log,
pexpect.spawn(
f'idf.py -B {dut.app.binary_path} gdb --batch -x {gdbinit}',
timeout=60,
logfile=gdb_log,
encoding='utf-8',
codec_errors='ignore',
) as p,
):
p.expect_exact('hit Breakpoint 1, app_main ()')
dut.expect('example: Created task') # dut has been restarted by gdb since the last dut.expect()
dut_expect_task_event()
@@ -55,14 +60,59 @@ def _test_examples_sysview_tracing(openocd_dut: 'OpenOCD', dut: IdfDut) -> None:
@pytest.mark.jtag
@idf_parametrize('config', ['sysview_jtag'], indirect=['config'])
@idf_parametrize('target', ['esp32', 'esp32c2', 'esp32s2'], indirect=['target'])
def test_examples_sysview_tracing(openocd_dut: 'OpenOCD', dut: IdfDut) -> None:
_test_examples_sysview_tracing(openocd_dut, dut)
def test_sysview_tracing_jtag(openocd_dut: 'OpenOCD', dut: IdfDut) -> None:
_test_sysview_tracing_jtag(openocd_dut, dut)
@pytest.mark.usb_serial_jtag
@idf_parametrize('config', ['sysview_jtag'], indirect=['config'])
@idf_parametrize(
'target', ['esp32s3', 'esp32c3', 'esp32c5', 'esp32c6', 'esp32c61', 'esp32h2', 'esp32p4'], indirect=['target']
)
def test_examples_sysview_tracing_usj(openocd_dut: 'OpenOCD', dut: IdfDut) -> None:
_test_examples_sysview_tracing(openocd_dut, dut)
def test_sysview_tracing_usj(openocd_dut: 'OpenOCD', dut: IdfDut) -> None:
_test_sysview_tracing_jtag(openocd_dut, dut)
def _test_sysview_tracing_uart(dut: IdfDut) -> None:
dut.serial.close()
time.sleep(2) # Wait for the DUT to reboot
with serial.Serial(dut.serial.port, baudrate=dut.app.sdkconfig.get('APPTRACE_UART_BAUDRATE'), timeout=10) as ser:
trace_log = os.path.join(dut.logdir, 'sys_log_uart.svdat') # pylint: disable=protected-access
# Send Start command to start SysView tracing
ser.write(b'\x01')
with open(trace_log, 'w+b') as f:
start_time = time.time()
while True:
try:
if ser.in_waiting:
data = ser.read(1024)
f.write(data)
if time.time() - start_time > 3:
break
except serial.SerialTimeoutException:
assert False, 'Timeout reached while reading from serial port, exiting...'
# Send Stop command
ser.write(b'\x02')
f.seek(0)
content = f.read()
search_str = f'N=FreeRTOS Application,D={dut.target},C=core0,O=FreeRTOS'.encode()
assert search_str in content, 'SysView trace data not found in the log file'
@pytest.mark.generic
@idf_parametrize('config', ['sysview_uart'], indirect=['config'])
@idf_parametrize('target', ['supported_targets'], indirect=['target'])
def test_sysview_tracing_uart(dut: IdfDut) -> None:
_test_sysview_tracing_uart(dut)
@pytest.mark.generic
@pytest.mark.xtal_26mhz
@idf_parametrize('config', ['sysview_uart_esp32c2_26Mhz'], indirect=['config'])
@idf_parametrize('target', ['esp32c2'], indirect=['target'])
def test_sysview_tracing_uart_c2(dut: IdfDut) -> None:
_test_sysview_tracing_uart(dut)

View File

@@ -0,0 +1 @@
CONFIG_APPTRACE_DEST_JTAG=y

View File

@@ -0,0 +1,5 @@
CONFIG_ESP_CONSOLE_NONE=y
CONFIG_ESP_CONSOLE_SECONDARY_NONE=y
CONFIG_APPTRACE_DEST_UART=y
CONFIG_APPTRACE_DEST_UART_NUM=0
CONFIG_APPTRACE_SV_DEST_UART=y

View File

@@ -0,0 +1,8 @@
CONFIG_IDF_TARGET="esp32c2"
CONFIG_ESP_CONSOLE_NONE=y
CONFIG_ESP_CONSOLE_SECONDARY_NONE=y
CONFIG_APPTRACE_DEST_UART=y
CONFIG_APPTRACE_DEST_UART_NUM=0
CONFIG_APPTRACE_SV_DEST_UART=y
CONFIG_APPTRACE_UART_BAUDRATE=74880
CONFIG_XTAL_FREQ_26=y

View File

@@ -1,9 +1,7 @@
# 1ms tick period
CONFIG_FREERTOS_HZ=1000
# Enable application tracing by default
CONFIG_APPTRACE_DEST_JTAG=y
CONFIG_APPTRACE_ENABLE=y
# Enable FreeRTOS SystemView Tracing by default
CONFIG_APPTRACE_ENABLE=y
CONFIG_APPTRACE_SV_ENABLE=y
CONFIG_APPTRACE_SV_TS_SOURCE_ESP_TIMER=y
CONFIG_APPTRACE_SV_EVT_OVERFLOW_ENABLE=y

View File

@@ -0,0 +1,3 @@
CONFIG_IDF_TARGET="esp32"
CONFIG_APPTRACE_UART_TX_GPIO=1
CONFIG_APPTRACE_UART_RX_GPIO=3

View File

@@ -0,0 +1,3 @@
CONFIG_IDF_TARGET="esp32c2"
CONFIG_APPTRACE_UART_TX_GPIO=20
CONFIG_APPTRACE_UART_RX_GPIO=19

View File

@@ -0,0 +1,3 @@
CONFIG_IDF_TARGET="esp32c3"
CONFIG_APPTRACE_UART_TX_GPIO=21
CONFIG_APPTRACE_UART_RX_GPIO=20

View File

@@ -0,0 +1,3 @@
CONFIG_IDF_TARGET="esp32c5"
CONFIG_APPTRACE_UART_TX_GPIO=11
CONFIG_APPTRACE_UART_RX_GPIO=12

View File

@@ -0,0 +1,3 @@
CONFIG_IDF_TARGET="esp32c6"
CONFIG_APPTRACE_UART_TX_GPIO=16
CONFIG_APPTRACE_UART_RX_GPIO=17

View File

@@ -0,0 +1,3 @@
CONFIG_IDF_TARGET="esp32c61"
CONFIG_APPTRACE_UART_TX_GPIO=11
CONFIG_APPTRACE_UART_RX_GPIO=10

View File

@@ -0,0 +1,3 @@
CONFIG_IDF_TARGET="esp32h2"
CONFIG_APPTRACE_UART_TX_GPIO=24
CONFIG_APPTRACE_UART_RX_GPIO=23

View File

@@ -0,0 +1,3 @@
CONFIG_IDF_TARGET="esp32p4"
CONFIG_APPTRACE_UART_TX_GPIO=37
CONFIG_APPTRACE_UART_RX_GPIO=38

View File

@@ -0,0 +1,3 @@
CONFIG_IDF_TARGET="esp32s2"
CONFIG_APPTRACE_UART_TX_GPIO=43
CONFIG_APPTRACE_UART_RX_GPIO=44

View File

@@ -0,0 +1,3 @@
CONFIG_IDF_TARGET="esp32s3"
CONFIG_APPTRACE_UART_TX_GPIO=43
CONFIG_APPTRACE_UART_RX_GPIO=44

View File

@@ -1 +1,2 @@
CONFIG_APPTRACE_DEST_UART1=y
CONFIG_APPTRACE_DEST_UART=y
CONFIG_APPTRACE_DEST_UART_NUM=1

View File

@@ -175,8 +175,8 @@ app_trace:
- components/app_trace/app_trace.c
- components/app_trace/app_trace_membufs_proto.c
- components/app_trace/app_trace_util.c
- components/app_trace/port/riscv/port.c
- components/app_trace/port/xtensa/port.c
- components/app_trace/port/riscv/port_jtag.c
- components/app_trace/port/xtensa/port_jtag.c
allowed_licenses:
- Apache-2.0
- MIT