west: runners: add file argument
adds --file argument to west flash/debug as described in #52262. Signed-off-by: Gerhard Jörges <joerges@metratec.com>
This commit is contained in:
parent
12f2258305
commit
87a751c266
6 changed files with 142 additions and 36 deletions
|
@ -802,6 +802,8 @@ __comp_west_runner_cmd()
|
|||
"
|
||||
|
||||
local file_opts="
|
||||
--file -f
|
||||
--file-type -t
|
||||
--elf-file
|
||||
--hex-file
|
||||
--bin-file
|
||||
|
|
|
@ -261,6 +261,8 @@ _west_sign() {
|
|||
typeset -a -g _west_runner_opts=(
|
||||
'(-H --context)'{-H,--context}'[print runner-specific options]'
|
||||
'--board-dir[board directory]:board dir:_directories'
|
||||
'(-f --file)'{-f,--file}'[path to binary]:path to binary:_files'
|
||||
'(-t --file-type)'{-t,--file-type}'[type of binary]:type of binary:(hex bin elf)'
|
||||
'--elf-file[path to zephyr.elf]:path to zephyr.elf:_files'
|
||||
'--hex-file[path to zephyr.hex]:path to zephyr.hex:_files'
|
||||
'--bin-file[path to zephyr.bin]:path to zephyr.bin:_files'
|
||||
|
|
|
@ -20,6 +20,7 @@ from build_helpers import find_build_dir, is_zephyr_build, load_domains, \
|
|||
FIND_BUILD_DIR_DESCRIPTION
|
||||
from west.commands import CommandError
|
||||
from west.configuration import config
|
||||
from runners.core import FileType
|
||||
import yaml
|
||||
|
||||
from zephyr_ext_common import ZEPHYR_SCRIPTS
|
||||
|
@ -132,11 +133,6 @@ def add_parser_common(command, parser_adder=None, parser=None):
|
|||
# Options used to override RunnerConfig values in runners.yaml.
|
||||
# TODO: is this actually useful?
|
||||
group.add_argument('--board-dir', metavar='DIR', help='board directory')
|
||||
# FIXME: we should just have a single --file argument. The variation
|
||||
# between runners is confusing people.
|
||||
group.add_argument('--elf-file', metavar='FILE', help='path to zephyr.elf')
|
||||
group.add_argument('--hex-file', metavar='FILE', help='path to zephyr.hex')
|
||||
group.add_argument('--bin-file', metavar='FILE', help='path to zephyr.bin')
|
||||
# FIXME: these are runner-specific and should be moved to where --context
|
||||
# can find them instead.
|
||||
group.add_argument('--gdb', help='path to GDB')
|
||||
|
@ -385,11 +381,40 @@ def get_runner_config(build_dir, yaml_path, runners_yaml, args=None):
|
|||
def config(attr, default=None):
|
||||
return getattr(args, attr, None) or yaml_config.get(attr, default)
|
||||
|
||||
def filetype(attr):
|
||||
ftype = str(getattr(args, attr, None)).lower()
|
||||
if ftype == "hex":
|
||||
return FileType.HEX
|
||||
elif ftype == "bin":
|
||||
return FileType.BIN
|
||||
elif ftype == "elf":
|
||||
return FileType.ELF
|
||||
elif getattr(args, attr, None) is not None:
|
||||
err = 'unknown --file-type ({}). Please use hex, bin or elf'
|
||||
raise ValueError(err.format(ftype))
|
||||
|
||||
# file-type not provided, try to get from filename
|
||||
file = getattr(args, "file", None)
|
||||
if file is not None:
|
||||
ext = Path(file).suffix
|
||||
if ext == ".hex":
|
||||
return FileType.HEX
|
||||
if ext == ".bin":
|
||||
return FileType.BIN
|
||||
if ext == ".elf":
|
||||
return FileType.ELF
|
||||
|
||||
# we couldn't get the file-type, set to
|
||||
# OTHER and let the runner deal with it
|
||||
return FileType.OTHER
|
||||
|
||||
return RunnerConfig(build_dir,
|
||||
yaml_config['board_dir'],
|
||||
output_file('elf'),
|
||||
output_file('hex'),
|
||||
output_file('bin'),
|
||||
config('file'),
|
||||
filetype('file_type'),
|
||||
config('gdb'),
|
||||
config('openocd'),
|
||||
config('openocd_search', []))
|
||||
|
|
|
@ -22,6 +22,8 @@ import shutil
|
|||
import signal
|
||||
import subprocess
|
||||
import re
|
||||
from functools import partial
|
||||
from enum import Enum
|
||||
from typing import Dict, List, NamedTuple, NoReturn, Optional, Set, Type, \
|
||||
Union
|
||||
|
||||
|
@ -237,19 +239,22 @@ class RunnerCaps:
|
|||
dev_id: bool = False,
|
||||
flash_addr: bool = False,
|
||||
erase: bool = False,
|
||||
tool_opt: bool = False):
|
||||
tool_opt: bool = False,
|
||||
file: bool = False):
|
||||
self.commands = commands
|
||||
self.dev_id = dev_id
|
||||
self.flash_addr = bool(flash_addr)
|
||||
self.erase = bool(erase)
|
||||
self.tool_opt = bool(tool_opt)
|
||||
self.file = bool(file)
|
||||
|
||||
def __str__(self):
|
||||
return (f'RunnerCaps(commands={self.commands}, '
|
||||
f'dev_id={self.dev_id}, '
|
||||
f'flash_addr={self.flash_addr}, '
|
||||
f'erase={self.erase}, '
|
||||
f'tool_opt={self.tool_opt}'
|
||||
f'tool_opt={self.tool_opt}, '
|
||||
f'file={self.file}'
|
||||
')')
|
||||
|
||||
|
||||
|
@ -261,6 +266,13 @@ def _missing_cap(cls: Type['ZephyrBinaryRunner'], option: str) -> NoReturn:
|
|||
raise ValueError(f"{cls.name()} doesn't support {option} option")
|
||||
|
||||
|
||||
class FileType(Enum):
|
||||
OTHER = 0
|
||||
HEX = 1
|
||||
BIN = 2
|
||||
ELF = 3
|
||||
|
||||
|
||||
class RunnerConfig(NamedTuple):
|
||||
'''Runner execution-time configuration.
|
||||
|
||||
|
@ -268,13 +280,15 @@ class RunnerConfig(NamedTuple):
|
|||
can register specific configuration options using their
|
||||
do_add_parser() hooks.
|
||||
'''
|
||||
build_dir: str # application build directory
|
||||
board_dir: str # board definition directory
|
||||
elf_file: Optional[str] # zephyr.elf path, or None
|
||||
hex_file: Optional[str] # zephyr.hex path, or None
|
||||
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
|
||||
build_dir: str # application build directory
|
||||
board_dir: str # board definition directory
|
||||
elf_file: Optional[str] # zephyr.elf path, or None
|
||||
hex_file: Optional[str] # zephyr.hex path, or None
|
||||
bin_file: Optional[str] # zephyr.bin path, or None
|
||||
file: Optional[str] # binary file path (provided by the user), or None
|
||||
file_type: Optional[FileType] = FileType.OTHER # binary file type
|
||||
gdb: Optional[str] = None # path to a usable gdb
|
||||
openocd: Optional[str] = None # path to a usable openocd
|
||||
openocd_search: List[str] = [] # add these paths to the openocd search path
|
||||
|
||||
|
||||
|
@ -298,12 +312,14 @@ class _ToggleAction(argparse.Action):
|
|||
class DeprecatedAction(argparse.Action):
|
||||
|
||||
def __call__(self, parser, namespace, values, option_string=None):
|
||||
_logger.warning(f'Argument {self.option_strings[0]} is deprecated, '
|
||||
f'use {self._replacement} instead.')
|
||||
_logger.warning(f'Argument {self.option_strings[0]} is deprecated' +
|
||||
(f' for your runner {self._cls.name()}' if self._cls is not None else '') +
|
||||
f', use {self._replacement} instead.')
|
||||
setattr(namespace, self.dest, values)
|
||||
|
||||
def depr_action(*args, replacement=None, **kwargs):
|
||||
def depr_action(*args, cls=None, replacement=None, **kwargs):
|
||||
action = DeprecatedAction(*args, **kwargs)
|
||||
setattr(action, '_cls', cls)
|
||||
setattr(action, '_replacement', replacement)
|
||||
return action
|
||||
|
||||
|
@ -465,6 +481,30 @@ class ZephyrBinaryRunner(abc.ABC):
|
|||
else:
|
||||
parser.add_argument('--dt-flash', help=argparse.SUPPRESS)
|
||||
|
||||
if caps.file:
|
||||
parser.add_argument('-f', '--file',
|
||||
dest='file',
|
||||
help="path to binary file")
|
||||
parser.add_argument('-t', '--file-type',
|
||||
dest='file_type',
|
||||
help="type of binary file")
|
||||
else:
|
||||
parser.add_argument('-f', '--file', help=argparse.SUPPRESS)
|
||||
parser.add_argument('-t', '--file-type', help=argparse.SUPPRESS)
|
||||
|
||||
parser.add_argument('--elf-file',
|
||||
metavar='FILE',
|
||||
action=(partial(depr_action, cls=cls, replacement='-f/--file') if caps.file else None),
|
||||
help='path to zephyr.elf' if not caps.file else 'Deprecated, use -f/--file instead.')
|
||||
parser.add_argument('--hex-file',
|
||||
metavar='FILE',
|
||||
action=(partial(depr_action, cls=cls, replacement='-f/--file') if caps.file else None),
|
||||
help='path to zephyr.hex' if not caps.file else 'Deprecated, use -f/--file instead.')
|
||||
parser.add_argument('--bin-file',
|
||||
metavar='FILE',
|
||||
action=(partial(depr_action, cls=cls, replacement='-f/--file') if caps.file else None),
|
||||
help='path to zephyr.bin' if not caps.file else 'Deprecated, use -f/--file instead.')
|
||||
|
||||
parser.add_argument('--erase', '--no-erase', nargs=0,
|
||||
action=_ToggleAction,
|
||||
help=("mass erase flash before loading, or don't"
|
||||
|
@ -500,6 +540,12 @@ class ZephyrBinaryRunner(abc.ABC):
|
|||
_missing_cap(cls, '--erase')
|
||||
if args.tool_opt and not caps.tool_opt:
|
||||
_missing_cap(cls, '--tool-opt')
|
||||
if args.file and not caps.file:
|
||||
_missing_cap(cls, '--file')
|
||||
if args.file_type and not args.file:
|
||||
raise ValueError("--file-type requires --file")
|
||||
if args.file_type and not caps.file:
|
||||
_missing_cap(cls, '--file-type')
|
||||
|
||||
ret = cls.do_create(cfg, args)
|
||||
if args.erase:
|
||||
|
|
|
@ -13,7 +13,7 @@ import subprocess
|
|||
import sys
|
||||
import tempfile
|
||||
|
||||
from runners.core import ZephyrBinaryRunner, RunnerCaps
|
||||
from runners.core import ZephyrBinaryRunner, RunnerCaps, FileType
|
||||
|
||||
try:
|
||||
import pylink
|
||||
|
@ -43,6 +43,8 @@ class JLinkBinaryRunner(ZephyrBinaryRunner):
|
|||
gdb_port=DEFAULT_JLINK_GDB_PORT,
|
||||
tui=False, tool_opt=[]):
|
||||
super().__init__(cfg)
|
||||
self.file = cfg.file
|
||||
self.file_type = cfg.file_type
|
||||
self.hex_name = cfg.hex_file
|
||||
self.bin_name = cfg.bin_file
|
||||
self.elf_name = cfg.elf_file
|
||||
|
@ -73,7 +75,7 @@ class JLinkBinaryRunner(ZephyrBinaryRunner):
|
|||
def capabilities(cls):
|
||||
return RunnerCaps(commands={'flash', 'debug', 'debugserver', 'attach'},
|
||||
dev_id=True, flash_addr=True, erase=True,
|
||||
tool_opt=True)
|
||||
tool_opt=True, file=True)
|
||||
|
||||
@classmethod
|
||||
def dev_id_help(cls) -> str:
|
||||
|
@ -246,11 +248,17 @@ class JLinkBinaryRunner(ZephyrBinaryRunner):
|
|||
else:
|
||||
if self.gdb_cmd is None:
|
||||
raise ValueError('Cannot debug; gdb is missing')
|
||||
if self.elf_name is None:
|
||||
if self.file is not None:
|
||||
if self.file_type != FileType.ELF:
|
||||
raise ValueError('Cannot debug; elf file required')
|
||||
elf_name = self.file
|
||||
elif self.elf_name is None:
|
||||
raise ValueError('Cannot debug; elf is missing')
|
||||
else:
|
||||
elf_name = self.elf_name
|
||||
client_cmd = (self.gdb_cmd +
|
||||
self.tui_arg +
|
||||
[self.elf_name] +
|
||||
[elf_name] +
|
||||
['-ex', 'target remote {}:{}'.format(self.gdb_host, self.gdb_port)])
|
||||
if command == 'debug':
|
||||
client_cmd += ['-ex', 'monitor halt',
|
||||
|
@ -276,20 +284,42 @@ class JLinkBinaryRunner(ZephyrBinaryRunner):
|
|||
if self.erase:
|
||||
lines.append('erase') # Erase all flash sectors
|
||||
|
||||
# Get the build artifact to flash, preferring .hex over .bin
|
||||
if self.hex_name is not None and os.path.isfile(self.hex_name):
|
||||
flash_file = self.hex_name
|
||||
flash_cmd = f'loadfile "{self.hex_name}"'
|
||||
elif self.bin_name is not None and os.path.isfile(self.bin_name):
|
||||
if self.dt_flash:
|
||||
flash_addr = self.flash_address_from_build_conf(self.build_conf)
|
||||
# Get the build artifact to flash
|
||||
if self.file is not None:
|
||||
# use file provided by the user
|
||||
if not os.path.isfile(self.file):
|
||||
err = 'Cannot flash; file ({}) not found'
|
||||
raise ValueError(err.format(self.file))
|
||||
|
||||
flash_file = self.file
|
||||
|
||||
if self.file_type == FileType.HEX:
|
||||
flash_cmd = f'loadfile "{self.file}"'
|
||||
elif self.file_type == FileType.BIN:
|
||||
if self.dt_flash:
|
||||
flash_addr = self.flash_address_from_build_conf(self.build_conf)
|
||||
else:
|
||||
flash_addr = 0
|
||||
flash_cmd = f'loadfile "{self.file}" 0x{flash_addr:x}'
|
||||
else:
|
||||
flash_addr = 0
|
||||
flash_file = self.bin_name
|
||||
flash_cmd = f'loadfile "{self.bin_name}" 0x{flash_addr:x}'
|
||||
err = 'Cannot flash; jlink runner only supports hex and bin files'
|
||||
raise ValueError(err)
|
||||
|
||||
else:
|
||||
err = 'Cannot flash; no hex ({}) or bin ({}) files found.'
|
||||
raise ValueError(err.format(self.hex_name, self.bin_name))
|
||||
# use hex or bin file provided by the buildsystem, preferring .hex over .bin
|
||||
if self.hex_name is not None and os.path.isfile(self.hex_name):
|
||||
flash_file = self.hex_name
|
||||
flash_cmd = f'loadfile "{self.hex_name}"'
|
||||
elif self.bin_name is not None and os.path.isfile(self.bin_name):
|
||||
if self.dt_flash:
|
||||
flash_addr = self.flash_address_from_build_conf(self.build_conf)
|
||||
else:
|
||||
flash_addr = 0
|
||||
flash_file = self.bin_name
|
||||
flash_cmd = f'loadfile "{self.bin_name}" 0x{flash_addr:x}'
|
||||
else:
|
||||
err = 'Cannot flash; no hex ({}) or bin ({}) files found.'
|
||||
raise ValueError(err.format(self.hex_name, self.bin_name))
|
||||
|
||||
# Flash the selected build artifact
|
||||
lines.append(flash_cmd)
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
import pytest
|
||||
|
||||
from runners.core import RunnerConfig
|
||||
from runners.core import RunnerConfig, FileType
|
||||
|
||||
RC_BUILD_DIR = '/test/build-dir'
|
||||
RC_BOARD_DIR = '/test/zephyr/boards/test-arch/test-board'
|
||||
|
@ -22,5 +22,6 @@ RC_OPENOCD_SEARCH = ['/test/openocd/search']
|
|||
def runner_config():
|
||||
'''Fixture which provides a runners.core.RunnerConfig.'''
|
||||
return RunnerConfig(RC_BUILD_DIR, RC_BOARD_DIR, RC_KERNEL_ELF,
|
||||
RC_KERNEL_HEX, RC_KERNEL_BIN, gdb=RC_GDB,
|
||||
openocd=RC_OPENOCD, openocd_search=RC_OPENOCD_SEARCH)
|
||||
RC_KERNEL_HEX, RC_KERNEL_BIN, None, FileType.OTHER,
|
||||
gdb=RC_GDB, openocd=RC_OPENOCD,
|
||||
openocd_search=RC_OPENOCD_SEARCH)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue