west: runner: add support for NXP's linkserver
Linkserver is a utility for launching and managing GDB servers for NXP debug probes, which also provides a command-line target flash programming capabilities. Linkserver can be used with NXP MCUXpresso for Visual Studio Code. For more information about LinkServer, please visit the LinkServer web page (link [1] below). This commit adds a runner to west, supporting debug and flash commands. Documentation is also added. [1] - LinkServer web page: https://www.nxp.com/design/software/development-software/mcuxpresso-software-and-tools-/linkserver-for-microcontrollers:LINKERSERVER Signed-off-by: Yves Vandervennet <yves.vandervennet@nxp.com>
This commit is contained in:
parent
a64f430d6f
commit
58e4df6460
6 changed files with 280 additions and 0 deletions
4
boards/common/linkserver.board.cmake
Normal file
4
boards/common/linkserver.board.cmake
Normal file
|
@ -0,0 +1,4 @@
|
|||
# Copyright 2023 NXP
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
board_finalize_runner_args(linkserver "--dt-flash=y")
|
|
@ -199,6 +199,55 @@ Windows PATH. A specific bossac executable can be used by passing the
|
|||
WSL is not currently supported.
|
||||
|
||||
|
||||
.. _linkserver-debug-host-tools:
|
||||
|
||||
LinkServer Debug Host Tools
|
||||
****************************
|
||||
|
||||
Linkserver is a utility for launching and managing GDB servers for NXP debug probes,
|
||||
which also provides a command-line target flash programming capabilities.
|
||||
Linkserver can be used with NXP MCUXpresso for Visual Studio Code implementation,
|
||||
with custom debug configurations based on GNU tools or as part of a headless solution
|
||||
for continuous integration and test. Linkserver can be used with MCU-Link, LPC-Link2,
|
||||
LPC11U35-based and OpenSDA based standalone or on-board debug probes from NXP.
|
||||
The Linkserver installer also includes the firmware update utilities for MCU-Link and
|
||||
the LPCScrypt utility for use with LPC-Link2. Linkserver can also be installed using
|
||||
the MCUXpresso Installer.
|
||||
|
||||
LinkServer is compatible with the following debug probes:
|
||||
|
||||
- :ref:`lpclink2-cmsis-onboard-debug-probe`
|
||||
|
||||
Supported west commands:
|
||||
|
||||
1. flash
|
||||
#. debug
|
||||
#. debugserver
|
||||
#. attach
|
||||
|
||||
Notes:
|
||||
|
||||
|
||||
1. Probes can be listed with LinkServer:
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
LinkServer probes
|
||||
|
||||
2. Use the LinkServer west runner ``--probe`` option to pass the probe index.
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
west flash --runner=linkserver --probe=3
|
||||
|
||||
3. device specific settings can be overridden with the west runner for LinkServer with
|
||||
the option '--override'. May be used multiple times. The format is dictated
|
||||
by LinkServer, e.g.:
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
west flash --runner=linkserver --override /device/memory/5/flash-driver=MIMXRT500_SFDP_MXIC_OSPI_S.cfx
|
||||
|
||||
.. _jlink-debug-host-tools:
|
||||
|
||||
J-Link Debug Host Tools
|
||||
|
|
|
@ -58,6 +58,35 @@ onboard debug probe may have limitations, such as lack of support for advanced
|
|||
debuggers or high-speed tracing. You may need to adjust jumpers to prevent the
|
||||
onboard debug probe from interfering with the external debug probe.
|
||||
|
||||
.. _lpclink2-cmsis-onboard-debug-probe:
|
||||
|
||||
LPC-LINK2 CMSIS DAP Onboard Debug Probe
|
||||
***************************************
|
||||
|
||||
The CMSIS-DAP debug probes allow debugging from any compatible toolchain,
|
||||
including IAR EWARM, Keil MDK, as well as NXP’s MCUXpresso IDE and
|
||||
MCUXpresso extension for VS Code.
|
||||
As well as providing debug probe functionality, the LPC-Link2 probes also
|
||||
provide:
|
||||
|
||||
1. SWO trace end point: this virtual device is used by MCUXpresso to retrieve
|
||||
SWO trace data. See the MCUXpresso IDE documentation for more information.
|
||||
2. Virtual COM (VCOM) port / UART bridge connected to the target processor
|
||||
3. LPCSIO bridge that provides communication to I2C and SPI slave devices
|
||||
|
||||
This probe is realized by programming the LPC-Link2 microcontroller with the CMSIS-DAP
|
||||
LPC-Link2 firmware. Download and install `LPCScrypt`_ to get the firmware and
|
||||
programming scripts.
|
||||
|
||||
.. note:: Verify the firmware supports your board by visiting `Firmware for LPCXpresso`_
|
||||
|
||||
1. Put the LPC-Link2 microcontroller into DFU boot mode by attaching the DFU
|
||||
jumper, then powering up the board.
|
||||
|
||||
#. Run the ``program_CMSIS`` script.
|
||||
|
||||
#. Remove the DFU jumper and power cycle the board.
|
||||
|
||||
.. _lpclink2-jlink-onboard-debug-probe:
|
||||
|
||||
LPC-Link2 J-Link Onboard Debug Probe
|
||||
|
|
|
@ -37,6 +37,7 @@ _names = [
|
|||
'intel_adsp',
|
||||
'intel_cyclonev',
|
||||
'jlink',
|
||||
'linkserver',
|
||||
'mdb',
|
||||
'misc',
|
||||
'native_gdb',
|
||||
|
|
196
scripts/west_commands/runners/linkserver.py
Normal file
196
scripts/west_commands/runners/linkserver.py
Normal file
|
@ -0,0 +1,196 @@
|
|||
# Copyright 2023 NXP
|
||||
# Copyright (c) 2017 Linaro Limited.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
# Based on jlink.py
|
||||
|
||||
'''Runner for debugging with NXP's LinkServer.'''
|
||||
|
||||
import logging
|
||||
import os
|
||||
import shlex
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
from runners.core import ZephyrBinaryRunner, RunnerCaps
|
||||
|
||||
|
||||
DEFAULT_LINKSERVER_EXE = 'Linkserver.exe' if sys.platform == 'win32' else 'LinkServer'
|
||||
DEFAULT_LINKSERVER_GDB_PORT = 3333
|
||||
DEFAULT_LINKSERVER_SEMIHOST_PORT = 3334
|
||||
|
||||
class LinkServerBinaryRunner(ZephyrBinaryRunner):
|
||||
'''Runner front-end for NXP Linkserver'''
|
||||
def __init__(self, cfg, device,
|
||||
linkserver=DEFAULT_LINKSERVER_EXE,
|
||||
dt_flash=True, erase=True,
|
||||
probe=1,
|
||||
gdb_host='',
|
||||
gdb_port=DEFAULT_LINKSERVER_GDB_PORT,
|
||||
semihost_port=DEFAULT_LINKSERVER_SEMIHOST_PORT,
|
||||
override=[],
|
||||
tui=False, tool_opt=[]):
|
||||
super().__init__(cfg)
|
||||
self.file = cfg.file
|
||||
self.file_type = cfg.file_type
|
||||
self.hex_name = cfg.hex_file
|
||||
self.bin_name = cfg.bin_file
|
||||
self.elf_name = cfg.elf_file
|
||||
self.gdb_cmd = cfg.gdb if cfg.gdb else None
|
||||
self.device = device
|
||||
self.linkserver = linkserver
|
||||
self.dt_flash = dt_flash
|
||||
self.erase = erase
|
||||
self.probe = probe
|
||||
self.gdb_host = gdb_host
|
||||
self.gdb_port = gdb_port
|
||||
self.semihost_port = semihost_port
|
||||
self.tui_arg = ['-tui'] if tui else []
|
||||
self.override = override
|
||||
self.override_cli = self._build_override_cli()
|
||||
|
||||
self.tool_opt = []
|
||||
for opts in [shlex.split(opt) for opt in tool_opt]:
|
||||
self.tool_opt += opts
|
||||
|
||||
@classmethod
|
||||
def name(cls):
|
||||
return 'linkserver'
|
||||
|
||||
@classmethod
|
||||
def capabilities(cls):
|
||||
return RunnerCaps(commands={'flash', 'debug', 'debugserver', 'attach'},
|
||||
dev_id=True, flash_addr=True, erase=True,
|
||||
tool_opt=True, file=True)
|
||||
|
||||
@classmethod
|
||||
def do_add_parser(cls, parser):
|
||||
parser.add_argument('--device', required=True, help='device name')
|
||||
|
||||
parser.add_argument('--probe', default=1,
|
||||
help='interface to use (index, no serial number), default is 1')
|
||||
|
||||
parser.add_argument('--tui', default=False, action='store_true',
|
||||
help='if given, GDB uses -tui')
|
||||
|
||||
parser.add_argument('--gdb-port', default=DEFAULT_LINKSERVER_GDB_PORT,
|
||||
help='gdb port to open, defaults to {}'.format(
|
||||
DEFAULT_LINKSERVER_GDB_PORT))
|
||||
|
||||
parser.add_argument('--semihost-port', default=DEFAULT_LINKSERVER_SEMIHOST_PORT,
|
||||
help='semihost port to open, defaults to the empty string '
|
||||
'and runs a gdb server')
|
||||
# keep this, we have to assume that the default 'commander' is on PATH
|
||||
parser.add_argument('--linkserver', default=DEFAULT_LINKSERVER_EXE,
|
||||
help=f'''LinkServer executable, default is
|
||||
{DEFAULT_LINKSERVER_EXE}''')
|
||||
# user may need to override settings.
|
||||
parser.add_argument('--override', required=False, action='append',
|
||||
help=f'''configuration overrides as defined bylinkserver. Example: /device/memory/0/location=0xcafecafe''')
|
||||
|
||||
@classmethod
|
||||
def do_create(cls, cfg, args):
|
||||
|
||||
return LinkServerBinaryRunner(cfg, args.device,
|
||||
linkserver=args.linkserver,
|
||||
dt_flash=args.dt_flash,
|
||||
erase=args.erase,
|
||||
probe=args.probe,
|
||||
semihost_port=args.semihost_port,
|
||||
gdb_port=args.gdb_port,
|
||||
override=args.override,
|
||||
tui=args.tui, tool_opt=args.tool_opt)
|
||||
|
||||
@property
|
||||
def linkserver_version_str(self):
|
||||
|
||||
if not hasattr(self, '_linkserver_version'):
|
||||
linkserver_version_cmd=[self.linkserver, "-v"]
|
||||
ls_output=self.check_output(linkserver_version_cmd)
|
||||
self.linkserver_version = str(ls_output.split()[1].decode())
|
||||
|
||||
return self.linkserver_version
|
||||
|
||||
def do_run(self, command, **kwargs):
|
||||
|
||||
self.linkserver = self.require(self.linkserver)
|
||||
self.logger.info(f'LinkServer: {self.linkserver}, version {self.linkserver_version_str}')
|
||||
|
||||
if command == 'flash':
|
||||
self.flash(**kwargs)
|
||||
else:
|
||||
linkserver_cmd = ([self.linkserver] +
|
||||
["gdbserver"] +
|
||||
["--probe", "#"+str(self.probe) ] +
|
||||
["--gdb-port", str(self.gdb_port )] +
|
||||
["--semihost-port", str(self.semihost_port) ] +
|
||||
self.override_cli +
|
||||
[self.device])
|
||||
|
||||
if command in ('debug', 'attach'):
|
||||
if self.elf_name is None or not os.path.isfile(self.elf_name):
|
||||
raise ValueError('Cannot debug; elf file required')
|
||||
|
||||
gdb_cmd = ([self.gdb_cmd] +
|
||||
self.tui_arg +
|
||||
[self.elf_name] +
|
||||
['-ex', 'target remote {}:{}'.format(self.gdb_host, self.gdb_port)])
|
||||
|
||||
if command == 'debug':
|
||||
gdb_cmd += [ '-ex', 'load', '-ex', 'monitor reset']
|
||||
|
||||
if command == 'attach':
|
||||
linkserver_cmd += ['--attach']
|
||||
|
||||
self.run_server_and_client(linkserver_cmd, gdb_cmd)
|
||||
|
||||
elif command == 'debugserver':
|
||||
if self.gdb_host:
|
||||
raise ValueError('Cannot run debugserver with --gdb-host')
|
||||
|
||||
self.check_call(linkserver_cmd)
|
||||
|
||||
def do_erase(self, **kwargs):
|
||||
|
||||
linkserver_cmd = ([self.linkserver, "flash"] + ["--probe", "#"+str(self.probe)] +
|
||||
[self.device] + ["erase"])
|
||||
self.logger.debug("flash erase command = " + str(linkserver_cmd))
|
||||
self.check_call(linkserver_cmd)
|
||||
|
||||
def _build_override_cli(self):
|
||||
|
||||
override_cli = []
|
||||
|
||||
if self.override is not None:
|
||||
for ov in self.override:
|
||||
override_cli = (override_cli + ["-o", str(ov)])
|
||||
|
||||
return override_cli
|
||||
|
||||
def flash(self, **kwargs):
|
||||
|
||||
linkserver_cmd = ([self.linkserver, "flash"] + ["--probe", "#"+str(self.probe)] + self.override_cli + [self.device])
|
||||
|
||||
if self.erase:
|
||||
self.do_erase()
|
||||
|
||||
if self.bin_name is not None and os.path.isfile(self.bin_name):
|
||||
if self.dt_flash:
|
||||
load_addr = self.flash_address_from_build_conf(self.build_conf)
|
||||
else:
|
||||
self.logger.critical("no load flash address could be found...")
|
||||
raise RuntimeError("no load flash address could be found...")
|
||||
|
||||
flash_cmd = (["load", "--addr", str(load_addr), self.bin_name])
|
||||
else:
|
||||
err = 'Cannot flash; no bin ({}) file found.'
|
||||
raise ValueError(err.format(self.bin_name))
|
||||
|
||||
# Flash the selected elf file
|
||||
linkserver_cmd = linkserver_cmd + flash_cmd
|
||||
self.logger.debug("flash command = " + str(linkserver_cmd))
|
||||
kwargs = {}
|
||||
if not self.logger.isEnabledFor(logging.DEBUG):
|
||||
kwargs['stderr'] = subprocess.DEVNULL
|
||||
self.check_call(linkserver_cmd, **kwargs)
|
|
@ -27,6 +27,7 @@ def test_runner_imports():
|
|||
'intel_adsp',
|
||||
'intel_cyclonev',
|
||||
'jlink',
|
||||
'linkserver',
|
||||
'mdb-nsim',
|
||||
'mdb-hw',
|
||||
'misc-flasher',
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue