fix(sysview): add prefix to the module desc to avoid stuck in Segger SystemView app

Closes https://github.com/espressif/esp-idf/issues/10483
This commit is contained in:
Erhan Kurubas 2024-11-20 14:35:43 +01:00
parent 688b86ba24
commit e5d377be8d
18 changed files with 49427 additions and 268264 deletions

View File

@ -21,7 +21,7 @@ const static char *TAG = "sysview_heap_trace";
#endif #endif
static SEGGER_SYSVIEW_MODULE s_esp_sysview_heap_module = { static SEGGER_SYSVIEW_MODULE s_esp_sysview_heap_module = {
.sModule = "ESP32 SystemView Heap Tracing Module", .sModule = "M=ESP32 SystemView Heap Tracing Module",
.NumEvents = 2, .NumEvents = 2,
}; };

View File

@ -1,4 +1,4 @@
# SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD # SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD
# SPDX-License-Identifier: Apache-2.0 # SPDX-License-Identifier: Apache-2.0
import copy import copy
import json import json
@ -87,7 +87,7 @@ def parse_trace(reader, parser, os_evt_map_file=''):
parser : SysViewTraceDataParser parser : SysViewTraceDataParser
Top level parser object. Top level parser object.
os_evt_map_file : string os_evt_map_file : string
Path to file containg events format description. Path to file containing events format description.
""" """
global _os_events_map global _os_events_map
# parse OS events formats file # parse OS events formats file
@ -106,12 +106,12 @@ def _read_events_map(os_evt_map_file):
Parameters Parameters
---------- ----------
os_evt_map_file : string os_evt_map_file : string
Path to file containg events format description. Path to file containing events format description.
Returns Returns
------- -------
dict dict
a dict with event IDs as keys and values as tuples containg event name and a list of parameters. a dict with event IDs as keys and values as tuples containing event name and a list of parameters.
""" """
os_evt_map = {} os_evt_map = {}
with open(os_evt_map_file) as f: with open(os_evt_map_file) as f:
@ -130,7 +130,7 @@ def _read_events_map(os_evt_map_file):
elif sp[1] == 's': elif sp[1] == 's':
params.append(SysViewEventParamSimple(sp[0], _decode_str)) params.append(SysViewEventParamSimple(sp[0], _decode_str))
elif sp[1] == 't' or sp[1] == 'T' or sp[1] == 'I' or sp[1] == 'p': elif sp[1] == 't' or sp[1] == 'T' or sp[1] == 'I' or sp[1] == 'p':
# TODO: handle shrinked task/queue ID and addresses # TODO: handle shrunk task/queue ID and addresses
params.append(SysViewEventParamSimple(sp[0], _decode_u32)) params.append(SysViewEventParamSimple(sp[0], _decode_u32))
os_evt_map[int(comps[0])] = (comps[1], params) os_evt_map[int(comps[0])] = (comps[1], params)
return os_evt_map return os_evt_map
@ -177,7 +177,7 @@ def _read_init_seq(reader):
sync_bytes = struct.unpack(SYNC_SEQ_FMT, reader.read(struct.calcsize(SYNC_SEQ_FMT))) sync_bytes = struct.unpack(SYNC_SEQ_FMT, reader.read(struct.calcsize(SYNC_SEQ_FMT)))
for b in sync_bytes: for b in sync_bytes:
if b != 0: if b != 0:
raise SysViewTraceParseError('Invalid sync sequense!') raise SysViewTraceParseError('Invalid sync sequence!')
def _decode_u32(reader): def _decode_u32(reader):
@ -192,7 +192,7 @@ def _decode_u32(reader):
Returns Returns
------- -------
tuple tuple
a tuple containg number of read bytes and decoded value. a tuple containing number of read bytes and decoded value.
""" """
sz = 0 sz = 0
val = 0 val = 0
@ -219,7 +219,7 @@ def _decode_id(reader):
Returns Returns
------- -------
tuple tuple
a tuple containg number of read bytes and decoded value. a tuple containing number of read bytes and decoded value.
""" """
return _decode_u32(reader) return _decode_u32(reader)
@ -236,7 +236,7 @@ def _decode_u64(reader):
Returns Returns
------- -------
tuple tuple
a tuple containg number of read bytes and decoded value. a tuple containing number of read bytes and decoded value.
""" """
sz,val = _decode_u32(reader) sz,val = _decode_u32(reader)
sz2,high = _decode_u32(reader) sz2,high = _decode_u32(reader)
@ -256,7 +256,7 @@ def _decode_str(reader):
Returns Returns
------- -------
tuple tuple
a tuple containg number of read bytes and decoded value. a tuple containing number of read bytes and decoded value.
""" """
sz = 0 sz = 0
val = '' val = ''
@ -411,7 +411,7 @@ class SysViewEventParam:
Returns Returns
------- -------
tuple tuple
a tuple containg number of read bytes and decoded value. a tuple containing number of read bytes and decoded value.
""" """
pass pass
@ -900,7 +900,7 @@ class SysViewTraceDataProcessor(apptrace.TraceDataProcessor):
# empty list means IDLE context or self.start_ctx # empty list means IDLE context or self.start_ctx
self.ctx_stack[t.core_id] = [] self.ctx_stack[t.core_id] = []
# context is undefined, we do not know have we started the tracing in task/IDLE or IRQ context # context is undefined, we do not know have we started the tracing in task/IDLE or IRQ context
# in general there are three scenarious when we can start tracing: when core is in task, IDLE task or IRQ context # in general there are three scenarios when we can start tracing: when core is in task, IDLE task or IRQ context
self.prev_ctx[t.core_id] = None self.prev_ctx[t.core_id] = None
def _get_curr_context(self, core_id): def _get_curr_context(self, core_id):
@ -963,13 +963,13 @@ class SysViewTraceDataProcessor(apptrace.TraceDataProcessor):
def event_supported(self, e): def event_supported(self, e):
""" """
Should be overriden in child class. Should be overridden in child class.
""" """
return False return False
def handle_event(self, e): def handle_event(self, e):
""" """
Should be overriden in child class. Should be overridden in child class.
""" """
pass pass
@ -1263,7 +1263,7 @@ class SysViewHeapTraceDataParser(SysViewTraceDataExtEventParser):
""" """
if self.root_proc == self: if self.root_proc == self:
SysViewTraceDataParser.on_new_event(self, event) SysViewTraceDataParser.on_new_event(self, event)
if event.id == SYSVIEW_EVTID_MODULEDESC and event.params['desc'].value == 'ESP32 SystemView Heap Tracing Module': if event.id == SYSVIEW_EVTID_MODULEDESC and event.params['desc'].value == 'M=ESP32 SystemView Heap Tracing Module':
self.events_off = event.params['evt_off'].value self.events_off = event.params['evt_off'].value

