Debuggers API

Contents

Debuggers API#

Architecture overview#

The spsdk.debuggers package provides a hardware-independent debug-probe abstraction that is used by the rest of SPSDK to communicate with NXP target devices. The application code always calls the same API — open a probe, read or write memory, exchange debug-mailbox commands — and the concrete probe implementation handles all low-level protocol details.

A debug probe is any physical adapter that connects a host PC to a target chip’s debug port. SPSDK represents this concept with the abstract base class DebugProbe. All higher-level features (firmware signing, secure provisioning, fuse programming, authenticated debug) are built on top of this single interface.

Two chip architectures are supported natively; each requires a completely different low-level protocol.

ARM CoreSight probes#

All NXP Cortex-M devices (LPC55, MCX, i.MX RT, MIMXRT, …) implement the ARM CoreSight debug architecture. The debug port (DP) is exposed over SWD (two-wire) or JTAG (four-wire) and acts as a gateway to a chain of Access Ports (APs).

Two APs are relevant for SPSDK:

MEM-AP (AHB-AP / AXI-AP)

Provides 32-bit read/write access to every address on the chip’s AHB or AXI bus fabric — SRAM, flash, and peripheral registers. SPSDK automatically locates the correct MEM-AP index for each device from the device database, and configures the CSW (Control/Status Word) to match the hardware capabilities of the specific part (including a preserve_csw_ro_bits flag needed for some MCX variants that have hardware-managed CSW bits).

Debug Mailbox AP

An NXP-proprietary AP implemented on LPC, MCX, and related families. It provides a command/response channel used to:

  • Inject a debug credential certificate signed with the device’s debug-authentication key, enabling fully authenticated debug on RoT-locked production parts.

  • Trigger an ISP mode entry without physical reset pins.

  • Initiate a device-level reset independently of the power rail.

SPSDK auto-detects the Debug Mailbox AP by scanning the AP IDR chain at connection time.

The ARM implementation also handles the complete debug port power-up / power-down lifecycle and implements four progressive sticky-error recovery levels — ranging from a soft ABORT to a full hardware reset — so that transient bus faults do not permanently stall provisioning scripts.

ARM access is handled by DebugProbeCoreSightOnly. Only MemorySpace.DATA is valid; passing MemorySpace.PROGRAM raises SPSDKError immediately.

DSC56800EX probes#

NXP’s Digital Signal Controller (DSC) family (MC56F8xx, MC56F81xx, …) is built around the DSC56800EX core — a Harvard-architecture dual-MAC DSP with an on-chip debug engine called OnCE (On-Chip Emulation), accessed over JTAG.

The key difference from ARM is the dual memory bus (Harvard) architecture:

X: DATA bus

Holds variables, stack, and peripheral registers. Accesses are made using OnCE’s DMOVX instruction, which performs a direct load/store to an absolute X: address. Both 16-bit and 32-bit (two consecutive 16-bit) transfers are supported.

P: PROGRAM bus

Holds executable code and constants stored in program flash. The P: bus is not reachable via the same DMOVX path used for X: space — the same numerical address refers to a completely different physical location. To access P: memory, OnCE requires a dedicated sequence:

  1. Load the P: target address into core register R3 using a move.l #addr, R3 instruction (three 16-bit words: opcode 0xE41B followed by the high and low 16-bit halves of the address).

  2. Execute a move.w P:(R3), Y0 or move.w Y0, P:(R3) to read or write the P: word through the program bus.

This sequence is generated automatically by DebugProbeDsc; callers simply pass space=MemorySpace.PROGRAM.

Warning

Verifying freshly-programmed DSC flash by reading back using X: (DATA) addresses always returns data from a different memory than was just written. Always use MemorySpace.PROGRAM for P: flash readback.

DSC devices may appear in JTAG TAP chains alongside other TAPs (e.g. an ARM companion core or an on-board FPGA). The TapConfig dataclass captures the IR/DR lengths, IDCODE, and the TAP-selection IR value. The device database (database.yaml per chip) stores these values so no manual JTAG configuration is needed.

Memory space selection#

The space parameter on every memory method accepts a MemorySpace value:

MemorySpace

ARM

DSC

DATA (default)

AHB/AXI via MEM-AP

OnCE DMOVX direct X: access; 16- and 32-bit word transfers

PROGRAM

raises SPSDKError

OnCE R3-indirect P: sequence; 16-bit word transfers only

Plugin architecture#

Physical probe drivers (J-Link, PyOCD, PE Micro, Lauterbach, MCU-Link) are distributed as optional plugin packages so that the SPSDK base installation stays lean. Each plugin:

  1. Derives from DebugProbeCoreSightOnly (ARM targets) or DebugProbeDsc (DSC targets).

  2. Sets NAME and ARCHITECTURE class variables ("arm_cortex" or "dsc56800ex").)

  3. Registers itself via the spsdk.debug_probe setuptools entry-point.

At run time, get_connected_probes() iterates all registered entry-points, instantiates each probe class, and filters by ARCHITECTURE when the caller requests a specific architecture.

NXP-maintained plugin packages are available at nxp-mcuxpresso/spsdk_plugins

To create a custom probe plugin use the Cookiecutter template at examples/plugins/templates/cookiecutter-spsdk-debug-probe-plugin.zip.


API Reference#

Package#

SPSDK debugger interface wrappers.

Overview#

SPSDK communicates with NXP target devices through debug probes — physical hardware adapters that connect a host PC to the chip’s debug port (SWD or JTAG). This package provides a hardware-independent abstraction layer so that the rest of SPSDK never has to care which physical probe is plugged in or which architecture is being debugged.

Architecture support#

Two fundamentally different architectures are supported, each requiring a different low-level protocol:

ARM Cortex-M / CoreSight (module spsdk.debuggers.debug_probe_arm)

NXP’s mainstream Cortex-M portfolio (LPC, MCX, i.MX RT, …) exposes the standard ARM CoreSight debug architecture over SWD or JTAG. Access to the CPU and its tightly-coupled memory is made through a chain of Access Ports (APs): a MEM-AP provides 32-bit load/store access to the AHB/AXI bus fabric, and an optional Debug Mailbox AP enables secure debug credential injection and RoT-authenticated debug sessions.

DSC56800EX (module spsdk.debuggers.debug_probe_dsc)

NXP’s Digital Signal Controller (DSC) family uses an entirely different on-chip debug engine called OnCE (On-Chip Emulation) accessed over JTAG. The DSC Harvard architecture exposes two separate memory buses — the X: DATA bus for operand data and the P: PROGRAM bus for instruction words. Reading or writing program-space flash/RAM requires explicit P: addressing; naive DATA-space reads would return garbage from the wrong address space. MemorySpace selects which bus to use on every memory operation.

Plugin system#

Physical probe support (J-Link, PyOCD, PE Micro, Lauterbach, MCU-Link) is deliberately kept outside the SPSDK core as optional packages so that the base installation stays lean. Each plugin registers itself via the spsdk.debug_probe setuptools entry-point and is auto-discovered at run time. Custom probes can be created by deriving from DebugProbeCoreSightOnly (for ARM targets) or DebugProbeDsc (for DSC targets) and distributing a package with the appropriate entry-point metadata. See examples/plugins/README.md for a step-by-step guide and Cookiecutter templates.

Base interface and infrastructure#

SPSDK debug probe base interface and infrastructure.

This module is the foundation of the SPSDK debug-probe subsystem. It defines the contracts (abstract base class, exceptions, enumerations) that every concrete probe implementation must fulfil, plus the ProbeDescription / DebugProbes helpers used for probe discovery and selection.

Design goals#

  • Hardware independence — the rest of SPSDK calls only the API defined in DebugProbe. Switching from J-Link to PyOCD to a custom probe requires zero changes in application code.

  • Architecture independence — a single space parameter on every memory method (MemorySpace) makes ARM and DSC targets look identical to the caller. The concrete implementation decides how to honour a PROGRAM-space request.

  • Plugin-friendly — new probe hardware can be added as an installable Python package without touching the SPSDK core.

Class hierarchy#

DebugProbe  (ABC — this module)
├── DebugProbeCoreSightOnly   (spsdk.debuggers.debug_probe_arm)
│     ARM CoreSight / SWD / JTAG; MEM-AP, debug mailbox AP
└── DebugProbeDsc             (spsdk.debuggers.debug_probe_dsc)
      DSC56800EX OnCE; DATA bus and PROGRAM bus

Memory spaces#

MemorySpace reflects the hardware reality of the DSC Harvard architecture:

MemorySpace.DATA

The default. Accesses the X: data bus (DSC) or the normal AHB/AXI fabric (ARM). Supports 16- and 32-bit word transfers.

MemorySpace.PROGRAM

DSC P: program bus only. Because the P: bus is instruction-addressed, the DSC OnCE engine must use an R3-register-indirect move sequence to reach it — a detail hidden inside DebugProbeDsc. Passing MemorySpace.PROGRAM to an ARM probe raises SPSDKError immediately, making unintended cross-architecture use a hard error rather than silent data corruption.

Concrete implementations live in separate modules; import them directly from their home module:

class spsdk.debuggers.debug_probe.DebugProbe(hardware_id, options=None)#

Bases: ABC

Abstract base class for SPSDK debug probe interfaces.

This class defines the common interface and constants for all debug probes supported by SPSDK, providing standardized access to target devices through various debug probe hardware implementations.

Variables:
  • NAME – Debug probe implementation name identifier.

  • APBANKSEL – Access Port bank selection mask for debug mailbox detection.

  • DP_IDR_REG – Debug Port Identification Register address.

  • DP_CTRL_STAT_REG – Debug Port Control/Status Register address.

  • DHCSR_REG – Debug Halting Control and Status Register address.

  • DHCSR_DEBUGKEY – Debug key value for DHCSR register access.

  • ARCHITECTURE – DB architecture identifier for this probe family. "abstract" means no restriction — the probe works with any architecture.

Initialize debug probe with hardware ID and configuration options.

This is general initialization function for SPSDK library to support various DEBUG PROBES. Sets up the probe connection parameters, family configuration, and memory access point index.

Parameters:
  • hardware_id (str) – Hardware identifier to open specific debug probe

  • options (Optional[dict]) – Configuration dictionary containing family, revision and other probe settings

AFTER_RESET_TIME = 0.05#
ARCHITECTURE = 'abstract'#
DEBUG_ACCESS_STATUS_LABELS: dict[str, str] = {'dp_idr_ok': 'Debug Port IDR readable (target chip responds on the debug port)', 'probe_connected': 'Probe attached to target (debug probe is correctly connected to the board via SWD/JTAG)', 'probe_opened': 'Debug probe opened (PC is correctly connected to the debug probe hardware)'}#
NAME = 'abstract'#
RESET_TIME = 0.1#
SUPPORTED_PROTOCOLS: tuple[DebugProbeProtocol, ...] = ()#
abstract assert_reset_line(assert_reset=False)#

Control reset line at a target.

Parameters:

assert_reset (bool) – If True, the reset line is asserted (pulled down), if False the reset line is not affected.

Return type:

None

abstract close()#

Close the debug probe connection.

This method provides a unified interface for closing debug probe connections across different debug probe implementations in the SPSDK library.

Return type:

None

abstract connect()#

Connect to the debug probe.

Initializes the connection to the target device through the debug probe. This is a general connecting function that supports various debug probe types across the SPSDK library.

Raises:
Return type:

None

abstract connect_safe()#

Debug probe connect in safe manner.

General connecting function for SPSDK library to support various DEBUG PROBES. The function is used to initialize the connection to target and establishes communication with the debug probe hardware.

Raises:
Return type:

None

abstract dbgmlbx_reg_read(addr=0)#

Read debug mailbox access port register.

This function reads a debug mailbox register through the debug probe interface to support various debug probes in the SPSDK library.

Parameters:

addr (int) – The register address to read from.

Return type:

int

Returns:

The read value of addressed register (4 bytes).

abstract dbgmlbx_reg_write(addr=0, data=0)#

Write debug mailbox access port register.

Writes data to a specified register address in the debug mailbox access port using the configured debug probe’s CoreSight interface.

Parameters:
  • addr (int) – Register address to write to.

  • data (int) – Data value to write into the register.

Return type:

None

abstract debug_halt()#

Halt the CPU execution.

This method stops the target CPU from executing instructions, putting it into a halted state for debugging purposes.

Raises:

SPSDKError – If the halt operation fails or the debug probe is not connected.

Return type:

None

abstract debug_resume()#

Resume the CPU execution.

This method continues the execution of the target CPU from its current state, typically used after the CPU has been halted or paused during debugging operations.

Raises:

SPSDKError – If the debug probe communication fails or the target is not connected.

Return type:

None

abstract debug_step()#

Step the CPU execution by one instruction.

This method advances the CPU execution by a single instruction step, allowing for detailed debugging and program flow analysis.

Raises:
Return type:

None

abstract classmethod get_connected_probes(hardware_id=None, options=None)#

Get connected debug probes in the system.

Retrieves a list of all connected debug probes, with an option to filter by hardware ID.

Parameters:
  • hardware_id (Optional[str]) – Hardware ID to filter for specific probe, None to list all probes.

  • options (Optional[dict]) – Additional options for probe discovery.

Return type:

DebugProbes

Returns:

Collection of connected debug probes.

get_never_tested_debug_access_gates()#

Get gate keys that will never be exercised due to a device-database shortcut.

Some gates could be tested in principle, but a device-database configuration shortcut (e.g. a fixed MEM-AP index skipping the AP-scan loop on DebugProbeCoreSightOnly) means the corresponding code path is never exercised for this family. Such gates are still shown in the diagnostic table (unlike get_not_applicable_debug_access_gates()), but rendered as “N/A” instead of “NOT TESTED” to avoid implying a real test was skipped or failed. Subclasses override this to compute the actual set from the device database.

Return type:

set[str]

Returns:

Set of gate keys to render as N/A. Empty for the base (architecture with no such shortcuts).

get_not_applicable_debug_access_gates()#

Get gate keys that can never apply to this probe/family combination.

Some gates in DEBUG_ACCESS_STATUS_LABELS are mutually exclusive at the device-database level (e.g. the SDA-AP secure-debug-unlock gate only applies to families with dat.sub_features: [sda], while the Debug Mailbox AP gate only applies to families with dat.dmbox_ap_ix set — no family currently has both). Such gates would otherwise always render as a misleading “NOT TESTED” even though they are, by design, never exercised for this particular chip. Subclasses (e.g. DebugProbeCoreSightOnly) override this to compute the actual set from the device database.

Return type:

set[str]

Returns:

Set of gate keys to omit entirely from the rendered diagnostic table for this probe instance. Empty for the base (architecture with no such mutually-exclusive gates).

classmethod get_options_help()#

Get full list of options of debug probe.

The method returns a dictionary containing all available configuration options for the debug probe with their corresponding help descriptions.

Return type:

dict[str, str]

Returns:

Dictionary with individual options. Key is parameter name and value the help text.

classmethod get_requested_protocol(options=None, default_protocol=False)#

Get generic debug probe protocol option.

Parameters:
  • options (Optional[dict]) – Optional debug probe options.

  • default_protocol (bool) – Return first supported protocol if protocol is not specified.

Return type:

DebugProbeProtocol | None

Returns:

Debug probe protocol or None if it was not specified.

Raises:

SPSDKDebugProbeError – Invalid debug probe protocol has been specified.

abstract is_cpu_halted()#

Check if the CPU is currently halted.

This method queries the hardware state directly without caching.

Return type:

bool

Returns:

True if CPU is halted, False if CPU is running.

Raises:

SPSDKDebugProbeError – If the check operation fails.

abstract mem_block_read(addr, size, space=MemorySpace(tag=0, label='data', description='Data memory bus (X: space) — default, 16/32-bit word access'))#

Read a block of memory from the MCU.

This method handles non-aligned addresses and sizes, providing flexibility for various memory operations.

Parameters:
  • addr (int) – The starting address to read from.

  • size (int) – The number of bytes to read.

  • space (MemorySpace) – Memory space selector. Defaults to DATA. PROGRAM is only valid for DSC architecture probes; ARM probes raise SPSDKError for non-DATA spaces.

Return type:

bytes

Returns:

The read data as a bytes object.

Raises:

SPSDKDebugProbeError – If there’s an error during the read operation.

abstract mem_block_write(addr, data, space=MemorySpace(tag=0, label='data', description='Data memory bus (X: space) — default, 16/32-bit word access'))#

Write a block of memory to the MCU.

This method handles non-aligned addresses and sizes, allowing for flexible memory write operations.

Parameters:
  • addr (int) – The starting address to write to.

  • data (bytes) – The data to be written, as a bytes object.

  • space (MemorySpace) – Memory space selector. Defaults to DATA. PROGRAM is only valid for DSC architecture probes; ARM probes raise SPSDKError for non-DATA spaces.

Raises:

SPSDKDebugProbeError – If there’s an error during the write operation.

Return type:

None

abstract mem_reg_read(addr=0, space=MemorySpace(tag=0, label='data', description='Data memory bus (X: space) — default, 16/32-bit word access'))#

Read 32-bit register in memory space of MCU.

This method reads a 32-bit register from the memory space of the target MCU through the debug probe interface.

Parameters:
  • addr (int) – The register address to read from.

  • space (MemorySpace) – Memory space selector. Defaults to DATA. PROGRAM is only valid for DSC architecture probes; ARM probes raise SPSDKError for non-DATA spaces.

Return type:

int

Returns:

The read value of addressed register (4 bytes).

abstract mem_reg_write(addr=0, data=0, space=MemorySpace(tag=0, label='data', description='Data memory bus (X: space) — default, 16/32-bit word access'))#

Write 32-bit register in memory space of MCU.

This method writes a 32-bit value to a specified register address in the MCU’s memory space through the debug probe interface.

Parameters:
  • addr (int) – The register address to write to.

  • data (int) – The 32-bit data value to be written into the register.

  • space (MemorySpace) – Memory space selector. Defaults to DATA. PROGRAM is only valid for DSC architecture probes; ARM probes raise SPSDKError for non-DATA spaces.

Return type:

None

abstract open()#

Open debug probe connection.

Establishes connection to the debug probe hardware, initializing communication interface and preparing the probe for debugging operations.

Raises:

SPSDKError – When debug probe connection fails or probe is not available.

Return type:

None

abstract read_dp_idr()#

Read Debug port identification register.

Return type:

int

Returns:

Debug port identification register value.

reset()#

Reset the target device.

Performs a hardware reset by asserting the reset line, waiting for the reset duration, then deasserting the reset line and waiting for the post-reset stabilization period.

Return type:

None

class spsdk.debuggers.debug_probe.DebugProbeProtocol(tag, label, description=None)#

Bases: SpsdkEnum

Debug probe physical protocol selector.

JTAG = (1, 'jtag', 'JTAG protocol')#
ONCE = (2, 'once', 'On-Chip Emulation protocol')#
SWD = (0, 'swd', 'Serial Wire Debug protocol')#
class spsdk.debuggers.debug_probe.DebugProbes(iterable=(), /)#

Bases: list[ProbeDescription]

Debug probe collection for hardware selection and display.

This class extends a list to specifically manage ProbeDescription objects, providing formatted output capabilities for debug probe selection interfaces. The class ensures type safety by accepting only ProbeDescription instances and offers colored table representation for user-friendly probe listing.

class spsdk.debuggers.debug_probe.MemorySpace(tag, label, description=None)#

Bases: SpsdkEnum

Memory space selector for debug probe memory access operations.

DSC56800EX architecture has two separate memory buses. DATA bus supports 16-bit and 32-bit word access via absolute addressing. PROGRAM bus supports only 16-bit word access via R3-register-indirect addressing. For non-DSC (e.g. ARM) probes only DATA is valid; passing PROGRAM raises SPSDKError.

DATA = (0, 'data', 'Data memory bus (X: space) — default, 16/32-bit word access')#
PROGRAM = (1, 'program', 'Program memory bus (P: space, DSC only) — 16-bit word access only')#
class spsdk.debuggers.debug_probe.ProbeDescription(interface, hardware_id, description, probe)#

Bases: object

Debug probe description container.

This class encapsulates information about a debug probe including its interface, hardware identification, description, and the probe class type. It provides a standardized way to describe and instantiate debug probes within the SPSDK framework.

Initialize Debug probe description class.

Parameters:
  • interface (str) – Probe interface type.

  • hardware_id (str) – Probe hardware ID for identification.

  • description (str) – Text description of the probe.

  • probe (type[DebugProbe]) – Debug probe class type.

property architecture: str#

Return the probe’s architecture identifier string.

Returns:

The ARCHITECTURE class variable of the underlying probe class.

get_probe(options=None)#

Get instance of debug probe.

Creates and returns a new instance of the debug probe with the specified hardware ID and optional configuration parameters.

Parameters:

options (Optional[dict]) – Optional dictionary containing probe-specific configuration options.

Return type:

DebugProbe

Returns:

Instance of the debug probe ready for use.

exception spsdk.debuggers.debug_probe.SPSDKDebugProbeError(desc=None)#

Bases: SPSDKError

SPSDK Debug Probe exception for debug probe related errors.

This exception is raised when debug probe operations fail or encounter errors during communication, initialization, or other debug probe specific operations within the SPSDK framework.

Initialize the base SPSDK Exception.

Parameters:

desc (Optional[str]) – Optional description of the exception.

exception spsdk.debuggers.debug_probe.SPSDKDebugProbeNotOpenError(desc=None)#

Bases: SPSDKDebugProbeError

Exception raised when attempting to use a debug probe that is not opened.

This exception is thrown when operations are performed on a debug probe instance that has not been properly opened or has been closed.

Initialize the base SPSDK Exception.

Parameters:

desc (Optional[str]) – Optional description of the exception.

exception spsdk.debuggers.debug_probe.SPSDKDebugProbeTransferError(desc=None)#

Bases: SPSDKDebugProbeError

SPSDK Debug Probe Transfer Error Exception.

Exception raised when communication transfer operations fail during debug probe interactions. This error indicates issues with data transmission between the host and target device through the debug probe interface.

Initialize the base SPSDK Exception.

Parameters:

desc (Optional[str]) – Optional description of the exception.

exception spsdk.debuggers.debug_probe.SPSDKMultipleProbesError(desc=None)#

Bases: SPSDKDebugProbeError

SPSDK exception for multiple debug probes found error.

This exception is raised when multiple debug probes are detected during probe discovery or selection operations, requiring explicit probe specification to resolve the ambiguity.

Initialize the base SPSDK Exception.

Parameters:

desc (Optional[str]) – Optional description of the exception.

exception spsdk.debuggers.debug_probe.SPSDKProbeNotFoundError(desc=None)#

Bases: SPSDKDebugProbeError

SPSDK debug probe not found exception.

Exception raised when a requested debug probe cannot be found or is not available for connection during SPSDK debugging operations.

Initialize the base SPSDK Exception.

Parameters:

desc (Optional[str]) – Optional description of the exception.

ARM CoreSight probe#

SPSDK ARM CoreSight debug probe implementation.

Background — ARM CoreSight debug architecture#

All NXP Cortex-M MCUs (LPC, MCX, i.MX RT, MIMXRT, Kinetis, …) implement the ARM CoreSight debug and trace architecture. The debug port (DP) is exposed over either SWD (two-wire: SWDIO + SWDCLK) or JTAG (four-wire). The DP acts as a gateway into a chain of Access Ports (APs); each AP gives access to a different on-chip resource:

MEM-AP (AHB-AP / AXI-AP)

The workhorse. Provides 8/16/32-bit read/write access to any address on the chip’s AHB or AXI bus — which includes SRAM, flash, and peripheral registers. The base address of the MEM-AP is chip-specific and is stored in SPSDK’s device database so the correct AP index is selected automatically.

Debug Mailbox AP

An NXP-proprietary AP present on LPC, MCX, and related families. It implements a command/response protocol used to:

  • Inject a debug credential signed with the device’s debug authentication key, enabling authenticated debug on RoT-locked parts.

  • Activate the ISP mode entry path.

  • Perform device-level reset without cycling the power rail.

Why a separate DebugProbeCoreSightOnly class?#

The SPSDK probe hierarchy separates protocol concerns (how to talk to the hardware) from application concerns (what to do with that access). DebugProbeCoreSightOnly provides all ARM-specific protocol intelligence:

  • CoreSight AP address calculation (get_coresight_ap_address())

  • MEM-AP discovery and CSW (Control/Status Word) configuration — including the chip-specific preserve_csw_ro_bits flag that prevents overwriting hardware-managed bits on MCX E-series and similar devices.

  • Debug mailbox AP auto-detection by scanning IDR values.

  • Debug port power-up / power-down sequences and sticky-error recovery with four progressive recovery levels (soft → power cycle → probe reconnect → hardware reset).

  • CPU halt/resume/step via DHCSR (Debug Halting Control and Status Register).

Memory space handling#

ARM does not have a separate PROGRAM bus. If a caller passes space=MemorySpace.PROGRAM to any memory method, the implementation raises SPSDKError immediately — this is an intentional hard failure to catch accidental cross-architecture code sharing. Only MemorySpace.DATA (the default) is valid on ARM targets.

Plugin development#

To support a new physical probe (e.g. a proprietary USB-JTAG adapter), derive from DebugProbeCoreSightOnly and implement the four abstract methods:

Register as a spsdk.debug_probe entry-point and SPSDK will discover the plugin automatically. See examples/plugins/README.md for a Cookiecutter template.

class spsdk.debuggers.debug_probe_arm.DebugProbeCoreSightOnly(hardware_id, options=None)#

Bases: DebugProbe

SPSDK Debug Probe with CoreSight-only interface support.

This class provides a specialized debug probe implementation that focuses exclusively on CoreSight debug architecture operations. It extends the base DebugProbe class with ARM CoreSight-specific register definitions and memory access patterns for debugging ARM Cortex-based MCUs.

Variables:
  • NAME – Debug probe identifier name.

  • CSW_SIZE_8BIT – Control/Status Word 8-bit transfer size configuration.

  • CSW_SIZE_16BIT – Control/Status Word 16-bit transfer size configuration.

  • CSW_SIZE_32BIT – Control/Status Word 32-bit transfer size configuration.

  • CSW_ADDRINC_OFF – Control/Status Word no address increment mode.

  • CSW_ADDRINC_SINGLE – Control/Status Word single address increment mode.

  • CSW_ADDRINC_PACKED – Control/Status Word packed address increment mode.

  • CSW_DEVICEEN – Control/Status Word device enable flag.

  • CSW_TRINPROG – Control/Status Word transfer in progress flag.

  • CSW_HPROT – Control/Status Word HPROT signal configuration.

  • CSW_MASTER_DEBUG – Control/Status Word master debug enable flag.

  • CSW_DBGSWENABLE – Control/Status Word debug software enable flag.

  • CSW_FULL_DEBUG – Combined CSW configuration for full debug capabilities.

  • CSW_REG – CoreSight Control/Status Word register address.

  • TAR_REG – CoreSight Transfer Address register address.

  • DRW_REG – CoreSight Data Read/Write register address.

  • DP_CTRL_STAT_ERROR_MASK – Combined error mask for Debug Port status flags.

