build: interpose zephyr_flash_debug.py in flash target
Zephyr board flashing and debugging is done via shell scripts. It would improve the CMake transition to remove the shell dependency. Add zephyr_flash_debug.py to allow phasing out the shell scripts. This takes two arguments: - a command (eventually flash, debug, and debugserver, but just flash for now) - the path to the corresponding shell script zephyr_flash_debug.py runs the command in pure Python if it knows how. Otherwise, it falls back on the shell script. In this patch, it always falls back. Subsequent patches add support for existing flash backends. Invoke zephyr_flash_debug.py from the Makefile flash target, but only if USE_ZEPHYR_FLASH_DEBUG_SHELL is empty. This lets users keep existing behavior in case of issues, and can be removed later once the Python script is more widely tested. Signed-off-by: Marti Bolivar <marti.bolivar@linaro.org>
This commit is contained in:
parent
c136a2eb83
commit
113ee65b89
6
Makefile
6
Makefile
|
@ -1374,9 +1374,15 @@ run:
|
|||
endif
|
||||
|
||||
ifneq ($(FLASH_SCRIPT),)
|
||||
ifeq ($(USE_ZEPHYR_FLASH_DEBUG_SHELL),)
|
||||
flash: zephyr
|
||||
@echo "Flashing $(BOARD_NAME)"
|
||||
$(Q)$(srctree)/scripts/support/zephyr_flash_debug.py flash $(srctree)/scripts/support/$(FLASH_SCRIPT)
|
||||
else
|
||||
flash: zephyr
|
||||
@echo "Flashing $(BOARD_NAME)"
|
||||
$(Q)$(CONFIG_SHELL) $(srctree)/scripts/support/$(FLASH_SCRIPT) flash
|
||||
endif
|
||||
else
|
||||
flash: FORCE
|
||||
@echo Flashing not supported with this board.
|
||||
|
|
105
scripts/support/zephyr_flash_debug.py
Executable file
105
scripts/support/zephyr_flash_debug.py
Executable file
|
@ -0,0 +1,105 @@
|
|||
#! /usr/bin/env python3
|
||||
|
||||
# Copyright (c) 2017 Linaro Limited.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
"""Zephyr board flashing script
|
||||
|
||||
This script is a transparent replacement for an existing Zephyr flash
|
||||
script. If it can invoke the flashing tools natively, it will do so; otherwise,
|
||||
it delegates to the shell script passed as second argument."""
|
||||
|
||||
import abc
|
||||
from os import path
|
||||
import os
|
||||
import sys
|
||||
import subprocess
|
||||
|
||||
|
||||
def get_env_bool_or(env_var, default_value):
|
||||
try:
|
||||
return bool(int(os.environ[env_var]))
|
||||
except KeyError:
|
||||
return default_value
|
||||
|
||||
|
||||
def check_call(cmd, debug):
|
||||
if debug:
|
||||
print(' '.join(cmd))
|
||||
subprocess.check_call(cmd)
|
||||
|
||||
|
||||
class ZephyrBinaryFlasher(abc.ABC):
|
||||
'''Abstract superclass for flasher objects.'''
|
||||
|
||||
def __init__(self, debug=False):
|
||||
self.debug = debug
|
||||
|
||||
@staticmethod
|
||||
def create_for_shell_script(shell_script, debug):
|
||||
'''Factory for using as a drop-in replacement to a shell script.
|
||||
|
||||
Get flasher instance to use in place of shell_script, deriving
|
||||
flasher configuration from the environment.'''
|
||||
for sub_cls in ZephyrBinaryFlasher.__subclasses__():
|
||||
if sub_cls.replaces_shell_script(shell_script):
|
||||
return sub_cls.create_from_env(debug)
|
||||
raise ValueError('no flasher replaces script {}'.format(shell_script))
|
||||
|
||||
@staticmethod
|
||||
@abc.abstractmethod
|
||||
def replaces_shell_script(shell_script):
|
||||
'''Check if this flasher class replaces FLASH_SCRIPT=shell_script.'''
|
||||
|
||||
@staticmethod
|
||||
@abc.abstractmethod
|
||||
def create_from_env(debug):
|
||||
'''Create new flasher instance from environment variables.
|
||||
|
||||
This class must be able to replace the current FLASH_SCRIPT. The
|
||||
environment variables expected by that script are used to build
|
||||
the flasher in a backwards-compatible manner.'''
|
||||
|
||||
@abc.abstractmethod
|
||||
def flash(self, **kwargs):
|
||||
'''Flash the board.'''
|
||||
|
||||
|
||||
# TODO: Stop using environment variables.
|
||||
#
|
||||
# Migrate the build system so we can use an argparse.ArgumentParser and
|
||||
# per-flasher subparsers, so invoking the script becomes something like:
|
||||
#
|
||||
# python zephyr_flash_debug.py openocd --openocd-bin=/openocd/path ...
|
||||
#
|
||||
# For now, maintain compatibility.
|
||||
def flash(shell_script_full, debug):
|
||||
shell_script = path.basename(shell_script_full)
|
||||
try:
|
||||
flasher = ZephyrBinaryFlasher.create_for_shell_script(shell_script,
|
||||
debug)
|
||||
except ValueError:
|
||||
# Can't create a flasher; fall back on shell script.
|
||||
check_call([shell_script_full, 'flash'], debug)
|
||||
return
|
||||
|
||||
flasher.flash()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
debug = True
|
||||
try:
|
||||
debug = get_env_bool_or('KBUILD_VERBOSE', False)
|
||||
if len(sys.argv) != 3 or sys.argv[1] != 'flash':
|
||||
raise ValueError('usage: {} flash path-to-script'.format(
|
||||
sys.argv[0]))
|
||||
flash(sys.argv[2], debug)
|
||||
except Exception as e:
|
||||
if debug:
|
||||
raise
|
||||
else:
|
||||
print('Error: {}'.format(e), file=sys.stderr)
|
||||
print('Re-run with KBUILD_VERBOSE=1 for a stack trace.',
|
||||
file=sys.stderr)
|
||||
sys.exit(1)
|
Loading…
Reference in a new issue