scripts: west: introduce Lauterbach TRACE32 runner
This patch introduces a West runner for flashing and debugging with Lauterbach TRACE32 debuggers. The runner consists of a wrapper around TRACE32 software, and allows a Zephyr board to execute a custom start-up script (Practice Script) for the different commands supported, including the ability to pass extra arguments from CMake. Is up to the board using this runner to define the actions performed on each command. The `debug` command launches TRACE32 GUI to allow debug the Zephyr application, while the `flash` command hides the GUI and executes the start-up script in a background process. Signed-off-by: Manuel Arguelles <manuel.arguelles@nxp.com>
This commit is contained in:
parent
1dd312fd17
commit
31b3993d58
6
boards/common/trace32.board.cmake
Normal file
6
boards/common/trace32.board.cmake
Normal file
|
@ -0,0 +1,6 @@
|
|||
# Copyright 2022 NXP
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
board_set_flasher_ifnset(trace32)
|
||||
board_set_debugger_ifnset(trace32)
|
||||
board_finalize_runner_args(trace32)
|
|
@ -255,6 +255,58 @@ These debug host tools are compatible with the following debug probes:
|
|||
|
||||
Check if your SoC is listed in `pyOCD Supported Devices`_.
|
||||
|
||||
.. _lauterbach-trace32-debug-host-tools:
|
||||
|
||||
Lauterbach TRACE32 Debug Host Tools
|
||||
***********************************
|
||||
|
||||
`Lauterbach TRACE32`_ is a product line of microprocessor development tools,
|
||||
debuggers and real-time tracer with support for JTAG, SWD, NEXUS or ETM over
|
||||
multiple core architectures, including Arm Cortex-A/-R/-M, RISC-V, Xtensa, etc.
|
||||
Zephyr allows users to develop and program boards with Lauterbach TRACE32
|
||||
support using :ref:`west <west-flashing>`.
|
||||
|
||||
The runner consists of a wrapper around TRACE32 software, and allows a Zephyr
|
||||
board to execute a custom start-up script (Practice Script) for the different
|
||||
commands supported, including the ability to pass extra arguments from CMake.
|
||||
Is up to the board using this runner to define the actions performed on each
|
||||
command.
|
||||
|
||||
Install Lauterbach TRACE32 Software
|
||||
-----------------------------------
|
||||
|
||||
Download Lauterbach TRACE32 software from the `Lauterbach TRACE32 download website`_
|
||||
(registration required) and follow the installation steps described in
|
||||
`Lauterbach TRACE32 Installation Guide`_.
|
||||
|
||||
Flashing and Debugging
|
||||
----------------------
|
||||
|
||||
Set the :ref:`environment variable <env_vars>` :envvar:`T32_DIR` to the TRACE32
|
||||
system directory. Then execute ``west flash`` or ``west debug`` commands to
|
||||
flash or debug the Zephyr application as detailed in :ref:`west-build-flash-debug`.
|
||||
The ``debug`` command launches TRACE32 GUI to allow debug the Zephyr
|
||||
application, while the ``flash`` command hides the GUI and perform all
|
||||
operations in the background.
|
||||
|
||||
By default, the ``t32`` runner will launch TRACE32 using the default
|
||||
configuration file named ``config.t32`` located in the TRACE32 system
|
||||
directory. To use a different configuration file, supply the argument
|
||||
``--config CONFIG`` to the runner, for example:
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
west flash --config myconfig.t32
|
||||
|
||||
For more options, run ``west flash --context -r t32`` to print the usage.
|
||||
|
||||
Zephyr RTOS Awareness
|
||||
---------------------
|
||||
|
||||
To enable Zephyr RTOS awareness follow the steps described in
|
||||
`Lauterbach TRACE32 Zephyr OS Awareness Manual`_.
|
||||
|
||||
|
||||
.. _J-Link Software and Documentation Pack:
|
||||
https://www.segger.com/downloads/jlink/#J-LinkSoftwareAndDocumentationPack
|
||||
|
||||
|
@ -272,3 +324,15 @@ Check if your SoC is listed in `pyOCD Supported Devices`_.
|
|||
|
||||
.. _OpenOCD Windows:
|
||||
http://gnutoolchains.com/arm-eabi/openocd/
|
||||
|
||||
.. _Lauterbach TRACE32:
|
||||
https://www.lauterbach.com/
|
||||
|
||||
.. _Lauterbach TRACE32 download website:
|
||||
http://www.lauterbach.com/download_trace32.html
|
||||
|
||||
.. _Lauterbach TRACE32 Installation Guide:
|
||||
https://www2.lauterbach.com/pdf/installation.pdf
|
||||
|
||||
.. _Lauterbach TRACE32 Zephyr OS Awareness Manual:
|
||||
https://www2.lauterbach.com/pdf/rtos_zephyr.pdf
|
||||
|
|
|
@ -48,6 +48,7 @@ _names = [
|
|||
'spi_burn',
|
||||
'stm32cubeprogrammer',
|
||||
'stm32flash',
|
||||
'trace32',
|
||||
'xtensa',
|
||||
# Keep this list sorted by runner name; don't add to the end.
|
||||
]
|
||||
|
|
145
scripts/west_commands/runners/trace32.py
Normal file
145
scripts/west_commands/runners/trace32.py
Normal file
|
@ -0,0 +1,145 @@
|
|||
# Copyright 2022 NXP
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
'''Runner for Lauterbach TRACE32.'''
|
||||
|
||||
import argparse
|
||||
import os
|
||||
import platform
|
||||
import subprocess
|
||||
from pathlib import Path
|
||||
from tempfile import TemporaryDirectory
|
||||
from typing import List, Optional
|
||||
|
||||
from runners.core import BuildConfiguration, RunnerCaps, RunnerConfig, ZephyrBinaryRunner
|
||||
|
||||
DEFAULT_T32_CONFIG = Path('config.t32')
|
||||
|
||||
|
||||
class TRACE32BinaryRunner(ZephyrBinaryRunner):
|
||||
'''
|
||||
Runner front-end for Lauterbach TRACE32.
|
||||
|
||||
The runner is a wrapper around Lauterbach TRACE32 PowerView. It executes a Lauterbach Practice
|
||||
script (.cmm) after launching the debugger, which should be located at
|
||||
zephyr/boards/<board>/support/<command>.cmm, where <board> is the board directory and <command>
|
||||
is the name of the west runner command executed (e.g. flash or debug). Extra arguments can be
|
||||
passed to the startup script by using the command line option --startup-args.
|
||||
'''
|
||||
|
||||
def __init__(self,
|
||||
cfg: RunnerConfig,
|
||||
t32_cfg: Path,
|
||||
arch: str,
|
||||
startup_args: List[str] = None,
|
||||
timeout: int = 60) -> None:
|
||||
super(TRACE32BinaryRunner, self).__init__(cfg)
|
||||
self.arch = arch
|
||||
self.t32_cfg = t32_cfg
|
||||
self.t32_exec: Optional[Path] = None
|
||||
self.startup_dir = Path(cfg.board_dir) / 'support'
|
||||
self.startup_args = startup_args
|
||||
self.timeout = timeout
|
||||
|
||||
@classmethod
|
||||
def name(cls) -> str:
|
||||
return 'trace32'
|
||||
|
||||
@classmethod
|
||||
def capabilities(cls) -> RunnerCaps:
|
||||
return RunnerCaps(commands={'flash', 'debug'})
|
||||
|
||||
@classmethod
|
||||
def do_add_parser(cls, parser: argparse.ArgumentParser) -> None:
|
||||
parser.add_argument('--arch',
|
||||
default='auto',
|
||||
choices=('auto', 'arm', 'riscv', 'xtensa'),
|
||||
help='Target architecture. Set to "auto" to select the architecture '
|
||||
'based on CONFIG_ARCH value')
|
||||
parser.add_argument('--config',
|
||||
default=DEFAULT_T32_CONFIG,
|
||||
type=Path,
|
||||
help='Override TRACE32 configuration file path. Can be a relative path '
|
||||
'to T32_DIR environment variable, or an absolute path')
|
||||
parser.add_argument('--startup-args',
|
||||
nargs='*',
|
||||
help='Arguments to pass to the start-up script')
|
||||
parser.add_argument('--timeout',
|
||||
default=60,
|
||||
type=int,
|
||||
help='Timeout, in seconds, of the flash operation')
|
||||
|
||||
@classmethod
|
||||
def do_create(cls, cfg: RunnerConfig, args: argparse.Namespace) -> 'TRACE32BinaryRunner':
|
||||
build_conf = BuildConfiguration(cfg.build_dir)
|
||||
if args.arch == 'auto':
|
||||
arch = build_conf.get('CONFIG_ARCH').replace('"', '')
|
||||
# there is a single binary for all ARM architectures
|
||||
arch = arch.replace('arm64', 'arm')
|
||||
else:
|
||||
arch = args.arch
|
||||
return TRACE32BinaryRunner(cfg, args.config, arch, startup_args=args.startup_args,
|
||||
timeout=args.timeout)
|
||||
|
||||
def do_run(self, command, **kwargs) -> None:
|
||||
t32_dir = os.environ.get('T32_DIR')
|
||||
if not t32_dir:
|
||||
raise RuntimeError('T32_DIR environment variable undefined')
|
||||
|
||||
if platform.system() == 'Windows':
|
||||
os_name = 'windows64'
|
||||
suffix = '.exe'
|
||||
elif platform.system() == 'Linux':
|
||||
os_name = 'pc_linux64'
|
||||
suffix = ''
|
||||
else:
|
||||
raise RuntimeError('Host OS not supported by this runner')
|
||||
|
||||
self.t32_exec = Path(t32_dir) / 'bin' / os_name / f't32m{self.arch}{suffix}'
|
||||
if not self.t32_exec.exists():
|
||||
raise RuntimeError(f'Cannot find Lauterbach executable at {self.t32_exec}')
|
||||
|
||||
if not self.t32_cfg.is_absolute():
|
||||
self.t32_cfg = Path(t32_dir) / self.t32_cfg
|
||||
if not self.t32_cfg.exists():
|
||||
raise RuntimeError(f'Cannot find Lauterbach configuration at {self.t32_cfg}')
|
||||
|
||||
startup_script = self.startup_dir / f'{command}.cmm'
|
||||
if not startup_script.exists():
|
||||
raise RuntimeError(f'Cannot find start-up script at {startup_script}')
|
||||
|
||||
if command == 'flash':
|
||||
self.flash(**kwargs)
|
||||
elif command == 'debug':
|
||||
self.debug(**kwargs)
|
||||
|
||||
def flash(self, **kwargs) -> None:
|
||||
with TemporaryDirectory(suffix='t32') as tmp_dir:
|
||||
# use a temporary config file, based on the provided configuration,
|
||||
# to hide the TRACE32 software graphical interface
|
||||
cfg_content = f'{self.t32_cfg.read_text()}\n\nSCREEN=OFF\n'
|
||||
tmp_cfg = Path(tmp_dir) / DEFAULT_T32_CONFIG.name
|
||||
tmp_cfg.write_text(cfg_content)
|
||||
|
||||
cmd = self.get_launch_command('flash', cfg=tmp_cfg)
|
||||
self.logger.info(f'Launching TRACE32: {" ".join(cmd)}')
|
||||
try:
|
||||
self.check_call(cmd, timeout=self.timeout)
|
||||
self.logger.info('Finished')
|
||||
except subprocess.TimeoutExpired:
|
||||
self.logger.error(f'Timed out after {self.timeout} seconds')
|
||||
|
||||
def debug(self, **kwargs) -> None:
|
||||
cmd = self.get_launch_command('debug')
|
||||
self.logger.info(f'Launching TRACE32: {" ".join(cmd)}')
|
||||
self.check_call(cmd)
|
||||
|
||||
def get_launch_command(self, command_name: str, cfg: Path = None) -> List[str]:
|
||||
cmd = [
|
||||
str(self.t32_exec),
|
||||
'-c', str(cfg if cfg else self.t32_cfg),
|
||||
'-s', str(self.startup_dir / f'{command_name}.cmm')
|
||||
]
|
||||
if self.startup_args:
|
||||
cmd.extend(self.startup_args)
|
||||
return cmd
|
|
@ -38,5 +38,6 @@ def test_runner_imports():
|
|||
'spi_burn',
|
||||
'stm32cubeprogrammer',
|
||||
'stm32flash',
|
||||
'trace32',
|
||||
'xtensa'))
|
||||
assert runner_names == expected
|
||||
|
|
Loading…
Reference in a new issue