Initialize debug probe with hardware ID and options.

General initialization function for SPSDK library to support various debug probes.

Parameters:
  • hardware_id (str) – Hardware ID of the debug probe to open

  • options (Optional[dict[str, str]]) – Optional dictionary with probe-specific configuration options

ADIV5_DBGMLBX_AP_INDICES = [2, 0, 1, 3, 8]#
ADIV5_MEM_AP_INDICES = [0, 1, 3]#
ADIV6_ADDR_SIZE_32 = 32#
ADIV6_BASEPTR_ADDR_MASK = 18446744073709547520#
ADIV6_BASEPTR_VALID_MASK = 1#
ADIV6_DPBANKSEL_MASK = 15#
ADIV6_DPIDR1_ASIZE_MASK = 127#
ADIV6_DPIDR1_REG = 0#
ADIV6_DP_BASEPTR0_BANK = 2#
ADIV6_DP_BASEPTR1_BANK = 3#
ADIV6_DP_BASEPTR_REG = 0#
ADIV6_MAX_ROM_DEPTH = 8#
ADIV6_SELECT1_REG = 20#
ADIV6_SELECT_REG = 8#
APADDR = 16777215#
APBANKSEL = 240#
APBANK_SHIFT = 4#
APSEL = 4278190080#
APSEL_APBANKSEL = 4278190320#
APSEL_SHIFT = 24#
AP_IDR_REG = 252#
AP_IDR_REG_ADIv6 = 3580#
ARCHITECTURE = 'arm-cortex'#
CDBGPWRUPACK = 536870912#
CDBGPWRUPREQ = 268435456#
CIDR1_CLASS_CORESIGHT = 144#
CIDR1_CLASS_MASK = 240#
CIDR1_CLASS_ROM = 16#
CIDR1_OFFSET = 4084#
CORE_REG_LR = 14#
CORE_REG_MSP = 17#
CORE_REG_PC = 15#
CORE_REG_PSP = 18#
CORE_REG_SP = 13#
CORE_REG_XPSR = 16#
CSW_ADDRINC_OFF = 0#
CSW_ADDRINC_PACKED = 32#
CSW_ADDRINC_SINGLE = 16#
CSW_DBGSWENABLE = 2147483648#
CSW_DEVICEEN = 64#
CSW_FULL_DEBUG = 2717909074#
CSW_HPROT = 33554432#
CSW_MASTER_DEBUG = 536870912#
CSW_REG = 0#
CSW_SIZE_16BIT = 1#
CSW_SIZE_32BIT = 2#
CSW_SIZE_8BIT = 0#
CSW_TRINPROG = 128#
CSYSPWRUPACK = 2147483648#
CSYSPWRUPREQ = 1073741824#
DBGMLBX_IDR_VALUE = 2752512#
DCRDR_REG = 3758157304#
DCRSR_REG = 3758157300#
DCRSR_REGWNR = 65536#
DEBUG_ACCESS_STATUS_LABELS: dict[str, str] = {'ahb_system_bus_ok': 'System bus (AHB) access (the debug probe can read/write chip RAM/registers)', 'ap_dbgswenable': 'AP CSW.DbgSwEnable (core debug is enabled - DBGEN signal asserted on the chip)', 'ap_idr_ok': 'Access Port IDR readable / MEM-AP found (a memory access channel to the chip exists)', 'core_dhcsr_ok': 'Core PPB access / DHCSR readable (CPU debug registers are reachable)', 'dbgmlbx_ap_idr_ok': 'Debug Mailbox AP IDR valid (secure debug authentication channel is available)', 'dp_idr_ok': 'Debug Port IDR readable (target chip responds on the debug port)', 'dp_power_domains_ok': 'DP power domains up / CDBGPWRUPACK+CSYSPWRUPACK (target power supply and clocks are on)', 'probe_connected': 'Probe attached to target (debug probe is correctly connected to the board via SWD/JTAG)', 'probe_opened': 'Debug probe opened (PC is correctly connected to the debug probe hardware)', 'sda_dbgenctrl_written': 'SDA-AP DBGENCTRL written / GDBGEN+CDBGEN (secure debug authentication unlocked the debug paths)'}#
DEVARCH_ARCHID_MASK = 4095#
DEVARCH_CLASS9_ROM = 2807#
DEVARCH_MEM_AP = 2583#
DEVARCH_OFFSET = 4028#
DEVTYPE_MEM_AP = 17#
DEVTYPE_OFFSET = 4044#
DHCSR_C_DEBUGEN = 1#
DHCSR_C_HALT = 2#
DHCSR_C_STEP = 4#
DHCSR_DEBUGKEY = 2690580480#
DHCSR_REG = 3758157296#
DHCSR_S_HALT = 131072#
DHCSR_S_REGRDY = 65536#
DPVER_ADIv6 = 3#
DPVER_MASK = 61440#
DPVER_SHIFT = 12#
DP_ABORT_REG = 0#
DP_CTRL_STAT_ERROR_MASK = 178#
DP_CTRL_STAT_READOK = 64#
DP_CTRL_STAT_REG = 4#
DP_CTRL_STAT_STICKYCMP = 16#
DP_CTRL_STAT_STICKYERR = 32#
DP_CTRL_STAT_STICKYORUN = 2#
DP_CTRL_STAT_WDATAERR = 128#
DP_IDR_REG = 0#
DRW_REG = 12#
MASKLANE = 3840#
NAME = 'base-arm'#
ROM_ENTRY_OFFSET_MASK = 4294963200#
ROM_ENTRY_PRESENT_MASK = 1#
ROM_ENTRY_SIGN_BIT = 2147483648#
ROM_ENTRY_SIGN_EXTEND = 4294967296#
SELECT_APADDR_MASK = 4294967280#
SELECT_DPBANKSEL_MASK = 15#
SUPPORTED_PROTOCOLS: tuple[DebugProbeProtocol, ...] = (DebugProbeProtocol(tag=0, label='swd', description='Serial Wire Debug protocol'),)#
SUPPORTED_VERSIONS: tuple[int, ...] = (5,)#
TAR_REG = 4#
clear_sticky_errors()#

Clear sticky errors of Debug port interface.

This method reads the debug port control/status register to check for sticky errors and clears them if found. For JTAG interface, it performs an additional write operation. The method handles communication failures gracefully by attempting recovery.

Raises:

SPSDKDebugProbeTransferError – When debug probe communication cannot be reestablished.

Return type:

None

connect_safe()#

Debug probe connect in safe manner.

General connecting function for SPSDK library to support various DEBUG PROBES. The function is used to initialize the connection to target and attempts recovery if the initial connection fails.

Raises:

Exception – Re-raises the original connection exception if recovery fails.

Return type:

None

abstract coresight_reg_read(access_port=True, addr=0)#

Read coresight register.

It reads coresight register function for SPSDK library to support various DEBUG PROBES.

Parameters:
  • access_port (bool) – if True, the Access Port (AP) register will be read (default), otherwise the Debug Port (DP) register will be read.

  • addr (int) – the register address.

Return type:

int

Returns:

The read value of addressed register (4 bytes).

coresight_reg_read_safe(access_port=True, addr=0, max_retries=3)#

Safe coresight register read with error handling and recovery.

This method attempts to read a CoreSight register with automatic retry and recovery mechanisms. If a read fails, it will attempt to recover the debug connection and retry the operation up to the specified maximum number of attempts.

Parameters:
  • access_port (bool) – If True, reads Access Port (AP) register, otherwise Debug Port (DP).

  • addr (int) – The register address to read from.

  • max_retries (int) – Maximum number of retry attempts before giving up.

Return type:

int

Returns:

The read value of addressed register (4 bytes).

Raises:

SPSDKDebugProbeTransferError – If all retry attempts fail.

abstract coresight_reg_write(access_port=True, addr=0, data=0)#

Write coresight register.

It writes coresight register function for SPSDK library to support various DEBUG PROBES.

Parameters:
  • access_port (bool) – if True, the Access Port (AP) register will be written (default), otherwise the Debug Port register will be written.

  • addr (int) – the register address.

  • data (int) – the data to be written into register.

Return type:

None

coresight_reg_write_safe(access_port=True, addr=0, data=0, max_retries=3)#

Write CoreSight register with automatic retry and error recovery.

Performs a CoreSight register write operation with built-in error handling and automatic recovery attempts. If the initial write fails, the method attempts to recover the debug connection and retry the operation up to the specified maximum number of attempts.

Parameters:
  • access_port (bool) – If True, writes to Access Port register, otherwise Debug Port register

  • addr (int) – Register address to write to

  • data (int) – Data value to write into the register

  • max_retries (int) – Maximum number of retry attempts before giving up

Raises:

SPSDKDebugProbeTransferError – If all retry attempts fail

Return type:

None

dbgmlbx_reg_read(addr=0)#

Read debug mailbox access port register.

This function reads a debug mailbox register through the debug probe interface to support various debug probes in the SPSDK library.

Parameters:

addr (int) – The register address to read from.

Return type:

int

Returns:

The read value of addressed register (4 bytes).

