Skip to main content
Drive a debug probe from a cargo test: connect, flash firmware, reset or halt the target, and read its memory. Debug nets are the one net type that does not talk to the box’s API on port 9000. They reach the box’s debug service on port 8765 instead.

Handle

The net’s saved record is fetched once on first use and cached on the handle. The cache is dropped whenever an operation fails, so a re-saved net is picked up on the next attempt rather than needing a new handle.

Methods

RTT streaming lives on the same handle and is covered in RTT.

Types

ConnectOptions

Default sets gdb: true and everything else off, so connect() starts a GDB server. Build the struct with ..Default::default(), so a field added later does not break your code. jlink_script and openocd_config replace a script saved on the net, for this connection only. An OpenOCD config must be complete and must select the adapter driver.

FirmwareKind

FlashReport and EraseReport

flash() and its variants return a FlashReport: erase() and erase_range() return an EraseReport: An EraseRange carries start, end (inclusive), length, text, and source. source is "request", "script" or "default".

Method Reference

connect() -> Result<DebugConnection>

Connect using ConnectOptions::default().
Returns: DebugConnection, carrying the device, probe, serial, backend, and a GdbServer with the ports that were opened. On a J-Link these come back as gdb 2331, SWO 2332, telnet 2333 and RTT telnet 9090. tcl_port is OpenOCD-only and is None on a J-Link, just as swo_port is J-Link-only.

connect_with(opts: &ConnectOptions) -> Result<DebugConnection>

Connect with explicit options.
halt: true resets the target and then halts it. On a part that executes in place out of QSPI, that reset runs the bootloader again. To stop the core without a reset, use halt().

disconnect(keep_running: bool) -> Result<()>

Disconnect. Pass true to leave the gdbserver up for an external GDB client to attach to; pass false to tear it down.

reset(halt: bool) -> Result<()>

Reset the target. halt: true leaves it stopped at the reset vector.

halt() -> Result<()>

Stop the core where it is. halt() sends OpenOCD’s bare halt, so nRESET stays untouched. Use it on a part that executes in place out of QSPI, where a reset runs the bootloader again. halt() requires box software 0.60.0 or later and an OpenOCD net:
  • The crate reads the debug service’s features first. A box without halt fails with Error::UnsupportedByBox, and nothing reaches the probe.
  • A J-Link net fails with Error::Box and HTTP 400. J-Link has no halt-in-place primitive, so connect with a halt-first .JLinkScript instead.
  • A net with no running debugger fails with Error::Box and No debugger connection found.

erase() -> Result<EraseReport>

Erase the target’s flash: the whole chip, or the part family’s default range on parts where the box defines one (DA1469x, nRF5340). The report says which range the box erased.
On a J-Link probe, or on a DA1469x target, erase() drops the debugger connection. The next read_memory() fails with Error::Box and No debugger connection found. flash re-establishes on its own, so an erase-then-flash sequence works, but an erase-then-read does not — call connect() again first. On an OpenOCD probe with any other target, the OpenOCD daemon stays up after the erase.

erase_range(start: u64, size: u64) -> Result<EraseReport>

Erase only size bytes of flash, starting at start.
erase_range() requires box software 0.50.0 or later. An older box ignores the range and erases the whole chip. So the crate reads the debug service’s features first, and fails with Error::UnsupportedByBox before anything is erased. The box refuses a range outside what it can erase on the part with HTTP 400.

flash(firmware_path) -> Result<FlashReport>

Flash a file, inferring the type from its extension: .hex, .elf or .bin. An unrecognized extension is Error::Config. A flash that programmed nothing fails with Error::FlashFailed, which carries the box’s verdict line and the backend’s output. Box software 0.51.0 and later reports this. An older box reports no verdict, and programmed is None.
A .bin is flashed at 0x08000000, the STM32 application base. On any other family that address is wrong, and the call still returns Ok. This was verified on an nRF5340: flash() of a .bin succeeded while flash at 0x0 stayed erased. This is a silent wrong result, not an error. Off STM32, use flash_bin() with the correct base address.

flash_bin(firmware_path, address: u32) -> Result<FlashReport>

Flash a raw binary at an explicit base address. This is the correct call for any target whose application does not start at 0x08000000.

flash_bytes(contents: &[u8], kind: FirmwareKind, address: Option<u32>) -> Result<FlashReport>

Flash bytes you already hold, without writing them to a file first. address is used only for FirmwareKind::Bin and defaults to 0x08000000.

read_memory(address: u64, length: usize) -> Result<Vec<u8>>

Read length bytes from the target starting at address.
Requires a live connection: without one it fails with Error::Box and No debugger connection found. On a J-Link net with a DA1469x target, the box resets and halts the target before it reads. Other targets, and OpenOCD nets, do not reset for a read.

read_memory_no_reset(address: u64, length: usize) -> Result<Vec<u8>>

Read target memory without the reset and halt that read_memory() does first on a J-Link DA1469x target. A running target keeps running. A box that predates this option ignores it, and reads as read_memory() does.

info(), status(), info_probed() and status_probed()

info() reports the device, architecture, probe, serial and backend, plus whether a connection is live. status() reports the gdbserver: whether one is active, its pid, and the probe serial. Both work without connecting first.
Both carry two fields from box software 0.44.0 and later. An older box leaves them None. From info() and status(), target_attached is None unless the box already knows that the attach failed. info_probed() and status_probed() read the target to settle it, which takes about a second longer.

Examples

Flash and verify

Stop a running target and inspect it

Leave a gdbserver up for an interactive session

Supported Hardware

Notes

  • Timeout budgets are per operation and match the CLI:
    • connect 30 s
    • flash 180 s
    • erase 120 s
    • memory read 30 s
    • 10 s for reset, halt, info, status and disconnect
  • Net resolution requires the debug role. A net that exists with another role gives net 'adc1' exists but is not a debug net. A name that does not exist gives debug net 'nosuch' not found on this box.
  • The debug service does not use the same success envelope as the port-9000 API. A 200 is success; anything else is an error carrying the service’s message.
  • Another operation can hold the probe longer than the box waits. The box then answers HTTP 503, and the crate returns Error::ProbeBusy. Retry when the other operation is done.
  • A net configured with allow_destructive: false refuses erase() and flash() with HTTP 403, which the crate returns as Error::SafetyRefused. See Client and Box.
  • Async note: AsyncDebugNet provides everything here, but no RTT.