scripts: west: introduce common runner configuration

Continue better integration of the runner subpackage into west by
moving the common runner configuration options into the command
core. This allows commands like "west flash -h" to display help for
common overrides like --kernel-hex.

Adjustments needed to make this happen are:

- Change the build system to separate common configuration values from
  runner-specific options and arguments

- Prepare the runner core by defining a new RunnerConfig class that
  represents the common configuration, and accepting that from a new
  create() method, which replaces create_from_args().

- Convert all concrete runner classes to use the new style of
  argument parsing and initialization.

- Group the command options appropriately for help output readability

There's still a bit of tool-specific stuff in the common
configuration (gdb and openocd configuration in particular); a more
generic way to deal with that will be necessary to better support
things like non-GDB debuggers, but that's out of scope of this patch.

All the runner-specific options are still in the runner packge, which
currently prevents them from being included in "west flash -h" etc.
Fixing that is also out of scope of this patch.

This has the ancillary benefit of getting rid of the legacy 'debug'
argument to ZephyrBinaryRunner, which is no longer appropriate since
verbose debug logging is handled by log.py in west.

Signed-off-by: Marti Bolivar <marti@opensourcefoundries.com>
This commit is contained in:
Marti Bolivar 2018-05-10 00:58:03 -04:00 committed by Anas Nashif
commit 5317f76dec
15 changed files with 314 additions and 224 deletions

View file

@ -3,20 +3,6 @@ assert_not(DEBUG_SCRIPT "DEBUG_SCRIPT has been removed; use BOARD_DEBUG_RUNNER")
get_property(RUNNERS GLOBAL PROPERTY ZEPHYR_RUNNERS)
# These arguments are common to all runners.
set(RUNNER_ARGS_COMMON
# Required:
"--board-dir=${BOARD_DIR}"
"--kernel-elf=${PROJECT_BINARY_DIR}/${KERNEL_ELF_NAME}"
"--kernel-hex=${PROJECT_BINARY_DIR}/${KERNEL_HEX_NAME}"
"--kernel-bin=${PROJECT_BINARY_DIR}/${KERNEL_BIN_NAME}"
# Optional, but so often needed that they're provided by default:
# (TODO: revisit whether we really want these here)
"--gdb=${CMAKE_GDB}"
"--openocd=${OPENOCD}"
"--openocd-search=${OPENOCD_DEFAULT_PATH}"
)
# Enable verbose output, if requested.
if(CMAKE_VERBOSE_MAKEFILE)
set(RUNNER_VERBOSE "--verbose")
@ -33,8 +19,37 @@ endif()
# configuration if the board files change.
if(RUNNERS)
set(ZEPHYR_RUNNERS ${RUNNERS} CACHE INTERNAL "Available runners")
set(ZEPHYR_RUNNER_ARGS_COMMON ${RUNNER_ARGS_COMMON} CACHE STRING
"Common arguments to all runners" FORCE)
# Runner configuration. This is provided to all runners, and is
# distinct from the free-form arguments provided by e.g.
# board_runner_args().
#
# Always applicable:
set(ZEPHYR_RUNNER_CONFIG_BOARD_DIR "${BOARD_DIR}"
CACHE STRING "Board definition directory" FORCE)
set(ZEPHYR_RUNNER_CONFIG_KERNEL_ELF "${PROJECT_BINARY_DIR}/${KERNEL_ELF_NAME}"
CACHE STRING "Path to kernel image in ELF format" FORCE)
set(ZEPHYR_RUNNER_CONFIG_KERNEL_HEX "${PROJECT_BINARY_DIR}/${KERNEL_HEX_NAME}"
CACHE STRING "Path to kernel image in Intel Hex format" FORCE)
set(ZEPHYR_RUNNER_CONFIG_KERNEL_BIN "${PROJECT_BINARY_DIR}/${KERNEL_BIN_NAME}"
CACHE STRING "Path to kernel image as raw binary" FORCE)
# Not always applicable, but so often needed that they're provided
# by default: (TODO: clean this up)
if(DEFINED CMAKE_GDB)
set(ZEPHYR_RUNNER_CONFIG_GDB "${CMAKE_GDB}"
CACHE STRING "Path to GDB binary, if applicable" FORCE)
endif()
if(DEFINED OPENOCD)
set(ZEPHYR_RUNNER_CONFIG_OPENOCD "${OPENOCD}"
CACHE STRING "Path to openocd binary, if applicable" FORCE)
endif()
if(DEFINED OPENOCD_DEFAULT_PATH)
set(ZEPHYR_RUNNER_CONFIG_OPENOCD_SEARCH "${OPENOCD_DEFAULT_PATH}"
CACHE STRING "Path to add to openocd search path, if applicable" FORCE)
endif()
# Runner-specific command line arguments obtained from the board's
# build scripts, the application's scripts, etc.
foreach(runner ${RUNNERS})
string(MAKE_C_IDENTIFIER ${runner} runner_id)
# E.g. args = BOARD_RUNNER_ARGS_openocd, BOARD_RUNNER_ARGS_dfu_util, etc.

