zephyr/scripts/west_commands/runners/pyocd.py
Marti Bolivar ab82264ace scripts: add west build, flash, and debug commands
West now supports a mechanism for extension commands. Use it to move
the command implementations that are tightly coupled with boards and
the zephyr build system back into the Zephyr repository.

This patch doesn't include test cases. Those will be moved over in a
subsequent patch.

Signed-off-by: Marti Bolivar <marti@foundries.io>
2019-01-29 10:15:01 +01:00

171 lines
6.2 KiB
Python

# Copyright (c) 2017 Linaro Limited.
#
# SPDX-License-Identifier: Apache-2.0
'''Runner for pyOCD .'''
import os
from west import log
from runners.core import ZephyrBinaryRunner, RunnerCaps, \
BuildConfiguration
DEFAULT_PYOCD_GDB_PORT = 3333
class PyOcdBinaryRunner(ZephyrBinaryRunner):
'''Runner front-end for pyOCD.'''
def __init__(self, cfg, target,
flashtool='pyocd-flashtool', flash_addr=0x0,
flashtool_opts=None,
gdbserver='pyocd-gdbserver',
gdb_port=DEFAULT_PYOCD_GDB_PORT, tui=False,
board_id=None, daparg=None, frequency=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 = [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.hex_name = cfg.hex_file
self.bin_name = cfg.bin_file
self.elf_name = cfg.elf_file
board_args = []
if board_id is not None:
board_args = ['-b', board_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.flashtool_extra = flashtool_opts if flashtool_opts else []
@classmethod
def name(cls):
return 'pyocd'
@classmethod
def capabilities(cls):
return RunnerCaps(commands={'flash', 'debug', 'debugserver', 'attach'},
flash_addr=True)
@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('--flashtool', default='pyocd-flashtool',
help='flash tool path, default is pyocd-flashtool')
parser.add_argument('--flashtool-opt', default=[], action='append',
help='''Additional options for pyocd-flashtool,
e.g. -ce to chip erase''')
parser.add_argument('--frequency',
help='SWD clock frequency in Hz')
parser.add_argument('--gdbserver', default='pyocd-gdbserver',
help='GDB server, default is pyocd-gdbserver')
parser.add_argument('--gdb-port', default=DEFAULT_PYOCD_GDB_PORT,
help='pyocd gdb port, defaults to {}'.format(
DEFAULT_PYOCD_GDB_PORT))
parser.add_argument('--tui', default=False, action='store_true',
help='if given, GDB uses -tui')
parser.add_argument('--board-id',
help='ID of board to flash, default is to prompt')
@classmethod
def create(cls, cfg, args):
daparg = os.environ.get('PYOCD_DAPARG')
if daparg:
log.wrn('Setting PYOCD_DAPARG in the environment is',
'deprecated; use the --daparg option instead.')
if args.daparg is None:
log.dbg('Missing --daparg set to {} from environment'.format(
daparg), level=log.VERBOSE_VERY)
args.daparg = daparg
build_conf = BuildConfiguration(cfg.build_dir)
flash_addr = cls.get_flash_address(args, build_conf)
return PyOcdBinaryRunner(
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,
board_id=args.board_id, daparg=args.daparg,
frequency=args.frequency)
def port_args(self):
return ['-p', str(self.gdb_port)]
def do_run(self, command, **kwargs):
if command == 'flash':
self.flash(**kwargs)
else:
self.debug_debugserver(command, **kwargs)
def flash(self, **kwargs):
if os.path.isfile(self.hex_name):
fname = self.hex_name
elif os.path.isfile(self.bin_name):
fname = self.bin_name
else:
raise ValueError(
'Cannot flash; no hex ({}) or bin ({}) files'.format(
self.hex_name, self.bin_name))
cmd = ([self.flashtool] +
self.flash_addr_args +
self.daparg_args +
self.target_args +
self.board_args +
self.frequency_args +
self.flashtool_extra +
[fname])
log.inf('Flashing Target Device')
self.check_call(cmd)
def print_gdbserver_message(self):
log.inf('pyOCD GDB server running on port {}'.format(self.gdb_port))
def debug_debugserver(self, command, **kwargs):
server_cmd = ([self.gdbserver] +
self.daparg_args +
self.port_args() +
self.target_args +
self.board_args +
self.frequency_args)
if command == 'debugserver':
self.print_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.print_gdbserver_message()
self.run_server_and_client(server_cmd, client_cmd)