mirror of
https://github.com/espressif/esp-idf.git
synced 2026-09-22 13:01:16 +03:00
Merge branch 'tracing_test_fixes_v6.0' into 'release/v6.0'
Tracing test fixes (v6.0) See merge request espressif/esp-idf!52328
This commit is contained in:
@@ -1,17 +1,5 @@
|
||||
# Documentation: .gitlab/ci/README.md#manifest-file-to-control-the-buildtest-apps
|
||||
|
||||
examples/system/app_trace_basic:
|
||||
disable_test:
|
||||
- if: IDF_TARGET == "esp32h21"
|
||||
temporary: true
|
||||
reason: not supported yet #TODO: OCD-1081
|
||||
- if: IDF_TARGET == "esp32h4"
|
||||
temporary: true
|
||||
reason: not supported yet #TODO: OCD-1137
|
||||
depends_components:
|
||||
- esp_trace
|
||||
- app_trace
|
||||
|
||||
examples/system/base_mac_address:
|
||||
depends_components:
|
||||
- *common_components
|
||||
@@ -68,21 +56,6 @@ examples/system/esp_timer:
|
||||
- *common_components
|
||||
- esp_timer
|
||||
|
||||
examples/system/esp_trace_custom_library:
|
||||
disable:
|
||||
- if: SOC_USB_SERIAL_JTAG_SUPPORTED != 1
|
||||
reason: example transport is USB Serial JTAG
|
||||
disable_test:
|
||||
- if: IDF_TARGET == "esp32h21"
|
||||
temporary: true
|
||||
reason: lack of runners
|
||||
- if: IDF_TARGET == "esp32h4"
|
||||
temporary: true
|
||||
reason: lack of runners
|
||||
depends_components:
|
||||
- esp_trace
|
||||
- freertos
|
||||
|
||||
examples/system/eventfd:
|
||||
disable:
|
||||
- if: SOC_GPTIMER_SUPPORTED != 1 and (IDF_TARGET != "esp32" and (NIGHTLY_RUN != "1" or IDF_TARGET == "linux"))
|
||||
@@ -116,21 +89,6 @@ examples/system/freertos/real_time_stats:
|
||||
- *common_components
|
||||
- freertos
|
||||
|
||||
examples/system/gcov:
|
||||
disable_test:
|
||||
- if: IDF_TARGET == "esp32h21"
|
||||
temporary: true
|
||||
reason: not supported yet #TODO: OCD-1079
|
||||
- if: IDF_TARGET == "esp32h4"
|
||||
temporary: true
|
||||
reason: not supported yet #TODO: OCD-1138
|
||||
- if: IDF_TARGET == "esp32p4"
|
||||
temporary: true
|
||||
reason: p4 rev3 migration # TODO: IDF-14440
|
||||
depends_components:
|
||||
- esp_trace
|
||||
- app_trace
|
||||
|
||||
examples/system/heap_task_tracking:
|
||||
disable:
|
||||
- if: IDF_TARGET != "esp32c3" and (NIGHTLY_RUN != "1" or IDF_TARGET == "linux")
|
||||
@@ -299,34 +257,6 @@ examples/system/select:
|
||||
- *common_components
|
||||
- vfs
|
||||
|
||||
examples/system/sysview_tracing:
|
||||
disable:
|
||||
- if: SOC_GPTIMER_SUPPORTED != 1
|
||||
disable_test:
|
||||
- if: IDF_TARGET == "esp32h21"
|
||||
temporary: true
|
||||
reason: not supported yet #TODO: OCD-1082
|
||||
- if: IDF_TARGET == "esp32h4"
|
||||
temporary: true
|
||||
reason: not supported yet #TODO: OCD-1136
|
||||
depends_components:
|
||||
- esp_trace
|
||||
- app_trace
|
||||
|
||||
examples/system/sysview_tracing_heap_log:
|
||||
disable:
|
||||
- if: SOC_GPTIMER_SUPPORTED != 1
|
||||
disable_test:
|
||||
- if: IDF_TARGET == "esp32h21"
|
||||
temporary: true
|
||||
reason: not supported yet #TODO: OCD-1082
|
||||
- if: IDF_TARGET == "esp32h4"
|
||||
temporary: true
|
||||
reason: not supported yet #TODO: OCD-1136
|
||||
depends_components:
|
||||
- esp_trace
|
||||
- app_trace
|
||||
|
||||
examples/system/task_watchdog:
|
||||
disable:
|
||||
- if: IDF_TARGET != "esp32" and (NIGHTLY_RUN != "1" or IDF_TARGET == "linux")
|
||||
|
||||
@@ -1,8 +0,0 @@
|
||||
#include <stdio.h>
|
||||
|
||||
|
||||
void blink_dummy_func(void)
|
||||
{
|
||||
static int i;
|
||||
printf("blink_dummy_func: Counter = %d\n", i++);
|
||||
}
|
||||
71
examples/system/tracing/.build-test-rules.yml
Normal file
71
examples/system/tracing/.build-test-rules.yml
Normal file
@@ -0,0 +1,71 @@
|
||||
# Documentation: .gitlab/ci/README.md#manifest-file-to-control-the-buildtest-apps
|
||||
|
||||
examples/system/tracing/app_trace_basic:
|
||||
disable_test:
|
||||
- if: IDF_TARGET == "esp32h21"
|
||||
temporary: true
|
||||
reason: not supported yet #TODO: OCD-1081
|
||||
- if: IDF_TARGET == "esp32h4"
|
||||
temporary: true
|
||||
reason: not supported yet #TODO: OCD-1137
|
||||
depends_components:
|
||||
- esp_trace
|
||||
- app_trace
|
||||
|
||||
examples/system/tracing/esp_trace_custom_library:
|
||||
disable:
|
||||
- if: SOC_USB_SERIAL_JTAG_SUPPORTED != 1
|
||||
reason: example transport is USB Serial JTAG
|
||||
disable_test:
|
||||
- if: IDF_TARGET == "esp32h21"
|
||||
temporary: true
|
||||
reason: lack of runners
|
||||
- if: IDF_TARGET == "esp32h4"
|
||||
temporary: true
|
||||
reason: lack of runners
|
||||
depends_components:
|
||||
- esp_trace
|
||||
- freertos
|
||||
|
||||
examples/system/tracing/gcov:
|
||||
disable_test:
|
||||
- if: IDF_TARGET == "esp32h21"
|
||||
temporary: true
|
||||
reason: not supported yet #TODO: OCD-1079
|
||||
- if: IDF_TARGET == "esp32h4"
|
||||
temporary: true
|
||||
reason: not supported yet #TODO: OCD-1138
|
||||
- if: IDF_TARGET == "esp32p4"
|
||||
temporary: true
|
||||
reason: p4 rev3 migration # TODO: IDF-14440
|
||||
depends_components:
|
||||
- esp_trace
|
||||
- app_trace
|
||||
|
||||
examples/system/tracing/sysview_tracing:
|
||||
disable:
|
||||
- if: SOC_GPTIMER_SUPPORTED != 1
|
||||
disable_test:
|
||||
- if: IDF_TARGET == "esp32h21"
|
||||
temporary: true
|
||||
reason: not supported yet #TODO: OCD-1082
|
||||
- if: IDF_TARGET == "esp32h4"
|
||||
temporary: true
|
||||
reason: not supported yet #TODO: OCD-1136
|
||||
depends_components:
|
||||
- esp_trace
|
||||
- app_trace
|
||||
|
||||
examples/system/tracing/sysview_tracing_heap_log:
|
||||
disable:
|
||||
- if: SOC_GPTIMER_SUPPORTED != 1
|
||||
disable_test:
|
||||
- if: IDF_TARGET == "esp32h21"
|
||||
temporary: true
|
||||
reason: not supported yet #TODO: OCD-1082
|
||||
- if: IDF_TARGET == "esp32h4"
|
||||
temporary: true
|
||||
reason: not supported yet #TODO: OCD-1136
|
||||
depends_components:
|
||||
- esp_trace
|
||||
- app_trace
|
||||
@@ -23,7 +23,7 @@ This example will assume that an ESP-WROVER-KIT is used.
|
||||
|
||||
1. Connect the JTAG interface to the target board. For details about how to set up JTAG interface, please see [JTAG Debugging](https://docs.espressif.com/projects/esp-idf/en/latest/api-guides/jtag-debugging/index.html). Power up both the JTAG debugger and target board.
|
||||
|
||||
2. To start the tcp socket server, you need to run `read_trace.py` tool under the `esp-idf/examples/system/app_trace_to_plot` path.
|
||||
2. To start the tcp socket server, you need to run `read_trace.py` tool under the `esp-idf/examples/system/tracing/app_trace_to_plot` path.
|
||||
|
||||
3. After connecting JTAG interface and starting the tcp socket server, you need to [Run OpenOCD](https://docs.espressif.com/projects/esp-idf/en/latest/api-guides/jtag-debugging/index.html#run-openocd).
|
||||
|
||||
@@ -46,7 +46,7 @@ idf.py -p PORT flash monitor
|
||||
|
||||
(Replace PORT with the name of the serial port to use.)
|
||||
|
||||
**Run Plotting Tool** To plot data and open TCP socket, there is a tool named `read_trace.py` under the `examples/system/app_trace_to_plot` path. Run this tool in the terminal session with configured IDF development environment by entering the command below. This command opens a TCP socket and plots the given data when OpenOCD triggered to start App Trace. If you are running tool at first time, you need to install dash with `pip install dash` in the same terminal session after running configuring IDF development environment.
|
||||
**Run Plotting Tool** To plot data and open TCP socket, there is a tool named `read_trace.py` under the `examples/system/tracing/app_trace_to_plot` path. Run this tool in the terminal session with configured IDF development environment by entering the command below. This command opens a TCP socket and plots the given data when OpenOCD triggered to start App Trace. If you are running tool at first time, you need to install dash with `pip install dash` in the same terminal session after running configuring IDF development environment.
|
||||
|
||||
```bash
|
||||
python read_trace.py --plot-config data.json --source tcp://localhost:53535 --output-file data.log
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"//data.json": "Apptrace plotting config file for 'read_trace.py'",
|
||||
"//Summary and usage": "This file is used for apptrace plotting. You can use this json file with '--plot-config' parameter of the 'read_trace.py' file is to configure graphs for visualizing sensor data",
|
||||
"//More information": "To get more information about apptrace plotting and configuration file, please check 'app_trace_to_plot' example in '../examples/system' and 'read_trace.py' file",
|
||||
"//More information": "To get more information about apptrace plotting and configuration file, please check 'app_trace_to_plot' example in '../examples/system/tracing' and 'read_trace.py' file",
|
||||
"Temperature sensors": {
|
||||
"data_streams" : {
|
||||
"Outside temperature": {
|
||||
@@ -27,7 +27,7 @@
|
||||
}
|
||||
},
|
||||
"xaxis_title": "Timestamp",
|
||||
"yaxis_title": "Temperature in Celcius"
|
||||
"yaxis_title": "Temperature in Celsius"
|
||||
},
|
||||
"Altitude sensors": {
|
||||
"data_streams" : {
|
||||
|
Before Width: | Height: | Size: 787 KiB After Width: | Height: | Size: 787 KiB |
@@ -3,7 +3,7 @@
|
||||
|
||||
# ESP Trace External Library Integration Example
|
||||
|
||||
This example shows the **minimal** set of files and configuration needed to plug a third-party trace library into the [`esp_trace`](../../../components/esp_trace) component using the public `CONFIG_ESP_TRACE_LIB_EXTERNAL` extension point. It is meant as a copy-paste starting point for vendors and users who want to integrate their own trace recorder (e.g. Percepio TraceRecorder, a custom CTF emitter, a printf-style logger, …) without patching ESP-IDF itself.
|
||||
This example shows the **minimal** set of files and configuration needed to plug a third-party trace library into the [`esp_trace`](../../../../components/esp_trace) component using the public `CONFIG_ESP_TRACE_LIB_EXTERNAL` extension point. It is meant as a copy-paste starting point for vendors and users who want to integrate their own trace recorder (e.g. Percepio TraceRecorder, a custom CTF emitter, a printf-style logger, …) without patching ESP-IDF itself.
|
||||
|
||||
The example covers:
|
||||
|
||||
@@ -94,7 +94,7 @@ esp_trace_custom_library/
|
||||
|
||||
### 2. Providing the FreeRTOS trace hooks
|
||||
|
||||
`esp_trace`'s public header [`esp_trace_freertos.h`](../../../components/esp_trace/include/esp_trace_freertos.h) is included from `FreeRTOSConfig.h`. When `CONFIG_ESP_TRACE_LIB_EXTERNAL=y` is set, it pulls in **your** `esp_trace_freertos_impl.h`:
|
||||
`esp_trace`'s public header [`esp_trace_freertos.h`](../../../../components/esp_trace/include/esp_trace_freertos.h) is included from `FreeRTOSConfig.h`. When `CONFIG_ESP_TRACE_LIB_EXTERNAL=y` is set, it pulls in **your** `esp_trace_freertos_impl.h`:
|
||||
|
||||
```c
|
||||
#if CONFIG_ESP_TRACE_LIB_EXTERNAL
|
||||
@@ -177,7 +177,7 @@ Because the transport is USB-Serial-JTAG and the console is on UART (`CONFIG_ESP
|
||||
|
||||
## Runtime Control — `esp_trace_start` / `_stop` / `_flush`
|
||||
|
||||
[`esp_trace.h`](../../../components/esp_trace/include/esp_trace.h) exposes three generic lifecycle calls that dispatch to the active encoder's vtable. The application uses only the public API — it never reaches into the external library:
|
||||
[`esp_trace.h`](../../../../components/esp_trace/include/esp_trace.h) exposes three generic lifecycle calls that dispatch to the active encoder's vtable. The application uses only the public API — it never reaches into the external library:
|
||||
|
||||
```c
|
||||
esp_trace_start(); // resume emission (also resets the delta baseline)
|
||||
@@ -194,7 +194,7 @@ In this example the library boots with `s_enabled = false`, so nothing is emitte
|
||||
|
||||
## Other `esp_trace` Helpers
|
||||
|
||||
Beyond what this example uses, [`esp_trace.h`](../../../components/esp_trace/include/esp_trace.h) and [`esp_trace_util.h`](../../../components/esp_trace/include/esp_trace_util.h) also expose:
|
||||
Beyond what this example uses, [`esp_trace.h`](../../../../components/esp_trace/include/esp_trace.h) and [`esp_trace_util.h`](../../../../components/esp_trace/include/esp_trace_util.h) also expose:
|
||||
|
||||
* `esp_trace_is_host_connected()` — gate expensive work when no host is listening.
|
||||
* `esp_trace_get_link_type()` — returns `ESP_TRACE_LINK_DEBUG_PROBE`, `_UART`, or `_USB_SERIAL_JTAG`.
|
||||
@@ -203,5 +203,5 @@ Beyond what this example uses, [`esp_trace.h`](../../../components/esp_trace/inc
|
||||
|
||||
## See Also
|
||||
|
||||
* [`components/esp_trace/README.md`](../../../components/esp_trace/README.md) — full architecture overview and adapter API reference.
|
||||
* [`components/esp_trace/README.md`](../../../../components/esp_trace/README.md) — full architecture overview and adapter API reference.
|
||||
* [`examples/system/sysview_tracing`](../sysview_tracing) — a production-grade integration of SEGGER SystemView built on the same extension points.
|
||||
@@ -36,6 +36,9 @@ void init_trace_lib(esp_trace_encoder_t *enc);
|
||||
void trace_lib_start(void);
|
||||
void trace_lib_stop(void);
|
||||
|
||||
/* @brief Get the number of trace lines written to and dropped by the transport */
|
||||
void trace_lib_get_stats(uint32_t *written, uint32_t *dropped);
|
||||
|
||||
/* Hook implementations — defined in trace_FreeRTOS.c.
|
||||
* Kept void*-typed to avoid depending on FreeRTOS types in this header. */
|
||||
void trace_lib_task_switched_in(void);
|
||||
@@ -85,14 +85,6 @@ static esp_err_t stop(esp_trace_encoder_t *enc)
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t flush(esp_trace_encoder_t *enc)
|
||||
{
|
||||
if (!enc || !enc->tp || !enc->tp->vt->flush_nolock) {
|
||||
return ESP_ERR_NOT_SUPPORTED;
|
||||
}
|
||||
return enc->tp->vt->flush_nolock(enc->tp);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Panic handler
|
||||
*
|
||||
@@ -104,7 +96,11 @@ static esp_err_t flush(esp_trace_encoder_t *enc)
|
||||
static void panic_handler(esp_trace_encoder_t *enc, const void *info)
|
||||
{
|
||||
(void)info;
|
||||
flush(enc);
|
||||
|
||||
/* No lock here, the panicking core may already hold it */
|
||||
if (enc && enc->tp && enc->tp->vt->flush_nolock) {
|
||||
enc->tp->vt->flush_nolock(enc->tp);
|
||||
}
|
||||
}
|
||||
|
||||
static unsigned int take_lock(esp_trace_encoder_t *enc, uint32_t tmo_us)
|
||||
@@ -127,6 +123,34 @@ static void give_lock(esp_trace_encoder_t *enc, unsigned int int_state)
|
||||
esp_trace_lock_give(&ctx->lock);
|
||||
}
|
||||
|
||||
/* Total time for the flush, split over several flush_nolock() calls */
|
||||
#define EXT_TRACE_LIB_FLUSH_TMO_US (1000000)
|
||||
|
||||
static esp_err_t flush(esp_trace_encoder_t *enc)
|
||||
{
|
||||
if (!enc || !enc->tp || !enc->tp->vt->flush_nolock) {
|
||||
return ESP_ERR_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
/* One call may be too short to send all the data, so repeat it and release
|
||||
* the lock in between to keep interrupts enabled */
|
||||
esp_trace_tmo_t tmo;
|
||||
esp_trace_tmo_init(&tmo, EXT_TRACE_LIB_FLUSH_TMO_US);
|
||||
|
||||
esp_err_t err;
|
||||
do {
|
||||
unsigned int int_state = take_lock(enc, ESP_TRACE_TMO_INFINITE);
|
||||
err = enc->tp->vt->flush_nolock(enc->tp);
|
||||
give_lock(enc, int_state);
|
||||
|
||||
if (err != ESP_ERR_TIMEOUT) {
|
||||
break; /* done, or an error that repeating cannot fix */
|
||||
}
|
||||
} while (esp_trace_tmo_check(&tmo) == ESP_OK);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static const esp_trace_encoder_vtable_t s_ext_trace_lib_vt = {
|
||||
.init = init,
|
||||
.write = write,
|
||||
@@ -35,6 +35,8 @@ static esp_trace_encoder_t *s_enc = NULL;
|
||||
static uint32_t s_ts_freq_hz = 1000000; /* default assume 1 MHz */
|
||||
static uint32_t s_last_ts = 0;
|
||||
static volatile bool s_enabled = false;
|
||||
static uint32_t s_written = 0;
|
||||
static uint32_t s_dropped = 0;
|
||||
|
||||
void init_trace_lib(esp_trace_encoder_t *enc)
|
||||
{
|
||||
@@ -87,12 +89,26 @@ static void encode(const char *type, const char *detail)
|
||||
if (n >= (int)sizeof(line)) {
|
||||
n = (int)sizeof(line) - 1;
|
||||
}
|
||||
esp_trace_write(s_esp_trace_handle, line, (size_t)n, 0);
|
||||
if (esp_trace_write(s_esp_trace_handle, line, (size_t)n, 0) == ESP_OK) {
|
||||
s_written++;
|
||||
} else {
|
||||
s_dropped++; /* transport buffer was full, line dropped */
|
||||
}
|
||||
}
|
||||
|
||||
s_enc->vt->give_lock(s_enc, int_state);
|
||||
}
|
||||
|
||||
void trace_lib_get_stats(uint32_t *written, uint32_t *dropped)
|
||||
{
|
||||
if (written) {
|
||||
*written = s_written;
|
||||
}
|
||||
if (dropped) {
|
||||
*dropped = s_dropped;
|
||||
}
|
||||
}
|
||||
|
||||
void trace_lib_task_switched_in(void)
|
||||
{
|
||||
TaskHandle_t h = xTaskGetCurrentTaskHandle();
|
||||
@@ -5,6 +5,7 @@
|
||||
*/
|
||||
#include "sdkconfig.h"
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
@@ -13,6 +14,7 @@
|
||||
#include "freertos/queue.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_trace.h"
|
||||
#include "trace_FreeRTOS.h"
|
||||
|
||||
static const char *TAG = "main";
|
||||
|
||||
@@ -70,7 +72,16 @@ void app_main(void)
|
||||
vTaskDelay(1000 / portTICK_PERIOD_MS);
|
||||
|
||||
esp_trace_stop();
|
||||
esp_trace_flush();
|
||||
esp_err_t err = esp_trace_flush();
|
||||
|
||||
/* Logged from task context, so it goes to the console UART and not to the
|
||||
* trace port. Shows whether the device sent the trace data or not. */
|
||||
uint32_t written = 0;
|
||||
uint32_t dropped = 0;
|
||||
trace_lib_get_stats(&written, &dropped);
|
||||
ESP_LOGI(TAG, "Trace flush: %s, host connected: %d, lines written: %" PRIu32 ", dropped: %" PRIu32,
|
||||
esp_err_to_name(err), (int)esp_trace_is_host_connected(esp_trace_get_active_handle()),
|
||||
written, dropped);
|
||||
|
||||
ESP_LOGI(TAG, "End of trace session");
|
||||
}
|
||||
@@ -76,7 +76,6 @@ def _validate_trace_data(trace_log_path: str) -> None:
|
||||
|
||||
def _capture_trace(ser: serial.Serial, trace_log_path: str, capture_s: float = 5.0) -> None:
|
||||
"""Capture trace output from the USB-Serial-JTAG endpoint."""
|
||||
ser.reset_input_buffer()
|
||||
with open(trace_log_path, 'w+b') as f:
|
||||
end_time = time.time() + capture_s
|
||||
while time.time() < end_time:
|
||||
@@ -107,10 +106,13 @@ def _capture_trace(ser: serial.Serial, trace_log_path: str, capture_s: float = 5
|
||||
def test_esp_trace_ext_lib_usj(dut: IdfDut) -> None:
|
||||
dut.expect('Start of trace session', timeout=5)
|
||||
|
||||
time.sleep(1) # wait for USJ port to be ready
|
||||
# Open the port before the DUT starts tracing
|
||||
usj_port = '/dev/serial_ports/ttyACM-esp32'
|
||||
ser = serial.Serial(usj_port, baudrate=1000000, timeout=10)
|
||||
trace_log_path = os.path.join(dut.logdir, 'ext_trace.log')
|
||||
time.sleep(1) # Wait for the USJ port to be ready
|
||||
with serial.Serial(usj_port, baudrate=1000000, timeout=10) as ser:
|
||||
# Discard data from before this test, the DUT is not tracing yet
|
||||
ser.reset_input_buffer()
|
||||
_capture_trace(ser, trace_log_path)
|
||||
|
||||
_capture_trace(ser, trace_log_path)
|
||||
_validate_trace_data(trace_log_path)
|
||||
@@ -3,4 +3,4 @@ CONFIG_ESP_TRACE_LIB_EXTERNAL=y
|
||||
CONFIG_ESP_TRACE_TS_SOURCE_ESP_TIMER=y
|
||||
CONFIG_ESP_CONSOLE_SECONDARY_NONE=y
|
||||
CONFIG_ESP_TRACE_TRANSPORT_USB_SERIAL_JTAG=y
|
||||
CONFIG_ESP_TRACE_USJ_TX_BUFFER_SIZE=32768
|
||||
CONFIG_ESP_TRACE_USJ_TX_BUFFER_SIZE=16384
|
||||
@@ -1,3 +1,8 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Unlicense OR CC0-1.0
|
||||
*/
|
||||
#include <stdio.h>
|
||||
|
||||
|
||||
13
examples/system/tracing/gcov/main/gcov_example_func.c
Normal file
13
examples/system/tracing/gcov/main/gcov_example_func.c
Normal file
@@ -0,0 +1,13 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Unlicense OR CC0-1.0
|
||||
*/
|
||||
#include <stdio.h>
|
||||
|
||||
|
||||
void blink_dummy_func(void)
|
||||
{
|
||||
static int i;
|
||||
printf("blink_dummy_func: Counter = %d\n", i++);
|
||||
}
|
||||
@@ -1,11 +1,8 @@
|
||||
/* Blink Example with covergae info
|
||||
|
||||
This example code is in the Public Domain (or CC0 licensed, at your option.)
|
||||
|
||||
Unless required by applicable law or agreed to in writing, this
|
||||
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||
CONDITIONS OF ANY KIND, either express or implied.
|
||||
*/
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Unlicense OR CC0-1.0
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
@@ -1,11 +1,8 @@
|
||||
/* Application Trace to Host Example
|
||||
|
||||
This example code is in the Public Domain (or CC0 licensed, at your option.)
|
||||
|
||||
Unless required by applicable law or agreed to in writing, this
|
||||
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||
CONDITIONS OF ANY KIND, either express or implied.
|
||||
*/
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Unlicense OR CC0-1.0
|
||||
*/
|
||||
|
||||
#include "esp_err.h"
|
||||
#include "sdkconfig.h"
|
||||
@@ -16,6 +16,24 @@ if typing.TYPE_CHECKING:
|
||||
from conftest import OpenOCD
|
||||
|
||||
|
||||
STOP_EVENT_ID = 0x0B # SYSVIEW_EVTID_TRACE_STOP
|
||||
|
||||
|
||||
def _assert_has_stop_record(segment: bytes, label: str) -> None:
|
||||
"""Assert a SysView data segment ends with a TRACE_STOP record.
|
||||
|
||||
A STOP record is the STOP event ID followed by a variable-length timestamp
|
||||
delta. Walk back over the trailing continuation bytes (0x80 bit set) to find
|
||||
the event ID, since its offset is not fixed.
|
||||
"""
|
||||
size = len(segment)
|
||||
assert size >= 2, f'{label}: segment too small to contain STOP record'
|
||||
i = size - 2
|
||||
while i >= 0 and (segment[i] & 0x80):
|
||||
i -= 1
|
||||
assert i >= 0 and segment[i] == STOP_EVENT_ID, f'{label}: does not end with a TRACE_STOP record'
|
||||
|
||||
|
||||
def _validate_trace_data(trace_log: list[str], target: str, is_uart: bool = False) -> None:
|
||||
"""Validate SysView trace data in log file(s).
|
||||
|
||||
@@ -24,23 +42,14 @@ def _validate_trace_data(trace_log: list[str], target: str, is_uart: bool = Fals
|
||||
target: Target chip name (e.g., 'esp32', 'esp32s3')
|
||||
is_uart: If True, also validate STOP record at end of file
|
||||
"""
|
||||
STOP_EVENT_ID = 0x0B # SYSVIEW_EVTID_TRACE_STOP
|
||||
|
||||
for idx, log in enumerate(trace_log):
|
||||
with open(log, 'rb') as f:
|
||||
content = f.read()
|
||||
search_str = f'N=FreeRTOS Application,D={target},C=core{idx},O=FreeRTOS'.encode()
|
||||
assert search_str in content, f'SysView trace data not found in {log}'
|
||||
# The file must end with a TRACE_STOP record: the STOP event ID
|
||||
# followed by a variable-length timestamp delta. Walk back
|
||||
# over the trailing continuation bytes (0x80 bit set)
|
||||
# to find the event ID, since its offset is not fixed.
|
||||
size = len(content)
|
||||
assert size >= 2, 'Trace file too small to contain STOP record'
|
||||
i = size - 2
|
||||
while i >= 0 and (content[i] & 0x80):
|
||||
i -= 1
|
||||
assert i >= 0 and content[i] == STOP_EVENT_ID, 'STOP record does not start with STOP eventID'
|
||||
search_str = f'N=FreeRTOS Application,D={target},C=core{idx},O=FreeRTOS'.encode()
|
||||
assert search_str in content, f'SysView trace data not found in {log}'
|
||||
# Each core is captured to its own file; require each to end
|
||||
# with its own TRACE_STOP record.
|
||||
_assert_has_stop_record(content, f'core{idx}')
|
||||
|
||||
|
||||
def _capture_sysview_trace(ser: serial.Serial, trace_log_path: str) -> None:
|
||||
@@ -125,8 +134,9 @@ def _test_sysview_tracing_jtag(openocd_dut: 'OpenOCD', dut: IdfDut) -> None:
|
||||
dut.expect('example: Created task') # dut has been restarted by gdb since the last dut.expect()
|
||||
dut_expect_task_event()
|
||||
|
||||
# Do a sleep while sysview samples are captured.
|
||||
time.sleep(3)
|
||||
# Capture sysview samples and keep reading telnet so OpenOCD's blocking log writes don't stall its
|
||||
# main loop and leave the 'stop' below unserviced.
|
||||
openocd.consume_output(3)
|
||||
openocd.write('esp sysview stop')
|
||||
openocd.apptrace_wait_stop()
|
||||
|
||||
@@ -173,7 +183,7 @@ def test_sysview_tracing_uart(dut: IdfDut) -> None:
|
||||
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)
|
||||
with serial.Serial(usj_port, baudrate=1000000, timeout=10) as ser:
|
||||
_capture_sysview_trace(ser, trace_log[0])
|
||||
_validate_trace_data(trace_log, dut.target, is_uart=True)
|
||||
@@ -1,3 +1,4 @@
|
||||
CONFIG_ESP_CONSOLE_SECONDARY_NONE=y
|
||||
CONFIG_ESP_TRACE_TRANSPORT_USB_SERIAL_JTAG=y
|
||||
CONFIG_USE_CUSTOM_EVENT_ID=y
|
||||
CONFIG_ESP_TRACE_USJ_TX_BUFFER_SIZE=16384
|
||||
@@ -1,11 +1,8 @@
|
||||
/* Application Trace to Host Example
|
||||
|
||||
This example code is in the Public Domain (or CC0 licensed, at your option.)
|
||||
|
||||
Unless required by applicable law or agreed to in writing, this
|
||||
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||
CONDITIONS OF ANY KIND, either express or implied.
|
||||
*/
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Unlicense OR CC0-1.0
|
||||
*/
|
||||
|
||||
#include "sdkconfig.h"
|
||||
#include <inttypes.h>
|
||||
Reference in New Issue
Block a user