west: runner: add support for stm32flash runner
Add stm32flash runner and 8 stm32flash runner tests Signed-off-by: Thomas Kupper <thomas.kupper@gmail.com>
This commit is contained in:
parent
991287b26a
commit
ef0e3ed31d
4
boards/common/stm32flash.board.cmake
Normal file
4
boards/common/stm32flash.board.cmake
Normal file
|
@ -0,0 +1,4 @@
|
|||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
board_set_flasher_ifnset(stm32flash)
|
||||
board_finalize_runner_args(stm32flash)
|
|
@ -26,6 +26,7 @@ from runners import qemu
|
|||
from runners import xtensa
|
||||
from runners import intel_s1000
|
||||
from runners import blackmagicprobe
|
||||
from runners import stm32flash
|
||||
|
||||
def get_runner_cls(runner):
|
||||
'''Get a runner's class object, given its name.'''
|
||||
|
|
150
scripts/west_commands/runners/stm32flash.py
Normal file
150
scripts/west_commands/runners/stm32flash.py
Normal file
|
@ -0,0 +1,150 @@
|
|||
# Copyright (c) 2019 Thomas Kupper <thomas.kupper@gmail.com>
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
'''Runner for flashing with stm32flash.'''
|
||||
|
||||
from os import path
|
||||
import platform
|
||||
|
||||
from runners.core import ZephyrBinaryRunner, RunnerCaps
|
||||
|
||||
DEFAULT_DEVICE = '/dev/ttyUSB0'
|
||||
if platform.system() == 'Darwin':
|
||||
DEFAULT_DEVICE = '/dev/tty.SLAB_USBtoUART'
|
||||
|
||||
class Stm32flashBinaryRunner(ZephyrBinaryRunner):
|
||||
'''Runner front-end for stm32flash.'''
|
||||
|
||||
def __init__(self, cfg, device, action='write', baud=57600,
|
||||
force_binary=False, start_addr=0, exec_addr=None,
|
||||
serial_mode='8e1', reset=False, verify=False):
|
||||
super(Stm32flashBinaryRunner, self).__init__(cfg)
|
||||
|
||||
self.device = device
|
||||
self.action = action
|
||||
self.baud = baud
|
||||
self.force_binary = force_binary
|
||||
self.start_addr = start_addr
|
||||
self.exec_addr = exec_addr
|
||||
self.serial_mode = serial_mode
|
||||
self.reset = reset
|
||||
self.verify = verify
|
||||
|
||||
@classmethod
|
||||
def name(cls):
|
||||
return 'stm32flash'
|
||||
|
||||
@classmethod
|
||||
def capabilities(cls):
|
||||
return RunnerCaps(commands={'flash'})
|
||||
|
||||
@classmethod
|
||||
def do_add_parser(cls, parser):
|
||||
|
||||
# required argument(s)
|
||||
# none for now
|
||||
|
||||
# optional argument(s)
|
||||
parser.add_argument('--device', default=DEFAULT_DEVICE, required=False,
|
||||
help='serial port to flash, default \'' + DEFAULT_DEVICE + '\'')
|
||||
|
||||
parser.add_argument('--action', default='write', required=False,
|
||||
choices=['erase', 'info', 'start', 'write'],
|
||||
help='erase / get device info / start execution / write flash')
|
||||
|
||||
parser.add_argument('--baud-rate', default='57600', required=False,
|
||||
choices=['1200', '1800', '2400', '4800', '9600', '19200',
|
||||
'38400', '57600', '115200', '230400', '256000', '460800',
|
||||
'500000', '576000', '921600', '1000000', '1500000', '2000000'],
|
||||
help='serial baud rate, default \'57600\'')
|
||||
|
||||
parser.add_argument('--force-binary', required=False, action='store_true',
|
||||
help='force the binary parser')
|
||||
|
||||
parser.add_argument('--start-addr', default=0, required=False,
|
||||
help='specify start address for write operation, default \'0\'')
|
||||
|
||||
parser.add_argument('--execution-addr', default=None, required=False,
|
||||
help='start execution at specified address, default \'0\' \
|
||||
which means start of flash')
|
||||
|
||||
parser.add_argument('--serial-mode', default='8e1', required=False,
|
||||
help='serial port mode, default \'8e1\'')
|
||||
|
||||
parser.add_argument('--reset', default=False, required=False, action='store_true',
|
||||
help='reset device at exit, default False')
|
||||
|
||||
parser.add_argument('--verify', default=False, required=False, action='store_true',
|
||||
help='verify writes, default False')
|
||||
|
||||
@classmethod
|
||||
def create(cls, cfg, args):
|
||||
return Stm32flashBinaryRunner(cfg, device=args.device, action=args.action,
|
||||
baud=args.baud_rate, force_binary=args.force_binary,
|
||||
start_addr=args.start_addr, exec_addr=args.execution_addr,
|
||||
serial_mode=args.serial_mode, reset=args.reset, verify=args.verify)
|
||||
|
||||
def do_run(self, command, **kwargs):
|
||||
self.require('stm32flash')
|
||||
|
||||
bin_name = self.cfg.bin_file
|
||||
bin_size = path.getsize(bin_name)
|
||||
|
||||
cmd_flash = ['stm32flash', '-b', self.baud,
|
||||
'-m', self.serial_mode]
|
||||
|
||||
action = self.action.lower()
|
||||
msg_text = "something went wrong"
|
||||
|
||||
if action == 'info':
|
||||
# show device information and exit
|
||||
msg_text = "get device info from {}".format(self.device)
|
||||
|
||||
elif action == 'erase':
|
||||
# erase flash
|
||||
#size_aligned = (int(bin_size) >> 12) + 1 << 12
|
||||
size_aligned = (int(bin_size) & 0xfffff000) + 4096
|
||||
msg_text = "erase {} bit starting at {}".format(size_aligned, self.start_addr)
|
||||
cmd_flash.extend([
|
||||
'-S', self.start_addr + ":" + str(size_aligned), '-o'])
|
||||
|
||||
elif action == 'start':
|
||||
# start execution
|
||||
msg_text = "start code execution at {}".format(self.exec_addr)
|
||||
if self.exec_addr:
|
||||
if self.exec_addr == 0 or self.exec_addr.lower() == '0x0':
|
||||
msg_text += " (flash start)"
|
||||
else:
|
||||
self.exec_addr = 0
|
||||
cmd_flash.extend([
|
||||
'-g', str(self.exec_addr)])
|
||||
|
||||
elif action == 'write':
|
||||
# flash binary file
|
||||
msg_text = "write {} bytes starting at {}".format(bin_size, self.start_addr)
|
||||
cmd_flash.extend([
|
||||
'-S', self.start_addr + ":" + str(bin_size),
|
||||
'-w', bin_name])
|
||||
|
||||
if self.exec_addr:
|
||||
cmd_flash.extend(['-g', self.exec_addr])
|
||||
|
||||
if self.force_binary:
|
||||
cmd_flash.extend(['-f'])
|
||||
|
||||
if self.reset:
|
||||
cmd_flash.extend(['-R'])
|
||||
|
||||
if self.verify:
|
||||
cmd_flash.extend(['-v'])
|
||||
|
||||
else:
|
||||
msg_text = "invalid action \'{}\' passed!".format(action)
|
||||
self.logger.error('Invalid action \'{}\' passed!'.format(action))
|
||||
return -1
|
||||
|
||||
cmd_flash.extend([self.device])
|
||||
self.logger.info("Board: " + msg_text)
|
||||
self.check_call(cmd_flash)
|
||||
self.logger.info('Board: finished \'{}\' .'.format(action))
|
|
@ -15,5 +15,5 @@ def test_runner_imports():
|
|||
expected = set(('arc-nsim', 'bossac', 'dfu-util', 'em-starterkit', 'esp32',
|
||||
'hifive1', 'jlink', 'nios2', 'nrfjprog', 'openocd', 'pyocd',
|
||||
'qemu', 'xtensa', 'intel_s1000', 'blackmagicprobe',
|
||||
'dediprog'))
|
||||
'dediprog', 'stm32flash'))
|
||||
assert runner_names == expected
|
||||
|
|
103
scripts/west_commands/tests/test_stm32flash.py
Normal file
103
scripts/west_commands/tests/test_stm32flash.py
Normal file
|
@ -0,0 +1,103 @@
|
|||
# Copyright (c) 2019 Thomas Kupper
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
import argparse
|
||||
import os
|
||||
import platform
|
||||
from unittest.mock import patch, call
|
||||
|
||||
import pytest
|
||||
|
||||
from runners.stm32flash import Stm32flashBinaryRunner
|
||||
from conftest import RC_KERNEL_BIN
|
||||
|
||||
TEST_CMD = 'stm32flash'
|
||||
|
||||
TEST_DEVICE = '/dev/ttyUSB0'
|
||||
if platform.system() == 'Darwin':
|
||||
TEST_DEVICE = '/dev/tty.SLAB_USBtoUART'
|
||||
TEST_BAUD = '115200'
|
||||
TEST_FORCE_BINARY = False
|
||||
TEST_ADDR = '0x08000000'
|
||||
TEST_BIN_SIZE = '4095'
|
||||
TEST_EXEC_ADDR = '0'
|
||||
TEST_SERIAL_MODE = '8e1'
|
||||
TEST_RESET = False
|
||||
TEST_VERIFY = False
|
||||
|
||||
# Expected subprocesses to be run for each action. Using the
|
||||
# runner_config fixture (and always specifying all necessary
|
||||
# parameters) means we don't get 100% coverage, but it's a
|
||||
# starting out point.
|
||||
EXPECTED_COMMANDS = {
|
||||
'info':
|
||||
([TEST_CMD,
|
||||
'-b', TEST_BAUD,
|
||||
'-m', TEST_SERIAL_MODE,
|
||||
TEST_DEVICE],),
|
||||
'erase':
|
||||
([TEST_CMD,
|
||||
'-b', TEST_BAUD,
|
||||
'-m', TEST_SERIAL_MODE,
|
||||
'-S', TEST_ADDR + ":" + str((int(TEST_BIN_SIZE) >> 12) + 1 << 12),
|
||||
'-o', TEST_DEVICE],),
|
||||
'start':
|
||||
([TEST_CMD,
|
||||
'-b', TEST_BAUD,
|
||||
'-m', TEST_SERIAL_MODE,
|
||||
'-g', TEST_EXEC_ADDR, TEST_DEVICE],),
|
||||
|
||||
'write':
|
||||
([TEST_CMD,
|
||||
'-b', TEST_BAUD,
|
||||
'-m', TEST_SERIAL_MODE,
|
||||
'-S', TEST_ADDR + ":" + TEST_BIN_SIZE,
|
||||
'-w', RC_KERNEL_BIN,
|
||||
TEST_DEVICE],),
|
||||
}
|
||||
|
||||
def require_patch(program):
|
||||
assert program == TEST_CMD
|
||||
|
||||
def os_path_getsize_patch(filename):
|
||||
if filename == RC_KERNEL_BIN:
|
||||
return TEST_BIN_SIZE
|
||||
return os.path.isfile(filename)
|
||||
|
||||
@pytest.mark.parametrize('action', EXPECTED_COMMANDS)
|
||||
@patch('runners.core.ZephyrBinaryRunner.require', side_effect=require_patch)
|
||||
@patch('runners.core.ZephyrBinaryRunner.check_call')
|
||||
def test_stm32flash_init(cc, req, action, runner_config):
|
||||
'''Test actions using a runner created by constructor.'''
|
||||
test_exec_addr = TEST_EXEC_ADDR
|
||||
if action == 'write':
|
||||
test_exec_addr = None
|
||||
|
||||
runner = Stm32flashBinaryRunner(runner_config, device=TEST_DEVICE,
|
||||
action=action, baud=TEST_BAUD, force_binary=TEST_FORCE_BINARY,
|
||||
start_addr=TEST_ADDR, exec_addr=test_exec_addr,
|
||||
serial_mode=TEST_SERIAL_MODE, reset=TEST_RESET, verify=TEST_VERIFY)
|
||||
|
||||
with patch('os.path.getsize', side_effect=os_path_getsize_patch):
|
||||
runner.run('flash')
|
||||
assert cc.call_args_list == [call(x) for x in EXPECTED_COMMANDS[action]]
|
||||
|
||||
@pytest.mark.parametrize('action', EXPECTED_COMMANDS)
|
||||
@patch('runners.core.ZephyrBinaryRunner.require', side_effect=require_patch)
|
||||
@patch('runners.core.ZephyrBinaryRunner.check_call')
|
||||
def test_stm32flash_create(cc, req, action, runner_config):
|
||||
'''Test actions using a runner created from action line parameters.'''
|
||||
if action == 'start':
|
||||
args = ['--action', action, '--baud-rate', TEST_BAUD, '--start-addr', TEST_ADDR,
|
||||
'--execution-addr', TEST_EXEC_ADDR]
|
||||
else:
|
||||
args = ['--action', action, '--baud-rate', TEST_BAUD, '--start-addr', TEST_ADDR]
|
||||
|
||||
parser = argparse.ArgumentParser()
|
||||
Stm32flashBinaryRunner.add_parser(parser)
|
||||
arg_namespace = parser.parse_args(args)
|
||||
runner = Stm32flashBinaryRunner.create(runner_config, arg_namespace)
|
||||
with patch('os.path.getsize', side_effect=os_path_getsize_patch):
|
||||
runner.run('flash')
|
||||
assert cc.call_args_list == [call(x) for x in EXPECTED_COMMANDS[action]]
|
Loading…
Reference in a new issue