mirror of
https://github.com/espressif/esp-idf
synced 2025-03-10 01:29:21 -04:00
tools: add test for ROM symbols in GDB
This commit is contained in:
parent
b9ed89228d
commit
0fd4b09a46
@ -235,8 +235,10 @@ build_non_test_components_apps:
|
|||||||
- "**/build*/flasher_args.json"
|
- "**/build*/flasher_args.json"
|
||||||
- "**/build*/flash_project_args"
|
- "**/build*/flash_project_args"
|
||||||
- "**/build*/config/sdkconfig.json"
|
- "**/build*/config/sdkconfig.json"
|
||||||
|
- "**/build*/bootloader/*.elf"
|
||||||
- "**/build*/bootloader/*.bin"
|
- "**/build*/bootloader/*.bin"
|
||||||
- "**/build*/partition_table/*.bin"
|
- "**/build*/partition_table/*.bin"
|
||||||
|
- "**/build*/project_description.json"
|
||||||
- list_job_*.json
|
- list_job_*.json
|
||||||
- size_info.txt
|
- size_info.txt
|
||||||
when: always
|
when: always
|
||||||
|
@ -34,3 +34,11 @@ URL_TO_DOC = 'https://docs.espressif.com/projects/esp-idf'
|
|||||||
|
|
||||||
SUPPORTED_TARGETS = ['esp32', 'esp32s2', 'esp32c3', 'esp32s3', 'esp32c2']
|
SUPPORTED_TARGETS = ['esp32', 'esp32s2', 'esp32c3', 'esp32s3', 'esp32c2']
|
||||||
PREVIEW_TARGETS = ['linux', 'esp32h2', 'esp32c6']
|
PREVIEW_TARGETS = ['linux', 'esp32h2', 'esp32c6']
|
||||||
|
|
||||||
|
OPENOCD_TAGET_CONFIG_DEFAULT = '-f interface/ftdi/esp32_devkitj_v1.cfg -f target/{target}.cfg'
|
||||||
|
OPENOCD_TAGET_CONFIG: Dict[str, str] = {
|
||||||
|
'esp32': '-f board/esp32-wrover-kit-3.3v.cfg',
|
||||||
|
'esp32s2': '-f board/esp32s2-kaluga-1.cfg',
|
||||||
|
'esp32c3': '-f board/esp32c3-builtin.cfg',
|
||||||
|
'esp32s3': '-f board/esp32s3-builtin.cfg',
|
||||||
|
}
|
||||||
|
@ -14,6 +14,7 @@ from threading import Thread
|
|||||||
from typing import Any, Dict, List, Optional
|
from typing import Any, Dict, List, Optional
|
||||||
|
|
||||||
from click.core import Context
|
from click.core import Context
|
||||||
|
from idf_py_actions.constants import OPENOCD_TAGET_CONFIG, OPENOCD_TAGET_CONFIG_DEFAULT
|
||||||
from idf_py_actions.errors import FatalError
|
from idf_py_actions.errors import FatalError
|
||||||
from idf_py_actions.tools import PropertyDict, ensure_build_directory
|
from idf_py_actions.tools import PropertyDict, ensure_build_directory
|
||||||
|
|
||||||
@ -59,6 +60,11 @@ source {connect}
|
|||||||
'''
|
'''
|
||||||
|
|
||||||
|
|
||||||
|
def get_openocd_arguments(target: str) -> str:
|
||||||
|
default_args = OPENOCD_TAGET_CONFIG_DEFAULT.format(target=target)
|
||||||
|
return str(OPENOCD_TAGET_CONFIG.get(target, default_args))
|
||||||
|
|
||||||
|
|
||||||
def action_extensions(base_actions: Dict, project_path: str) -> Dict:
|
def action_extensions(base_actions: Dict, project_path: str) -> Dict:
|
||||||
OPENOCD_OUT_FILE = 'openocd_out.txt'
|
OPENOCD_OUT_FILE = 'openocd_out.txt'
|
||||||
GDBGUI_OUT_FILE = 'gdbgui_out.txt'
|
GDBGUI_OUT_FILE = 'gdbgui_out.txt'
|
||||||
@ -286,12 +292,6 @@ def action_extensions(base_actions: Dict, project_path: str) -> Dict:
|
|||||||
"""
|
"""
|
||||||
Execute openocd as external tool
|
Execute openocd as external tool
|
||||||
"""
|
"""
|
||||||
OPENOCD_TAGET_CONFIG = {
|
|
||||||
'esp32': '-f board/esp32-wrover-kit-3.3v.cfg',
|
|
||||||
'esp32s2': '-f board/esp32s2-kaluga-1.cfg',
|
|
||||||
'esp32c3': '-f board/esp32c3-builtin.cfg',
|
|
||||||
'esp32s3': '-f board/esp32s3-builtin.cfg',
|
|
||||||
}
|
|
||||||
if os.getenv('OPENOCD_SCRIPTS') is None:
|
if os.getenv('OPENOCD_SCRIPTS') is None:
|
||||||
raise FatalError('OPENOCD_SCRIPTS not found in the environment: Please run export.sh/export.bat', ctx)
|
raise FatalError('OPENOCD_SCRIPTS not found in the environment: Please run export.sh/export.bat', ctx)
|
||||||
openocd_arguments = os.getenv('OPENOCD_COMMANDS') if openocd_commands is None else openocd_commands
|
openocd_arguments = os.getenv('OPENOCD_COMMANDS') if openocd_commands is None else openocd_commands
|
||||||
@ -299,8 +299,7 @@ def action_extensions(base_actions: Dict, project_path: str) -> Dict:
|
|||||||
if openocd_arguments is None:
|
if openocd_arguments is None:
|
||||||
# use default value if commands not defined in the environment nor command line
|
# use default value if commands not defined in the environment nor command line
|
||||||
target = project_desc['target']
|
target = project_desc['target']
|
||||||
default_args = '-f interface/ftdi/esp32_devkitj_v1.cfg -f target/{}.cfg'.format(target)
|
openocd_arguments = get_openocd_arguments(target)
|
||||||
openocd_arguments = OPENOCD_TAGET_CONFIG.get(target, default_args)
|
|
||||||
print('Note: OpenOCD cfg not found (via env variable OPENOCD_COMMANDS nor as a --openocd-commands argument)\n'
|
print('Note: OpenOCD cfg not found (via env variable OPENOCD_COMMANDS nor as a --openocd-commands argument)\n'
|
||||||
'OpenOCD arguments default to: "{}"'.format(openocd_arguments))
|
'OpenOCD arguments default to: "{}"'.format(openocd_arguments))
|
||||||
# script directory is taken from the environment by OpenOCD, update only if command line arguments to override
|
# script directory is taken from the environment by OpenOCD, update only if command line arguments to override
|
||||||
@ -405,9 +404,9 @@ def action_extensions(base_actions: Dict, project_path: str) -> Dict:
|
|||||||
"""
|
"""
|
||||||
Synchronous GDB target with text ui mode
|
Synchronous GDB target with text ui mode
|
||||||
"""
|
"""
|
||||||
gdb(action, ctx, args, 1, gdbinit, require_openocd)
|
gdb(action, ctx, args, False, 1, gdbinit, require_openocd)
|
||||||
|
|
||||||
def gdb(action: str, ctx: Context, args: PropertyDict, gdb_tui: Optional[int], gdbinit: Optional[str], require_openocd: bool) -> None:
|
def gdb(action: str, ctx: Context, args: PropertyDict, batch: bool, gdb_tui: Optional[int], gdbinit: Optional[str], require_openocd: bool) -> None:
|
||||||
"""
|
"""
|
||||||
Synchronous GDB target
|
Synchronous GDB target
|
||||||
"""
|
"""
|
||||||
@ -420,6 +419,8 @@ def action_extensions(base_actions: Dict, project_path: str) -> Dict:
|
|||||||
args = [gdb, *get_gdb_args(project_desc)]
|
args = [gdb, *get_gdb_args(project_desc)]
|
||||||
if gdb_tui is not None:
|
if gdb_tui is not None:
|
||||||
args += ['-tui']
|
args += ['-tui']
|
||||||
|
if batch:
|
||||||
|
args += ['--batch']
|
||||||
t = Thread(target=run_gdb, args=(args,))
|
t = Thread(target=run_gdb, args=(args,))
|
||||||
t.start()
|
t.start()
|
||||||
while True:
|
while True:
|
||||||
@ -476,12 +477,17 @@ def action_extensions(base_actions: Dict, project_path: str) -> Dict:
|
|||||||
'callback': gdb,
|
'callback': gdb,
|
||||||
'help': 'Run the GDB.',
|
'help': 'Run the GDB.',
|
||||||
'options': [
|
'options': [
|
||||||
|
{
|
||||||
|
'names': ['--batch'],
|
||||||
|
'help': ('exit after processing gdbinit.\n'),
|
||||||
|
'hidden': True,
|
||||||
|
'is_flag': True,
|
||||||
|
'default': False,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
'names': ['--gdb-tui', '--gdb_tui'],
|
'names': ['--gdb-tui', '--gdb_tui'],
|
||||||
'help':
|
'help': ('run gdb in TUI mode\n'),
|
||||||
('run gdb in TUI mode\n'),
|
'default': None,
|
||||||
'default':
|
|
||||||
None,
|
|
||||||
}, gdbinit, fail_if_openocd_failed
|
}, gdbinit, fail_if_openocd_failed
|
||||||
],
|
],
|
||||||
'order_dependencies': ['all', 'flash'],
|
'order_dependencies': ['all', 'flash'],
|
||||||
|
6
tools/test_apps/system/gdb/CMakeLists.txt
Normal file
6
tools/test_apps/system/gdb/CMakeLists.txt
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
# The following lines of boilerplate have to be in your project's
|
||||||
|
# CMakeLists in this exact order for cmake to work correctly
|
||||||
|
cmake_minimum_required(VERSION 3.16)
|
||||||
|
|
||||||
|
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
|
||||||
|
project(gdb)
|
6
tools/test_apps/system/gdb/README.md
Normal file
6
tools/test_apps/system/gdb/README.md
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-S2 | ESP32-S3 |
|
||||||
|
| ----------------- | ----- | -------- | -------- | -------- | -------- |
|
||||||
|
|
||||||
|
# IDF GDB test application
|
||||||
|
|
||||||
|
This project tests if `idf.py gdb` works correct
|
3
tools/test_apps/system/gdb/main/CMakeLists.txt
Normal file
3
tools/test_apps/system/gdb/main/CMakeLists.txt
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
idf_component_register(SRCS "hello_world_main.c"
|
||||||
|
INCLUDE_DIRS "")
|
||||||
|
target_compile_options(${COMPONENT_LIB} PRIVATE "-Wno-format")
|
46
tools/test_apps/system/gdb/main/hello_world_main.c
Normal file
46
tools/test_apps/system/gdb/main/hello_world_main.c
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2010-2022 Espressif Systems (Shanghai) CO LTD
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: CC0-1.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include "sdkconfig.h"
|
||||||
|
#include "freertos/FreeRTOS.h"
|
||||||
|
#include "freertos/task.h"
|
||||||
|
#include "esp_chip_info.h"
|
||||||
|
#include "esp_flash.h"
|
||||||
|
|
||||||
|
void app_main(void)
|
||||||
|
{
|
||||||
|
printf("Hello world!\n");
|
||||||
|
|
||||||
|
/* Print chip information */
|
||||||
|
esp_chip_info_t chip_info;
|
||||||
|
uint32_t flash_size;
|
||||||
|
esp_chip_info(&chip_info);
|
||||||
|
printf("This is %s chip with %d CPU core(s), WiFi%s%s, ",
|
||||||
|
CONFIG_IDF_TARGET,
|
||||||
|
chip_info.cores,
|
||||||
|
(chip_info.features & CHIP_FEATURE_BT) ? "/BT" : "",
|
||||||
|
(chip_info.features & CHIP_FEATURE_BLE) ? "/BLE" : "");
|
||||||
|
|
||||||
|
printf("silicon revision %d, ", chip_info.revision);
|
||||||
|
if(esp_flash_get_size(NULL, &flash_size) != ESP_OK) {
|
||||||
|
printf("Get flash size failed");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("%uMB %s flash\n", flash_size / (1024 * 1024),
|
||||||
|
(chip_info.features & CHIP_FEATURE_EMB_FLASH) ? "embedded" : "external");
|
||||||
|
|
||||||
|
printf("Minimum free heap size: %d bytes\n", esp_get_minimum_free_heap_size());
|
||||||
|
|
||||||
|
for (int i = 10; i >= 0; i--) {
|
||||||
|
printf("Restarting in %d seconds...\n", i);
|
||||||
|
vTaskDelay(1000 / portTICK_PERIOD_MS);
|
||||||
|
}
|
||||||
|
printf("Restarting now.\n");
|
||||||
|
fflush(stdout);
|
||||||
|
esp_restart();
|
||||||
|
}
|
53
tools/test_apps/system/gdb/pytest_gdb.py
Normal file
53
tools/test_apps/system/gdb/pytest_gdb.py
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
# SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
|
||||||
|
# SPDX-License-Identifier: Unlicense OR CC0-1.0
|
||||||
|
import os
|
||||||
|
import re
|
||||||
|
import signal
|
||||||
|
import subprocess
|
||||||
|
import sys
|
||||||
|
|
||||||
|
import pexpect
|
||||||
|
import pytest
|
||||||
|
from pytest_embedded import Dut
|
||||||
|
|
||||||
|
try:
|
||||||
|
from idf_py_actions.debug_ext import get_openocd_arguments
|
||||||
|
except ModuleNotFoundError:
|
||||||
|
sys.path.append(os.path.join(os.path.dirname(__file__), '..', '..', '..'))
|
||||||
|
from idf_py_actions.debug_ext import get_openocd_arguments
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.supported_targets
|
||||||
|
@pytest.mark.test_jtag_arm
|
||||||
|
def test_idf_gdb(dut: Dut) -> None:
|
||||||
|
# Need to wait a moment to connect via OpenOCD after the hard reset happened.
|
||||||
|
# Along with this check that app runs ok
|
||||||
|
dut.expect('Hello world!')
|
||||||
|
|
||||||
|
# Don't need to have output from UART any more
|
||||||
|
dut.serial.stop_redirect_thread()
|
||||||
|
|
||||||
|
with open(os.path.join(dut.logdir, 'ocd.log'), 'w') as ocd_log:
|
||||||
|
ocd = subprocess.Popen(f'openocd {get_openocd_arguments(dut.target)}', stdout=ocd_log, stderr=ocd_log, shell=True)
|
||||||
|
|
||||||
|
try:
|
||||||
|
gdb_env = os.environ.copy()
|
||||||
|
gdb_env['ESP_IDF_GDB_TESTING'] = '1'
|
||||||
|
|
||||||
|
with open(os.path.join(dut.logdir, 'gdb.log'), 'w') as gdb_log, \
|
||||||
|
pexpect.spawn(f'idf.py -B {dut.app.binary_path} gdb --batch',
|
||||||
|
env=gdb_env,
|
||||||
|
timeout=60,
|
||||||
|
logfile=gdb_log,
|
||||||
|
encoding='utf-8',
|
||||||
|
codec_errors='ignore') as p:
|
||||||
|
p.expect(re.compile(r'add symbol table from file.*bootloader.elf'))
|
||||||
|
p.expect(re.compile(r'add symbol table from file.*rom.elf'))
|
||||||
|
p.expect_exact('hit Temporary breakpoint 1, app_main ()')
|
||||||
|
finally:
|
||||||
|
try:
|
||||||
|
ocd.send_signal(signal.SIGINT)
|
||||||
|
ocd.communicate(timeout=15)
|
||||||
|
except subprocess.TimeoutExpired:
|
||||||
|
ocd.kill()
|
||||||
|
ocd.communicate()
|
Loading…
x
Reference in New Issue
Block a user