zephyr/scripts/support/runner/openocd.py
Anas Nashif 539d2af654 flash: support flashing multiple configurations of a single board
Some boards define multiple configuration which all are maintained under
the same board directory. The flasher was looking for an openocd.cfg
based on the board name, which can't be found for such boards.

Use the variable BOARD_DIR provided by cmake instead of trying to
assemble the board directory location on our own.

Signed-off-by: Anas Nashif <anas.nashif@intel.com>
2017-11-13 10:55:26 -05:00

206 lines
7.5 KiB
Python

# Copyright (c) 2017 Linaro Limited.
#
# SPDX-License-Identifier: Apache-2.0
'''Runner for openocd.'''
from os import path
import os
import shlex
from .core import ZephyrBinaryRunner, get_env_or_bail, get_env_strip_or
DEFAULT_OPENOCD_TCL_PORT = 6333
DEFAULT_OPENOCD_TELNET_PORT = 4444
DEFAULT_OPENOCD_GDB_PORT = 3333
class OpenOcdBinaryRunner(ZephyrBinaryRunner):
'''Runner front-end for openocd.'''
def __init__(self, openocd_config,
openocd='openocd', default_path=None,
bin_name=None, elf_name=None,
load_cmd=None, verify_cmd=None, pre_cmd=None, post_cmd=None,
extra_init=None,
tcl_port=DEFAULT_OPENOCD_TCL_PORT,
telnet_port=DEFAULT_OPENOCD_TELNET_PORT,
gdb_port=DEFAULT_OPENOCD_GDB_PORT,
gdb=None, tui=None, debug=False):
super(OpenOcdBinaryRunner, self).__init__(debug=debug)
self.openocd_config = openocd_config
search_args = []
if default_path is not None:
search_args = ['-s', default_path]
self.openocd_cmd = [openocd] + search_args
self.bin_name = bin_name
self.elf_name = elf_name
self.load_cmd = load_cmd
self.verify_cmd = verify_cmd
self.pre_cmd = pre_cmd
self.post_cmd = post_cmd
self.extra_init = extra_init if extra_init is not None else []
self.tcl_port = tcl_port
self.telnet_port = telnet_port
self.gdb_port = gdb_port
self.gdb_cmd = [gdb] if gdb is not None else None
self.tui_arg = [tui] if tui is not None else []
def replaces_shell_script(shell_script, command):
return (command in {'flash', 'debug', 'debugserver'} and
shell_script == 'openocd.sh')
def create_from_env(command, debug):
'''Create runner from environment.
Required:
- ZEPHYR_BASE: zephyr Git repository base directory
- BOARD_DIR: directory of board definition
Optional:
- OPENOCD: path to openocd, defaults to openocd
- OPENOCD_DEFAULT_PATH: openocd search path to use
Required for 'flash':
- O: build output directory
- KERNEL_BIN_NAME: zephyr kernel binary
- OPENOCD_LOAD_CMD: command to load binary into flash
- OPENOCD_VERIFY_CMD: command to verify flash executed correctly
Optional for 'flash':
- OPENOCD_PRE_CMD: command to run before any others
- OPENOCD_POST_CMD: command to run after verifying flash write
Required for 'debug':
- GDB: GDB executable
- O: build output directory
- KERNEL_ELF_NAME: zephyr kernel binary, ELF format
Optional for 'debug':
- TUI: one additional argument to GDB (e.g. -tui)
- OPENOCD_EXTRA_INIT: additional arguments to pass to openocd
- TCL_PORT: openocd TCL port, defaults to 6333
- TELNET_PORT: openocd telnet port, defaults to 4444
- GDB_PORT: openocd gdb port, defaults to 3333
'''
zephyr_base = get_env_or_bail('ZEPHYR_BASE')
board_dir = get_env_or_bail('BOARD_DIR')
openocd_config = path.join(board_dir, 'support', 'openocd.cfg')
openocd = os.environ.get('OPENOCD', 'openocd')
default_path = os.environ.get('OPENOCD_DEFAULT_PATH', None)
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)
load_cmd = get_env_strip_or('OPENOCD_LOAD_CMD', '"', None)
verify_cmd = get_env_strip_or('OPENOCD_VERIFY_CMD', '"', None)
pre_cmd = get_env_strip_or('OPENOCD_PRE_CMD', '"', None)
post_cmd = get_env_strip_or('OPENOCD_POST_CMD', '"', None)
gdb = os.environ.get('GDB', None)
tui = os.environ.get('TUI', None)
extra_init = os.environ.get('OPENOCD_EXTRA_INIT', None)
if extra_init is not None:
extra_init = shlex.split(extra_init)
tcl_port = int(os.environ.get('TCL_PORT',
str(DEFAULT_OPENOCD_TCL_PORT)))
telnet_port = int(os.environ.get('TELNET_PORT',
str(DEFAULT_OPENOCD_TELNET_PORT)))
gdb_port = int(os.environ.get('GDB_PORT',
str(DEFAULT_OPENOCD_GDB_PORT)))
return OpenOcdBinaryRunner(openocd_config,
openocd=openocd, default_path=default_path,
bin_name=bin_name, elf_name=elf_name,
load_cmd=load_cmd, verify_cmd=verify_cmd,
pre_cmd=pre_cmd, post_cmd=post_cmd,
extra_init=extra_init, tcl_port=tcl_port,
telnet_port=telnet_port, gdb_port=gdb_port,
gdb=gdb, tui=tui, 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.do_flash(**kwargs)
elif command == 'debug':
self.do_debug(**kwargs)
else:
self.do_debugserver(**kwargs)
def do_flash(self, **kwargs):
if self.bin_name is None:
raise ValueError('Cannot flash; binary name is missing')
if self.load_cmd is None:
raise ValueError('Cannot flash; load command is missing')
if self.verify_cmd is None:
raise ValueError('Cannot flash; verify command is missing')
pre_cmd = []
if self.pre_cmd is not None:
pre_cmd = ['-c', self.pre_cmd]
post_cmd = []
if self.post_cmd is not None:
post_cmd = ['-c', self.post_cmd]
cmd = (self.openocd_cmd +
['-f', self.openocd_config,
'-c', 'init',
'-c', 'targets'] +
pre_cmd +
['-c', 'reset halt',
'-c', self.load_cmd,
'-c', 'reset halt',
'-c', self.verify_cmd] +
post_cmd +
['-c', 'reset run',
'-c', 'shutdown'])
self.check_call(cmd)
def do_debug(self, **kwargs):
if self.gdb_cmd is None:
raise ValueError('Cannot debug; no gdb specified')
if self.elf_name is None:
raise ValueError('Cannot debug; no .elf specified')
server_cmd = (self.openocd_cmd +
['-f', self.openocd_config] +
self.extra_init +
['-c', 'tcl_port {}'.format(self.tcl_port),
'-c', 'telnet_port {}'.format(self.telnet_port),
'-c', 'gdb_port {}'.format(self.gdb_port),
'-c', 'init',
'-c', 'targets',
'-c', 'halt'])
gdb_cmd = (self.gdb_cmd + self.tui_arg +
['-ex', 'target remote :{}'.format(self.gdb_port),
self.elf_name])
self.run_server_and_client(server_cmd, gdb_cmd)
def do_debugserver(self, **kwargs):
cmd = (self.openocd_cmd +
['-f', self.openocd_config,
'-c', 'init',
'-c', 'targets',
'-c', 'reset halt'])
self.check_call(cmd)