scripts: west_commands: runners: add ST-LINK GDB server
Add the ST-Link GDB server (part of the STM32CubeCLT) as west runner. The STM32CubeCLT is an all-in-one multi-OS command-line toolset, which is part of the STM32Cube ecosystem, and notably includes a GDB server for debugging using ST-Link probes. This runner supports the "attach", "debug" and "debugserver" commands. Documentation: https://www.st.com/en/development-tools/stm32cubeclt.html Signed-off-by: Mathieu Choplain <mathieu.choplain@st.com>
This commit is contained in:
parent
0829c2bb8c
commit
19fe604aef
4
boards/common/stlink_gdbserver.board.cmake
Normal file
4
boards/common/stlink_gdbserver.board.cmake
Normal file
@ -0,0 +1,4 @@
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
board_set_debugger_ifnset(stlink_gdbserver)
|
||||
board_finalize_runner_args(stlink_gdbserver)
|
||||
@ -525,6 +525,50 @@ to ``rfp-cli`` when flashing:
|
||||
|
||||
west flash --rfp-cli ~/Downloads/RFP_CLI_Linux_V31800_x64/linux-x64/rfp-cli
|
||||
|
||||
.. _stm32cubeclt-host-tools:
|
||||
.. _runner_stlink_gdbserver:
|
||||
|
||||
STM32CubeCLT Flash & Debug Host Tools
|
||||
*************************************
|
||||
|
||||
STMicroelectronics provides `STM32CubeCLT`_ as an official all-in-one toolset compatible with
|
||||
Linux |reg|, macOS |reg| and Windows |reg|, allowing the use of STMicroelectronics proprietary
|
||||
tools within third-party development environments.
|
||||
|
||||
It notably provides a GDB debugging server (the *ST-LINK GDB Server*) that can be used to debug
|
||||
applications on STM32 boards thanks to on-board or external ST-LINK debug probes.
|
||||
|
||||
It is compatible with the following debug probes:
|
||||
|
||||
- :ref:`stlink-v21-onboard-debug-probe`
|
||||
- Standalone `ST-LINK-V2`_, `ST-LINK-V3`_, and `STLINK-V3PWR`_ probes
|
||||
|
||||
Install STM32CubeCLT
|
||||
--------------------
|
||||
|
||||
The easiest way to get the ST-LINK GDB Server is to install `STM32CubeCLT`_ from STMicroelectronics' website.
|
||||
A valid email address is needed to receive the downloading link.
|
||||
|
||||
Basic usage
|
||||
-----------
|
||||
|
||||
The ST-Link GDB Server can be used through the ``west attach``, ``west debug`` or ``west debugserver`` commands
|
||||
to debug Zephyr applications.
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
west debug --runner stlink_gdbserver
|
||||
|
||||
.. note::
|
||||
|
||||
The `STM32CubeProgrammer`_ version contained in the `STM32CubeCLT`_ installation can also be used to flash
|
||||
applications. To do so, the dedicated :ref:`STM32CubeProgrammer runner <runner_stm32cubeprogrammer>` should
|
||||
be used instead of ``stlink_gdbserver``, as done in the following example:
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
west flash --runner stm32cubeprogrammer
|
||||
|
||||
.. _stm32cubeprog-flash-host-tools:
|
||||
.. _runner_stm32cubeprogrammer:
|
||||
|
||||
@ -650,12 +694,12 @@ For more about the UF2 format and its tooling, see `USB Flashing Format (UF2)`_.
|
||||
.. _probe-rs Supported Devices:
|
||||
https://probe.rs/targets/
|
||||
|
||||
.. _STM32CubeProgrammer:
|
||||
https://www.st.com/en/development-tools/stm32cubeprog.html
|
||||
|
||||
.. _STM32CubeCLT:
|
||||
https://www.st.com/en/development-tools/stm32cubeclt.html
|
||||
|
||||
.. _STM32CubeProgrammer:
|
||||
https://www.st.com/en/development-tools/stm32cubeprog.html
|
||||
|
||||
.. _STM32CubeProgrammer User Manual:
|
||||
https://www.st.com/resource/en/user_manual/um2237-stm32cubeprogrammer-software-description-stmicroelectronics.pdf
|
||||
|
||||
|
||||
@ -36,29 +36,29 @@ with pyOCD or OpenOCD debug host tools, or with J-Link firmware to communicate
|
||||
with J-Link debug host tools.
|
||||
|
||||
|
||||
+------------------------------------------+---------------------------------------------------------------------------------------------------------+
|
||||
|| *Debug Probes & Host Tools* | Host Tools |
|
||||
+| *Compatibility Chart* +--------------------+--------------------+---------------------+--------------------+--------------------+
|
||||
| | **J-Link Debug** | **OpenOCD** | **pyOCD** | **NXP S32DS** | **NXP LinkServer** |
|
||||
+----------------+-------------------------+--------------------+--------------------+---------------------+--------------------+--------------------+
|
||||
| | **J-Link External** | ✓ | ✓ | | | |
|
||||
| +-------------------------+--------------------+--------------------+---------------------+--------------------+--------------------+
|
||||
| | **LPC-Link2 CMSIS-DAP** | | | | | ✓ |
|
||||
| +-------------------------+--------------------+--------------------+---------------------+--------------------+--------------------+
|
||||
| | **LPC-Link2 J-Link** | ✓ | | | | |
|
||||
| +-------------------------+--------------------+--------------------+---------------------+--------------------+--------------------+
|
||||
| | **MCU-Link CMSIS-DAP** | | | | | ✓ |
|
||||
| Debug Probes +-------------------------+--------------------+--------------------+---------------------+--------------------+--------------------+
|
||||
| | **MCU-Link J-Link** | ✓ | | | | |
|
||||
| +-------------------------+--------------------+--------------------+---------------------+--------------------+--------------------+
|
||||
| | **NXP S32 Debug Probe** | | | | ✓ | |
|
||||
| +-------------------------+--------------------+--------------------+---------------------+--------------------+--------------------+
|
||||
| | **OpenSDA DAPLink** | | ✓ | ✓ | | ✓ |
|
||||
| +-------------------------+--------------------+--------------------+---------------------+--------------------+--------------------+
|
||||
| | **OpenSDA J-Link** | ✓ | | | | |
|
||||
| +-------------------------+--------------------+--------------------+---------------------+--------------------+--------------------+
|
||||
| | **ST-LINK/V2-1** | ✓ | ✓ | *some STM32 boards* | | |
|
||||
+----------------+-------------------------+--------------------+--------------------+---------------------+--------------------+--------------------+
|
||||
+------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------+
|
||||
|| *Debug Probes & Host Tools* | Host Tools |
|
||||
+| *Compatibility Chart* +--------------------+--------------------+---------------------+--------------------+--------------------+------------------------+
|
||||
| | **J-Link Debug** | **OpenOCD** | **pyOCD** | **NXP S32DS** | **NXP LinkServer** | **ST-LINK GDB Server** |
|
||||
+----------------+-------------------------+--------------------+--------------------+---------------------+--------------------+--------------------+------------------------+
|
||||
| | **J-Link External** | ✓ | ✓ | | | | |
|
||||
| +-------------------------+--------------------+--------------------+---------------------+--------------------+--------------------+------------------------+
|
||||
| | **LPC-Link2 CMSIS-DAP** | | | | | ✓ | |
|
||||
| +-------------------------+--------------------+--------------------+---------------------+--------------------+--------------------+------------------------+
|
||||
| | **LPC-Link2 J-Link** | ✓ | | | | | |
|
||||
| +-------------------------+--------------------+--------------------+---------------------+--------------------+--------------------+------------------------+
|
||||
| | **MCU-Link CMSIS-DAP** | | | | | ✓ | |
|
||||
| Debug Probes +-------------------------+--------------------+--------------------+---------------------+--------------------+--------------------+------------------------+
|
||||
| | **MCU-Link J-Link** | ✓ | | | | | |
|
||||
| +-------------------------+--------------------+--------------------+---------------------+--------------------+--------------------+------------------------+
|
||||
| | **NXP S32 Debug Probe** | | | | ✓ | | |
|
||||
| +-------------------------+--------------------+--------------------+---------------------+--------------------+--------------------+------------------------+
|
||||
| | **OpenSDA DAPLink** | | ✓ | ✓ | | ✓ | |
|
||||
| +-------------------------+--------------------+--------------------+---------------------+--------------------+--------------------+------------------------+
|
||||
| | **OpenSDA J-Link** | ✓ | | | | | |
|
||||
| +-------------------------+--------------------+--------------------+---------------------+--------------------+--------------------+------------------------+
|
||||
| | **ST-LINK/V2-1** | ✓ | ✓ | *some STM32 boards* | | | ✓ |
|
||||
+----------------+-------------------------+--------------------+--------------------+---------------------+--------------------+--------------------+------------------------+
|
||||
|
||||
|
||||
Some supported boards in Zephyr do not include an onboard debug probe and
|
||||
@ -374,6 +374,7 @@ It is compatible with the following host debug tools:
|
||||
|
||||
- :ref:`openocd-debug-host-tools`
|
||||
- :ref:`jlink-debug-host-tools`
|
||||
- :ref:`stm32cubeclt-host-tools`
|
||||
|
||||
For some STM32 based boards, it is also compatible with:
|
||||
|
||||
|
||||
@ -59,6 +59,7 @@ _names = [
|
||||
'silabs_commander',
|
||||
'spi_burn',
|
||||
'spsdk',
|
||||
'stlink_gdbserver',
|
||||
'stm32cubeprogrammer',
|
||||
'stm32flash',
|
||||
'sy1xx',
|
||||
|
||||
188
scripts/west_commands/runners/stlink_gdbserver.py
Normal file
188
scripts/west_commands/runners/stlink_gdbserver.py
Normal file
@ -0,0 +1,188 @@
|
||||
# Copyright (c) 2025 STMicroelectronics
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
"""
|
||||
Runner for debugging applications using the ST-LINK GDB server
|
||||
from STMicroelectronics, provided as part of the STM32CubeCLT.
|
||||
"""
|
||||
|
||||
import argparse
|
||||
import platform
|
||||
import re
|
||||
import shutil
|
||||
from pathlib import Path
|
||||
|
||||
from runners.core import MissingProgram, RunnerCaps, RunnerConfig, ZephyrBinaryRunner
|
||||
|
||||
STLINK_GDB_SERVER_DEFAULT_PORT = 61234
|
||||
|
||||
|
||||
class STLinkGDBServerRunner(ZephyrBinaryRunner):
|
||||
@classmethod
|
||||
def _get_stm32cubeclt_paths(cls) -> tuple[Path, Path]:
|
||||
"""
|
||||
Returns a tuple of two elements of class pathlib.Path:
|
||||
[0]: path to the ST-LINK_gdbserver executable
|
||||
[1]: path to the "STM32CubeProgrammer/bin" folder
|
||||
"""
|
||||
|
||||
def find_highest_clt_version(tools_folder: Path) -> Path | None:
|
||||
if not tools_folder.is_dir():
|
||||
return None
|
||||
|
||||
# List all CubeCLT installations present in tools folder
|
||||
CUBECLT_FLDR_RE = re.compile(r"stm32cubeclt_([1-9]).(\d+).(\d+)", re.IGNORECASE)
|
||||
installations: list[tuple[int, Path]] = []
|
||||
for f in tools_folder.iterdir():
|
||||
m = CUBECLT_FLDR_RE.match(f.name)
|
||||
if m is not None:
|
||||
# Compute a number that can be easily compared
|
||||
# from the STM32CubeCLT version number
|
||||
major, minor, revis = int(m[1]), int(m[2]), int(m[3])
|
||||
ver_num = major * 1000000 + minor * 1000 + revis
|
||||
installations.append((ver_num, f))
|
||||
|
||||
if len(installations) == 0:
|
||||
return None
|
||||
|
||||
# Sort candidates and return the path to the most recent version
|
||||
most_recent_install = sorted(installations, key=lambda e: e[0], reverse=True)[0]
|
||||
return most_recent_install[1]
|
||||
|
||||
cur_platform = platform.system()
|
||||
|
||||
# Attempt to find via shutil.which()
|
||||
if cur_platform in ["Linux", "Windows"]:
|
||||
gdbserv = shutil.which("ST-LINK_gdbserver")
|
||||
cubeprg = shutil.which("STM32_Programmer_CLI")
|
||||
if gdbserv and cubeprg:
|
||||
# Return the parent of cubeprg as [1] should be the path
|
||||
# to the folder containing STM32_Programmer_CLI, not the
|
||||
# path to the executable itself
|
||||
return (Path(gdbserv), Path(cubeprg).parent)
|
||||
|
||||
# Search in OS-specific paths
|
||||
search_path: str
|
||||
tool_suffix = ""
|
||||
if cur_platform == "Linux":
|
||||
search_path = "/opt/st/"
|
||||
elif cur_platform == "Windows":
|
||||
search_path = "C:\\ST\\"
|
||||
tool_suffix = ".exe"
|
||||
elif cur_platform == "Darwin":
|
||||
search_path = "/opt/ST/"
|
||||
else:
|
||||
raise RuntimeError("Unsupported OS")
|
||||
|
||||
clt = find_highest_clt_version(Path(search_path))
|
||||
if clt is None:
|
||||
raise MissingProgram("ST-LINK_gdbserver (from STM32CubeCLT)")
|
||||
|
||||
gdbserver_path = clt / "STLink-gdb-server" / "bin" / f"ST-LINK_gdbserver{tool_suffix}"
|
||||
cubeprg_bin_path = clt / "STM32CubeProgrammer" / "bin"
|
||||
|
||||
return (gdbserver_path, cubeprg_bin_path)
|
||||
|
||||
@classmethod
|
||||
def name(cls) -> str:
|
||||
return "stlink_gdbserver"
|
||||
|
||||
@classmethod
|
||||
def capabilities(cls) -> RunnerCaps:
|
||||
return RunnerCaps(commands={"attach", "debug", "debugserver"}, dev_id=True, extload=True)
|
||||
|
||||
@classmethod
|
||||
def extload_help(cls) -> str:
|
||||
return "External Loader for ST-Link GDB server"
|
||||
|
||||
@classmethod
|
||||
def do_add_parser(cls, parser: argparse.ArgumentParser):
|
||||
# Expose a subset of the ST-LINK GDB server arguments
|
||||
parser.add_argument(
|
||||
"--swd", action='store_true', default=True, help="Enable SWD debug mode"
|
||||
)
|
||||
parser.add_argument("--apid", type=int, default=0, help="Target DAP ID")
|
||||
parser.add_argument(
|
||||
"--port-number",
|
||||
type=int,
|
||||
default=STLINK_GDB_SERVER_DEFAULT_PORT,
|
||||
help="Port number for GDB client",
|
||||
)
|
||||
|
||||
@classmethod
|
||||
def do_create(cls, cfg: RunnerConfig, args: argparse.Namespace) -> "STLinkGDBServerRunner":
|
||||
return STLinkGDBServerRunner(
|
||||
cfg, args.swd, args.apid, args.dev_id, args.port_number, args.extload
|
||||
)
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
cfg: RunnerConfig,
|
||||
swd: bool,
|
||||
ap_id: int | None,
|
||||
stlink_serial: str | None,
|
||||
gdb_port: int,
|
||||
external_loader: str | None,
|
||||
):
|
||||
super().__init__(cfg)
|
||||
self.ensure_output('elf')
|
||||
|
||||
self._swd = swd
|
||||
self._gdb_port = gdb_port
|
||||
self._stlink_serial = stlink_serial
|
||||
self._ap_id = ap_id
|
||||
self._external_loader = external_loader
|
||||
|
||||
def do_run(self, command: str, **kwargs):
|
||||
if command in ["attach", "debug", "debugserver"]:
|
||||
self.do_attach_debug_debugserver(command)
|
||||
else:
|
||||
raise ValueError(f"{command} not supported")
|
||||
|
||||
def do_attach_debug_debugserver(self, command: str):
|
||||
# self.ensure_output('elf') is called in constructor
|
||||
# and validated that self.cfg.elf_file is non-null.
|
||||
# This assertion is required for the test framework,
|
||||
# which doesn't have this insight - it should never
|
||||
# trigger in real-world scenarios.
|
||||
assert self.cfg.elf_file is not None
|
||||
elf_path = Path(self.cfg.elf_file).as_posix()
|
||||
|
||||
gdb_args = ["-ex", f"target remote :{self._gdb_port}", elf_path]
|
||||
|
||||
(gdbserver_path, cubeprg_path) = STLinkGDBServerRunner._get_stm32cubeclt_paths()
|
||||
gdbserver_cmd = [gdbserver_path.as_posix()]
|
||||
gdbserver_cmd += ["--stm32cubeprogrammer-path", str(cubeprg_path.absolute())]
|
||||
gdbserver_cmd += ["--port-number", str(self._gdb_port)]
|
||||
gdbserver_cmd += ["--apid", str(self._ap_id)]
|
||||
gdbserver_cmd += ["--halt"]
|
||||
|
||||
if self._swd:
|
||||
gdbserver_cmd.append("--swd")
|
||||
|
||||
if command == "attach":
|
||||
gdbserver_cmd += ["--attach"]
|
||||
else: # debug/debugserver
|
||||
gdbserver_cmd += ["--initialize-reset"]
|
||||
gdb_args += ["-ex", f"load {elf_path}"]
|
||||
|
||||
if self._stlink_serial:
|
||||
gdbserver_cmd += ["--serial-number", self._stlink_serial]
|
||||
|
||||
if self._external_loader:
|
||||
extldr_path = cubeprg_path / "ExternalLoader" / self._external_loader
|
||||
if not extldr_path.exists():
|
||||
raise RuntimeError(f"External loader {self._external_loader} does not exist")
|
||||
gdbserver_cmd += ["--extload", str(extldr_path)]
|
||||
|
||||
self.require(gdbserver_cmd[0])
|
||||
|
||||
if command == "debugserver":
|
||||
self.check_call(gdbserver_cmd)
|
||||
elif self.cfg.gdb is None: # attach/debug
|
||||
raise RuntimeError("GDB is required for attach/debug")
|
||||
else: # attach/debug
|
||||
gdb_cmd = [self.cfg.gdb] + gdb_args
|
||||
self.require(gdb_cmd[0])
|
||||
self.run_server_and_client(gdbserver_cmd, gdb_cmd)
|
||||
@ -50,6 +50,7 @@ def test_runner_imports():
|
||||
'silabs_commander',
|
||||
'spi_burn',
|
||||
'spsdk',
|
||||
'stlink_gdbserver',
|
||||
'stm32cubeprogrammer',
|
||||
'stm32flash',
|
||||
'sy1xx',
|
||||
|
||||
Loading…
Reference in New Issue
Block a user