# probe-rs: a Rust debugging toolkit for ARM, RISC-V and Xtensa targets

> probe-rs talks to DAPLink, STLink, JLink and other probes from a host machine, and ships a Cargo runner, a GDB server and a VS Code debug adapter. It is strongest when your firmware is Rust and your chip is in its target database.

**probe-rs/probe-rs** — A debugging toolset and library for debugging embedded ARM and RISC-V targets on a separate host

- Repository: https://github.com/probe-rs/probe-rs
- Website: https://probe.rs
- Stars: 2,956 · Forks: 650
- Language: Rust
- License: Apache-2.0
- Published: 2026-09-24 · Updated: 2026-09-24 · Language: en
- Canonical page: https://hysenlabs.com/projects/probe-rs-probe-rs

## What probe-rs replaces on an embedded bench

The usual embedded setup is a vendor IDE talking to a vendor probe over a proprietary driver, with flashing and debugging fused into one vendor-specific application. probe-rs separates those layers. The library exposes a direct interface to the debug probe, and other software can build on that interface instead of reimplementing SWD or JTAG handling per probe family.

The README lists the hardware it can connect to: DAPLink, STLink, JLink, FTDI probes, ESP32 devices with USB JTAG, WLink and the Blackmagic probe. On the target side it talks to ARM, RISC-V and Xtensa cores over SWD or JTAG. That combination matters because it means one host-side toolchain covers boards that would otherwise need three different vendor utilities.

The audience is narrower than "embedded developers". It is people who write firmware in Rust, or who at least want to flash an ELF that came out of a C or C++ compiler, and who are willing to run a command-line tool on a separate host rather than inside an IDE. The README describes cargo-flash as able to download arbitrary ELF files from a C/C++ compiler, so a mixed project is not excluded.

## How the library, the tools and the debug adapter fit together

The repository is a Cargo workspace, not a single crate. The members list includes probe-rs itself, probe-rs-target, probe-rs-tools, probe-rs-debug, probe-rs-mi, probe-rs-rpc, probe-rs-rpc-client, probe-rs-espressif and probe-rs-linux. The split tells you where a given capability lives: the core library in probe-rs, the target descriptions in probe-rs-target, and the command-line surface in probe-rs-tools.

The data flow is probe to host to tool. A session is opened against a named chip, then a core is selected from that session, and memory or execution operations go through the core. The README's halting example shows the sequence directly: create a Lister, call list_all, open the first probe, attach to a chip by name such as nRF52840_xxAA, call session.core(0), then core.halt with a timeout.

On top of that core sits the tool layer. probe-rs run flashes firmware, resets the target and streams RTT and defmt output plus panics back to the console. cargo-flash only programs the chip. cargo-embed adds an interactive RTT terminal and config files, and the README states it is expected to be phased out in the future, with probe-rs run preferred for new setups. The Microsoft Debug Adapter Protocol implementation is what makes the same debugging available in editors that support DAP, VS Code among them.

One architectural detail worth noticing is probe-rs-linux, which lets a Linux host act as the probe itself. It offers a linuxgpiod backend that bit-bangs SWD over the GPIO character-device interface and a linuxspidevswd backend that emulates SWD over a spidev bus. That is a different shape from the usual probe-plus-USB arrangement, and it is selected with a synthetic probe string rather than a USB device.

## Installing probe-rs and running your first firmware

The README states that the recommended installation path is a precompiled version, and points at https://probe.rs/docs/getting-started/installation for the detailed guide. It does not list per-platform package commands in the repository README, so treat the website as the authoritative source for the download step rather than copying a package manager invocation from a blog post.

Once the tools are on your PATH, the first thing to confirm is that the host can see the probe. The README uses probe-rs list for enumeration, and notes that for the Linux SWD backends it only exposes explicit /dev/spidev_swd* udev links so the tool does not implicitly try every SPI device on the system.

```bash
probe-rs list
```

If your probe appears, the next step is to check that the chip is known. The target database is what maps a chip name to flash algorithms and core layout, and the name you pass has to match an entry in it.

```bash
probe-rs info --probe 0:0:/dev/spidev0.0
```

For day-to-day work, the README's recommendation is to wire probe-rs run into Cargo as the runner. The example config targets ARM bare-metal builds and names the chip inline.

```toml
# .cargo/config.toml
[target.'cfg(all(target_arch = "arm", target_os = "none"))']
runner = "probe-rs run --chip nRF52840_xxAA"
```

With that file in place, `cargo run` flashes and runs the firmware, and RTT or defmt output and panics come back to the same console. That single integration is the reason most users never invoke the flashing tools directly.

If you are writing host-side code instead of using the CLI, the library API is the entry point. The README's RAM example constructs a SessionConfig with a speed and a WireProtocol, calls Session::auto_attach with the chip name, selects core 0, and then uses read_32, read_word_32, write_32 and write_8 through the MemoryInterface trait. Note that this example attaches to a chip by name; it does not enumerate probes first, which is the difference from the halting example above.

## Where probe-rs stops being the right tool

The support list is the boundary. ARM, RISC-V and Xtensa are covered. A core family outside those three is not something the README claims, and no amount of probe compatibility compensates for a target the library cannot talk to.

Probe support is a second boundary, and it is not the same as "any USB debugger". DAPLink, STLink, JLink, FTDI, ESP32 USB JTAG, WLink and Blackmagic are named. A proprietary probe that does not fall into one of those categories has no documented path here.

