mirror of
https://github.com/espressif/esp-idf.git
synced 2026-04-28 19:34:59 +00:00
411 lines
13 KiB
Markdown
411 lines
13 KiB
Markdown
# ESP Trace Component
|
|
|
|
The `esp_trace` component provides a unified tracing infrastructure for ESP-IDF. It acts as a central hub that coordinates different trace libraries (like SEGGER SystemView) and trace transports (like apptrace over JTAG/UART).
|
|
|
|
## Overview
|
|
|
|
The `esp_trace` component enables:
|
|
- Integration of multiple trace libraries through a common interface
|
|
- Flexible transport layer selection (JTAG, UART, or custom)
|
|
- Centralized trace configuration and management
|
|
- Support for both built-in and external trace libraries
|
|
|
|
## Architecture
|
|
|
|
The `esp_trace` component uses a **Port & Adapter** design pattern (also known as Hexagonal Architecture) to provide flexibility and extensibility:
|
|
|
|
```mermaid
|
|
flowchart TB
|
|
|
|
%% =======================
|
|
%% Application Layer
|
|
%% =======================
|
|
subgraph APP["📱 APPLICATION"]
|
|
app_main["app_main()"]
|
|
sysview_tracing["sysview_tracing.c"]
|
|
examples["tracing_heap_log.c"]
|
|
freertos_events["FreeRTOS Events"]
|
|
end
|
|
|
|
|
|
%% =======================
|
|
%% Primary Port (Driver Port)
|
|
%% =======================
|
|
subgraph PRIMARY["🔌 PUBLIC INTERFACE"]
|
|
api["- esp_trace.h
|
|
- esp_trace_init()
|
|
- esp_trace_record()
|
|
- esp_trace_write()
|
|
- esp_trace_flush()
|
|
- esp_trace_print()"]
|
|
end
|
|
|
|
%% wiring: App uses API (labels land on the short pre-edges to api_in)
|
|
app_main -->|esp_trace.h| api
|
|
sysview_tracing -->|esp_trace.h| api
|
|
examples -->|esp_trace.h| api
|
|
freertos_events -->|trace macros| api
|
|
%% =======================
|
|
%% Core Domain
|
|
%% =======================
|
|
subgraph CORE["⚙️ CORE DOMAIN"]
|
|
corec["- esp_trace_core.c
|
|
- Creates encoder + transport instances
|
|
- Thread safe multi-core init
|
|
- Adapter coordination"]
|
|
regc["esp_trace_registry.c
|
|
- Runtime adapter discovery
|
|
- Maps names to vtables"]
|
|
end
|
|
|
|
api --> corec
|
|
corec --- regc
|
|
|
|
%% =======================
|
|
%% Ports (Outbound)
|
|
%% =======================
|
|
subgraph PORT_ENC["🔌 PORT Encoder"]
|
|
enc_port["esp_trace_port_encoder.h
|
|
Interface:
|
|
- init()
|
|
- print_event()
|
|
- write()
|
|
- flush()"]
|
|
end
|
|
|
|
subgraph PORT_TR["🔌 PORT Transport"]
|
|
tr_port["esp_trace_port_transport.h
|
|
Interface:
|
|
- init()
|
|
- write()
|
|
- flush()
|
|
- is_host_connected()"]
|
|
end
|
|
|
|
corec --> enc_port
|
|
corec --> tr_port
|
|
|
|
%% =======================
|
|
%% Adapters
|
|
%% =======================
|
|
subgraph ADAPTERS["🔶 ADAPTERS"]
|
|
%% Encoders
|
|
enc_sysview["encoder_sysview.c implements sysview vtable"]
|
|
enc_ctf["encoder_ctf.c implements ctf vtable"]
|
|
enc_percepio["encoder_percepio.c implements percepio vtable"]
|
|
|
|
%% Transports
|
|
tr_apptrace["transport_apptrace.c implements apptrace vtable"]
|
|
end
|
|
|
|
enc_port --> enc_sysview
|
|
enc_port --> enc_ctf
|
|
enc_port --> enc_percepio
|
|
tr_port --> tr_apptrace
|
|
|
|
%% =======================
|
|
%% Host tools
|
|
%% =======================
|
|
subgraph HOST_TOOLS["💻 TOOLS"]
|
|
direction LR
|
|
view_openocd["OpenOCD"]
|
|
view_sysview["SEGGER SystemView"]
|
|
view_ctf["Trace Compass"]
|
|
view_perfetto["Perfetto"]
|
|
view_babeltrace["Babeltrace2"]
|
|
view_percepio["TraceAlyzer"]
|
|
end
|
|
|
|
%% invisible hub to center align
|
|
hub(("HOST"))
|
|
|
|
%% Adapters feed into the hub (not directly into subgraph)
|
|
enc_sysview --> hub
|
|
enc_ctf --> hub
|
|
tr_apptrace --> hub
|
|
|
|
%% hub connects downward to host tools
|
|
hub --> view_openocd & view_sysview & view_ctf & view_perfetto & view_babeltrace & view_percepio
|
|
|
|
%% Styling
|
|
classDef appStyle fill:#e3f2fd,stroke:#1976d2,stroke-width:2px,color:#000
|
|
classDef primaryStyle fill:#f3e5f5,stroke:#7b1fa2,stroke-width:2px,color:#000
|
|
classDef coreStyle fill:#fff3e0,stroke:#f57c00,stroke-width:2px,color:#000
|
|
classDef portStyle fill:#e1f5fe,stroke:#0277bd,stroke-width:3px,color:#000
|
|
classDef adapterStyle fill:#fff9c4,stroke:#f9a825,stroke-width:2px,color:#000
|
|
classDef hostStyle fill:#e8f5e9,stroke:#388e3c,stroke-width:2px,color:#000
|
|
classDef hubStyle fill:#ffebee,stroke:#c62828,stroke-width:3px,color:#000
|
|
|
|
class APP appStyle
|
|
class PRIMARY,api primaryStyle
|
|
class CORE,corec,regc coreStyle
|
|
class PORT_ENC,PORT_TR,enc_port,tr_port portStyle
|
|
class ADAPTERS,enc_sysview,enc_ctf,enc_percepio,tr_apptrace adapterStyle
|
|
class HOST_TOOLS,view_openocd,view_sysview,view_ctf,view_perfetto,view_babeltrace,view_percepio hostStyle
|
|
class hub hubStyle
|
|
|
|
```
|
|
|
|
The architecture follows a layered Port & Adapter pattern where the core manages trace sessions and coordinates adapters through well-defined interfaces (ports). Applications interact with a public API that forwards calls to the core, which then delegates work to encoder adapters (for trace formatting) and transport adapters (for data transmission). The registry enables runtime discovery of adapters that register themselves at link time using `ESP_TRACE_REGISTER_ENCODER()` and `ESP_TRACE_REGISTER_TRANSPORT()` macros. Encoders use transport ports to send formatted trace data, allowing any encoder to work with any transport. This separation means you can, for example, use SystemView with JTAG, other library with UART, or any other combination without modifying the core or adapters themselves.
|
|
|
|
## How to Enable
|
|
|
|
### Using Menuconfig
|
|
|
|
1. Go to `Component config` → `ESP Trace Configuration`
|
|
2. Select your trace library under `Trace library`:
|
|
- **External library from component registry** - Use a custom encoder provided by an external component (e.g. SystemView)
|
|
- **Disabled** - Disable trace library
|
|
3. Select your desired trace transport under `Trace transport`:
|
|
- **ESP-IDF apptrace** - Use built-in apptrace for custom tracing
|
|
- **External transport from component registry** - Use a custom transport provided by an external component
|
|
- **None** - Disable tracing transport
|
|
|
|
### Using sdkconfig
|
|
|
|
For standalone apptrace (without a trace library):
|
|
|
|
```
|
|
CONFIG_ESP_TRACE_ENABLE=y
|
|
CONFIG_ESP_TRACE_LIB_NONE=y
|
|
CONFIG_ESP_TRACE_TRANSPORT_APPTRACE=y
|
|
```
|
|
|
|
For SystemView tracing over JTAG:
|
|
|
|
1. Add `espressif/esp_sysview` component to your `idf_component.yml`:
|
|
|
|
```yaml
|
|
dependencies:
|
|
espressif/esp_sysview: "^1"
|
|
```
|
|
|
|
2. Configure in `sdkconfig`:
|
|
|
|
```
|
|
CONFIG_ESP_TRACE_ENABLE=y
|
|
CONFIG_ESP_TRACE_LIB_EXTERNAL=y
|
|
CONFIG_ESP_TRACE_TRANSPORT_APPTRACE=y
|
|
CONFIG_APPTRACE_DEST_JTAG=y
|
|
```
|
|
|
|
## Component Dependencies
|
|
|
|
### When Using External Trace Libraries (e.g., SystemView)
|
|
|
|
If you're using an external trace library from the component registry (like `espressif/esp_sysview`), you **don't need** to explicitly add `esp_trace` to your dependencies. The external component already has a public dependency on `esp_trace` (using `REQUIRES`), so it's automatically available to your application code:
|
|
|
|
```cmake
|
|
idf_component_register(
|
|
SRCS "main.c"
|
|
INCLUDE_DIRS "."
|
|
# No need to add esp_trace here when using esp_sysview
|
|
)
|
|
```
|
|
|
|
This means you can directly use both the trace library APIs (e.g., SystemView) and `esp_trace` APIs (like `esp_trace_get_user_params()`, `esp_trace_is_host_connected()`, etc.) without explicitly declaring the dependency.
|
|
|
|
### When Using Standalone Apptrace
|
|
|
|
For standalone apptrace usage (without an external trace library), add `esp_trace` to your component's dependencies:
|
|
|
|
```cmake
|
|
idf_component_register(
|
|
SRCS "main.c"
|
|
INCLUDE_DIRS "."
|
|
REQUIRES esp_trace
|
|
)
|
|
```
|
|
|
|
The `esp_trace` component will automatically include necessary sub-components (like `app_trace`) based on your configuration.
|
|
|
|
## Adding External Trace Libraries
|
|
|
|
The `esp_trace` component supports integration of external trace libraries through two types of adapters:
|
|
|
|
- **Transport Adapters**: Handle the physical transport layer (e.g., JTAG, UART)
|
|
- **Encoder Adapters**: Handle the trace encoding/formatting (e.g., SystemView, custom formats)
|
|
|
|
### Creating a Transport Adapter
|
|
|
|
Transport adapters provide the physical communication layer for trace data.
|
|
|
|
**Example: Creating a custom transport adapter**
|
|
|
|
```c
|
|
#include "esp_trace_registry.h"
|
|
#include "esp_trace_port_transport.h"
|
|
|
|
static esp_err_t my_transport_init(esp_trace_transport_t *tp, const void *cfg)
|
|
{
|
|
// Initialize your transport
|
|
return ESP_OK;
|
|
}
|
|
|
|
static esp_err_t my_transport_write(esp_trace_transport_t *tp, const void *data, size_t size, uint32_t tmo)
|
|
{
|
|
// Write data to your transport
|
|
return ESP_OK;
|
|
}
|
|
|
|
static esp_err_t my_transport_flush(esp_trace_transport_t *tp, uint32_t tmo)
|
|
{
|
|
// Flush transport buffers
|
|
return ESP_OK;
|
|
}
|
|
|
|
// Create the vtable with your functions
|
|
static const esp_trace_transport_vtable_t s_my_transport_vt = {
|
|
.init = my_transport_init,
|
|
.write = my_transport_write,
|
|
.flush = my_transport_flush,
|
|
// Add other required function pointers as needed
|
|
};
|
|
|
|
// Register the transport adapter
|
|
ESP_TRACE_REGISTER_TRANSPORT("my_transport", &s_my_transport_vt);
|
|
```
|
|
|
|
See `components/esp_trace/adapters/transport/adapter_transport_apptrace.c` for a complete reference implementation.
|
|
|
|
### Creating an Encoder Adapter
|
|
|
|
Encoder adapters handle trace data formatting and encoding for specific trace libraries.
|
|
|
|
**Example: Creating a custom encoder adapter**
|
|
|
|
```c
|
|
#include "esp_trace_registry.h"
|
|
#include "esp_trace_port_encoder.h"
|
|
|
|
static esp_err_t my_encoder_init(esp_trace_encoder_t *enc, const void *cfg)
|
|
{
|
|
// Initialize your encoder
|
|
// Configure transport if needed:
|
|
// enc->tp->vt->set_config(enc->tp, ESP_TRACE_TRANSPORT_CFG_HEADER_SIZE, &value);
|
|
return ESP_OK;
|
|
}
|
|
|
|
static esp_err_t my_encoder_print_event(esp_trace_encoder_t *enc,
|
|
const char *event_name,
|
|
const char *formatted_str)
|
|
{
|
|
// Format and send trace event
|
|
return ESP_OK;
|
|
}
|
|
|
|
static esp_err_t my_encoder_flush(esp_trace_encoder_t *enc, uint32_t tmo)
|
|
{
|
|
// Flush encoder buffers
|
|
return ESP_OK;
|
|
}
|
|
|
|
// Create the vtable with your functions
|
|
static const esp_trace_encoder_vtable_t s_my_encoder_vt = {
|
|
.init = my_encoder_init,
|
|
.print_event = my_encoder_print_event,
|
|
.flush = my_encoder_flush,
|
|
// Add other required function pointers as needed
|
|
};
|
|
|
|
// Register the encoder adapter
|
|
ESP_TRACE_REGISTER_ENCODER("my_encoder", &s_my_encoder_vt);
|
|
```
|
|
|
|
**Key Points:**
|
|
- Use `ESP_TRACE_REGISTER_ENCODER(name, vtable)` to register your encoder
|
|
- Use `ESP_TRACE_REGISTER_TRANSPORT(name, vtable)` if you're implementing a custom transport
|
|
- Registration happens automatically at link time (no manual initialization needed)
|
|
|
|
See `espressif/esp_sysview` component source (specifically `adapter_encoder_sysview.c`) for a complete reference implementation.
|
|
|
|
### FreeRTOS Trace Integration
|
|
|
|
If your external trace library needs to capture FreeRTOS events, you must provide an `esp_trace_freertos_impl.h` header in your component's include directory. This header should define FreeRTOS trace macros (like `traceTASK_SWITCHED_IN()`, `traceISR_ENTER()`, etc.) that will be called by FreeRTOS.
|
|
|
|
The `esp_trace` component includes this header when `CONFIG_ESP_TRACE_LIB_EXTERNAL=y` is set:
|
|
|
|
```c
|
|
// In esp_trace_freertos.h
|
|
#if CONFIG_ESP_TRACE_LIB_EXTERNAL
|
|
#include "esp_trace_freertos_impl.h"
|
|
#endif
|
|
```
|
|
|
|
**Example esp_trace_freertos_impl.h:**
|
|
```c
|
|
#pragma once
|
|
|
|
#include "your_trace_library.h"
|
|
|
|
#define traceTASK_SWITCHED_IN() your_lib_task_switched_in(xTaskGetCurrentTaskHandle())
|
|
#define traceISR_ENTER(irq_num) your_lib_isr_enter(irq_num)
|
|
#define traceISR_EXIT() your_lib_isr_exit()
|
|
// ... define other FreeRTOS trace macros as needed
|
|
```
|
|
|
|
### Component CMakeLists.txt Setup
|
|
|
|
For external adapters to work properly, your component's CMakeLists.txt needs two important settings:
|
|
|
|
**Example CMakeLists.txt:**
|
|
```cmake
|
|
idf_component_register(
|
|
SRCS "src/adapter_encoder_ctf.c"
|
|
INCLUDE_DIRS "include"
|
|
REQUIRES esp_trace
|
|
WHOLE_ARCHIVE TRUE # Important: ensures adapter registration is linked
|
|
)
|
|
|
|
# Auto-register this component with esp_trace
|
|
# This allows esp_trace to find your esp_trace_freertos_impl.h
|
|
idf_component_get_property(esp_trace_lib esp_trace COMPONENT_LIB)
|
|
target_link_libraries(${esp_trace_lib} INTERFACE $<TARGET_NAME_IF_EXISTS:${COMPONENT_LIB}>)
|
|
```
|
|
|
|
**Important:**
|
|
- `WHOLE_ARCHIVE TRUE` ensures your adapter registration code is linked
|
|
- The `target_link_libraries` trick makes your headers visible to esp_trace component
|
|
|
|
### Using an External Adapter
|
|
|
|
1. **Add the component to your project dependencies** in your main component's `CMakeLists.txt`:
|
|
```cmake
|
|
idf_component_register(
|
|
SRCS "main.c"
|
|
INCLUDE_DIRS "."
|
|
REQUIRES my_trace_component esp_trace
|
|
)
|
|
```
|
|
|
|
2. **Configure trace settings** in your project's `sdkconfig.defaults`:
|
|
```ini
|
|
# Enable esp_trace
|
|
CONFIG_ESP_TRACE_ENABLE=y
|
|
|
|
# Use external trace library
|
|
CONFIG_ESP_TRACE_LIB_EXTERNAL=y
|
|
|
|
# Select transport (e.g., apptrace over UART)
|
|
CONFIG_ESP_TRACE_TRANSPORT_APPTRACE=y
|
|
CONFIG_APPTRACE_DEST_UART=y
|
|
CONFIG_APPTRACE_DEST_UART_NUM=0
|
|
```
|
|
|
|
3. **Build and run** - The adapter will be automatically registered and used when the component is linked.
|
|
|
|
**Note:** External trace libraries should use `CONFIG_ESP_TRACE_LIB_EXTERNAL=y` instead of defining their own Kconfig option in the esp_trace menu. This keeps the external component independent from the esp_trace component.
|
|
|
|
## Documentation
|
|
|
|
For detailed usage instructions, see:
|
|
- [Application Tracing Guide](../../docs/en/api-guides/app_trace.rst)
|
|
- [Migration Guide](../../docs/en/migration-guides/release-6.x/6.0/system.rst)
|
|
|
|
## Examples
|
|
|
|
Examples demonstrating trace usage can be found in:
|
|
- `examples/system/app_trace_basic/` - Basic application tracing
|
|
- `examples/system/sysview_tracing/` - SystemView tracing example
|
|
- `examples/system/sysview_tracing_heap_log/` - SystemView heap and log tracing example
|