zephyr/scripts/west_commands/runners/pyocd.py
Marti Bolivar a2f203dd1a runners: restore obsolete synonyms for -i/--dev-id
This is a partial revert of commit
2cee5ff519
("scripts: west_commands: runners: remove deprecated options").

I remarked at the time that the removal of the older way of writing
things from the runners themselves seemed gratuitous since they are
easy to continue to support indefinitely and people may have been used
to the old way of doing things. It didn't seem worth the fight to push
for a revert at the time, though.

Since then I've run into real problems that their removal has caused
in the wild and I am convinced that this part of that patch was wrong.

Restore the original, undeprecated forms of these options, but make it
clear in the command line help that they're just obsolete alternative
spellings at this point.

Signed-off-by: Marti Bolivar <marti.bolivar@nordicsemi.no>
2023-02-02 09:47:17 -08:00

216 lines
7.7 KiB
Python

# Copyright (c) 2017 Linaro Limited.
#
# SPDX-License-Identifier: Apache-2.0
'''Runner for pyOCD .'''
import os
from os import path
from runners.core import ZephyrBinaryRunner, RunnerCaps, BuildConfiguration
DEFAULT_PYOCD_GDB_PORT = 3333
DEFAULT_PYOCD_TELNET_PORT = 4444
class PyOcdBinaryRunner(ZephyrBinaryRunner):
'''Runner front-end for pyOCD.'''
def __init__(self, cfg, target,
pyocd='pyocd',
dev_id=None, flash_addr=0x0, erase=False, flash_opts=None,
gdb_port=DEFAULT_PYOCD_GDB_PORT,
telnet_port=DEFAULT_PYOCD_TELNET_PORT, tui=False,
pyocd_config=None,
daparg=None, frequency=None, tool_opt=None):
super().__init__(cfg)
default = path.join(cfg.board_dir, 'support', 'pyocd.yaml')
if path.exists(default):
self.pyocd_config = default
else:
self.pyocd_config = None
self.target_args = ['-t', target]
self.pyocd = pyocd
self.flash_addr_args = ['-a', hex(flash_addr)] if flash_addr else []
self.erase = erase
self.gdb_cmd = [cfg.gdb] if cfg.gdb is not None else None
self.gdb_port = gdb_port
self.telnet_port = telnet_port
self.tui_args = ['-tui'] if tui else []
self.hex_name = cfg.hex_file
self.bin_name = cfg.bin_file
self.elf_name = cfg.elf_file
pyocd_config_args = []
if self.pyocd_config is not None:
pyocd_config_args = ['--config', self.pyocd_config]
self.pyocd_config_args = pyocd_config_args
board_args = []
if dev_id is not None:
board_args = ['-u', dev_id]
self.board_args = board_args
daparg_args = []
if daparg is not None:
daparg_args = ['-da', daparg]
self.daparg_args = daparg_args
frequency_args = []
if frequency is not None:
frequency_args = ['-f', frequency]
self.frequency_args = frequency_args
self.tool_opt_args = tool_opt or []
self.flash_extra = flash_opts if flash_opts else []
@classmethod
def name(cls):
return 'pyocd'
@classmethod
def capabilities(cls):
return RunnerCaps(commands={'flash', 'debug', 'debugserver', 'attach'},
dev_id=True, flash_addr=True, erase=True,
tool_opt=True)
@classmethod
def dev_id_help(cls) -> str:
return '''Device identifier. Use it to select the probe's unique ID
or substring thereof.'''
@classmethod
def do_add_parser(cls, parser):
parser.add_argument('--target', required=True,
help='target override')
parser.add_argument('--daparg',
help='Additional -da arguments to pyocd tool')
parser.add_argument('--pyocd', default='pyocd',
help='path to pyocd tool, default is pyocd')
parser.add_argument('--flash-opt', default=[], action='append',
help='''Additional options for pyocd flash,
e.g. --flash-opt="-e=chip" to chip erase''')
parser.add_argument('--frequency',
help='SWD clock frequency in Hz')
parser.add_argument('--gdb-port', default=DEFAULT_PYOCD_GDB_PORT,
help='pyocd gdb port, defaults to {}'.format(
DEFAULT_PYOCD_GDB_PORT))
parser.add_argument('--telnet-port', default=DEFAULT_PYOCD_TELNET_PORT,
help='pyocd telnet port, defaults to {}'.format(
DEFAULT_PYOCD_TELNET_PORT))
parser.add_argument('--tui', default=False, action='store_true',
help='if given, GDB uses -tui')
parser.add_argument('--board-id', dest='dev_id',
help='obsolete synonym for -i/--dev-id')
@classmethod
def tool_opt_help(cls) -> str:
return """Additional options for pyocd commander,
e.g. '--script=user.py'"""
@classmethod
def do_create(cls, cfg, args):
build_conf = BuildConfiguration(cfg.build_dir)
flash_addr = cls.get_flash_address(args, build_conf)
ret = PyOcdBinaryRunner(
cfg, args.target,
pyocd=args.pyocd,
flash_addr=flash_addr, erase=args.erase, flash_opts=args.flash_opt,
gdb_port=args.gdb_port, telnet_port=args.telnet_port, tui=args.tui,
dev_id=args.dev_id, daparg=args.daparg,
frequency=args.frequency,
tool_opt=args.tool_opt)
daparg = os.environ.get('PYOCD_DAPARG')
if not ret.daparg_args and daparg:
ret.logger.warning('PYOCD_DAPARG is deprecated; use --daparg')
ret.logger.debug('--daparg={} via PYOCD_DAPARG'.format(daparg))
ret.daparg_args = ['-da', daparg]
return ret
def port_args(self):
return ['-p', str(self.gdb_port), '-T', str(self.telnet_port)]
def do_run(self, command, **kwargs):
self.require(self.pyocd)
if command == 'flash':
self.flash(**kwargs)
else:
self.debug_debugserver(command, **kwargs)
def flash(self, **kwargs):
if self.hex_name is not None and os.path.isfile(self.hex_name):
fname = self.hex_name
elif self.bin_name is not None and os.path.isfile(self.bin_name):
self.logger.warning(
'hex file ({}) does not exist; falling back on .bin ({}). '.
format(self.hex_name, self.bin_name) +
'Consider enabling CONFIG_BUILD_OUTPUT_HEX.')
fname = self.bin_name
else:
raise ValueError(
'Cannot flash; no hex ({}) or bin ({}) files found. '.format(
self.hex_name, self.bin_name))
erase_method = 'chip' if self.erase else 'sector'
cmd = ([self.pyocd] +
['flash'] +
self.pyocd_config_args +
['-e', erase_method] +
self.flash_addr_args +
self.daparg_args +
self.target_args +
self.board_args +
self.frequency_args +
self.tool_opt_args +
self.flash_extra +
[fname])
self.logger.info('Flashing file: {}'.format(fname))
self.check_call(cmd)
def log_gdbserver_message(self):
self.logger.info('pyOCD GDB server running on port {}'.
format(self.gdb_port))
def debug_debugserver(self, command, **kwargs):
server_cmd = ([self.pyocd] +
['gdbserver'] +
self.daparg_args +
self.port_args() +
self.target_args +
self.board_args +
self.frequency_args +
self.tool_opt_args)
if command == 'debugserver':
self.log_gdbserver_message()
self.check_call(server_cmd)
else:
if self.gdb_cmd is None:
raise ValueError('Cannot debug; gdb is missing')
if self.elf_name is None:
raise ValueError('Cannot debug; elf is missing')
client_cmd = (self.gdb_cmd +
self.tui_args +
[self.elf_name] +
['-ex', 'target remote :{}'.format(self.gdb_port)])
if command == 'debug':
client_cmd += ['-ex', 'monitor halt',
'-ex', 'monitor reset',
'-ex', 'load']
self.require(client_cmd[0])
self.log_gdbserver_message()
self.run_server_and_client(server_cmd, client_cmd)