The Linux-host-as-probe feature deserves a specific caution. Bit-banging SWD over GPIO is a convenience, not a replacement for a real probe, and the README itself shows the project is careful about it: probe-rs list deliberately restricts what it exposes for spidev so the tool does not probe every SPI device. If you need reliable high-speed flashing or trace, a dedicated probe is the safer choice.

There is also a lifecycle issue. cargo-embed is documented as expected to be phased out. Anyone with an existing cargo-embed workflow and embedded config files is on a path that the project has already signalled will end, and the migration target is probe-rs run. That is a real cost to budget for, not a footnote.

Finally, the workspace pins a minimum Rust version of 1.95 in Cargo.toml, with a justfile recipe that checks it. Building the library from source on an older toolchain will fail, and the edition is 2024. That constrains anyone integrating probe-rs as a dependency into a project with a conservative toolchain policy.

## probe-rs against OpenOCD and vendor GDB servers

The natural comparison is OpenOCD, which most people reach for when they want a GDB server for an embedded target. The difference is where the abstraction sits. OpenOCD is a GDB server with its own configuration language and a large set of target and adapter config files; you typically start it, then connect GDB to a port. probe-rs is a Rust library first, and its GDB server is one of several front ends built on that library, alongside the CLI, the DAP implementation for editors, and the Cargo runner.

That ordering changes what you get. With probe-rs, RTT and defmt output streaming is a first-class part of probe-rs run rather than something you bolt on, and the Cargo runner integration means `cargo run` is the whole flash-and-observe loop. With OpenOCD, the equivalent workflow involves a separate GDB client and, for RTT, additional tooling.

The trade-off runs the other way too. OpenOCD has a long history and a configuration ecosystem that covers boards and adapters that probe-rs does not list. If your probe is not a DAPLink, STLink, JLink, FTDI, WLink or Blackmagic unit, or your core is not ARM, RISC-V or Xtensa, OpenOCD is the more likely fit. probe-rs is the better choice when the target is in its database and you want the debug session driven from Rust tooling rather than from a separate server process you manage yourself.

## Licence, releases and what an upgrade costs

The workspace declares `MIT OR Apache-2.0`, and the repository carries both LICENSE-MIT and LICENSE-APACHE at the top level. That is the standard permissive dual licence used across the Rust ecosystem, and it is the same pair you will find on most crates you already depend on. If you redistribute probe-rs inside a product, the usual obligations of whichever of the two you pick apply; that is a question for your own legal review, not something this article can settle.

Release cadence is visible from the tags. v0.32.0 was published on 2026-07-22, v0.31.0 on 2026-01-17 and v0.30.0 on 2025-10-31. The version numbering is still pre-1.0, which is worth factoring into an upgrade plan: the project uses a shared workspace version, so the library and the tools move together rather than versioning independently.

For upgrade cost, the repository gives you two things to read. CHANGELOG.md holds released changes, and the changelog/ directory holds individual fragments for changes that have not been released yet. Reading the fragments before a bump tells you what is coming rather than what already landed. The justfile also defines the checks the maintainers run, including clippy, formatting checks, a no-default-features build and a full-feature test run via cargo nextest, so a downstream project can mirror the same gates.

## Conclusion

Adopt probe-rs if your targets are ARM, RISC-V or Xtensa cores, your probe is a DAPLink, STLink, JLink, FTDI, WLink or Blackmagic unit, and you want flashing plus RTT output driven from Cargo or VS Code. Do not adopt it if you need a debugger for a core family outside that list, or if your workflow depends on cargo-embed, which the README says is expected to be phased out. Before committing, verify that your exact chip name appears in the target database and that `probe-rs list` sees your probe, since a missing chip or an unenumerated probe is the failure you will hit first.

## FAQ

### How do I install probe-rs?

The README states the recommended way is to download a precompiled version, and points to https://probe.rs/docs/getting-started/installation for the detailed guide. The repository README does not list per-platform package commands itself.

### What is probe-rs?

It is a debugging toolkit and library written in Rust that interacts with embedded MCUs and debug probes, providing a direct interface to the probe so other software can use its debug functionality. It also ships tools for flashing and debugging, including Cargo extensions, a VS Code extension, a GDB server and a standalone CLI.

### How do I use probe-rs with VS Code?

probe-rs implements the Microsoft Debug Adapter Protocol, which makes embedded debugging available in editors that support the standard, VS Code included. The probe-rs website carries the VS Code configuration instructions.

### How do I debug Rust code with probe-rs?

The README recommends probe-rs run for most projects: it flashes firmware, resets the target and streams RTT and defmt output plus panics to the console. Pointing Cargo at it as the runner means `cargo run` performs the flash and run cycle.

### How do I use probe-rs?

For most projects the README points at probe-rs run, which flashes firmware, resets the target and streams RTT and defmt output back to the console. It can be set as the Cargo runner so that `cargo run` performs the whole cycle.

## Sources

- [License: Apache-2.0](https://github.com/probe-rs/probe-rs/blob/master/LICENSE)
- [probe-rs/probe-rs on GitHub](https://github.com/probe-rs/probe-rs)
- [Project website](https://probe.rs)
- [README](https://github.com/probe-rs/probe-rs/blob/master/README.md)
- [Releases](https://github.com/probe-rs/probe-rs/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/probe-rs-probe-rs
