mirror of
https://github.com/espressif/esp-idf.git
synced 2026-10-02 11:10:54 +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
|
mon reset halt
|
||||||
b app_main
|
b app_main
|
||||||
commands
|
commands
|
||||||
mon esp sysview start file:///tmp/sysview_example.svdat
|
mon esp sysview_mcore 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
|
|
||||||
c
|
c
|
||||||
end
|
end
|
||||||
c
|
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:
|
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:
|
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.
|
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:
|
9. Right-click on any event in `Events` view and select:
|
||||||
|
|
||||||
|
|||||||
@@ -6,9 +6,7 @@ maintenance flush register-cache
|
|||||||
|
|
||||||
b app_main
|
b app_main
|
||||||
commands
|
commands
|
||||||
mon esp sysview start file:///tmp/sysview_example.svdat
|
mon esp sysview_mcore 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
|
|
||||||
c
|
c
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -16,31 +16,35 @@ if typing.TYPE_CHECKING:
|
|||||||
from conftest import OpenOCD
|
from conftest import OpenOCD
|
||||||
|
|
||||||
|
|
||||||
def _validate_trace_data(trace_log: list[str], target: str, is_uart: bool = False) -> None:
|
def _validate_trace_data(trace_log: str, target: str, dual_core: bool = False, is_uart: bool = False) -> None:
|
||||||
"""Validate SysView trace data in log file(s).
|
"""Validate SysView trace data in a single trace log file.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
trace_log: List of trace log paths
|
trace_log: Path to the trace log file
|
||||||
target: Target chip name (e.g., 'esp32', 'esp32s3')
|
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
|
is_uart: If True, also validate STOP record at end of file
|
||||||
"""
|
"""
|
||||||
STOP_EVENT_ID = 0x0B # SYSVIEW_EVTID_TRACE_STOP
|
STOP_EVENT_ID = 0x0B # SYSVIEW_EVTID_TRACE_STOP
|
||||||
|
|
||||||
for idx, log in enumerate(trace_log):
|
with open(trace_log, 'rb') as f:
|
||||||
with open(log, 'rb') as f:
|
content = f.read()
|
||||||
content = f.read()
|
|
||||||
search_str = f'N=FreeRTOS Application,D={target},C=core{idx},O=FreeRTOS'.encode()
|
for idx in range(2 if dual_core else 1):
|
||||||
assert search_str in content, f'SysView trace data not found in {log}'
|
search_str = f'N=FreeRTOS Application,D={target},C=core{idx},O=FreeRTOS'.encode()
|
||||||
# The file must end with a TRACE_STOP record: the STOP event ID
|
assert search_str in content, f'SysView core{idx} trace data not found in {trace_log}'
|
||||||
# followed by a variable-length timestamp delta. Walk back
|
|
||||||
# over the trailing continuation bytes (0x80 bit set)
|
# The file must end with a TRACE_STOP record: the STOP event ID
|
||||||
# to find the event ID, since its offset is not fixed.
|
# followed by a variable-length timestamp delta. Walk back
|
||||||
size = len(content)
|
# over the trailing continuation bytes (0x80 bit set)
|
||||||
assert size >= 2, 'Trace file too small to contain STOP record'
|
# to find the event ID, since its offset is not fixed.
|
||||||
i = size - 2
|
size = len(content)
|
||||||
while i >= 0 and (content[i] & 0x80):
|
assert size >= 2, 'Trace file too small to contain STOP record'
|
||||||
i -= 1
|
i = size - 2
|
||||||
assert i >= 0 and content[i] == STOP_EVENT_ID, 'STOP record does not start with STOP eventID'
|
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:
|
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:
|
def _test_sysview_tracing_jtag(openocd_dut: 'OpenOCD', dut: IdfDut) -> None:
|
||||||
# Construct trace log paths
|
# Single multi-core capture file (esp sysview_mcore): one file is enough for
|
||||||
trace_log = [
|
# both single- and dual-core targets.
|
||||||
os.path.join(dut.logdir, 'sys_log0.svdat') # pylint: disable=protected-access
|
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'
|
||||||
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])
|
|
||||||
|
|
||||||
# Prepare gdbinit file
|
# Prepare gdbinit file pointing at this run's capture file
|
||||||
gdb_logfile = os.path.join(dut.logdir, 'gdb.txt')
|
gdb_logfile = os.path.join(dut.logdir, 'gdb.txt')
|
||||||
gdbinit_orig = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'gdbinit')
|
gdbinit_orig = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'gdbinit')
|
||||||
gdbinit = os.path.join(dut.logdir, 'gdbinit')
|
gdbinit = os.path.join(dut.logdir, 'gdbinit')
|
||||||
with open(gdbinit_orig) 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:
|
for line in f_r:
|
||||||
if line.startswith('mon esp sysview start'):
|
if line.startswith('mon esp sysview_mcore start'):
|
||||||
f_w.write(f'mon esp sysview start {trace_files}\n')
|
f_w.write(f'mon esp sysview_mcore start file://{trace_log}\n')
|
||||||
else:
|
else:
|
||||||
f_w.write(line)
|
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.
|
# Do a sleep while sysview samples are captured.
|
||||||
time.sleep(3)
|
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
|
@pytest.mark.jtag
|
||||||
@@ -155,8 +156,8 @@ def _test_sysview_tracing_uart(dut: IdfDut) -> None:
|
|||||||
dut.serial.close()
|
dut.serial.close()
|
||||||
time.sleep(2) # Wait for the DUT to reboot
|
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:
|
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
|
trace_log = os.path.join(dut.logdir, 'sys_log_uart.svdat') # pylint: disable=protected-access
|
||||||
_capture_sysview_trace(ser, trace_log[0])
|
_capture_sysview_trace(ser, trace_log)
|
||||||
_validate_trace_data(trace_log, dut.target, is_uart=True)
|
_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
|
time.sleep(1) # wait for USJ port to be ready
|
||||||
usj_port = '/dev/serial_ports/ttyACM-esp32'
|
usj_port = '/dev/serial_ports/ttyACM-esp32'
|
||||||
ser = serial.Serial(usj_port, baudrate=1000000, timeout=10)
|
ser = serial.Serial(usj_port, baudrate=1000000, timeout=10)
|
||||||
trace_log = [os.path.join(dut.logdir, 'sys_log_usj.svdat')] # pylint: disable=protected-access
|
trace_log = os.path.join(dut.logdir, 'sys_log_usj.svdat') # pylint: disable=protected-access
|
||||||
_capture_sysview_trace(ser, trace_log[0])
|
_capture_sysview_trace(ser, trace_log)
|
||||||
_validate_trace_data(trace_log, dut.target, is_uart=True)
|
_validate_trace_data(trace_log, dut.target, is_uart=True)
|
||||||
|
|||||||
Reference in New Issue
Block a user