View file

@ -13,6 +13,7 @@ from textwrap import dedent
from .. import cmake
from .. import log
from ..runner import get_runner_cls
from ..runner.core import RunnerConfig
from . import CommandContextError
@ -22,24 +23,56 @@ def add_parser_common(parser_adder, command):
formatter_class=argparse.RawDescriptionHelpFormatter,
description=command.description)
parser.add_argument('-d', '--build-dir',
help='''Build directory to obtain runner information
from; default is the current working directory.''')
parser.add_argument('-c', '--cmake-cache', default=cmake.DEFAULT_CACHE,
help='''Path to CMake cache file containing runner
configuration (this is generated by the Zephyr
build system when compiling binaries);
default: {}.
group = parser.add_argument_group(title='General Options')
group.add_argument('-d', '--build-dir',
help='''Build directory to obtain runner information
from; default is the current working directory.''')
group.add_argument('-c', '--cmake-cache', default=cmake.DEFAULT_CACHE,
help='''Path to CMake cache file containing runner
configuration (this is generated by the Zephyr
build system when compiling binaries);
default: {}.
If this is a relative path, it is assumed relative to
the build directory. An absolute path can also be
given instead.'''.format(cmake.DEFAULT_CACHE))
parser.add_argument('-r', '--runner',
help='''If given, overrides any cached {}
runner.'''.format(command.name))
parser.add_argument('--skip-rebuild', action='store_true',
help='''If given, do not rebuild the application
before running {} commands.'''.format(command.name))
If this is a relative path, it is assumed relative to
the build directory. An absolute path can also be
given instead.'''.format(cmake.DEFAULT_CACHE))
group.add_argument('-r', '--runner',
help='''If given, overrides any cached {}
runner.'''.format(command.name))
group.add_argument('--skip-rebuild', action='store_true',
help='''If given, do not rebuild the application
before running {} commands.'''.format(command.name))
group = parser.add_argument_group(
title='Configuration overrides',
description=dedent('''\
These values usually come from the Zephyr build system itself
as stored in the CMake cache; providing these options
overrides those settings.'''))
# Important:
#
# 1. The destination variables of these options must match
# the RunnerConfig slots.
# 2. The default values for all of these must be None.
#
# This is how we detect if the user provided them or not when
# overriding values from the cached configuration.
group.add_argument('--board-dir',
help='Zephyr board directory')
group.add_argument('--kernel-elf',
help='Path to kernel binary in .elf format')
group.add_argument('--kernel-hex',
help='Path to kernel binary in .hex format')
group.add_argument('--kernel-bin',
help='Path to kernel binary in .bin format')
group.add_argument('--gdb',
help='Path to GDB, if applicable')
group.add_argument('--openocd',
help='Path to OpenOCD, if applicable')
group.add_argument(
'--openocd-search',
help='Path to add to OpenOCD search path, if applicable')
return parser
@ -57,6 +90,30 @@ def desc_common(command_name):
'''.format(**{'command': command_name}))
def cached_runner_config(cache):
'''Parse the RunnerConfig from a CMake Cache.'''
board_dir = cache['ZEPHYR_RUNNER_CONFIG_BOARD_DIR']
kernel_elf = cache['ZEPHYR_RUNNER_CONFIG_KERNEL_ELF']
kernel_hex = cache['ZEPHYR_RUNNER_CONFIG_KERNEL_HEX']
kernel_bin = cache['ZEPHYR_RUNNER_CONFIG_KERNEL_BIN']
gdb = cache.get('ZEPHYR_RUNNER_CONFIG_GDB')
openocd = cache.get('ZEPHYR_RUNNER_CONFIG_OPENOCD')
openocd_search = cache.get('ZEPHYR_RUNNER_CONFIG_OPENOCD_SEARCH')
return RunnerConfig(board_dir, kernel_elf, kernel_hex, kernel_bin,
gdb=gdb, openocd=openocd,
openocd_search=openocd_search)
def _override_config_from_namespace(cfg, namespace):
'''Override a RunnerConfig's contents with command-line values.'''
for var in cfg.__slots__:
if var in namespace:
val = getattr(namespace, var)
if val is not None:
setattr(cfg, var, val)
def do_run_common(command, args, runner_args, cached_runner_var):
command_name = command.name
build_dir = args.build_dir or getcwd()
@ -79,6 +136,12 @@ def do_run_common(command, args, runner_args, cached_runner_var):
# places.
chdir(build_dir)
# Runner creation, phase 1.
#
# Get the default runner name from the cache, allowing a command
# line override. Get the ZephyrBinaryRunner class by name, and
# make sure it supports the command.
# TODO: build this by joining with build_dir once the above chdir
# goes away.
cache_file = args.cmake_cache
@ -104,22 +167,38 @@ def do_run_common(command, args, runner_args, cached_runner_var):
log.die('Runner {} does not support command {}'.format(
runner, command_name))
cached_common_args = cache.get_list('ZEPHYR_RUNNER_ARGS_COMMON')
# Runner creation, phase 2.
#
# At this point, the common options above are already parsed in
# 'args', and unrecognized arguments are in 'runner_args'.
#
# - Pull the RunnerConfig out of the cache
# - Override cached values with applicable command-line options
cfg = cached_runner_config(cache)
_override_config_from_namespace(cfg, args)
# Runner creation, phase 3.
#
# - Pull out cached runner arguments, and append command-line
# values (which should override the cache)
# - Construct a runner-specific argument parser to handle cached
# values plus overrides given in runner_args
# - Parse arguments and create runner instance from final
# RunnerConfig and parsed arguments.
cached_runner_args = cache.get_list(
'ZEPHYR_RUNNER_ARGS_{}'.format(cmake.make_c_identifier(runner)))
# Construct the final command line arguments, create a
# runner-specific parser to handle them, and run the command.
assert isinstance(runner_args, list), runner_args
final_runner_args = cached_common_args + cached_runner_args + runner_args
# Having the runners themselves be the place where their argument
# parsing is handled is hackish; it's an artifact of the time
# before the runner package was part of west.
#
# TODO: refactor runner argument parsing higher up into west.
# If the user passed -- to force the parent argument parser to stop
# parsing, it will show up here, and needs to be filtered out.
runner_args = [arg for arg in runner_args if arg != '--']
final_runner_args = cached_runner_args + runner_args
parser = argparse.ArgumentParser(prog=runner)
runner_cls.add_parser(parser)
parsed_args = parser.parse_args(args=final_runner_args)
parsed_args.verbose = args.verbose
runner = runner_cls.create_from_args(parsed_args)
parsed_args, unknown = parser.parse_known_args(args=final_runner_args)
if unknown:
raise CommandContextError('Runner', runner,
'received unknown arguments', unknown)
runner = runner_cls.create(cfg, parsed_args)
runner.run(command_name)

