Black Magic Probe supports a "monitor connect_srst" command [1] to configure whether to assert reset when connecting to the target. This is useful to reprogram a target that may be idling in a low power state, with an otherwise unresponsive debug core. Adding a --connect-srst runner option for enabling this for "flash" and "debug" operations to ensure that programming works in that case, but also explicitly disabling it for "attach", to allow attaching to a running target without changing its state. Not turning this on by default since apparently some MCUs disable the SWD interface while in reset. [1] https://github.com/blacksphere/blackmagic/wiki/Useful-GDB-commands Signed-off-by: Fabio Baltieri <fabio.baltieri@gmail.com>
118 lines
4.4 KiB
Python
118 lines
4.4 KiB
Python
# Copyright (c) 2018 Roman Tataurov <diytronic@yandex.ru>
|
|
# Modified 2018 Tavish Naruka <tavishnaruka@gmail.com>
|
|
#
|
|
# SPDX-License-Identifier: Apache-2.0
|
|
'''Runner for flashing with Black Magic Probe.'''
|
|
# https://github.com/blacksphere/blackmagic/wiki
|
|
|
|
import signal
|
|
|
|
from runners.core import ZephyrBinaryRunner, RunnerCaps
|
|
|
|
class BlackMagicProbeRunner(ZephyrBinaryRunner):
|
|
'''Runner front-end for Black Magic probe.'''
|
|
|
|
def __init__(self, cfg, gdb_serial, connect_srst=False):
|
|
super().__init__(cfg)
|
|
self.gdb = [cfg.gdb] if cfg.gdb else None
|
|
self.elf_file = cfg.elf_file
|
|
self.gdb_serial = gdb_serial
|
|
if connect_srst:
|
|
self.connect_srst_enable_arg = [
|
|
'-ex', "monitor connect_srst enable"]
|
|
self.connect_srst_disable_arg = [
|
|
'-ex', "monitor connect_srst disable"]
|
|
else:
|
|
self.connect_srst_enable_arg = []
|
|
self.connect_srst_disable_arg = []
|
|
|
|
@classmethod
|
|
def name(cls):
|
|
return 'blackmagicprobe'
|
|
|
|
@classmethod
|
|
def capabilities(cls):
|
|
return RunnerCaps(commands={'flash', 'debug', 'attach'})
|
|
|
|
@classmethod
|
|
def do_create(cls, cfg, args):
|
|
return BlackMagicProbeRunner(cfg, args.gdb_serial, args.connect_srst)
|
|
|
|
@classmethod
|
|
def do_add_parser(cls, parser):
|
|
parser.add_argument('--gdb-serial', default='/dev/ttyACM0',
|
|
help='GDB serial port')
|
|
parser.add_argument('--connect-srst', action='store_true',
|
|
help='Assert SRST during connect? (default: no)')
|
|
|
|
def bmp_flash(self, command, **kwargs):
|
|
if self.elf_file is None:
|
|
raise ValueError('Cannot debug; elf file is missing')
|
|
command = (self.gdb +
|
|
['-ex', "set confirm off",
|
|
'-ex', "target extended-remote {}".format(
|
|
self.gdb_serial)] +
|
|
self.connect_srst_enable_arg +
|
|
['-ex', "monitor swdp_scan",
|
|
'-ex', "attach 1",
|
|
'-ex', "load {}".format(self.elf_file),
|
|
'-ex', "kill",
|
|
'-ex', "quit",
|
|
'-silent'])
|
|
self.check_call(command)
|
|
|
|
def check_call_ignore_sigint(self, command):
|
|
previous = signal.signal(signal.SIGINT, signal.SIG_IGN)
|
|
try:
|
|
self.check_call(command)
|
|
finally:
|
|
signal.signal(signal.SIGINT, previous)
|
|
|
|
def bmp_attach(self, command, **kwargs):
|
|
if self.elf_file is None:
|
|
command = (self.gdb +
|
|
['-ex', "set confirm off",
|
|
'-ex', "target extended-remote {}".format(
|
|
self.gdb_serial)] +
|
|
self.connect_srst_disable_arg +
|
|
['-ex', "monitor swdp_scan",
|
|
'-ex', "attach 1"])
|
|
else:
|
|
command = (self.gdb +
|
|
['-ex', "set confirm off",
|
|
'-ex', "target extended-remote {}".format(
|
|
self.gdb_serial)] +
|
|
self.connect_srst_disable_arg +
|
|
['-ex', "monitor swdp_scan",
|
|
'-ex', "attach 1",
|
|
'-ex', "file {}".format(self.elf_file)])
|
|
self.check_call_ignore_sigint(command)
|
|
|
|
def bmp_debug(self, command, **kwargs):
|
|
if self.elf_file is None:
|
|
raise ValueError('Cannot debug; elf file is missing')
|
|
command = (self.gdb +
|
|
['-ex', "set confirm off",
|
|
'-ex', "target extended-remote {}".format(
|
|
self.gdb_serial)] +
|
|
self.connect_srst_enable_arg +
|
|
['-ex', "monitor swdp_scan",
|
|
'-ex', "attach 1",
|
|
'-ex', "file {}".format(self.elf_file),
|
|
'-ex', "load {}".format(self.elf_file)])
|
|
self.check_call_ignore_sigint(command)
|
|
|
|
def do_run(self, command, **kwargs):
|
|
if self.gdb is None:
|
|
raise ValueError('Cannot execute; gdb not specified')
|
|
self.require(self.gdb[0])
|
|
|
|
if command == 'flash':
|
|
self.bmp_flash(command, **kwargs)
|
|
elif command == 'debug':
|
|
self.bmp_debug(command, **kwargs)
|
|
elif command == 'attach':
|
|
self.bmp_attach(command, **kwargs)
|
|
else:
|
|
self.bmp_flash(command, **kwargs)
|