scripts: zephyr_flash_debug: refactor into new "runner" package
Factor the classes which do the work into a new "runner" package. This package has a core module where ZephyrBinaryRunner and common helpers will live, and one file per subclass / runner front-end. The top-level script, zephyr_flash_debug.py, still exists, but just delegates its work to the core. Signed-off-by: Marti Bolivar <marti.bolivar@linaro.org>
This commit is contained in:
parent
12802cf36e
commit
32b475ebb9
11 changed files with 1158 additions and 1013 deletions
22
scripts/support/runner/__init__.py
Normal file
22
scripts/support/runner/__init__.py
Normal file
|
@ -0,0 +1,22 @@
|
|||
# Copyright (c) 2017 Linaro Limited.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
from .core import ZephyrBinaryRunner
|
||||
|
||||
# We import these here to ensure the ZephyrBinaryRunner subclasses are
|
||||
# defined; otherwise, ZephyrBinaryRunner.create_for_shell_script()
|
||||
# won't work.
|
||||
|
||||
# Explicitly silence the unused import warning.
|
||||
# flake8: noqa: F401
|
||||
from . import arc
|
||||
from . import bossac
|
||||
from . import dfu
|
||||
from . import esp32
|
||||
from . import nios2
|
||||
from . import nrfjprog
|
||||
from . import openocd
|
||||
from . import pyocd
|
||||
|
||||
__all__ = ['ZephyrBinaryRunner']
|
155
scripts/support/runner/arc.py
Normal file
155
scripts/support/runner/arc.py
Normal file
|
@ -0,0 +1,155 @@
|
|||
# Copyright (c) 2017 Linaro Limited.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
'''ARC architecture-specific runner.'''
|
||||
|
||||
from os import path
|
||||
import os
|
||||
import shlex
|
||||
|
||||
from .core import ZephyrBinaryRunner, get_env_or_bail
|
||||
|
||||
DEFAULT_ARC_TCL_PORT = 6333
|
||||
DEFAULT_ARC_TELNET_PORT = 4444
|
||||
DEFAULT_ARC_GDB_PORT = 3333
|
||||
|
||||
|
||||
class ArcBinaryRunner(ZephyrBinaryRunner):
|
||||
'''Runner front-end for the ARC architecture, using openocd.'''
|
||||
|
||||
# This unusual 'flash' implementation matches the original shell script.
|
||||
#
|
||||
# It works by starting a GDB server in a separate session, connecting a
|
||||
# client to it to load the program, and running 'continue' within the
|
||||
# client to execute the application.
|
||||
#
|
||||
# TODO: exit immediately when flashing is done, leaving Zephyr running.
|
||||
|
||||
def __init__(self, elf, zephyr_base, arch, board_name, python,
|
||||
gdb, openocd='openocd', extra_init=None, default_path=None,
|
||||
tui=None, tcl_port=DEFAULT_ARC_TCL_PORT,
|
||||
telnet_port=DEFAULT_ARC_TELNET_PORT,
|
||||
gdb_port=DEFAULT_ARC_GDB_PORT, debug=False):
|
||||
super(ArcBinaryRunner, self).__init__(debug=debug)
|
||||
self.elf = elf
|
||||
self.zephyr_base = zephyr_base
|
||||
self.arch = arch
|
||||
self.board_name = board_name
|
||||
self.python = python
|
||||
self.gdb = gdb
|
||||
search_args = []
|
||||
if default_path is not None:
|
||||
search_args = ['-s', default_path]
|
||||
self.openocd_cmd = [openocd] + search_args
|
||||
self.extra_init = extra_init if extra_init is not None else []
|
||||
self.tui = tui
|
||||
self.tcl_port = tcl_port
|
||||
self.telnet_port = telnet_port
|
||||
self.gdb_port = gdb_port
|
||||
|
||||
def replaces_shell_script(shell_script, command):
|
||||
return (command in {'flash', 'debug', 'debugserver'} and
|
||||
shell_script == 'arc_debugger.sh')
|
||||
|
||||
def create_from_env(command, debug):
|
||||
'''Create runner from environment.
|
||||
|
||||
Required:
|
||||
|
||||
- O: build output directory
|
||||
- KERNEL_ELF_NAME: zephyr kernel binary in ELF format
|
||||
- ZEPHYR_BASE: zephyr Git repository base directory
|
||||
- ARCH: board architecture
|
||||
- BOARD_NAME: zephyr name of board
|
||||
- PYTHON: python executable
|
||||
- GDB: gdb executable
|
||||
|
||||
Optional:
|
||||
|
||||
- OPENOCD: path to openocd, defaults to openocd
|
||||
- OPENOCD_EXTRA_INIT: initialization command for GDB server
|
||||
- OPENOCD_DEFAULT_PATH: openocd search path to use
|
||||
- TUI: if present, passed to gdb server used to flash
|
||||
- TCL_PORT: openocd TCL port, defaults to 6333
|
||||
- TELNET_PORT: openocd telnet port, defaults to 4444
|
||||
- GDB_PORT: openocd gdb port, defaults to 3333
|
||||
'''
|
||||
elf = path.join(get_env_or_bail('O'),
|
||||
get_env_or_bail('KERNEL_ELF_NAME'))
|
||||
zephyr_base = get_env_or_bail('ZEPHYR_BASE')
|
||||
arch = get_env_or_bail('ARCH')
|
||||
board_name = get_env_or_bail('BOARD_NAME')
|
||||
python = get_env_or_bail('PYTHON')
|
||||
gdb = get_env_or_bail('GDB')
|
||||
|
||||
openocd = os.environ.get('OPENOCD', 'openocd')
|
||||
extra_init = os.environ.get('OPENOCD_EXTRA_INIT', None)
|
||||
if extra_init is not None:
|
||||
extra_init = shlex.split(extra_init)
|
||||
default_path = os.environ.get('OPENOCD_DEFAULT_PATH', None)
|
||||
tui = os.environ.get('TUI', None)
|
||||
tcl_port = int(os.environ.get('TCL_PORT',
|
||||
str(DEFAULT_ARC_TCL_PORT)))
|
||||
telnet_port = int(os.environ.get('TELNET_PORT',
|
||||
str(DEFAULT_ARC_TELNET_PORT)))
|
||||
gdb_port = int(os.environ.get('GDB_PORT',
|
||||
str(DEFAULT_ARC_GDB_PORT)))
|
||||
|
||||
return ArcBinaryRunner(elf, zephyr_base, arch, board_name, python,
|
||||
gdb, openocd=openocd, extra_init=extra_init,
|
||||
default_path=default_path, tui=tui,
|
||||
tcl_port=tcl_port, telnet_port=telnet_port,
|
||||
gdb_port=gdb_port, debug=debug)
|
||||
|
||||
def run(self, command, **kwargs):
|
||||
if command not in {'flash', 'debug', 'debugserver'}:
|
||||
raise ValueError('{} is not supported'.format(command))
|
||||
|
||||
kwargs['openocd-cfg'] = path.join(self.zephyr_base, 'boards',
|
||||
self.arch, self.board_name,
|
||||
'support', 'openocd.cfg')
|
||||
|
||||
if command in {'flash', 'debug'}:
|
||||
self.flash_debug(command, **kwargs)
|
||||
else:
|
||||
self.debugserver(**kwargs)
|
||||
|
||||
def flash_debug(self, command, **kwargs):
|
||||
config = kwargs['openocd-cfg']
|
||||
|
||||
server_cmd = (self.openocd_cmd +
|
||||
['-f', 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'])
|
||||
|
||||
tui_arg = []
|
||||
if self.tui is not None:
|
||||
tui_arg = [self.tui]
|
||||
|
||||
continue_arg = []
|
||||
if command == 'flash':
|
||||
continue_arg = ['-ex', 'c']
|
||||
|
||||
gdb_cmd = ([self.gdb] +
|
||||
tui_arg +
|
||||
['-ex', 'target remote :{}'.format(self.gdb_port),
|
||||
'-ex', 'load'] +
|
||||
continue_arg +
|
||||
[self.elf])
|
||||
|
||||
self.run_server_and_client(server_cmd, gdb_cmd)
|
||||
|
||||
def debugserver(self, **kwargs):
|
||||
config = kwargs['openocd-cfg']
|
||||
cmd = (self.openocd_cmd +
|
||||
['-f', config,
|
||||
'-c', 'init',
|
||||
'-c', 'targets',
|
||||
'-c', 'reset halt'])
|
||||
self.check_call(cmd)
|
64
scripts/support/runner/bossac.py
Normal file
64
scripts/support/runner/bossac.py
Normal file
|
@ -0,0 +1,64 @@
|
|||
# Copyright (c) 2017 Linaro Limited.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
'''bossac-specific runner (flash only) for Atmel SAM microcontrollers.'''
|
||||
|
||||
from os import path
|
||||
import os
|
||||
import platform
|
||||
|
||||
from .core import ZephyrBinaryRunner, get_env_or_bail
|
||||
|
||||
DEFAULT_BOSSAC_PORT = '/dev/ttyACM0'
|
||||
|
||||
|
||||
class BossacBinaryRunner(ZephyrBinaryRunner):
|
||||
'''Runner front-end for bossac.'''
|
||||
|
||||
def __init__(self, bin_name, bossac='bossac',
|
||||
port=DEFAULT_BOSSAC_PORT, debug=False):
|
||||
super(BossacBinaryRunner, self).__init__(debug=debug)
|
||||
self.bin_name = bin_name
|
||||
self.bossac = bossac
|
||||
self.port = port
|
||||
|
||||
def replaces_shell_script(shell_script, command):
|
||||
return command == 'flash' and shell_script == 'bossa-flash.sh'
|
||||
|
||||
def create_from_env(command, debug):
|
||||
'''Create flasher from environment.
|
||||
|
||||
Required:
|
||||
|
||||
- O: build output directory
|
||||
- KERNEL_BIN_NAME: name of kernel binary
|
||||
|
||||
Optional:
|
||||
|
||||
- BOSSAC: path to bossac, default is bossac
|
||||
- BOSSAC_PORT: serial port to use, default is /dev/ttyACM0
|
||||
'''
|
||||
bin_name = path.join(get_env_or_bail('O'),
|
||||
get_env_or_bail('KERNEL_BIN_NAME'))
|
||||
bossac = os.environ.get('BOSSAC', 'bossac')
|
||||
port = os.environ.get('BOSSAC_PORT', DEFAULT_BOSSAC_PORT)
|
||||
return BossacBinaryRunner(bin_name, bossac=bossac, port=port,
|
||||
debug=debug)
|
||||
|
||||
def run(self, command, **kwargs):
|
||||
if command != 'flash':
|
||||
raise ValueError('only flash is supported')
|
||||
|
||||
if platform.system() != 'Linux':
|
||||
msg = 'CAUTION: No flash tool for your host system found!'
|
||||
raise NotImplementedError(msg)
|
||||
|
||||
cmd_stty = ['stty', '-F', self.port, 'raw', 'ispeed', '1200',
|
||||
'ospeed', '1200', 'cs8', '-cstopb', 'ignpar', 'eol', '255',
|
||||
'eof', '255']
|
||||
cmd_flash = [self.bossac, '-p', self.port, '-R', '-e', '-w', '-v',
|
||||
'-b', self.bin_name]
|
||||
|
||||
self.check_call(cmd_stty)
|
||||
self.check_call(cmd_flash)
|
219
scripts/support/runner/core.py
Normal file
219
scripts/support/runner/core.py
Normal file
|
@ -0,0 +1,219 @@
|
|||
#! /usr/bin/env python3
|
||||
|
||||
# Copyright (c) 2017 Linaro Limited.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
"""Zephyr binary runner core interfaces
|
||||
|
||||
This provides the core ZephyrBinaryRunner class meant for public use,
|
||||
as well as some other helpers for concrete runner classes.
|
||||
"""
|
||||
|
||||
import abc
|
||||
import os
|
||||
import platform
|
||||
import pprint
|
||||
import shlex
|
||||
import signal
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
|
||||
def get_env_or_bail(env_var):
|
||||
'''Get an environment variable, or raise an error.
|
||||
|
||||
In case of KeyError, an error message is printed, along with the
|
||||
environment, and the exception is re-raised.
|
||||
'''
|
||||
try:
|
||||
return os.environ[env_var]
|
||||
except KeyError:
|
||||
print('Variable {} not in environment:'.format(
|
||||
env_var), file=sys.stderr)
|
||||
pprint.pprint(dict(os.environ), stream=sys.stderr)
|
||||
raise
|
||||
|
||||
|
||||
def get_env_bool_or(env_var, default_value):
|
||||
'''Get an environment variable as a boolean, or return a default value.
|
||||
|
||||
Get an environment variable, interpret it as a base ten
|
||||
integer, and convert that to a boolean.
|
||||
|
||||
In case the environment variable is not defined, return default_value.
|
||||
'''
|
||||
try:
|
||||
return bool(int(os.environ[env_var]))
|
||||
except KeyError:
|
||||
return default_value
|
||||
|
||||
|
||||
def get_env_strip_or(env_var, to_strip, default_value):
|
||||
'''Get and clean up an environment variable, or return a default value.
|
||||
|
||||
Get the value of env_var from the environment. If it is
|
||||
defined, return that value with to_strip stripped off. If it
|
||||
is undefined, return default_value (without any stripping).
|
||||
'''
|
||||
value = os.environ.get(env_var, None)
|
||||
if value is not None:
|
||||
return value.strip(to_strip)
|
||||
else:
|
||||
return default_value
|
||||
|
||||
|
||||
def quote_sh_list(cmd):
|
||||
'''Transform a command from list into shell string form.'''
|
||||
fmt = ' '.join('{}' for _ in cmd)
|
||||
args = [shlex.quote(s) for s in cmd]
|
||||
return fmt.format(*args)
|
||||
|
||||
|
||||
class ZephyrBinaryRunner(abc.ABC):
|
||||
'''Abstract superclass for binary runners (flashers, debuggers).
|
||||
|
||||
With some exceptions, boards supported by Zephyr must provide
|
||||
generic means to be flashed (have a Zephyr firmware binary
|
||||
permanently installed on the device for running) and debugged
|
||||
(have a breakpoint debugger and program loader on a host
|
||||
workstation attached to a running target). This is supported by
|
||||
three top-level commands managed by the Zephyr build system:
|
||||
|
||||
- 'flash': flash a previously configured binary to the board,
|
||||
start execution on the target, then return.
|
||||
|
||||
- 'debug': connect to the board via a debugging protocol, then
|
||||
drop the user into a debugger interface with symbol tables
|
||||
loaded from the current binary, and block until it exits.
|
||||
|
||||
- 'debugserver': connect via a board-specific debugging protocol,
|
||||
then reset and halt the target. Ensure the user is now able to
|
||||
connect to a debug server with symbol tables loaded from the
|
||||
binary.
|
||||
|
||||
Runner functionality relies on a variety of target-specific tools
|
||||
and configuration values, the user interface to which is
|
||||
abstracted by this class. Each runner subclass should take any
|
||||
values it needs to execute one of these commands in its
|
||||
constructor. The actual command execution is handled in the run()
|
||||
method.
|
||||
|
||||
This functionality is also replacing the legacy Zephyr runners,
|
||||
which are shell scripts.
|
||||
|
||||
At present, the Zephyr build system uses a variety of
|
||||
tool-specific environment variables to control runner behavior.
|
||||
To support a transition to ZephyrBinaryRunner and subclasses, this
|
||||
class provides a create_for_shell_script() static factory method.
|
||||
This method iterates over ZephyrBinaryRUnner subclasses,
|
||||
determines which (if any) can provide equivalent functionality to
|
||||
the shell-based runner, and returns a subclass instance with its
|
||||
configuration determined from the environment.
|
||||
|
||||
To support this, subclasess currently must provide a pair of
|
||||
static methods, replaces_shell_script() and create_from_env(). The
|
||||
first allows the runner subclass to declare which commands and
|
||||
scripts it can replace. The second is called by
|
||||
create_for_shell_script() to create a concrete runner instance.
|
||||
|
||||
The environment-based factories are for legacy use *only*; the
|
||||
user must be able to construct and use a runner using only the
|
||||
constructor and run() method.'''
|
||||
|
||||
def __init__(self, debug=False):
|
||||
self.debug = debug
|
||||
|
||||
@staticmethod
|
||||
def create_for_shell_script(shell_script, command, debug):
|
||||
'''Factory for using as a drop-in replacement to a shell script.
|
||||
|
||||
Command is one of 'flash', 'debug', 'debugserver'.
|
||||
|
||||
Get runner instance to use in place of shell_script, deriving
|
||||
configuration from the environment.'''
|
||||
for sub_cls in ZephyrBinaryRunner.__subclasses__():
|
||||
if sub_cls.replaces_shell_script(shell_script, command):
|
||||
return sub_cls.create_from_env(command, debug)
|
||||
raise ValueError('cannot implement script {} command {}'.format(
|
||||
shell_script, command))
|
||||
|
||||
@staticmethod
|
||||
@abc.abstractmethod
|
||||
def replaces_shell_script(shell_script, command):
|
||||
'''Check if this class replaces shell_script for the given command.'''
|
||||
|
||||
@staticmethod
|
||||
@abc.abstractmethod
|
||||
def create_from_env(command, debug):
|
||||
'''Create new flasher instance from environment variables.
|
||||
|
||||
This class must be able to replace the current shell script
|
||||
(FLASH_SCRIPT or DEBUG_SCRIPT, depending on command). The
|
||||
environment variables expected by that script are used to build
|
||||
the flasher in a backwards-compatible manner.'''
|
||||
|
||||
@abc.abstractmethod
|
||||
def run(self, command, **kwargs):
|
||||
'''Run a command ('flash', 'debug', 'debugserver').
|
||||
|
||||
In case of an unsupported command, raise a ValueError.'''
|
||||
|
||||
def run_server_and_client(self, server, client):
|
||||
'''Run a server that ignores SIGINT, and a client that handles it.
|
||||
|
||||
This routine portably:
|
||||
|
||||
- creates a Popen object for the `server' command which ignores SIGINT
|
||||
- runs `client' in a subprocess while temporarily ignoring SIGINT
|
||||
- cleans up the server after the client exits.
|
||||
|
||||
It's useful to e.g. open a GDB server and client.'''
|
||||
server_proc = self.popen_ignore_int(server)
|
||||
previous = signal.signal(signal.SIGINT, signal.SIG_IGN)
|
||||
try:
|
||||
self.check_call(client)
|
||||
finally:
|
||||
signal.signal(signal.SIGINT, previous)
|
||||
server_proc.terminate()
|
||||
server_proc.wait()
|
||||
|
||||
def check_call(self, cmd):
|
||||
'''Subclass subprocess.check_call() wrapper.
|
||||
|
||||
Subclasses should use this command to run command in a
|
||||
subprocess and check that it executed correctly, rather than
|
||||
using subprocess directly, to keep accurate debug logs.
|
||||
'''
|
||||
if self.debug:
|
||||
print(quote_sh_list(cmd))
|
||||
subprocess.check_call(cmd)
|
||||
|
||||
def check_output(self, cmd):
|
||||
'''Subclass subprocess.check_output() wrapper.
|
||||
|
||||
Subclasses should use this command to run command in a
|
||||
subprocess and check that it executed correctly, rather than
|
||||
using subprocess directly, to keep accurate debug logs.
|
||||
'''
|
||||
if self.debug:
|
||||
print(quote_sh_list(cmd))
|
||||
return subprocess.check_output(cmd)
|
||||
|
||||
def popen_ignore_int(self, cmd):
|
||||
'''Spawn a child command, ensuring it ignores SIGINT.
|
||||
|
||||
The returned subprocess.Popen object must be manually terminated.'''
|
||||
cflags = 0
|
||||
preexec = None
|
||||
system = platform.system()
|
||||
|
||||
if system == 'Windows':
|
||||
cflags |= subprocess.CREATE_NEW_PROCESS_GROUP
|
||||
elif system in {'Linux', 'Darwin'}:
|
||||
preexec = os.setsid
|
||||
|
||||
if self.debug:
|
||||
print(quote_sh_list(cmd))
|
||||
|
||||
return subprocess.Popen(cmd, creationflags=cflags, preexec_fn=preexec)
|
78
scripts/support/runner/dfu.py
Normal file
78
scripts/support/runner/dfu.py
Normal file
|
@ -0,0 +1,78 @@
|
|||
# Copyright (c) 2017 Linaro Limited.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
'''Runner for flashing with dfu-util.'''
|
||||
|
||||
import os
|
||||
import sys
|
||||
import time
|
||||
|
||||
from .core import ZephyrBinaryRunner, get_env_or_bail
|
||||
|
||||
|
||||
class DfuUtilBinaryRunner(ZephyrBinaryRunner):
|
||||
'''Runner front-end for dfu-util.'''
|
||||
|
||||
def __init__(self, pid, alt, img, dfuse=None, exe='dfu-util', debug=False):
|
||||
super(DfuUtilBinaryRunner, self).__init__(debug=debug)
|
||||
self.alt = alt
|
||||
self.img = img
|
||||
self.dfuse = dfuse
|
||||
self.cmd = [exe, '-d,{}'.format(pid)]
|
||||
try:
|
||||
self.list_pattern = ', alt={},'.format(int(self.alt))
|
||||
except ValueError:
|
||||
self.list_pattern = ', name="{}",'.format(self.alt)
|
||||
|
||||
def replaces_shell_script(shell_script, command):
|
||||
return command == 'flash' and shell_script == 'dfuutil.sh'
|
||||
|
||||
def create_from_env(command, debug):
|
||||
'''Create flasher from environment.
|
||||
|
||||
Required:
|
||||
|
||||
- DFUUTIL_PID: USB VID:PID of the board
|
||||
- DFUUTIL_ALT: interface alternate setting number or name
|
||||
- DFUUTIL_IMG: binary to flash
|
||||
|
||||
Optional:
|
||||
|
||||
- DFUUTIL_DFUSE_ADDR: target address if the board is a
|
||||
DfuSe device. Ignored if not present.
|
||||
- DFUUTIL: dfu-util executable, defaults to dfu-util.
|
||||
'''
|
||||
pid = get_env_or_bail('DFUUTIL_PID')
|
||||
alt = get_env_or_bail('DFUUTIL_ALT')
|
||||
img = get_env_or_bail('DFUUTIL_IMG')
|
||||
dfuse = os.environ.get('DFUUTIL_DFUSE_ADDR', None)
|
||||
exe = os.environ.get('DFUUTIL', 'dfu-util')
|
||||
|
||||
return DfuUtilBinaryRunner(pid, alt, img, dfuse=dfuse, exe=exe,
|
||||
debug=debug)
|
||||
|
||||
def find_device(self):
|
||||
cmd = list(self.cmd) + ['-l']
|
||||
output = self.check_output(cmd)
|
||||
output = output.decode(sys.getdefaultencoding())
|
||||
return self.list_pattern in output
|
||||
|
||||
def run(self, command, **kwargs):
|
||||
if command != 'flash':
|
||||
raise ValueError('only flash is supported')
|
||||
|
||||
reset = 0
|
||||
if not self.find_device():
|
||||
reset = 1
|
||||
print('Please reset your board to switch to DFU mode...')
|
||||
while not self.find_device():
|
||||
time.sleep(0.1)
|
||||
|
||||
cmd = list(self.cmd)
|
||||
if self.dfuse is not None:
|
||||
cmd.extend(['-s', '{}:leave'.format(self.dfuse)])
|
||||
cmd.extend(['-a', self.alt, '-D', self.img])
|
||||
self.check_call(cmd)
|
||||
if reset:
|
||||
print('Now reset your board again to switch back to runtime mode.')
|
88
scripts/support/runner/esp32.py
Normal file
88
scripts/support/runner/esp32.py
Normal file
|
@ -0,0 +1,88 @@
|
|||
# Copyright (c) 2017 Linaro Limited.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
'''Runner for flashing ESP32 devices with esptool/espidf.'''
|
||||
|
||||
from os import path
|
||||
import os
|
||||
|
||||
from .core import ZephyrBinaryRunner, get_env_or_bail
|
||||
|
||||
|
||||
class Esp32BinaryRunner(ZephyrBinaryRunner):
|
||||
'''Runner front-end for espidf.'''
|
||||
|
||||
def __init__(self, elf, device, baud=921600, flash_size='detect',
|
||||
flash_freq='40m', flash_mode='dio', espidf='espidf',
|
||||
debug=False):
|
||||
super(Esp32BinaryRunner, self).__init__(debug=debug)
|
||||
self.elf = elf
|
||||
self.device = device
|
||||
self.baud = baud
|
||||
self.flash_size = flash_size
|
||||
self.flash_freq = flash_freq
|
||||
self.flash_mode = flash_mode
|
||||
self.espidf = espidf
|
||||
|
||||
def replaces_shell_script(shell_script, command):
|
||||
return command == 'flash' and shell_script == 'esp32.sh'
|
||||
|
||||
def create_from_env(command, debug):
|
||||
'''Create flasher from environment.
|
||||
|
||||
Required:
|
||||
|
||||
- O: build output directory
|
||||
- KERNEL_ELF_NAME: name of kernel binary in ELF format
|
||||
|
||||
Optional:
|
||||
|
||||
- ESP_DEVICE: serial port to flash, default /dev/ttyUSB0
|
||||
- ESP_BAUD_RATE: serial baud rate, default 921600
|
||||
- ESP_FLASH_SIZE: flash size, default 'detect'
|
||||
- ESP_FLASH_FREQ: flash frequency, default '40m'
|
||||
- ESP_FLASH_MODE: flash mode, default 'dio'
|
||||
- ESP_TOOL: complete path to espidf, or set to 'espidf' to look for it
|
||||
in $ESP_IDF_PATH/components/esptool_py/esptool/esptool.py
|
||||
'''
|
||||
elf = path.join(get_env_or_bail('O'),
|
||||
get_env_or_bail('KERNEL_ELF_NAME'))
|
||||
|
||||
# TODO add sane device defaults on other platforms than Linux.
|
||||
device = os.environ.get('ESP_DEVICE', '/dev/ttyUSB0')
|
||||
baud = os.environ.get('ESP_BAUD_RATE', '921600')
|
||||
flash_size = os.environ.get('ESP_FLASH_SIZE', 'detect')
|
||||
flash_freq = os.environ.get('ESP_FLASH_FREQ', '40m')
|
||||
flash_mode = os.environ.get('ESP_FLASH_MODE', 'dio')
|
||||
espidf = os.environ.get('ESP_TOOL', 'espidf')
|
||||
|
||||
if espidf == 'espidf':
|
||||
idf_path = get_env_or_bail('ESP_IDF_PATH')
|
||||
espidf = path.join(idf_path, 'components', 'esptool_py', 'esptool',
|
||||
'esptool.py')
|
||||
|
||||
return Esp32BinaryRunner(elf, device, baud=baud,
|
||||
flash_size=flash_size, flash_freq=flash_freq,
|
||||
flash_mode=flash_mode, espidf=espidf,
|
||||
debug=debug)
|
||||
|
||||
def run(self, command, **kwargs):
|
||||
if command != 'flash':
|
||||
raise ValueError('only flash is supported')
|
||||
|
||||
bin_name = path.splitext(self.elf)[0] + path.extsep + 'bin'
|
||||
cmd_convert = [self.espidf, '--chip', 'esp32', 'elf2image', self.elf]
|
||||
cmd_flash = [self.espidf, '--chip', 'esp32', '--port', self.device,
|
||||
'--baud', self.baud, '--before', 'default_reset',
|
||||
'--after', 'hard_reset', 'write_flash', '-u',
|
||||
'--flash_mode', self.flash_mode,
|
||||
'--flash_freq', self.flash_freq,
|
||||
'--flash_size', self.flash_size,
|
||||
'0x1000', bin_name]
|
||||
|
||||
print("Converting ELF to BIN")
|
||||
self.check_call(cmd_convert)
|
||||
|
||||
print("Flashing ESP32 on {} ({}bps)".format(self.device, self.baud))
|
||||
self.check_call(cmd_flash)
|
65
scripts/support/runner/nios2.py
Normal file
65
scripts/support/runner/nios2.py
Normal file
|
@ -0,0 +1,65 @@
|
|||
# Copyright (c) 2017 Linaro Limited.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
'''Runner for NIOS II.'''
|
||||
|
||||
from os import path
|
||||
|
||||
from .core import ZephyrBinaryRunner, get_env_or_bail
|
||||
|
||||
|
||||
class Nios2BinaryRunner(ZephyrBinaryRunner):
|
||||
'''Runner front-end for NIOS II.'''
|
||||
|
||||
# From the original shell script:
|
||||
#
|
||||
# "XXX [flash] only support[s] cases where the .elf is sent
|
||||
# over the JTAG and the CPU directly boots from __start. CONFIG_XIP
|
||||
# and CONFIG_INCLUDE_RESET_VECTOR must be disabled."
|
||||
|
||||
def __init__(self, hex_, cpu_sof, zephyr_base, debug=False):
|
||||
super(Nios2BinaryRunner, self).__init__(debug=debug)
|
||||
self.hex_ = hex_
|
||||
self.cpu_sof = cpu_sof
|
||||
self.zephyr_base = zephyr_base
|
||||
|
||||
def replaces_shell_script(shell_script, command):
|
||||
return command == 'flash' and shell_script == 'nios2.sh'
|
||||
|
||||
def create_from_env(command, debug):
|
||||
'''Create runner from environment.
|
||||
|
||||
Required:
|
||||
|
||||
- O: build output directory
|
||||
- KERNEL_HEX_NAME: name of kernel binary in HEX format
|
||||
- NIOS2_CPU_SOF: location of the CPU .sof data
|
||||
- ZEPHYR_BASE: zephyr Git repository base directory
|
||||
'''
|
||||
hex_ = path.join(get_env_or_bail('O'),
|
||||
get_env_or_bail('KERNEL_HEX_NAME'))
|
||||
cpu_sof = get_env_or_bail('NIOS2_CPU_SOF')
|
||||
zephyr_base = get_env_or_bail('ZEPHYR_BASE')
|
||||
|
||||
return Nios2BinaryRunner(hex_, cpu_sof, zephyr_base, 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):
|
||||
cmd = [path.join(self.zephyr_base, 'scripts', 'support',
|
||||
'quartus-flash.py'),
|
||||
'--sof', self.cpu_sof,
|
||||
'--kernel', self.hex_]
|
||||
|
||||
self.check_call(cmd)
|
||||
|
||||
def debug_debugserver(command, **kwargs):
|
||||
raise NotImplementedError()
|
96
scripts/support/runner/nrfjprog.py
Normal file
96
scripts/support/runner/nrfjprog.py
Normal file
|
@ -0,0 +1,96 @@
|
|||
# Copyright (c) 2017 Linaro Limited.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
'''Runner for flashing with nrfjprog.'''
|
||||
|
||||
from os import path
|
||||
import sys
|
||||
|
||||
from .core import ZephyrBinaryRunner, get_env_or_bail
|
||||
|
||||
|
||||
class NrfJprogBinaryRunner(ZephyrBinaryRunner):
|
||||
'''Runner front-end for nrfjprog.'''
|
||||
|
||||
def __init__(self, hex_, family, board, debug=False):
|
||||
super(NrfJprogBinaryRunner, self).__init__(debug=debug)
|
||||
self.hex_ = hex_
|
||||
self.family = family
|
||||
self.board = board
|
||||
|
||||
def replaces_shell_script(shell_script, command):
|
||||
return command == 'flash' and shell_script == 'nrf_flash.sh'
|
||||
|
||||
def create_from_env(command, debug):
|
||||
'''Create flasher from environment.
|
||||
|
||||
Required:
|
||||
|
||||
- O: build output directory
|
||||
- KERNEL_HEX_NAME: name of kernel binary in ELF format
|
||||
- NRF_FAMILY: e.g. NRF51 or NRF52
|
||||
- BOARD: Zephyr board name
|
||||
'''
|
||||
hex_ = path.join(get_env_or_bail('O'),
|
||||
get_env_or_bail('KERNEL_HEX_NAME'))
|
||||
family = get_env_or_bail('NRF_FAMILY')
|
||||
board = get_env_or_bail('BOARD')
|
||||
|
||||
return NrfJprogBinaryRunner(hex_, family, board, debug=debug)
|
||||
|
||||
def get_board_snr_from_user(self):
|
||||
snrs = self.check_output(['nrfjprog', '--ids'])
|
||||
snrs = snrs.decode(sys.getdefaultencoding()).strip().splitlines()
|
||||
|
||||
if len(snrs) == 1:
|
||||
return snrs[0]
|
||||
|
||||
print('There are multiple boards connected.')
|
||||
for i, snr in enumerate(snrs, 1):
|
||||
print('{}. {}'.format(i, snr))
|
||||
|
||||
p = 'Please select one with desired serial number (1-{}): '.format(
|
||||
len(snrs))
|
||||
while True:
|
||||
value = input(p)
|
||||
try:
|
||||
value = int(value)
|
||||
except ValueError:
|
||||
continue
|
||||
if 1 <= value <= len(snrs):
|
||||
break
|
||||
|
||||
return snrs[value - 1]
|
||||
|
||||
def run(self, command, **kwargs):
|
||||
if command != 'flash':
|
||||
raise ValueError('only flash is supported')
|
||||
|
||||
board_snr = self.get_board_snr_from_user()
|
||||
|
||||
print('Flashing file: {}'.format(self.hex_))
|
||||
commands = [
|
||||
['nrfjprog', '--eraseall', '-f', self.family, '--snr', board_snr],
|
||||
['nrfjprog', '--program', self.hex_, '-f', self.family, '--snr',
|
||||
board_snr],
|
||||
]
|
||||
if self.family == 'NRF52':
|
||||
commands.extend([
|
||||
# Set reset pin
|
||||
['nrfjprog', '--memwr', '0x10001200', '--val', '0x00000015',
|
||||
'-f', self.family, '--snr', board_snr],
|
||||
['nrfjprog', '--memwr', '0x10001204', '--val', '0x00000015',
|
||||
'-f', self.family, '--snr', board_snr],
|
||||
['nrfjprog', '--reset', '-f', self.family, '--snr', board_snr],
|
||||
])
|
||||
commands.append(['nrfjprog',
|
||||
'--pinreset',
|
||||
'-f', self.family,
|
||||
'--snr', board_snr])
|
||||
|
||||
for cmd in commands:
|
||||
self.check_call(cmd)
|
||||
|
||||
print('{} Serial Number {} flashed with success.'.format(
|
||||
self.board, board_snr))
|
209
scripts/support/runner/openocd.py
Normal file
209
scripts/support/runner/openocd.py
Normal file
|
@ -0,0 +1,209 @@
|
|||
# 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
|
||||
- ARCH: board architecture
|
||||
- BOARD_NAME: zephyr name of board
|
||||
|
||||
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')
|
||||
arch = get_env_or_bail('ARCH')
|
||||
board_name = get_env_or_bail('BOARD_NAME')
|
||||
openocd_config = path.join(zephyr_base, 'boards', arch,
|
||||
board_name, '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)
|
157
scripts/support/runner/pyocd.py
Normal file
157
scripts/support/runner/pyocd.py
Normal file
|
@ -0,0 +1,157 @@
|
|||
# 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)
|
File diff suppressed because it is too large
Load diff
Loading…
Add table
Add a link
Reference in a new issue