View file

@ -24,19 +24,16 @@ class EmStarterKitBinaryRunner(ZephyrBinaryRunner):
# client to execute the application.
#
def __init__(self, board_dir, elf, gdb,
openocd='openocd', search=None,
def __init__(self, cfg,
tui=False, tcl_port=DEFAULT_ARC_TCL_PORT,
telnet_port=DEFAULT_ARC_TELNET_PORT,
gdb_port=DEFAULT_ARC_GDB_PORT, debug=False):
super(EmStarterKitBinaryRunner, self).__init__(debug=debug)
self.board_dir = board_dir
self.elf = elf
self.gdb_cmd = [gdb] + (['-tui'] if tui else [])
gdb_port=DEFAULT_ARC_GDB_PORT):
super(EmStarterKitBinaryRunner, self).__init__(cfg)
self.gdb_cmd = [cfg.gdb] + (['-tui'] if tui else [])
search_args = []
if search is not None:
search_args = ['-s', search]
self.openocd_cmd = [openocd] + search_args
if cfg.openocd_search is not None:
search_args = ['-s', cfg.openocd_search]
self.openocd_cmd = [cfg.openocd or 'openocd'] + search_args
self.tcl_port = tcl_port
self.telnet_port = telnet_port
self.gdb_port = gdb_port
@ -57,18 +54,17 @@ class EmStarterKitBinaryRunner(ZephyrBinaryRunner):
help='openocd gdb port, defaults to 3333')
@classmethod
def create_from_args(cls, args):
if args.gdb is None:
def create(cls, cfg, args):
if cfg.gdb is None:
raise ValueError('--gdb not provided at command line')
return EmStarterKitBinaryRunner(
args.board_dir, args.kernel_elf, args.gdb,
openocd=args.openocd, search=args.openocd_search,
cfg,
tui=args.tui, tcl_port=args.tcl_port, telnet_port=args.telnet_port,
gdb_port=args.gdb_port, debug=args.verbose)
gdb_port=args.gdb_port)
def do_run(self, command, **kwargs):
kwargs['openocd-cfg'] = path.join(self.board_dir, 'support',
kwargs['openocd-cfg'] = path.join(self.cfg.board_dir, 'support',
'openocd.cfg')
if command in {'flash', 'debug'}:
@ -97,7 +93,7 @@ class EmStarterKitBinaryRunner(ZephyrBinaryRunner):
['-ex', 'target remote :{}'.format(self.gdb_port),
'-ex', 'load'] +
continue_arg +
[self.elf])
[self.cfg.kernel_elf])
self.run_server_and_client(server_cmd, gdb_cmd)

View file

@ -14,10 +14,8 @@ DEFAULT_BOSSAC_PORT = '/dev/ttyACM0'
class BossacBinaryRunner(ZephyrBinaryRunner):
'''Runner front-end for bossac.'''
def __init__(self, bin_name, bossac='bossac',
port=DEFAULT_BOSSAC_PORT, debug=False):
super(BossacBinaryRunner, self).__init__(debug=debug)
self.bin_name = bin_name
def __init__(self, cfg, bossac='bossac', port=DEFAULT_BOSSAC_PORT):
super(BossacBinaryRunner, self).__init__(cfg)
self.bossac = bossac
self.port = port
@ -37,9 +35,9 @@ class BossacBinaryRunner(ZephyrBinaryRunner):
help='serial port to use, default is /dev/ttyACM0')
@classmethod
def create_from_args(command, args):
return BossacBinaryRunner(args.kernel_bin, bossac=args.bossac,
port=args.bossac_port, debug=args.verbose)
def create(cls, cfg, args):
return BossacBinaryRunner(cfg, bossac=args.bossac,
port=args.bossac_port)
def do_run(self, command, **kwargs):
if platform.system() != 'Linux':
@ -50,7 +48,7 @@ class BossacBinaryRunner(ZephyrBinaryRunner):
'ospeed', '1200', 'cs8', '-cstopb', 'ignpar', 'eol', '255',
'eof', '255']
cmd_flash = [self.bossac, '-p', self.port, '-R', '-e', '-w', '-v',
'-b', self.bin_name]
'-b', self.cfg.kernel_bin]
self.check_call(cmd_stty)
self.check_call(cmd_flash)

View file

@ -181,6 +181,48 @@ class RunnerCaps:
self.commands, self.flash_addr)
class RunnerConfig:
'''Runner execution-time configuration.
This is a common object shared by all runners. Individual runners
can register specific configuration options using their
do_add_parser() hooks.
This class's __slots__ contains exactly the configuration variables.
'''
__slots__ = ['board_dir', 'kernel_elf', 'kernel_hex', 'kernel_bin',
'gdb', 'openocd', 'openocd_search']
# TODO: revisit whether we can get rid of some of these. Having
# tool-specific configuration options here is a layering
# violation, but it's very convenient to have a single place to
# store the locations of tools (like gdb and openocd) that are
# needed by multiple ZephyrBinaryRunner subclasses.
def __init__(self, board_dir, kernel_elf, kernel_hex, kernel_bin,
gdb=None, openocd=None, openocd_search=None):
self.board_dir = board_dir
'''Zephyr board directory'''
self.kernel_elf = kernel_elf
'''Path to kernel binary in .elf format'''
self.kernel_hex = kernel_hex
'''Path to kernel binary in .hex format'''
self.kernel_bin = kernel_bin
'''Path to kernel binary in .bin format'''
self.gdb = gdb
''''Path to GDB compatible with the target, may be None.'''
self.openocd = openocd
'''Path to OpenOCD to use for this target, may be None.'''
self.openocd_search = openocd_search
'''directory to add to OpenOCD search path, may be None.'''
_YN_CHOICES = ['Y', 'y', 'N', 'n', 'yes', 'no', 'YES', 'NO']
@ -246,7 +288,7 @@ class ZephyrBinaryRunner(abc.ABC):
define their own argparse-based interface through the common
add_parser() (and runner-specific do_add_parser() it delegates
to), and provide a way to create instances of themselves from
parsed arguments via create_from_args().
a RunnerConfig and parsed runner-specific arguments via create().
Runners use a variety of target-specific tools and configuration
values, the user interface to which is abstracted by this
@ -254,8 +296,11 @@ class ZephyrBinaryRunner(abc.ABC):
execute one of these commands in its constructor. The actual
command execution is handled in the run() method.'''
def __init__(self, debug=False):
self.debug = debug
def __init__(self, cfg):
'''Initialize core runner state.
`cfg` is a RunnerConfig instance.'''
self.cfg = cfg
@staticmethod
def get_runners():
@ -289,42 +334,19 @@ class ZephyrBinaryRunner(abc.ABC):
argparse module. For more details, refer to the documentation
for argparse.ArgumentParser.add_subparsers().
The standard (required) arguments are:
The lone common optional argument is:
* --board-dir
* --kernel-elf, --kernel-hex, --kernel-bin
The standard optional arguments are:
* --gdb
* --openocd, --openocd-search
* --dt-flash (if the runner capabilities includes flash_addr)
Runner-specific options are added through the do_add_parser()
hook.'''
# Required options.
parser.add_argument('--board-dir', required=True,
help='Zephyr board directory')
parser.add_argument('--kernel-elf', required=True,
help='path to kernel binary in .elf format')
parser.add_argument('--kernel-hex', required=True,
help='path to kernel binary in .hex format')
parser.add_argument('--kernel-bin', required=True,
help='path to kernel binary in .bin format')
# Optional options.
# Common options that depend on runner capabilities.
if cls.capabilities().flash_addr:
parser.add_argument('--dt-flash', default='n', choices=_YN_CHOICES,
action=_DTFlashAction,
help='''If 'yes', use configuration
generated by device tree (DT) to compute flash
help='''If 'yes', use configuration generated
by device tree (DT) to compute flash
addresses.''')
parser.add_argument('--gdb', default=None,
help='GDB compatible with the target')
parser.add_argument('--openocd', default='openocd',
help='OpenOCD to use')
parser.add_argument('--openocd-search', default=None,
help='directory to add to OpenOCD search path')
# Runner-specific options.
cls.do_add_parser(parser)
@ -336,11 +358,12 @@ class ZephyrBinaryRunner(abc.ABC):
@classmethod
@abc.abstractmethod
def create_from_args(cls, args):
def create(cls, cfg, args):
'''Create an instance from command-line arguments.
These will have been parsed from the command line according to
the specification defined by add_parser().'''
- `cfg`: RunnerConfig instance (pass to superclass __init__)
- `args`: runner-specific argument namespace parsed from
execution environment, as specified by `add_parser()`.'''
@classmethod
def get_flash_address(cls, args, build_conf, default=0x0):

View file

@ -19,9 +19,9 @@ DfuSeConfig = namedtuple('DfuSeConfig', ['address', 'options'])
class DfuUtilBinaryRunner(ZephyrBinaryRunner):
'''Runner front-end for dfu-util.'''
def __init__(self, pid, alt, img, exe='dfu-util',
dfuse_config=None, debug=False):
super(DfuUtilBinaryRunner, self).__init__(debug=debug)
def __init__(self, cfg, pid, alt, img, exe='dfu-util',
dfuse_config=None):
super(DfuUtilBinaryRunner, self).__init__(cfg)
self.alt = alt
self.img = img
self.cmd = [exe, '-d,{}'.format(pid)]
@ -67,9 +67,9 @@ class DfuUtilBinaryRunner(ZephyrBinaryRunner):
help='dfu-util executable; defaults to "dfu-util"')
@classmethod
def create_from_args(cls, args):
def create(cls, cfg, args):
if args.img is None:
args.img = args.kernel_bin
args.img = cfg.kernel_bin
if args.dfuse:
args.dt_flash = True # --dfuse implies --dt-flash.
@ -79,9 +79,8 @@ class DfuUtilBinaryRunner(ZephyrBinaryRunner):
else:
dcfg = None
return DfuUtilBinaryRunner(args.pid, args.alt, args.img,
exe=args.dfu_util, dfuse_config=dcfg,
debug=args.verbose)
return DfuUtilBinaryRunner(cfg, args.pid, args.alt, args.img,
exe=args.dfu_util, dfuse_config=dcfg)
def find_device(self):
cmd = list(self.cmd) + ['-l']

