mirror of
https://github.com/espressif/esp-idf.git
synced 2026-10-01 10:40:47 +03:00
change(sysview): use esp sysview_mcore command for sysview_tracing JTAG capture
This commit is contained in:
@@ -111,15 +111,13 @@ NOTE: In order to run this example you need OpenOCD version `v0.10.0-esp32-20181
|
||||
mon reset halt
|
||||
b app_main
|
||||
commands
|
||||
mon esp sysview start file:///tmp/sysview_example.svdat
|
||||
# For dual-core mode uncomment the line below and comment the line above
|
||||
# mon esp sysview start file:///tmp/sysview_example0.svdat file:///tmp/sysview_example1.svdat
|
||||
mon esp sysview_mcore start file:///tmp/sysview_example.svdat
|
||||
c
|
||||
end
|
||||
c
|
||||
```
|
||||
|
||||
Using this file GDB will connect to the target, reset it, and start tracing when it hit breakpoint at `app_main`. Trace data will be saved to `/tmp/sysview_example.svdat`.
|
||||
Using this file GDB will connect to the target, reset it, and start tracing when it hit breakpoint at `app_main`. Trace data will be saved to `/tmp/sysview_example.svdat`. The `esp sysview_mcore` command uses the SEGGER SystemView multi-core format, so a single file holds the trace for both single- and dual-core targets.
|
||||
|
||||
6. Run GDB using the following command from the project root directory:
|
||||
|
||||
@@ -132,12 +130,12 @@ NOTE: In order to run this example you need OpenOCD version `v0.10.0-esp32-20181
|
||||
7. When program prints the last message, interrupt its execution (e.g. by pressing `CTRL+C`) and type the following command in GDB console to stop tracing:
|
||||
|
||||
```
|
||||
mon esp sysview stop
|
||||
mon esp sysview_mcore stop
|
||||
```
|
||||
|
||||
You can also use another breakpoint to stop tracing and add respective lines to `gdbinit` at step 5.
|
||||
|
||||
8. Open trace data file in SystemView tool.
|
||||
8. Open trace data file in SystemView tool. The multi-core format produced by `esp sysview_mcore` requires SEGGER SystemView v3.60 or later.
|
||||
|
||||
9. Right-click on any event in `Events` view and select:
|
||||
|
||||
|
||||
@@ -6,9 +6,7 @@ maintenance flush register-cache
|
||||
|
||||
b app_main
|
||||
commands
|
||||
mon esp sysview start file:///tmp/sysview_example.svdat
|
||||
# For dual-core mode uncomment the line below and comment the line above
|
||||
# mon esp sysview start file:///tmp/sysview_example0.svdat file:///tmp/sysview_example1.svdat
|
||||
mon esp sysview_mcore start file:///tmp/sysview_example.svdat
|
||||
c
|
||||
end
|
||||
|
||||
|
||||
@@ -16,31 +16,35 @@ if typing.TYPE_CHECKING:
|
||||
from conftest import OpenOCD
|
||||
|
||||
|
||||
def _validate_trace_data(trace_log: list[str], target: str, is_uart: bool = False) -> None:
|
||||
"""Validate SysView trace data in log file(s).
|
||||
def _validate_trace_data(trace_log: str, target: str, dual_core: bool = False, is_uart: bool = False) -> None:
|
||||
"""Validate SysView trace data in a single trace log file.
|
||||
|
||||
Args:
|
||||
trace_log: List of trace log paths
|
||||
trace_log: Path to the trace log file
|
||||
target: Target chip name (e.g., 'esp32', 'esp32s3')
|
||||
dual_core: If True, expect a per-core description block for both cores
|
||||
(the ``esp sysview_mcore`` multi-core capture embeds one per core)
|
||||
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'
|
||||
with open(trace_log, 'rb') as f:
|
||||
content = f.read()
|
||||
|
||||
for idx in range(2 if dual_core else 1):
|
||||
search_str = f'N=FreeRTOS Application,D={target},C=core{idx},O=FreeRTOS'.encode()
|
||||
assert search_str in content, f'SysView core{idx} trace data not found in {trace_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'
|
||||
|
||||
|
||||
def _capture_sysview_trace(ser: serial.Serial, trace_log_path: str) -> None:
|
||||
@@ -86,22 +90,19 @@ def _capture_sysview_trace(ser: serial.Serial, trace_log_path: str) -> 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
|
||||
]
|
||||
if not dut.app.sdkconfig.get('ESP_SYSTEM_SINGLE_CORE_MODE') or dut.target == 'esp32s3':
|
||||
trace_log.append(os.path.join(dut.logdir, 'sys_log1.svdat')) # pylint: disable=protected-access
|
||||
trace_files = ' '.join([f'file://{log}' for log in trace_log])
|
||||
# Single multi-core capture file (esp sysview_mcore): one file is enough for
|
||||
# both single- and dual-core targets.
|
||||
trace_log = os.path.join(dut.logdir, 'sys_log.svdat') # pylint: disable=protected-access
|
||||
dual_core = not dut.app.sdkconfig.get('ESP_SYSTEM_SINGLE_CORE_MODE') or dut.target == 'esp32s3'
|
||||
|
||||
# Prepare gdbinit file
|
||||
# Prepare gdbinit file pointing at this run's capture file
|
||||
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) 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')
|
||||
if line.startswith('mon esp sysview_mcore start'):
|
||||
f_w.write(f'mon esp sysview_mcore start file://{trace_log}\n')
|
||||
else:
|
||||
f_w.write(line)
|
||||
|
||||
@@ -127,9 +128,9 @@ def _test_sysview_tracing_jtag(openocd_dut: 'OpenOCD', dut: IdfDut) -> None:
|
||||
|
||||
# Do a sleep while sysview samples are captured.
|
||||
time.sleep(3)
|
||||
openocd.write('esp sysview stop')
|
||||
openocd.write('esp sysview_mcore stop')
|
||||
|
||||
_validate_trace_data(trace_log, dut.target)
|
||||
_validate_trace_data(trace_log, dut.target, dual_core=dual_core)
|
||||
|
||||
|
||||
@pytest.mark.jtag
|
||||
@@ -155,8 +156,8 @@ 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=3) as ser:
|
||||
trace_log = [os.path.join(dut.logdir, 'sys_log_uart.svdat')] # pylint: disable=protected-access
|
||||
_capture_sysview_trace(ser, trace_log[0])
|
||||
trace_log = os.path.join(dut.logdir, 'sys_log_uart.svdat') # pylint: disable=protected-access
|
||||
_capture_sysview_trace(ser, trace_log)
|
||||
_validate_trace_data(trace_log, dut.target, is_uart=True)
|
||||
|
||||
|
||||
@@ -184,6 +185,6 @@ 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])
|
||||
trace_log = os.path.join(dut.logdir, 'sys_log_usj.svdat') # pylint: disable=protected-access
|
||||
_capture_sysview_trace(ser, trace_log)
|
||||
_validate_trace_data(trace_log, dut.target, is_uart=True)
|
||||
|
||||
Reference in New Issue
Block a user