mirror of
https://github.com/zephyrproject-rtos/zephyr
synced 2025-08-14 01:16:15 +00:00
West now supports a mechanism for extension commands. Use it to move the command implementations that are tightly coupled with boards and the zephyr build system back into the Zephyr repository. This patch doesn't include test cases. Those will be moved over in a subsequent patch. Signed-off-by: Marti Bolivar <marti@foundries.io>
123 lines
4.3 KiB
Python
123 lines
4.3 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 west import log
|
|
|
|
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(DfuUtilBinaryRunner, self).__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
|
|
|
|
@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='''set if target is a DfuSe device;
|
|
implies --dt-flash.''')
|
|
parser.add_argument("--dfuse-modifiers", default='leave',
|
|
help='''colon-separated list of DfuSe modifiers
|
|
(default is "leave", which starts execution
|
|
immediately); --dfuse must also be given for this
|
|
option to take effect.''')
|
|
parser.add_argument('--dfu-util', default='dfu-util',
|
|
help='dfu-util executable; defaults to "dfu-util"')
|
|
|
|
@classmethod
|
|
def 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
|
|
|
|
return DfuUtilBinaryRunner(cfg, args.pid, args.alt, args.img,
|
|
exe=args.dfu_util, dfuse_config=dcfg)
|
|
|
|
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):
|
|
reset = False
|
|
if not self.find_device():
|
|
reset = True
|
|
log.dbg('Device not found, waiting for it',
|
|
level=log.VERBOSE_EXTREME)
|
|
# Use of print() here is advised. We don't want to lose
|
|
# this information in a separate log -- this is
|
|
# interactive and requires a terminal.
|
|
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:
|
|
# 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.
|
|
reset = False
|
|
if reset:
|
|
print('Now reset your board again to switch back to runtime mode.')
|