View file

@ -13,11 +13,10 @@ from .core import ZephyrBinaryRunner, RunnerCaps
class Esp32BinaryRunner(ZephyrBinaryRunner):
'''Runner front-end for espidf.'''
def __init__(self, elf, device, baud=921600, flash_size='detect',
flash_freq='40m', flash_mode='dio', espidf='espidf',
debug=False):
super(Esp32BinaryRunner, self).__init__(debug=debug)
self.elf = elf
def __init__(self, cfg, device, baud=921600, flash_size='detect',
flash_freq='40m', flash_mode='dio', espidf='espidf'):
super(Esp32BinaryRunner, self).__init__(cfg)
self.elf = cfg.kernel_elf
self.device = device
self.baud = baud
self.flash_size = flash_size
@ -56,7 +55,7 @@ class Esp32BinaryRunner(ZephyrBinaryRunner):
it in [ESP_IDF_PATH]/components/esptool_py/esptool/esptool.py''')
@classmethod
def create_from_args(command, args):
def create(cls, cfg, args):
if args.esp_tool:
espidf = args.esp_tool
else:
@ -64,10 +63,9 @@ class Esp32BinaryRunner(ZephyrBinaryRunner):
'esptool', 'esptool.py')
return Esp32BinaryRunner(
args.kernel_elf, args.esp_device, baud=args.esp_baud_rate,
cfg, args.esp_device, baud=args.esp_baud_rate,
flash_size=args.esp_flash_size, flash_freq=args.esp_flash_freq,
flash_mode=args.esp_flash_mode, espidf=espidf,
debug=args.verbose)
flash_mode=args.esp_flash_mode, espidf=espidf)
def do_run(self, command, **kwargs):
bin_name = path.splitext(self.elf)[0] + path.extsep + 'bin'

View file

@ -17,19 +17,17 @@ DEFAULT_XT_GDB_PORT = 20000
class IntelS1000BinaryRunner(ZephyrBinaryRunner):
'''Runner front-end for Intel_s1000.'''
def __init__(self,
board_dir, xt_ocd_dir,
def __init__(self, cfg, xt_ocd_dir,
ocd_topology, ocd_jtag_instr, gdb_flash_file,
elf_name, gdb,
gdb_port=DEFAULT_XT_GDB_PORT, debug=False):
super(IntelS1000BinaryRunner, self).__init__(debug=debug)
self.board_dir = board_dir
gdb_port=DEFAULT_XT_GDB_PORT):
super(IntelS1000BinaryRunner, self).__init__(cfg)
self.board_dir = cfg.board_dir
self.elf_name = cfg.kernel_elf
self.gdb_cmd = cfg.gdb
self.xt_ocd_dir = xt_ocd_dir
self.ocd_topology = ocd_topology
self.ocd_jtag_instr = ocd_jtag_instr
self.gdb_flash_file = gdb_flash_file
self.elf_name = elf_name
self.gdb_cmd = gdb
self.gdb_port = gdb_port
@classmethod
@ -38,12 +36,7 @@ class IntelS1000BinaryRunner(ZephyrBinaryRunner):
@classmethod
def do_add_parser(cls, parser):
# Required
# Optional
parser.add_argument(
'--gdb-port', default=DEFAULT_XT_GDB_PORT,
help='xt-gdb port, defaults to 20000')
parser.add_argument(
'--xt-ocd-dir', default='/opt/Tensilica/xocd-12.0.4/xt-ocd',
help='ocd-dir, defaults to /opt/Tensilica/xocd-12.0.4/xt-ocd')
@ -56,14 +49,16 @@ class IntelS1000BinaryRunner(ZephyrBinaryRunner):
parser.add_argument(
'--gdb-flash-file', default='load_elf.txt',
help='gdb-flash-file, defaults to load_elf.txt')
parser.add_argument(
'--gdb-port', default=DEFAULT_XT_GDB_PORT,
help='xt-gdb port, defaults to 20000')
@classmethod
def create_from_args(command, args):
def create(cls, cfg, args):
return IntelS1000BinaryRunner(
args.board_dir, args.xt_ocd_dir,
cfg, args.xt_ocd_dir,
args.ocd_topology, args.ocd_jtag_instr, args.gdb_flash_file,
args.kernel_elf, args.gdb,
gdb_port=args.gdb_port, debug=args.verbose)
gdb_port=args.gdb_port)
def do_run(self, command, **kwargs):
kwargs['ocd-topology'] = path.join(self.board_dir, 'support',

View file

@ -16,23 +16,23 @@ DEFAULT_JLINK_GDB_PORT = 2331
class JLinkBinaryRunner(ZephyrBinaryRunner):
'''Runner front-end for the J-Link GDB server.'''
def __init__(self, device,
commander='JLinkExe', bin_name=None,
def __init__(self, cfg, device,
commander='JLinkExe',
flash_addr=0x0, erase=True,
gdbserver='JLinkGDBServer', iface='swd', speed='auto',
elf_name=None, gdb=None, gdb_port=DEFAULT_JLINK_GDB_PORT,
tui=False, debug=False):
super(JLinkBinaryRunner, self).__init__(debug=debug)
iface='swd', speed='auto',
gdbserver='JLinkGDBServer', gdb_port=DEFAULT_JLINK_GDB_PORT,
tui=False):
super(JLinkBinaryRunner, self).__init__(cfg)
self.bin_name = cfg.kernel_bin
self.elf_name = cfg.kernel_elf
self.gdb_cmd = [cfg.gdb] if cfg.gdb else None
self.device = device
self.commander = commander
self.bin_name = bin_name
self.flash_addr = flash_addr
self.erase = erase
self.gdbserver_cmd = [gdbserver]
self.iface = iface
self.speed = speed
self.elf_name = elf_name
self.gdb_cmd = [gdb] if gdb is not None else None
self.gdb_port = gdb_port
self.tui_arg = ['-tui'] if tui else []
@ -67,17 +67,16 @@ class JLinkBinaryRunner(ZephyrBinaryRunner):
help='if given, mass erase flash before loading')
@classmethod
def create_from_args(cls, args):
def create(cls, cfg, args):
build_conf = BuildConfiguration(os.getcwd())
flash_addr = cls.get_flash_address(args, build_conf)
return JLinkBinaryRunner(args.device, gdbserver=args.gdbserver,
return JLinkBinaryRunner(cfg, args.device,
commander=args.commander,
bin_name=args.kernel_bin,
flash_addr=flash_addr, erase=args.erase,
iface=args.iface, speed=args.speed,
elf_name=args.kernel_elf,
gdb=args.gdb, gdb_port=args.gdb_port,
tui=args.tui, debug=args.verbose)
gdbserver=args.gdbserver,
gdb_port=args.gdb_port,
tui=args.tui)
def print_gdbserver_message(self):
log.inf('J-Link GDB server running on port {}'.format(self.gdb_port))

View file

@ -17,14 +17,13 @@ class Nios2BinaryRunner(ZephyrBinaryRunner):
# over the JTAG and the CPU directly boots from __start. CONFIG_XIP
# and CONFIG_INCLUDE_RESET_VECTOR must be disabled."
def __init__(self, hex_name=None, elf_name=None, cpu_sof=None,
quartus_py=None, gdb=None, tui=False, debug=False):
super(Nios2BinaryRunner, self).__init__(debug=debug)
self.hex_name = hex_name
self.elf_name = elf_name
def __init__(self, cfg, quartus_py=None, cpu_sof=None, tui=False):
super(Nios2BinaryRunner, self).__init__(cfg)
self.hex_name = cfg.kernel_hex
self.elf_name = cfg.kernel_elf
self.cpu_sof = cpu_sof
self.quartus_py = quartus_py
self.gdb_cmd = [gdb] if gdb is not None else None
self.gdb_cmd = [cfg.gdbgdb] if cfg.gdb else None
self.tui_arg = ['-tui'] if tui else []
@classmethod
@ -41,13 +40,10 @@ class Nios2BinaryRunner(ZephyrBinaryRunner):
help='if given, GDB uses -tui')
@classmethod
def create_from_args(command, args):
return Nios2BinaryRunner(hex_name=args.kernel_hex,
elf_name=args.kernel_elf,
def create(cls, cfg, args):
return Nios2BinaryRunner(quartus_py=args.quartus_flash,
cpu_sof=args.cpu_sof,
quartus_py=args.quartus_flash,
gdb=args.gdb, tui=args.tui,
debug=args.verbose)
tui=args.tui)
def do_run(self, command, **kwargs):
if command == 'flash':

View file

@ -13,9 +13,9 @@ from .core import ZephyrBinaryRunner, RunnerCaps
class NrfJprogBinaryRunner(ZephyrBinaryRunner):
'''Runner front-end for nrfjprog.'''
def __init__(self, hex_, family, softreset, debug=False):
super(NrfJprogBinaryRunner, self).__init__(debug=debug)
self.hex_ = hex_
def __init__(self, cfg, family, softreset):
super(NrfJprogBinaryRunner, self).__init__(cfg)
self.hex_ = cfg.kernel_hex
self.family = family
self.softreset = softreset
@ -37,9 +37,8 @@ class NrfJprogBinaryRunner(ZephyrBinaryRunner):
help='use reset instead of pinreset')
@classmethod
def create_from_args(cls, args):
return NrfJprogBinaryRunner(args.kernel_hex, args.nrf_family,
args.softreset, debug=args.verbose)
def create(cls, cfg, args):
return NrfJprogBinaryRunner(cfg, args.nrf_family, args.softreset)
def get_board_snr_from_user(self):
snrs = self.check_output(['nrfjprog', '--ids'])

View file

@ -16,22 +16,21 @@ DEFAULT_OPENOCD_GDB_PORT = 3333
class OpenOcdBinaryRunner(ZephyrBinaryRunner):
'''Runner front-end for openocd.'''
def __init__(self, openocd_config,
openocd='openocd', search=None,
elf_name=None,
def __init__(self, cfg,
pre_cmd=None, load_cmd=None, verify_cmd=None, post_cmd=None,
tui=None,
tcl_port=DEFAULT_OPENOCD_TCL_PORT,
telnet_port=DEFAULT_OPENOCD_TELNET_PORT,
gdb_port=DEFAULT_OPENOCD_GDB_PORT,
gdb=None, tui=None, debug=False):
super(OpenOcdBinaryRunner, self).__init__(debug=debug)
self.openocd_config = openocd_config
gdb_port=DEFAULT_OPENOCD_GDB_PORT):
super(OpenOcdBinaryRunner, self).__init__(cfg)
self.openocd_config = path.join(cfg.board_dir, 'support',
'openocd.cfg')
search_args = []
if search is not None:
search_args = ['-s', search]
self.openocd_cmd = [openocd] + search_args
self.elf_name = elf_name
if cfg.openocd_search is not None:
search_args = ['-s', cfg.openocd_search]
self.openocd_cmd = [cfg.openocd] + search_args
self.elf_name = cfg.kernel_elf
self.load_cmd = load_cmd
self.verify_cmd = verify_cmd
self.pre_cmd = pre_cmd
@ -39,7 +38,7 @@ class OpenOcdBinaryRunner(ZephyrBinaryRunner):
self.tcl_port = tcl_port
self.telnet_port = telnet_port
self.gdb_port = gdb_port
self.gdb_cmd = [gdb] if gdb is not None else None
self.gdb_cmd = [cfg.gdb] if cfg.gdb else None
self.tui_arg = ['-tui'] if tui else []
@classmethod
@ -71,19 +70,14 @@ class OpenOcdBinaryRunner(ZephyrBinaryRunner):
help='openocd gdb port, defaults to 3333')
@classmethod
def create_from_args(cls, args):
openocd_config = path.join(args.board_dir, 'support', 'openocd.cfg')
def create(cls, cfg, args):
return OpenOcdBinaryRunner(
openocd_config,
openocd=args.openocd, search=args.openocd_search,
elf_name=args.kernel_elf,
pre_cmd=args.cmd_pre_load,
load_cmd=args.cmd_load, verify_cmd=args.cmd_verify,
post_cmd=args.cmd_post_verify,
cfg,
pre_cmd=args.cmd_pre_load, load_cmd=args.cmd_load,
verify_cmd=args.cmd_verify, post_cmd=args.cmd_post_verify,
tui=args.tui,
tcl_port=args.tcl_port, telnet_port=args.telnet_port,
gdb_port=args.gdb_port, gdb=args.gdb, tui=args.tui,
debug=args.verbose)
gdb_port=args.gdb_port)
def do_run(self, command, **kwargs):
if command == 'flash':

View file

@ -15,24 +15,23 @@ DEFAULT_PYOCD_GDB_PORT = 3333
class PyOcdBinaryRunner(ZephyrBinaryRunner):
'''Runner front-end for pyOCD.'''
def __init__(self, target,
def __init__(self, cfg, target,
flashtool='pyocd-flashtool', flash_addr=0x0,
flashtool_opts=None,
gdb=None, gdbserver='pyocd-gdbserver',
gdbserver='pyocd-gdbserver',
gdb_port=DEFAULT_PYOCD_GDB_PORT, tui=False,
bin_name=None, elf_name=None,
board_id=None, daparg=None, debug=False):
super(PyOcdBinaryRunner, self).__init__(debug=debug)
board_id=None, daparg=None):
super(PyOcdBinaryRunner, self).__init__(cfg)
self.target_args = ['-t', target]
self.flashtool = flashtool
self.flash_addr_args = ['-a', hex(flash_addr)] if flash_addr else []
self.gdb_cmd = [gdb] if gdb is not None else None
self.gdb_cmd = [cfg.gdb] if cfg.gdb is not None else None
self.gdbserver = gdbserver
self.gdb_port = gdb_port
self.tui_args = ['-tui'] if tui else []
self.bin_name = bin_name
self.elf_name = elf_name
self.bin_name = cfg.kernel_bin
self.elf_name = cfg.kernel_elf
board_args = []
if board_id is not None:
@ -77,7 +76,7 @@ class PyOcdBinaryRunner(ZephyrBinaryRunner):
help='ID of board to flash, default is to prompt')
@classmethod
def create_from_args(cls, args):
def create(cls, cfg, args):
daparg = os.environ.get('PYOCD_DAPARG')
if daparg:
log.wrn('Setting PYOCD_DAPARG in the environment is',
@ -91,12 +90,10 @@ class PyOcdBinaryRunner(ZephyrBinaryRunner):
flash_addr = cls.get_flash_address(args, build_conf)
return PyOcdBinaryRunner(
args.target, flashtool=args.flashtool,
flashtool_opts=args.flashtool_opt,
flash_addr=flash_addr, gdb=args.gdb,
cfg, args.target, flashtool=args.flashtool,
flash_addr=flash_addr, flashtool_opts=args.flashtool_opt,
gdbserver=args.gdbserver, gdb_port=args.gdb_port, tui=args.tui,
bin_name=args.kernel_bin, elf_name=args.kernel_elf,
board_id=args.board_id, daparg=args.daparg, debug=args.verbose)
board_id=args.board_id, daparg=args.daparg)
def port_args(self):
return ['-p', str(self.gdb_port)]

View file

@ -4,28 +4,31 @@
'''Runner stub for QEMU.'''
from .. import log
from .core import ZephyrBinaryRunner
from .core import ZephyrBinaryRunner, RunnerCaps
class QemuBinaryRunner(ZephyrBinaryRunner):
'''Place-holder for QEMU runner customizations.'''
def __init__(self, debug=False):
super(QemuBinaryRunner, self).__init__(debug=debug)
def __init__(self, cfg):
super(QemuBinaryRunner, self).__init__(cfg)
@classmethod
def name(cls):
return 'qemu'
@classmethod
def capabilities(cls):
# This is a stub.
return RunnerCaps(commands=set())
@classmethod
def do_add_parser(cls, parser):
pass # Nothing to do.
@classmethod
def create_from_args(command, args):
return QemuBinaryRunner(debug=args.verbose)
def create(cls, cfg, args):
return QemuBinaryRunner(cfg)
def do_run(self, command, **kwargs):
if command == 'debugserver':
log.inf('Detached GDB server')
pass

View file

@ -12,10 +12,8 @@ from .core import ZephyrBinaryRunner, RunnerCaps
class XtensaBinaryRunner(ZephyrBinaryRunner):
'''Runner front-end for xt-gdb.'''
def __init__(self, gdb, elf_name, debug=False):
super(XtensaBinaryRunner, self).__init__(debug=debug)
self.gdb_cmd = [gdb]
self.elf_name = elf_name
def __init__(self, cfg):
super(XtensaBinaryRunner, self).__init__(cfg)
@classmethod
def name(cls):
@ -31,11 +29,12 @@ class XtensaBinaryRunner(ZephyrBinaryRunner):
help='path to XTensa tools')
@classmethod
def create_from_args(command, args):
xt_gdb = path.join(args.xcc_tools, 'bin', 'xt-gdb')
return XtensaBinaryRunner(xt_gdb, args.kernel_elf, args.verbose)
def create(cls, cfg, args):
# Override any GDB with the one provided by the XTensa tools.
cfg.gdb = path.join(args.xcc_tools, 'bin', 'xt-gdb')
return XtensaBinaryRunner(cfg)
def do_run(self, command, **kwargs):
gdb_cmd = (self.gdb_cmd + [self.elf_name])
gdb_cmd = [self.cfg.gdb, self.cfg.kernel_elf]
self.check_call(gdb_cmd)