dbgmlbx_reg_write(addr=0, data=0)#

Write debug mailbox access port register.

Writes data to a specified register address in the debug mailbox access port using the configured debug probe’s CoreSight interface.

Parameters:
  • addr (int) – Register address to write to.

  • data (int) – Data value to write into the register.

Return type:

None

debug_halt()#

Halt the CPU execution.

This method stops the CPU by writing to the Debug Halting Control and Status Register (DHCSR) with the appropriate debug key, halt, and debug enable flags.

Raises:

SPSDKError – If the memory register write operation fails.

Return type:

None

debug_resume()#

Resume the CPU execution.

This method clears the debug halt bit in the Debug Halting Control and Status Register (DHCSR) to allow the CPU to continue execution from its current state.

Raises:

SPSDKError – If the memory register write operation fails.

Return type:

None

debug_step()#

Step the CPU execution by one instruction.

This method performs a single-step operation on the target CPU by writing to the Debug Halting Control and Status Register (DHCSR) with appropriate control bits to enable debug mode and execute one instruction.

Raises:

SPSDKError – If the memory register write operation fails.

Return type:

None

get_coresight_ap_address(access_port, address)#

Compute the coresight access port register address (ADIv5/ADIv6 aware).

For ADIv5 the access port is an AP index (0-255) shifted to bits [31:24] and combined with the register offset. For ADIv6 the access port is already a real AP base address, so it is only ORed with the register offset.

Parameters:
  • access_port (int) – AP index (ADIv5) or AP base address (ADIv6).

  • address (int) – Register address offset.

Return type:

int

Returns:

Computed coresight address.

Raises:

SPSDKValueError – If access port index exceeds 255 (ADIv5 only).

get_dbgmlbx_ap()#

Decorator function that secures getting the correct DEBUG MAILBOX AP index for first use.

The decorator automatically detects the debug mailbox access port index by trying predefined possible indices and validating against the expected IDR register value. If no valid access port is found, it raises an exception.

Parameters:

func – The function to be decorated that requires debug mailbox access.

Raises:

SPSDKError – When debug mailbox access port cannot be found.

Returns:

Decorated function wrapper.

get_debug_probe_protocol()#

Get effective ARM debug probe protocol.

Return type:

DebugProbeProtocol

Returns:

Effective debug probe protocol. If not specified, SWD is used.

Raises:

SPSDKDebugProbeError – JTAG protocol is requested but unsupported.

get_mem_ap()#

Decorator that ensures correct Memory Access Port index is found before first use.

This decorator automatically discovers and configures the appropriate Memory Access Port (MEM AP) by testing possible AP indices and validating memory access functionality. It performs CoreSight AP identification, enters debug state, tests memory access, and restores the original state.

Parameters:

func – The function to be decorated that requires MEM AP access.

Returns:

Decorated function wrapper.

Raises:

SPSDKDebugProbeError – When no valid memory access port is found.

get_never_tested_debug_access_gates()#

Get CoreSight gate keys that will never be exercised due to a DB shortcut.

When the device database pins a fixed MEM-AP index (debug_probe.mem_ap_index), the AP-scan loop in the get_mem_ap decorator is skipped entirely for performance, so ap_idr_ok and ap_dbgswenable are never actually exercised for this family. Unlike get_not_applicable_debug_access_gates() (gates that are architecturally impossible), these gates could be tested but simply are not, by design, on this DB-configured shortcut path — the diagnostic table renders them as “N/A” rather than “NOT TESTED” to avoid implying a real test was skipped/failed.

Return type:

set[str]

Returns:

Set of gate keys that are never exercised due to a fixed MEM-AP index. Empty when the MEM-AP index is auto-detected (normal AP scan).

get_not_applicable_debug_access_gates()#

Get CoreSight gate keys that can never apply to this family.

The SDA-AP secure-debug-unlock gate (sda_dbgenctrl_written) and the Debug Mailbox AP gate (dbgmlbx_ap_idr_ok) are mutually exclusive at the device-database level: a family either sets dat.sub_features: [sda] (SDA-AP) or dat.dmbox_ap_ix (Debug Mailbox), never both. The gate that does not apply to the current family is entirely omitted from the diagnostic table instead of being shown as a misleading “NOT TESTED”.

Return type:

set[str]

Returns:

Set of gate keys to omit for this probe’s family. Empty when the family is unknown (no filtering possible) so the table falls back to showing every gate, as before.

initialize_debug_port()#

Initialize Debug Port after low-level SWD/JTAG connection.

The method clears possible stale sticky DP errors and powers up system and debug domains together using the common CoreSight power-up sequence.

Raises:

SPSDKError – If debug port power-up fails.

Return type:

None

is_cpu_halted()#

Check if ARM Cortex CPU is halted by reading DHCSR.

Return type:

bool

mem_block_read(addr, size, space=MemorySpace(tag=0, label='data', description='Data memory bus (X: space) — default, 16/32-bit word access'))#

Read a block of memory from the MCU, handling non-aligned addresses and sizes.

This method implements a chunked reading approach to overcome the 1KB auto-increment limitation of the ARM Cortex Debug Access Port (DAP). The method handles memory alignment automatically and reads data in 1KB chunks to ensure reliable operation.

Parameters:
  • addr (int) – The starting memory address to read from.

  • size (int) – The number of bytes to read from memory.

  • space (MemorySpace) – Memory space selector. Must be DATA; PROGRAM is not supported on ARM probes.

Return type:

bytes

Returns:

The read data as a bytes object.

Raises:

SPSDKError – If space is not DATA.

mem_block_write(addr, data, space=MemorySpace(tag=0, label='data', description='Data memory bus (X: space) — default, 16/32-bit word access'))#

Write a block of memory to the MCU, handling unaligned addresses and sizes.

This method implements a three-stage writing approach: 1. Handles initial unaligned bytes using 8-bit writes. 2. Performs bulk 32-bit aligned writes for the main data block. 3. Handles any remaining bytes using 8-bit writes. This approach ensures efficient writing for aligned data while correctly handling unaligned start and end addresses.

Parameters:
  • addr (int) – The starting address to write to.

  • data (bytes) – The data to be written, as a bytes object.

  • space (MemorySpace) – Memory space selector. Must be DATA; PROGRAM is not supported on ARM probes.

Raises:
Return type:

None

mem_reg_read(addr=0, space=MemorySpace(tag=0, label='data', description='Data memory bus (X: space) — default, 16/32-bit word access'))#

Read 32-bit register in memory space of MCU.

This method reads a 32-bit register from the memory space of the connected MCU using the configured debug probe interface.

Parameters:
  • addr (int) – The register address to read from.

  • space (MemorySpace) – Memory space selector. Must be DATA; PROGRAM is not supported on ARM probes.

Return type:

int

Returns:

The read value of addressed register (4 bytes).

Raises:

SPSDKError – If space is not DATA.

mem_reg_write(addr=0, data=0, space=MemorySpace(tag=0, label='data', description='Data memory bus (X: space) — default, 16/32-bit word access'))#

Write 32-bit register in memory space of MCU.

This method writes a 32-bit value to a specified register address in the MCU’s memory space using the configured memory access port.

Parameters:
  • addr (int) – The register address to write to.

  • data (int) – The 32-bit data value to be written into the register.

  • space (MemorySpace) – Memory space selector. Must be DATA; PROGRAM is not supported on ARM probes.

Raises:

SPSDKError – If space is not DATA.

Return type:

None

power_down_target()#

Power down the target for the Probe connection.

This method performs a two-step power down sequence: first disabling system power while maintaining debug power, then disabling debug power completely to ensure proper target shutdown.

Return type:

None

power_up_target()#

Power up the target for the Probe connection.

This method enables both system and debug power to establish a proper connection with the target device through the debug probe.

Raises:

SPSDKError – If power control operation fails.

Return type:

None

read_core_register(reg_num)#

Read the value of an ARM core register via DCRSR/DCRDR.

The core must be halted for this transfer to have a defined effect.

Parameters:

reg_num (int) – Core register number (DCRSR REGSEL field), e.g. CORE_REG_PC.

Return type:

int

Returns:

32-bit value of the register.

Raises:
read_dp_idr()#

Read Debug port identification register.

Return type:

int

Returns:

Debug port identification register value.

recover_debug_connection()#

Recover debug connection using progressive recovery strategy.

Implements ARM CoreSight best practices by attempting multiple recovery levels in sequence: soft recovery, power cycle recovery, probe reconnect recovery, and hard reset recovery. Each level is progressively more invasive.

Return type:

bool

Returns:

True if recovery successful, False otherwise.

select_ap(addr)#

Select the access port in Debug Port (DP).

This method configures the Debug Port to access a specific Access Port by writing to the SELECT register. It includes caching optimization to avoid redundant writes when the same AP is already selected.

Parameters:

addr (int) – Requested AP access address containing AP selection and bank information.

Return type:

None

set_registers_and_resume(pc, sp)#

Set the Program Counter and Stack Pointer, then resume core execution.

