| # 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) |