View File

@ -0,0 +1,66 @@
# Steps to Generate Test Input Files
1. `sysview_tracing_heap_log.elf`
Build example `sysview_tracing_heap_log` project.
```
cd $IDF_PATH/examples/system/sysview_tracing_heap_log
idf.py set target esp32
idf.py build
cp build/sysview_tracing_heap_log.elf $IDF_PATH/tools/esp_app_trace/test/sysview/
cd $IDF_PATH/tools/esp_app_trace/test/sysview/
chmod -x sysview_tracing_heap_log.elf
```
2. `heap_log0.svdat` and `heap_log1.svdat`
Flash the example and run OpenOCD and GDB using the following command in a separate console
```
cd $IDF_PATH/examples/system/sysview_tracing_heap_log
idf.py openocd
```
```
cd $IDF_PATH/examples/system/sysview_tracing_heap_log
xtensa-esp32-elf-gdb -x gdbinit build/sysview_tracing_heap_log.elf
```
When program stops at `heap_trace_stop` quit GDB and OpenOCD
Copy generated svdat files
```
cp heap_log0.svdat $IDF_PATH/tools/esp_app_trace/test/sysview/
cp heap_log1.svdat $IDF_PATH/tools/esp_app_trace/test/sysview/
```
3. `heap_log_mcore.svdat`
Flash the example and run OpenOCD and GDB using the following command in a separate console
```
cd $IDF_PATH/examples/system/sysview_tracing_heap_log
idf.py openocd
```
```
cd $IDF_PATH/examples/system/sysview_tracing_heap_log
xtensa-esp32-elf-gdb -x gdbinit-mcore build/sysview_tracing_heap_log.elf
```
When program stops at `heap_trace_stop` quit GDB and OpenOCD
Copy generated svdat file
```
cp heap_log_mcore.svdat $IDF_PATH/tools/esp_app_trace/test/sysview/
```
4. `expected_output` and `expected_output_json` files
You can use the commands from the `test.sh` to generate expected result files
```
$IDF_PATH/tools/esp_app_trace/sysviewtrace_proc.py -d -p -b sysview_tracing_heap_log.elf heap_log0.svdat heap_log1.svdat &> expected_output
$IDF_PATH/tools/esp_app_trace/sysviewtrace_proc.py -j -b sysview_tracing_heap_log.elf heap_log0.svdat heap_log1.svdat &> expected_output.json
$IDF_PATH/tools/esp_app_trace/sysviewtrace_proc.py -d -p -b sysview_tracing_heap_log.elf heap_log_mcore.svdat &> expected_output_mcore
$IDF_PATH/tools/esp_app_trace/sysviewtrace_proc.py -j -b sysview_tracing_heap_log.elf heap_log_mcore.svdat &> expected_output_mcore.json
```

View File

