# Copyright (c) 2017 Linaro Limited. # # SPDX-License-Identifier: Apache-2.0 '''Runner for pyOCD .''' from os import path import os from .core import ZephyrBinaryRunner, get_env_or_bail DEFAULT_PYOCD_GDB_PORT = 3333 class PyOcdBinaryRunner(ZephyrBinaryRunner): '''Runner front-end for pyocd-flashtool.''' def __init__(self, target, flashtool='pyocd-flashtool', gdb=None, gdbserver='pyocd-gdbserver', gdb_port=DEFAULT_PYOCD_GDB_PORT, tui=None, bin_name=None, elf_name=None, board_id=None, daparg=None, debug=False): super(PyOcdBinaryRunner, self).__init__(debug=debug) self.target_args = ['-t', target] self.flashtool = flashtool self.gdb_cmd = [gdb] if gdb is not None else None self.gdbserver = gdbserver self.gdb_port = gdb_port self.tui_args = [tui] if tui is not None else [] self.bin_name = bin_name self.elf_name = elf_name 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 def replaces_shell_script(shell_script, command): return (command in {'flash', 'debug', 'debugserver'} and shell_script == 'pyocd.sh') def port_args(self): return ['-p', str(self.gdb_port)] def create_from_env(command, debug): '''Create runner from environment. Required: - PYOCD_TARGET: target override Optional: - PYOCD_DAPARG: arguments to pass to pyocd tool, default is none - PYOCD_BOARD_ID: ID of board to flash, default is to prompt Required for 'flash': - O: build output directory - KERNEL_BIN_NAME: name of kernel binary Optional for 'flash': - PYOCD_FLASHTOOL: flash tool path, defaults to pyocd-flashtool Required for 'debug': - O: build output directory - KERNEL_ELF_NAME - GDB: gdb executable Optional for 'debug', 'debugserver': - TUI: one additional argument to GDB (e.g. -tui) - GDB_PORT: pyocd gdb port, defaults to 3333 - PYOCD_GDBSERVER: gdb server executable, defaults to pyocd-gdbserver ''' target = get_env_or_bail('PYOCD_TARGET') o = os.environ.get('O', None) bin_ = os.environ.get('KERNEL_BIN_NAME', None) elf = os.environ.get('KERNEL_ELF_NAME', None) bin_name = None elf_name = None if o is not None: if bin_ is not None: bin_name = path.join(o, bin_) if elf is not None: elf_name = path.join(o, elf) flashtool = os.environ.get('PYOCD_FLASHTOOL', 'pyocd-flashtool') board_id = os.environ.get('PYOCD_BOARD_ID', None) daparg = os.environ.get('PYOCD_DAPARG', None) gdb = os.environ.get('GDB', None) gdbserver = os.environ.get('PYOCD_GDBSERVER', 'pyocd-gdbserver') gdb_port = os.environ.get('GDB_PORT', DEFAULT_PYOCD_GDB_PORT) tui = os.environ.get('TUI', None) return PyOcdBinaryRunner(target, flashtool=flashtool, gdb=gdb, gdbserver=gdbserver, gdb_port=gdb_port, tui=tui, bin_name=bin_name, elf_name=elf_name, board_id=board_id, daparg=daparg, debug=debug) def run(self, command, **kwargs): if command not in {'flash', 'debug', 'debugserver'}: raise ValueError('{} is not supported'.format(command)) if command == 'flash': self.flash(**kwargs) else: self.debug_debugserver(command, **kwargs) def flash(self, **kwargs): if self.bin_name is None: raise ValueError('Cannot flash; bin_name is missing') cmd = ([self.flashtool] + self.daparg_args + self.target_args + self.board_args + [self.bin_name]) print('Flashing Target Device') self.check_call(cmd) def print_gdbserver_message(self): print('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) 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), '-ex', 'load', '-ex', 'monitor reset halt']) self.print_gdbserver_message() self.run_server_and_client(server_cmd, client_cmd)