This provides the generic “load binary into RAM, then jump to it” primitive used by e.g. the nxpdebugmbox tool execute CLI command: after the target binary has been written into RAM via mem_block_write(), this halts the core if it is not already halted, sets SP/PC to the requested values, and resumes execution from there. Works identically on any Cortex-M based device, since DHCSR/DCRSR/DCRDR addresses and register numbering are fixed by the ARM debug architecture.

Parameters:
  • pc (int) – Value to set into the Program Counter (R15) - the execution start address.

  • sp (int) – Value to set into the Stack Pointer (R13) - the initial stack top.

Raises:

SPSDKError – If any of the underlying register accesses fail.

Return type:

None

trace_cs_event(message)#

Trace a high-level probe event (connect, power-up, reset, …) in a unified format.

Emits a single line on the shared spsdk.probe.trace logger so the TRACE stream is identical across all debug-probe plugins and can be compared directly.

Parameters:

message (str) – Human-readable description of the event.

Return type:

None

trace_cs_read(access_port, addr, data)#

Trace a completed high-level CoreSight register read in a unified format.

Emits a single line on the shared spsdk.probe.trace logger so the TRACE stream is identical across all debug-probe plugins and can be compared directly.

Parameters:
  • access_port (bool) – True if the Access Port (AP) was read, False for Debug Port (DP).

  • addr (int) – The CoreSight register address that was read.

  • data (int) – The 32-bit value that was read.

Return type:

None

trace_cs_write(access_port, addr, data)#

Trace a completed high-level CoreSight register write in a unified format.

Emits a single line on the shared spsdk.probe.trace logger so the TRACE stream is identical across all debug-probe plugins and can be compared directly.

Parameters:
  • access_port (bool) – True if the Access Port (AP) was written, False for Debug Port (DP).

  • addr (int) – The CoreSight register address that was written.

  • data (int) – The 32-bit value that was written.

Return type:

None

write_core_register(reg_num, value)#

Write a value into an ARM core register via DCRSR/DCRDR.

The core must be halted for this transfer to have a defined effect (per the ARM debug architecture); this method does not halt the core implicitly.

Parameters:
  • reg_num (int) – Core register number (DCRSR REGSEL field), e.g. CORE_REG_PC, CORE_REG_SP. Numbering is fixed by the ARM debug architecture and is the same for every ARMv6-M/v7-M/v8-M Cortex-M core.

  • value (int) – 32-bit value to write into the register.

Raises:
  • SPSDKError – If the memory register write operation fails.

  • SPSDKTimeoutError – If the transfer does not complete (S_REGRDY) in time.

Return type:

None

DSC56800EX probe#

SPSDK DSC debug probe implementation.

Background — DSC56800EX debug architecture#

NXP’s Digital Signal Controller (DSC) family (MC56F8xx, MC56F81xx, …) is built around the DSC56800EX core — a Harvard-architecture dual-MAC DSP with a dedicated on-chip debug engine called OnCE (On-Chip Emulation). OnCE is accessed over a standard four-wire JTAG TAP (Test Access Port) and provides instruction-level control of the DSP core as well as direct access to its memory buses.

The Harvard memory map#

The DSC56800EX core has two completely independent address spaces:

X: DATA bus

Holds variables, stack, and peripheral registers. Addressed in 16-bit words; SPSDK also supports 32-bit (long-word) transfers by issuing two consecutive 16-bit operations. This is the “normal” memory you access when reading or writing RAM/peripheral registers.

P: PROGRAM bus

Holds executable code and read-only constants stored in program flash. Addressed in 16-bit words using a different address range — address 0 in P-space is not the same chip location as address 0 in X-space. Crucially, the P-bus cannot be accessed by the standard data-move instructions that OnCE uses for X-space; a special R3-register-indirect move sequence must be used instead.

Why this matters in practice#

A common mistake when porting a flash programmer to DSC is to read back freshly-written program flash using DATA-space addresses. The readback returns data from the X: space at the same numerical address — an entirely different location — giving a false “verify OK” result. SPSDK avoids this by making the bus selection explicit on every memory operation through the space parameter (MemorySpace).

How OnCE memory access works#

DATA space (X:)

OnCE’s DMOVX instruction performs a direct load or store to an absolute X: address. The address and data are shifted into the OnCE data register via JTAG DR-scan.

PROGRAM space (P:)

OnCE does not have a DMOVP direct instruction. The correct sequence is:

  1. Load the P: target address into core register R3 using a move.l #addr, R3 instruction (three 16-bit JTAG words): 0xE41B followed by the high and low 16-bit halves of the address.

  2. Execute a move.w P:(R3), Y0 or move.w Y0, P:(R3) to transfer the data word through the P: bus.

This sequence is generated automatically by DebugProbeDsc; callers simply pass space=MemorySpace.PROGRAM.

JTAG TAP chain#

DSC devices may be daisy-chained with other JTAG TAPs (e.g. a companion ARM core on a multi-core SoC or an on-board FPGA). TapConfig captures the IR length, DR length, IDCODE, and the custom select-TAP IR value needed to route scans to the correct TAP. The device database (database.yaml) stores these values per chip so no manual JTAG configuration is needed.

Plugin development#

To add support for a new physical JTAG adapter targeting DSC devices, derive from DebugProbeDsc and implement the low-level JTAG primitives. Register the class via the spsdk.debug_probe setuptools entry-point. See examples/plugins/README.md for a Cookiecutter template.

class spsdk.debuggers.debug_probe_dsc.DebugProbeDsc(hardware_id, options=None)#

Bases: DebugProbe

SPSDK Debug Probe with DSC interface support.

This class provides a debug probe implementation for DSC (Digital Signal Controller) based MCUs, extending the base DebugProbe class with DSC-specific register definitions and memory access patterns.

Variables:
  • NAME – Debug probe identifier name.

  • ONCE_IR_EONCE – Core-TAP IR instruction to enable EOnCE register access (0x06).

  • CORE_IR_DEBUG_REQUEST – Core-TAP IR instruction to halt the CPU (0x07).

  • IDCODE_IR_INSTRUCTION – JTAG IR instruction to read chip IDCode.

Initialize debug probe with hardware ID and options.

Parameters:
  • hardware_id (str) – Hardware ID of the debug probe to open

  • options (Optional[dict]) – Optional dictionary with probe-specific configuration options

ARCHITECTURE = 'dsc56800ex'#
CHIP_TAP_DR_LENGTH = 32#
CHIP_TAP_IR_LENGTH = 8#
CORE_IR_DEBUGREQ_TLMSEL = 9#
CORE_IR_DEBUG_REQUEST = 7#
DEFAULT_TAP = 'CHIP-TAG'#
DEFAULT_TAPS: ClassVar[dict[str, TapConfig]] = {'CHIP-TAG': TapConfig(ir_length=8, dr_length=4, id=2260025387, id_ir=2, select_tap_ir=5, tlm_select_id=1, dtmcs_ir=None), 'CORE0-TAP': TapConfig(ir_length=4, dr_length=32, id=1639985181, id_ir=2, select_tap_ir=8, tlm_select_id=2, dtmcs_ir=None), 'CORE1-TAP': TapConfig(ir_length=4, dr_length=32, id=1640050717, id_ir=2, select_tap_ir=8, tlm_select_id=4, dtmcs_ir=None), 'DM-TAP': TapConfig(ir_length=5, dr_length=32, id=137891869, id_ir=1, select_tap_ir=5, tlm_select_id=8, dtmcs_ir=16)}#
DMI_DR_LENGTH = 42#
DMI_OP_NOP = 0#
DMI_OP_READ = 1#
DMI_OP_WRITE = 2#
DMTAP_DMI_IR = 17#
DMTAP_IR_LENGTH = 5#
DM_CSW_REG = 0#
DM_IDR_REG = 252#
DM_REQUEST_REG = 4#
DM_RETURN_REG = 8#
DSC_MOVE_L_IMM_R3 = 58395#
DSC_MOVE_L_XR0P_Y0 = 61856#
DSC_MOVE_L_XR0_Y0 = 63904#
DSC_MOVE_L_Y0_XR0 = 55712#
DSC_MOVE_L_Y0_XR0P = 53664#
DSC_MOVE_ORX_R0 = 59277#
DSC_MOVE_ORX_Y0 = 59293#
DSC_MOVE_W_IMM_X0 = 34628#
DSC_MOVE_W_PR3P_X0 = 33899#
DSC_MOVE_W_X0_PR3P = 33891#
DSC_MOVE_Y0_OTX = 59294#
DSC_NOP = 59840#
DSC_SAVE_R3_H = 65535#
DSC_SAVE_R3_L = 58239#
DSC_SAVE_R3_M = 56189#
DSC_SAVE_X0_H = 65535#
DSC_SAVE_X0_L = 59263#
DSC_SAVE_X0_M = 54396#
DTMCS_DMIHARDRESET = 131072#
DTMCS_DMIRESET = 65536#
DTMCS_RESET_MASK = 196608#
IDCODE_IR_INSTRUCTION = 2#
NAME = 'base-dsc'#
ONCE_CMD_DR_LENGTH = 8#
ONCE_CMD_NOP = 31#
ONCE_DATA_DR_LENGTH = 32#
ONCE_EX = 32#
ONCE_GO = 64#
ONCE_IR_EONCE = 6#
ONCE_OPDBR_DR_LENGTH = 16#
ONCE_OSCR_BUSY = 8#
ONCE_OSCR_DEBUG = 32#
ONCE_RS_NOP = 31#
ONCE_RS_OBASE = 5#
ONCE_RS_OCR = 1#
ONCE_RS_OPDBR = 4#
ONCE_RS_ORX = 11#
ONCE_RS_ORX1 = 13#
ONCE_RS_OSCNTR = 2#
ONCE_RS_OSR = 3#
ONCE_RS_OTX = 7#
ONCE_RS_OTX1 = 9#
ONCE_RS_OTXRXSR = 6#
ONCE_RW = 128#
SUPPORTED_PROTOCOLS: tuple[DebugProbeProtocol, ...] = (DebugProbeProtocol(tag=2, label='once', description='On-Chip Emulation protocol'),)#
TLM_DR_LENGTH = 4#
connect_safe()#