@ -1,88 +0,0 @@
/* Blink 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.
*/
#include <stdio.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "driver/gpio.h"
#include "sdkconfig.h"
#include "esp_heap_trace.h"
/* Can use project configuration menu (idf.py menuconfig) to choose the GPIO
to blink or you can edit the following line and set a number here.
*/
#define BLINK_GPIO CONFIG_BLINK_GPIO
void blink_task2(void *pvParameter)
{
TaskHandle_t task = (TaskHandle_t)pvParameter;
while(1) {
if (xTaskNotifyWait(0, 0, NULL, portMAX_DELAY) != pdPASS) {
printf("Failed to wait for main task!\n");
return;
}
void *a = malloc(65);
printf("Alloced 65 bytes @ %p\n", a);
void *b = malloc(97);
printf("Alloced 97 bytes @ %p\n", b);
free(a);
printf("Freed @ %p\n", a);
b = malloc(11);
printf("Alloced 11 bytes @ %p\n", b);
b = malloc(24);
printf("Alloced 24 bytes @ %p\n", b);
free(b);
printf("Freed @ %p\n", b);
if (xTaskNotify(task, 0, eNoAction) != pdPASS) {
printf("Failed to notify main task!\n");
return;
}
}
}
void blink_task(void *pvParameter)
{
TaskHandle_t task = 0;
if(heap_trace_init_tohost() != ESP_OK) {
printf("Failed to init heap trace!\n");
return;
}
xTaskCreatePinnedToCore(&blink_task2, "blink_task2", 2048, xTaskGetCurrentTaskHandle(), 5, &task, 1);
while(1) {
heap_trace_start(HEAP_TRACE_ALL);
if (xTaskNotify(task, 0, eNoAction) != pdPASS) {
printf("Failed to notify slave task!\n");
return;
}
void *a = malloc(64);
printf("Alloced 64 bytes @ %p\n", a);
void *b = malloc(96);
printf("Alloced 96 bytes @ %p\n", b);
free(a);
printf("Freed @ %p\n", a);
b = malloc(10);
printf("Alloced 10 bytes @ %p\n", b);
b = malloc(23);
printf("Alloced 23 bytes @ %p\n", b);
free(b);
printf("Freed @ %p\n", b);
if (xTaskNotifyWait(0, 0, NULL, portMAX_DELAY) != pdPASS) {
printf("Failed to wait for slave task!\n");
return;
}
heap_trace_stop();
}
}
void app_main(void)
{
xTaskCreatePinnedToCore(&blink_task, "blink_task", 2048, NULL, 5, NULL, 0);
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -6,14 +6,14 @@ maintenance flush register-cache
b heap_trace_start b heap_trace_start
commands commands
clear heap_trace_start clear heap_trace_start
mon esp32 sysview start file://cpu0.svdat file://cpu1.svdat mon esp sysview start file://heap_log0.svdat file://heap_log1.svdat
c c
end end
b heap_trace_stop b heap_trace_stop
commands commands
clear heap_trace_stop clear heap_trace_stop
mon esp32 sysview stop mon esp sysview stop
end end
c c

View File

@ -0,0 +1,19 @@
target remote :3333
mon reset halt
maintenance flush register-cache
b heap_trace_start
commands
clear heap_trace_start
mon esp sysview_mcore start file://heap_log_mcore.svdat
c
end
b heap_trace_stop
commands
clear heap_trace_stop
mon esp sysview_mcore stop
end
c

Binary file not shown.

Binary file not shown.

View File

@ -2,14 +2,14 @@
{ python -m coverage debug sys \ { python -m coverage debug sys \
&& python -m coverage erase &> output \ && python -m coverage erase &> output \
&& python -m coverage run -a $IDF_PATH/tools/esp_app_trace/sysviewtrace_proc.py -d -p -b test.elf cpu0.svdat cpu1.svdat &>> output \ && python -m coverage run -a $IDF_PATH/tools/esp_app_trace/sysviewtrace_proc.py -d -p -b sysview_tracing_heap_log.elf heap_log0.svdat heap_log1.svdat &>> output \
&& diff output expected_output \ && diff output expected_output \
&& python -m coverage report \ && python -m coverage report \
; } || { echo 'The test for sysviewtrace_proc has failed. Please examine the artifacts.' ; exit 1; } ; } || { echo 'The test for sysviewtrace_proc has failed. Please examine the artifacts.' ; exit 1; }
{ python -m coverage debug sys \ { python -m coverage debug sys \
&& python -m coverage erase &> output.json \ && python -m coverage erase &> output.json \
&& python -m coverage run -a $IDF_PATH/tools/esp_app_trace/sysviewtrace_proc.py -j -b test.elf cpu0.svdat cpu1.svdat &>> output.json \ && python -m coverage run -a $IDF_PATH/tools/esp_app_trace/sysviewtrace_proc.py -j -b sysview_tracing_heap_log.elf heap_log0.svdat heap_log1.svdat &>> output.json \
&& diff output.json expected_output.json \ && diff output.json expected_output.json \
&& python -m coverage report \ && python -m coverage report \
; } || { echo 'The test for sysviewtrace_proc JSON functionality has failed. Please examine the artifacts.' ; exit 1; } ; } || { echo 'The test for sysviewtrace_proc JSON functionality has failed. Please examine the artifacts.' ; exit 1; }