blob: 052c45dbb49cd8cf202e9ab7f1fff186c76e77e5 [file] [log] [blame]
# 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().__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 do_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')
self.ensure_output('bin')
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()
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', str(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', str(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))