Debug probe connect in safe manner.

Establishes communication with the DSC debug probe hardware in a safe manner with error recovery capabilities.

Raises:
  • SPSDKError – When connection to debug probe fails.

  • SPSDKTimeoutError – When connection timeout occurs.

  • Exception – Re-raises the original connection exception.

Return type:

None

dbgmlbx_reg_read(addr=0)#

Read debug mailbox access port register.

This function reads a debug mailbox register through the DSC JTAG interface by accessing the DM-TAP (Debug Mailbox TAP) via DMI protocol.

Parameters:

addr (int) – The register address to read from (0x00=CSW, 0x04=REQUEST, 0x08=RETURN, 0xFC=ID)

Return type:

int

Returns:

The read value of addressed register (4 bytes).

Raises:
dbgmlbx_reg_write(addr=0, data=0)#

Write debug mailbox access port register.

Writes data to a specified register address in the debug mailbox through the DSC JTAG interface by accessing the DM-TAP via DMI protocol.

Parameters:
  • addr (int) – Register address to write to (0x00=CSW, 0x04=REQUEST, 0x08=RETURN, 0xFC=ID)

  • data (int) – Data value to write into the register.

Raises:
Return type:

None

debug_halt()#

Halt the DSC CPU execution via Core-TAP DEBUGREQ_TLMSEL.

Uses DEBUGREQ_TLMSEL (IR=0x09) which combines DEBUG_REQUEST with TLM_SELECT, ensuring the debug request is asserted during the full DR scan phase. The TLM DR value re-selects Core0-TAP to maintain the current TAP selection while the debug request is latched.

Raises:
Return type:

None

debug_resume()#

Resume the DSC CPU execution via OnCE EX flag.

Switches to CORE0-TAP and sends an OnCE NOP command with the EX (exit) flag set, which causes the core to leave debug mode and resume execution.

Raises:
Return type:

None

debug_step()#

Step the DSC CPU by one instruction via OnCE.

Switches to CORE0-TAP and sends an OnCE NOP command with EX and GO flags set, causing the core to execute one instruction and re-enter debug mode.

Raises:
Return type:

None

is_cpu_halted()#

Check if DSC CPU is halted by reading OnCE status.

Sends a NOP OnCE command and reads the OSCR value shifted out on TDO. The OSCR[DEBUG] bit indicates whether the core is in debug (halted) mode.

Return type:

bool

Returns:

True if CPU is halted (in debug mode), False if running.

Raises:

SPSDKDebugProbeError – If the status read fails.

abstract jtag_idle(num_cycles=1)#

Perform JTAG idle cycles.

This method should be implemented by concrete probe classes to perform the specified number of JTAG idle (Run-Test/Idle) cycles.

Parameters:

num_cycles (int) – Number of idle cycles to perform

Raises:

SPSDKDebugProbeNotOpenError – If the debug probe is not opened.

Return type:

None

abstract jtag_init()#

Get JTAG TAP controller into known state.

Return type:

None

mem_block_read(addr, size, space=MemorySpace(tag=0, label='data', description='Data memory bus (X: space) — default, 16/32-bit word access'))#

Read a block of memory from DSC memory via OnCE.

Reads consecutive 16-bit words from the selected memory space. For DATA space (default) uses absolute D1 addressing. For PROGRAM space uses R3-indirect addressing (16-bit words only).

Parameters:
  • addr (int) – Starting DSC word address (24-bit).

  • size (int) – Number of bytes to read.

  • space (MemorySpace) – Memory bus to access. Defaults to DATA for full backward compatibility.

Return type:

bytes

Returns:

The read data as a bytes object.

Raises:

SPSDKDebugProbeError – If there’s an error during the read operation.

mem_block_write(addr, data, space=MemorySpace(tag=0, label='data', description='Data memory bus (X: space) — default, 16/32-bit word access'))#

Write a block of memory to DSC memory via OnCE.

Writes consecutive 16-bit words to the selected memory space. For DATA space (default) uses absolute D1 addressing. For PROGRAM space uses R3-indirect addressing (16-bit words only).

Parameters:
  • addr (int) – Starting DSC word address (24-bit).

  • data (bytes) – The data to be written, as a bytes object.

  • space (MemorySpace) – Memory bus to access. Defaults to DATA for full backward compatibility.

Raises:

SPSDKDebugProbeError – If there’s an error during the write operation.

Return type:

None

mem_reg_read(addr=0, space=MemorySpace(tag=0, label='data', description='Data memory bus (X: space) — default, 16/32-bit word access'))#

Read a value from DSC memory via OnCE instruction injection.

Supports both DATA bus (X: space, 32-bit read as two 16-bit words) and PROGRAM bus (P: space, 16-bit read only — upper 16 bits of the return value are always zero for program space reads).

DSC memory is 16-bit word-addressed. The address is used directly as a DSC word address (not byte-addressed).

DATA space — uses the proven JTAG_Driver.c approach with D1 register and absolute addressing. Reads two consecutive 16-bit words at addr (low) and addr+1 (high). Instruction sequence:

  1. Save D1: move.w D1, x:0xFFFFFF → read OTX1 via JTAG

  2. Read low word: move.w x:<addr>, D1 → move.w D1, x:0xFFFFFF → read OTX1

  3. Read high word: move.w x:<addr+1>, D1 → move.w D1, x:0xFFFFFF → read OTX1

  4. Restore D1: move.w #saved, D1

PROGRAM space — uses R3-register-indirect addressing (16-bit word only):

  1. Save R3: move.l R3, x:0xFFFFFF → read OTX via JTAG

  2. Save X0: move.w X0, x:0xFFFFFF → read OTX1 via JTAG

  3. Load address: move.l #addr, R3

  4. Read word: move.w p:(R3+), X0 → move.w X0, x:0xFFFFFF → read OTX1

  5. Restore R3 and X0

Parameters:
  • addr (int) – DSC memory word address (24-bit).

  • space (MemorySpace) – Memory bus to access. Defaults to DATA for full backward compatibility.

Return type:

int

Returns:

The value read from memory (32-bit for DATA space, 16-bit for PROGRAM space).

Raises:

SPSDKDebugProbeError – If the memory read operation fails.

mem_reg_write(addr=0, data=0, space=MemorySpace(tag=0, label='data', description='Data memory bus (X: space) — default, 16/32-bit word access'))#

Write a value to DSC memory via OnCE instruction injection.

Supports both DATA bus (X: space, 32-bit write as two 16-bit words) and PROGRAM bus (P: space, 16-bit write only — only the lower 16 bits of data are written; upper bits are silently ignored for program space).

DATA space — uses the proven JTAG_Driver.c approach with D1 register and absolute addressing. Writes two consecutive 16-bit words at addr (low) and addr+1 (high). Instruction sequence:

  1. Save D1: move.w D1, x:0xFFFFFF → read OTX1 via JTAG → saved value

  2. Load low word: move.w #low, D1

  3. Write low word: move.w D1, x:<addr>

  4. Load high word: move.w #high, D1

  5. Write high word: move.w D1, x:<addr+1>

  6. Restore D1: move.w #saved, D1

PROGRAM space — uses R3-register-indirect addressing (16-bit word only):

  1. Save R3: move.l R3, x:0xFFFFFF → read OTX via JTAG

  2. Save X0: move.w X0, x:0xFFFFFF → read OTX1 via JTAG

  3. Load address: move.l #addr, R3

  4. Load word: move.w #data, X0

  5. Write word: move.w X0, p:(R3+)

  6. Restore R3 and X0

Parameters:
  • addr (int) – DSC memory word address (24-bit).

  • data (int) – Value to write (32-bit for DATA space; only lower 16 bits used for PROGRAM space).

  • space (MemorySpace) – Memory bus to access. Defaults to DATA for full backward compatibility.

Raises:

SPSDKDebugProbeError – If the memory write operation fails.

Return type:

None

read_dp_idr()#

Read Debug port identification register.

For DSC architecture, this reads the chip IDCode through the JTAG interface by writing instruction register (IR) value 2 with 8-bit length, then reading the 32-bit data register (DR) to retrieve the chip identification code.

Return type:

int

Returns:

Debug port identification register value (chip IDCode).

Raises:
select_coretap()#

Decorator that ensures CORE0-TAP is selected before OnCE operations.

