scripts: runners: openocd: Enable thread awareness

Zephyr thread awareness is available for openocd but boards don't
have debuggers configuration.  This configure OpenOCD runner
automatically to complete configuration.

User still require enable CONFIG_DEBUG_THREAD_INFO=y to visualize
thread debug information.

Signed-off-by: Gerson Fernando Budke <nandojve@gmail.com>
This commit is contained in:
Gerson Fernando Budke 2021-08-25 22:07:54 -03:00 committed by Christopher Friedt
commit c3db83ba58
6 changed files with 68 additions and 18 deletions

View file

@ -27,7 +27,6 @@ set(pre_init_cmds
"source [find interface/${OPENOCD_NRF5_INTERFACE}.cfg]"
"transport select swd"
"source [find target/${OPENOCD_NRF5_SUBFAMILY}.cfg]"
"$_TARGETNAME configure -rtos auto"
)
foreach(cmd ${pre_init_cmds})

View file

@ -53,9 +53,10 @@ function(runners_yaml_append_config)
endif()
if(OPENOCD)
runners_yaml_append(" openocd: ${OPENOCD}")
endif()
if(OPENOCD_DEFAULT_PATH)
runners_yaml_append(" openocd_search: ${OPENOCD_DEFAULT_PATH}")
runners_yaml_append(" openocd_search:")
if(OPENOCD_DEFAULT_PATH)
runners_yaml_append(" - ${OPENOCD_DEFAULT_PATH}")
endif()
endif()
runners_yaml_append("")
endfunction()

View file

@ -356,8 +356,8 @@ def get_runner_config(build_dir, yaml_path, runners_yaml, args=None):
return None
def config(attr):
return getattr(args, attr, None) or yaml_config.get(attr)
def config(attr, default=None):
return getattr(args, attr, None) or yaml_config.get(attr, default)
return RunnerConfig(build_dir,
yaml_config['board_dir'],
@ -366,7 +366,7 @@ def get_runner_config(build_dir, yaml_path, runners_yaml, args=None):
output_file('bin'),
config('gdb'),
config('openocd'),
config('openocd_search'))
config('openocd_search', []))
def dump_traceback():
# Save the current exception to a file and return its path.

View file

@ -260,7 +260,7 @@ class RunnerConfig(NamedTuple):
bin_file: Optional[str] # zephyr.bin path, or None
gdb: Optional[str] = None # path to a usable gdb
openocd: Optional[str] = None # path to a usable openocd
openocd_search: Optional[str] = None # add this to openocd search path
openocd_search: List[str] = [] # add these paths to the openocd search path
_YN_CHOICES = ['Y', 'y', 'N', 'n', 'yes', 'no', 'YES', 'NO']

View file

@ -4,6 +4,9 @@
'''Runner for openocd.'''
import subprocess
import re
from os import path
from pathlib import Path
@ -38,13 +41,14 @@ class OpenOcdBinaryRunner(ZephyrBinaryRunner):
self.openocd_config = config
search_args = []
for i in self.openocd_config:
if path.exists(i):
search_args.append('-s')
search_args.append(path.dirname(i))
if self.openocd_config is not None:
for i in self.openocd_config:
if path.exists(i):
search_args.append('-s')
search_args.append(path.dirname(i))
if cfg.openocd_search is not None:
search_args.extend(['-s', cfg.openocd_search])
for p in cfg.openocd_search:
search_args.extend(['-s', p])
self.openocd_cmd = [cfg.openocd] + search_args
# openocd doesn't cope with Windows path names, so convert
# them to POSIX style just to be sure.
@ -117,6 +121,45 @@ class OpenOcdBinaryRunner(ZephyrBinaryRunner):
tcl_port=args.tcl_port, telnet_port=args.telnet_port,
gdb_port=args.gdb_port)
def print_gdbserver_message(self):
if not self.thread_info_enabled:
thread_msg = '; no thread info available'
elif self.supports_thread_info():
thread_msg = '; thread info enabled'
else:
thread_msg = '; update OpenOCD software for thread info'
self.logger.info('OpenOCD GDB server running on port '
f'{self.gdb_port}{thread_msg}')
# pylint: disable=R0201
def to_num(self, number):
dev_match = re.search(r"^\d*\+dev", number)
dev_version = not dev_match is None
num_match = re.search(r"^\d*", number)
num = int(num_match.group(0))
if dev_version:
num += 1
return num
def read_version(self):
self.require(self.openocd_cmd[0])
# OpenOCD prints in stderr, need redirect to get output
out = self.check_output([self.openocd_cmd[0], '--version'],
stderr=subprocess.STDOUT).decode()
return out.split('\n')[0]
def supports_thread_info(self):
# Zephyr rtos was introduced after 0.11.0
version_str = self.read_version().split(' ')[3]
version = version_str.split('.')
(major, minor, rev) = [self.to_num(i) for i in version]
return (major, minor, rev) > (0, 11, 0)
def do_run(self, command, **kwargs):
self.require(self.openocd_cmd[0])
if ELFFile is None:
@ -124,9 +167,10 @@ class OpenOcdBinaryRunner(ZephyrBinaryRunner):
'elftools missing; please "pip3 install elftools"')
self.cfg_cmd = []
for i in self.openocd_config:
self.cfg_cmd.append('-f')
self.cfg_cmd.append(i)
if self.openocd_config is not None:
for i in self.openocd_config:
self.cfg_cmd.append('-f')
self.cfg_cmd.append(i)
if command == 'flash' and self.use_elf:
self.do_flash_elf(**kwargs)
@ -213,6 +257,10 @@ class OpenOcdBinaryRunner(ZephyrBinaryRunner):
pre_init_cmd.append("-c")
pre_init_cmd.append(i)
if self.thread_info_enabled and self.supports_thread_info():
pre_init_cmd.append("-c")
pre_init_cmd.append("$_TARGETNAME configure -rtos Zephyr")
server_cmd = (self.openocd_cmd + self.serial + self.cfg_cmd +
['-c', 'tcl_port {}'.format(self.tcl_port),
'-c', 'telnet_port {}'.format(self.telnet_port),
@ -225,6 +273,7 @@ class OpenOcdBinaryRunner(ZephyrBinaryRunner):
if command == 'debug':
gdb_cmd.extend(['-ex', 'load'])
self.require(gdb_cmd[0])
self.print_gdbserver_message()
self.run_server_and_client(server_cmd, gdb_cmd)
def do_debugserver(self, **kwargs):
@ -240,4 +289,5 @@ class OpenOcdBinaryRunner(ZephyrBinaryRunner):
pre_init_cmd + ['-c', 'init',
'-c', 'targets',
'-c', 'reset halt'])
self.print_gdbserver_message()
self.check_call(cmd)

View file

@ -15,7 +15,7 @@ RC_KERNEL_HEX = 'test-zephyr.hex'
RC_KERNEL_BIN = 'test-zephyr.bin'
RC_GDB = 'test-none-gdb'
RC_OPENOCD = 'test-openocd'
RC_OPENOCD_SEARCH = '/test/openocd/search'
RC_OPENOCD_SEARCH = ['/test/openocd/search']
@pytest.fixture