Add the build directory to the central runner configuration. This is commonly useful information. The first place we can use it is to eliminate guessing the current working directory when building objects to parse .config. It's not necessary to modify the build system for this, so leave the relevant command line flag among the general options. Signed-off-by: Marti Bolivar <marti@opensourcefoundries.com>
122 lines
4.3 KiB
Python
122 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 os
|
|
import sys
|
|
import time
|
|
|
|
from .. import log
|
|
from .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 --kernel-bin")
|
|
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.kernel_bin
|
|
|
|
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.')
|