For DSC architecture, this decorator switches the JTAG chain to CORE0-TAP via TLM before performing OnCE (On-Chip Emulation) operations like halt, resume, step, and status read.

Parameters:

func – The function to be decorated that requires CORE0-TAP access.

Raises:

SPSDKDebugProbeError – When CORE0-TAP cannot be accessed.

Returns:

Decorated function wrapper.

select_dmtap()#

Decorator function that secures getting the correct DEBUG MAILBOX AP for DSC.

For DSC architecture, this decorator ensures that the DM-TAP (Debug Mailbox TAP) is properly selected and accessible before performing debug mailbox operations.

Parameters:

func – The function to be decorated that requires debug mailbox access.

Raises:

SPSDKError – When debug mailbox TAP cannot be accessed.

Returns:

Decorated function wrapper.

abstract write_dr(bitlength, data)#

Write to and read from JTAG Data Register.

This method writes data to the JTAG Data Register (DR) and returns the data shifted out during the operation.

Parameters:
  • bitlength (int) – Number of bits to shift through DR.

  • data (bytearray) – Data buffer to write to DR.

Return type:

bytearray

Returns:

Data read from DR during the shift operation.

Raises:
abstract write_ir(instruction, length)#

Write to JTAG Instruction Register.

This method writes an instruction value to the JTAG Instruction Register (IR) with the specified bit length.

Parameters:
  • instruction (int) – Instruction value to write to IR.

  • length (int) – Bit length of the instruction.

Raises:
Return type:

None

class spsdk.debuggers.debug_probe_dsc.TapConfig(ir_length, dr_length, id, id_ir, select_tap_ir, tlm_select_id, dtmcs_ir=None)#

Bases: object

JTAG TAP (Test Access Port) configuration.

This dataclass encapsulates the configuration parameters for a JTAG TAP, including register lengths, identification codes, and selection instructions.

dr_length: int#
dtmcs_ir: int | None = None#
classmethod from_dict(config)#

Create TapConfig from dictionary.

Parameters:

config (dict) – Dictionary containing TAP configuration parameters

Return type:

TapConfig

Returns:

TapConfig instance

id: int#
id_ir: int#
ir_length: int#
select_tap_ir: int#
tlm_select_id: int#

Probe utilities#

SPSDK debug probe utilities and management functions.

This module provides comprehensive functionality for discovering, selecting, and managing debug probes across different hardware interfaces. It includes utilities for probe detection, connection testing, and plugin loading for various debug probe types supported by SPSDK.

spsdk.debuggers.utils.get_all_debug_probe_plugins()#

Get dictionary of all available debug probe types.

This method loads all debug probe plugins and returns a mapping of probe names to their corresponding DebugProbe class types. It recursively searches through all DebugProbe subclasses to build the complete registry.

Return type:

dict[str, type[DebugProbe]]

Returns:

Dictionary mapping debug probe names to their DebugProbe class types.

spsdk.debuggers.utils.get_connected_probes(interface=None, hardware_id=None, options=None, architecture=None)#

Get connected debug probes in the system.

The caller can restrict the scanned interfaces by specifying interface type, hardware ID, or architecture. Probes with an ARCHITECTURE other than "abstract" are excluded when their architecture does not match, so DSC probes are automatically hidden when looking for a Cortex-M device and vice-versa.

Parameters:
  • interface (Optional[str]) – Interface type to scan, None to scan all available interfaces.

  • hardware_id (Optional[str]) – Hardware ID filter, None to list all probes or specific ID to match.

  • options (Optional[dict]) – Optional configuration dictionary for probe scanning.

  • architecture (Optional[str]) – DB architecture string (e.g. "arm-cortex", "dsc56800ex") used to filter probe types. None disables filtering.

Return type:

DebugProbes

Returns:

Collection of connected debug probes matching the specified criteria.

spsdk.debuggers.utils.get_test_address(family)#

Get AHB access test address for the device.

The address is resolved from debug-probe, DAT, and communication-buffer configuration. If none is defined, a warning is logged and the generic Cortex-M SRAM address is used.

Parameters:

family (FamilyRevision) – Family revision specification for the target device.

Return type:

int

Returns:

Test address for AHB access verification.

spsdk.debuggers.utils.load_all_probe_types()#

Load the current list of all debug probe types.

This method initializes the global PROBES variable by retrieving all available debug probe plugins from the system.

Return type:

None

spsdk.debuggers.utils.load_debug_probe_plugins()#

Load all installed debug probe plugins.

Discovers and loads debug probe plugins from entry points using the plugins manager.

Return type:

dict[str, ModuleType]

Returns:

Dictionary mapping plugin names to their corresponding module objects.

spsdk.debuggers.utils.open_debug_probe(interface=None, serial_no=None, debug_probe_params=None, print_func=<built-in function print>, input_func=<built-in function input>, architecture=None)#

Open debug probe as context manager.

The method scans for available debug probes based on the provided criteria, allows user selection if multiple probes are found, opens the selected probe, and yields it as a context manager that automatically closes the probe when done.

If architecture is not supplied and debug_probe_params contains a "family" key (set by DebugProbeParams.set_family()), the architecture is looked up from the device database and passed to get_connected_probes() for automatic filtering.

Parameters:
  • interface (Optional[str]) – Interface type to scan, None to scan all available interfaces.

  • serial_no (Optional[str]) – Serial number of specific probe, None to list all available probes.

  • debug_probe_params (Optional[dict]) – Dictionary with optional debug probe configuration parameters.

  • print_func (Callable[[str], None]) – Custom function to print data, defaults to print.

  • input_func (Callable[[], str]) – Custom function to handle user input, defaults to input.

  • architecture (Optional[str]) – DB architecture string to filter probe types. When None the value is derived automatically from debug_probe_params if a family is present.

Return type:

Iterator[DebugProbe]

Returns:

Active DebugProbe object as context manager.

Raises:
spsdk.debuggers.utils.render_debug_access_status_table(probe, depth=None)#

Render a colour-coded table of the debug-access gating status.

Renders the gates recorded in probe.debug_access_status (see DebugProbe.DEBUG_ACCESS_STATUS_LABELS for the ordered list of gates and their human-readable labels). Each gate is shown as PASSED (green), FAILED (red), NOT TESTED (grey) when the gate was never exercised during this session, or N/A (grey) when the gate can never be exercised for this probe/family (see below). The whole row - index, gate description, and status - is coloured consistently.

Two kinds of gates are handled specially via DebugProbe.get_not_applicable_debug_access_gates() and (on DebugProbeCoreSightOnly) get_never_tested_debug_access_gates:

  • Not applicable gates are architecturally impossible for this family (e.g. the SDA-AP secure-debug-unlock gate versus the Debug Mailbox AP gate are mutually exclusive per device database) and are omitted from the table entirely, rather than shown as a misleading “NOT TESTED”.

  • Never tested gates could apply in principle, but a device-database shortcut (e.g. a fixed MEM-AP index) means the corresponding code path is never exercised for this family. These are kept in the table but rendered as “N/A” instead of “NOT TESTED”, to avoid implying a real test was skipped.

debug_access_status always exists on DebugProbe (base class), for every architecture including DSC, so this function never needs to guard against a missing attribute.

This is purely a diagnostic helper; it does not affect probe behaviour.

Parameters:
  • probe (DebugProbe) – Debug probe instance whose gating status should be rendered.

  • depth (Optional[int]) – Limit the table to the first N gates (in evaluation order, after omitting not-applicable gates). None (default) renders all gates known to the probe. Useful e.g. for the debug_port test-connection destination, which only exercises the first two gates (probe connection, Debug Port IDR) and would otherwise show unrelated architecture-specific gates as NOT TESTED.

Return type:

str

Returns:

Formatted, colour-coded table string.

spsdk.debuggers.utils.select_probe(probes, silent=False, print_func=<built-in function print>, input_func=<built-in function input>)#

Select debug probe from available probes.

Handles automatic selection when only one probe is available, or prompts user for selection when multiple probes are found. Supports silent mode and custom input/output functions for testing.

Parameters:
  • probes (DebugProbes) – List of available debug probes to select from.

  • silent (bool) – If True, suppress output when only one probe is available.

  • print_func (Callable) – Custom function for output, defaults to print.

  • input_func (Callable[[], str]) – Custom function for user input, defaults to input.

Return type:

ProbeDescription

Returns:

Selected probe description.

Raises:
spsdk.debuggers.utils.test_ahb_access(probe, ap_mem=None, invasive=True, test_mem_address=None)#

Test the access of debug probe to AHB in target safely.

The function performs a safe test to verify if the debug probe has access to the AHB (Advanced High-performance Bus) in the target device. It can perform both non-invasive and invasive tests depending on the configuration.

Parameters:
  • probe (DebugProbe) – Debug probe object to use for testing.

  • ap_mem (Optional[int]) – Index of memory access port, defaults to current probe setting.

  • invasive (bool) – Enable invasive test that temporarily modifies destination RAM value.

  • test_mem_address (Optional[int]) – Address in volatile memory for testing AHB memory access.

Raises:

SPSDKError – When test connection verification fails during invasive testing.

Return type:

bool

Returns:

True if access to AHB is granted, False otherwise.