mirror of
https://github.com/zephyrproject-rtos/zephyr
synced 2025-08-03 05:43:45 +00:00
Require all implementations to provide a do_create(), a new ZephyrBinaryRunner abstract class method, and make create() itself concrete. This allows us to enforce common conventions related to individual runner capabilities as each runner provides to the core via RunnerCaps. For now, just enforce that: - common options related to capabilities are always added, so runners can't reuse them for different ends - common options provided for runners which don't support them emit sensible error messages that should be easy to diagnose and support Signed-off-by: Martí Bolívar <marti.bolivar@nordicsemi.no>
131 lines
4.6 KiB
Python
131 lines
4.6 KiB
Python
# Copyright (c) 2017 Linaro Limited.
|
|
#
|
|
# SPDX-License-Identifier: Apache-2.0
|
|
|
|
'''Runner for flashing with dfu-util.'''
|
|
|
|
from collections import namedtuple
|
|
import sys
|
|
import time
|
|
|
|
from runners.core import ZephyrBinaryRunner, RunnerCaps, \
|
|
BuildConfiguration
|
|
|
|
|
|
DfuSeConfig = namedtuple('DfuSeConfig', ['address', 'options'])
|
|
|
|
|
|
class DfuUtilBinaryRunner(ZephyrBinaryRunner):
|
|
'''Runner front-end for dfu-util.'''
|
|
|
|
def __init__(self, cfg, pid, alt, img, exe='dfu-util',
|
|
dfuse_config=None):
|
|
super().__init__(cfg)
|
|
self.alt = alt
|
|
self.img = img
|
|
self.cmd = [exe, '-d,{}'.format(pid)]
|
|
try:
|
|
self.list_pattern = ', alt={},'.format(int(self.alt))
|
|
except ValueError:
|
|
self.list_pattern = ', name="{}",'.format(self.alt)
|
|
|
|
if dfuse_config is None:
|
|
self.dfuse = False
|
|
else:
|
|
self.dfuse = True
|
|
self.dfuse_config = dfuse_config
|
|
self.reset = False
|
|
|
|
@classmethod
|
|
def name(cls):
|
|
return 'dfu-util'
|
|
|
|
@classmethod
|
|
def capabilities(cls):
|
|
return RunnerCaps(commands={'flash'}, flash_addr=True)
|
|
|
|
@classmethod
|
|
def do_add_parser(cls, parser):
|
|
# Required:
|
|
parser.add_argument("--pid", required=True,
|
|
help="USB VID:PID of the board")
|
|
parser.add_argument("--alt", required=True,
|
|
help="interface alternate setting number or name")
|
|
|
|
# Optional:
|
|
parser.add_argument("--img",
|
|
help="binary to flash, default is --bin-file")
|
|
parser.add_argument("--dfuse", default=False, action='store_true',
|
|
help='''use the DfuSe protocol extensions
|
|
supported by STMicroelectronics
|
|
devices (if given, the image flash
|
|
address respects
|
|
CONFIG_FLASH_BASE_ADDRESS and
|
|
CONFIG_FLASH_LOAD_OFFSET)''')
|
|
parser.add_argument("--dfuse-modifiers", default='leave',
|
|
help='''colon-separated list of additional
|
|
DfuSe modifiers for dfu-util's -s
|
|
option (default is
|
|
"-s <flash-address>:leave", which starts
|
|
execution immediately); requires
|
|
--dfuse
|
|
''')
|
|
parser.add_argument('--dfu-util', default='dfu-util',
|
|
help='dfu-util executable; defaults to "dfu-util"')
|
|
|
|
@classmethod
|
|
def do_create(cls, cfg, args):
|
|
if args.img is None:
|
|
args.img = cfg.bin_file
|
|
|
|
if args.dfuse:
|
|
args.dt_flash = True # --dfuse implies --dt-flash.
|
|
build_conf = BuildConfiguration(cfg.build_dir)
|
|
dcfg = DfuSeConfig(address=cls.get_flash_address(args, build_conf),
|
|
options=args.dfuse_modifiers)
|
|
else:
|
|
dcfg = None
|
|
|
|
ret = DfuUtilBinaryRunner(cfg, args.pid, args.alt, args.img,
|
|
exe=args.dfu_util, dfuse_config=dcfg)
|
|
ret.ensure_device()
|
|
return ret
|
|
|
|
def ensure_device(self):
|
|
if not self.find_device():
|
|
self.reset = True
|
|
print('Please reset your board to switch to DFU mode...')
|
|
while not self.find_device():
|
|
time.sleep(0.1)
|
|
|
|
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 do_run(self, command, **kwargs):
|
|
self.require(self.cmd[0])
|
|
|
|
if not self.find_device():
|
|
raise RuntimeError('device not found')
|
|
|
|
cmd = list(self.cmd)
|
|
if self.dfuse:
|
|
# http://dfu-util.sourceforge.net/dfuse.html
|
|
dcfg = self.dfuse_config
|
|
addr_opts = hex(dcfg.address) + ':' + dcfg.options
|
|
cmd.extend(['-s', addr_opts])
|
|
cmd.extend(['-a', self.alt, '-D', self.img])
|
|
self.check_call(cmd)
|
|
|
|
if self.dfuse and 'leave' in dcfg.options.split(':'):
|
|
# Normal DFU devices generally need to be reset to switch
|
|
# back to the flashed program.
|
|
#
|
|
# DfuSe targets do as well, except when 'leave' is given
|
|
# as an option.
|
|
self.reset = False
|
|
if self.reset:
|
|
print('Now reset your board again to switch back to runtime mode.')
|