runners: opeocd: Allow loading Elf-files
In some cases especially for on-going development & debugging of real application it might be useful to load and run not from flash but from RAM in that case there's one catch: we cannot reset the board after loading memory with our app. That's because: a) RAM we use might be either cleared on reset or might enter unpredictable state with portion of previously loaded data being corrupted. b) Reset vector most probably still point to ROM/flash and so our current application won't be executed on reset. So instead of "run reset" command of OpenOCD we'll use "resume 0x12345678". Where 0x12345678 is our application's entry-point (which BTW may very well not match beginning of the .text section or link base). Now to extract the entry-point we need our application's zephyr.elf and since we already have a requirement for Elf we may use it for loading because OpenOCD does it perfectly fine moreover automatically detecting loaded image type (binary, hex, Elf etc). And to use that nice feature just add "--use-elf" to west's command-line for boards that use "openocd" runner. Like that: ----------->8-------------- west flash --use-elf ----------->8-------------- Signed-off-by: Alexey Brodkin <abrodkin@synopsys.com>
This commit is contained in:
parent
946ed0e369
commit
83b346edef
3 changed files with 36 additions and 4 deletions
1
.github/workflows/doc-build.yml
vendored
1
.github/workflows/doc-build.yml
vendored
|
@ -33,6 +33,7 @@ jobs:
|
||||||
pip3 install 'breathe>=4.9.1' 'docutils>=0.14' \
|
pip3 install 'breathe>=4.9.1' 'docutils>=0.14' \
|
||||||
'sphinx>=1.7.5' sphinx_rtd_theme sphinx-tabs \
|
'sphinx>=1.7.5' sphinx_rtd_theme sphinx-tabs \
|
||||||
sphinxcontrib-svg2pdfconverter 'west>=0.6.2'
|
sphinxcontrib-svg2pdfconverter 'west>=0.6.2'
|
||||||
|
pip3 install pyelftools
|
||||||
|
|
||||||
- name: west setup
|
- name: west setup
|
||||||
run: |
|
run: |
|
||||||
|
|
2
.github/workflows/west_cmds.yml
vendored
2
.github/workflows/west_cmds.yml
vendored
|
@ -54,7 +54,7 @@ jobs:
|
||||||
${{ runner.os }}-pip-${{ matrix.python-version }}
|
${{ runner.os }}-pip-${{ matrix.python-version }}
|
||||||
- name: install pytest
|
- name: install pytest
|
||||||
run: |
|
run: |
|
||||||
pip3 install pytest west
|
pip3 install pytest west pyelftools
|
||||||
- name: run pytest-win
|
- name: run pytest-win
|
||||||
if: runner.os == 'Windows'
|
if: runner.os == 'Windows'
|
||||||
run: |
|
run: |
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
'''Runner for openocd.'''
|
'''Runner for openocd.'''
|
||||||
|
|
||||||
from os import path
|
from os import path
|
||||||
|
from elftools.elf.elffile import ELFFile
|
||||||
|
|
||||||
from runners.core import ZephyrBinaryRunner
|
from runners.core import ZephyrBinaryRunner
|
||||||
|
|
||||||
|
@ -18,7 +19,7 @@ class OpenOcdBinaryRunner(ZephyrBinaryRunner):
|
||||||
|
|
||||||
def __init__(self, cfg, pre_init=None, pre_load=None,
|
def __init__(self, cfg, pre_init=None, pre_load=None,
|
||||||
load_cmd=None, verify_cmd=None, post_verify=None,
|
load_cmd=None, verify_cmd=None, post_verify=None,
|
||||||
tui=None, config=None, serial=None,
|
tui=None, config=None, serial=None, use_elf=None,
|
||||||
tcl_port=DEFAULT_OPENOCD_TCL_PORT,
|
tcl_port=DEFAULT_OPENOCD_TCL_PORT,
|
||||||
telnet_port=DEFAULT_OPENOCD_TELNET_PORT,
|
telnet_port=DEFAULT_OPENOCD_TELNET_PORT,
|
||||||
gdb_port=DEFAULT_OPENOCD_GDB_PORT):
|
gdb_port=DEFAULT_OPENOCD_GDB_PORT):
|
||||||
|
@ -51,6 +52,7 @@ class OpenOcdBinaryRunner(ZephyrBinaryRunner):
|
||||||
self.gdb_cmd = [cfg.gdb] if cfg.gdb else None
|
self.gdb_cmd = [cfg.gdb] if cfg.gdb else None
|
||||||
self.tui_arg = ['-tui'] if tui else []
|
self.tui_arg = ['-tui'] if tui else []
|
||||||
self.serial = ['-c set _ZEPHYR_BOARD_SERIAL ' + serial] if serial else []
|
self.serial = ['-c set _ZEPHYR_BOARD_SERIAL ' + serial] if serial else []
|
||||||
|
self.use_elf = use_elf
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def name(cls):
|
def name(cls):
|
||||||
|
@ -62,6 +64,8 @@ class OpenOcdBinaryRunner(ZephyrBinaryRunner):
|
||||||
help='if given, override default config file')
|
help='if given, override default config file')
|
||||||
parser.add_argument('--serial', default="",
|
parser.add_argument('--serial', default="",
|
||||||
help='if given, selects FTDI instance by its serial number, defaults to empty')
|
help='if given, selects FTDI instance by its serial number, defaults to empty')
|
||||||
|
parser.add_argument('--use-elf', default=False, action='store_true',
|
||||||
|
help='if given, Elf file will be used for loading instead of HEX image')
|
||||||
# Options for flashing:
|
# Options for flashing:
|
||||||
parser.add_argument('--cmd-pre-init', action='append',
|
parser.add_argument('--cmd-pre-init', action='append',
|
||||||
help='''Command to run before calling init;
|
help='''Command to run before calling init;
|
||||||
|
@ -96,7 +100,7 @@ class OpenOcdBinaryRunner(ZephyrBinaryRunner):
|
||||||
pre_init=args.cmd_pre_init,
|
pre_init=args.cmd_pre_init,
|
||||||
pre_load=args.cmd_pre_load, load_cmd=args.cmd_load,
|
pre_load=args.cmd_pre_load, load_cmd=args.cmd_load,
|
||||||
verify_cmd=args.cmd_verify, post_verify=args.cmd_post_verify,
|
verify_cmd=args.cmd_verify, post_verify=args.cmd_post_verify,
|
||||||
tui=args.tui, config=args.config, serial=args.serial,
|
tui=args.tui, config=args.config, serial=args.serial, use_elf=args.use_elf,
|
||||||
tcl_port=args.tcl_port, telnet_port=args.telnet_port,
|
tcl_port=args.tcl_port, telnet_port=args.telnet_port,
|
||||||
gdb_port=args.gdb_port)
|
gdb_port=args.gdb_port)
|
||||||
|
|
||||||
|
@ -107,10 +111,14 @@ class OpenOcdBinaryRunner(ZephyrBinaryRunner):
|
||||||
if self.openocd_config is not None:
|
if self.openocd_config is not None:
|
||||||
self.cfg_cmd = ['-f', self.openocd_config]
|
self.cfg_cmd = ['-f', self.openocd_config]
|
||||||
|
|
||||||
if command == 'flash':
|
if command == 'flash' and self.use_elf:
|
||||||
|
self.do_flash_elf(**kwargs)
|
||||||
|
elif command == 'flash':
|
||||||
self.do_flash(**kwargs)
|
self.do_flash(**kwargs)
|
||||||
elif command == 'debug':
|
elif command == 'debug':
|
||||||
self.do_debug(**kwargs)
|
self.do_debug(**kwargs)
|
||||||
|
elif command == 'load':
|
||||||
|
self.do_load(**kwargs)
|
||||||
else:
|
else:
|
||||||
self.do_debugserver(**kwargs)
|
self.do_debugserver(**kwargs)
|
||||||
|
|
||||||
|
@ -153,6 +161,29 @@ class OpenOcdBinaryRunner(ZephyrBinaryRunner):
|
||||||
'-c', 'shutdown'])
|
'-c', 'shutdown'])
|
||||||
self.check_call(cmd)
|
self.check_call(cmd)
|
||||||
|
|
||||||
|
def do_flash_elf(self, **kwargs):
|
||||||
|
if self.elf_name is None:
|
||||||
|
raise ValueError('Cannot debug; no .elf specified')
|
||||||
|
|
||||||
|
# Extract entry point address from Elf to use it later with
|
||||||
|
# "resume" command of OpenOCD.
|
||||||
|
with open(self.elf_name, 'rb') as f:
|
||||||
|
ep_addr = f"0x{ELFFile(f).header['e_entry']:016x}"
|
||||||
|
|
||||||
|
pre_init_cmd = []
|
||||||
|
for i in self.pre_init:
|
||||||
|
pre_init_cmd.append("-c")
|
||||||
|
pre_init_cmd.append(i)
|
||||||
|
|
||||||
|
cmd = (self.openocd_cmd + self.serial + self.cfg_cmd +
|
||||||
|
pre_init_cmd + ['-c', 'init',
|
||||||
|
'-c', 'targets',
|
||||||
|
'-c', 'halt',
|
||||||
|
'-c', 'load_image ' + self.elf_name,
|
||||||
|
'-c', 'resume ' + ep_addr,
|
||||||
|
'-c', 'shutdown'])
|
||||||
|
self.check_call(cmd)
|
||||||
|
|
||||||
def do_debug(self, **kwargs):
|
def do_debug(self, **kwargs):
|
||||||
if self.gdb_cmd is None:
|
if self.gdb_cmd is None:
|
||||||
raise ValueError('Cannot debug; no gdb specified')
|
raise ValueError('Cannot debug; no gdb specified')
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue