Skip to main content

Crate tagprobe

Crate tagprobe 

Source
Expand description

Programming tags through the tag bases with probe-rs.

The replacement for qtprogram’s STM32_Programmer_CLI calls: list the bases, ask each who it is, check the connection, program an image with an erase plan, and read flash back. Every operation picks its probe driver from the base’s identity:

  • a base that answers the identify command (F6 99, see embedded/bases/README.md) has the ST-LINK fixes, so probe-rs’s own ST-LINK driver is used (Driver::Stock);
  • a base that does not – every base in the field – is driven through FieldSafeProbe, which uses only the commands all bases support (Driver::FieldSafe).

Attaches here go through reset, so they end whatever the tag was doing, like every tool in this tree. Nothing here may run while a tagcore monitor session holds the same base: detach first.

The evaluation that led here is docs/investigations/2026-10-probe-rs-evaluation.md; the crate’s design is in host/libraries/tagprobe-rs/design/architecture.md.

§Hardware side effects

  • list and identify never touch nRST or SWD, so the tag keeps running.
  • connect_check, program and read_memory all hold the tag in reset to attach. A running log is ended, and the tag reboots its firmware afterwards. program also rewrites internal flash.

§Threading

Every call opens the base, uses it and closes it again; nothing is held between calls, so calls may come from any thread. Two calls on the same base at once are not serialised here and would interleave their USB exchanges: the caller owns that exclusion. The Stock driver is opened through [StLinkFactory] only, never probe-rs’s Lister; see open_probe for why that matters on macOS.

§Examples

The connect check and programming sequence:

use std::path::Path;
use tagprobe::{Driver, Erase, Progress};

let base = tagprobe::list().into_iter().next().expect("no base on USB");
let driver = Driver::for_identity(tagprobe::identify(&base).as_deref());
let found = tagprobe::connect_check(&base)?;
let chip = tagprobe::chip_for(found.device_id, Some(0x40000))?;
tagprobe::program(&base, driver, chip, Path::new("tag.elf"), Erase::ImagePages, |p| {
    if let Progress::Step(step) = p {
        println!("{step}");
    }
})?;

Re-exports§

pub use fieldsafe::FieldSafeProbe;

Modules§

fieldsafe
A probe-rs probe driver for our tag bases, using only the ST-LINK commands every base in the field supports.

Structs§

Connect
What a connect check found (STM32_Programmer_CLI -c port=SWD mode=UR).
TagSequence
The attach/detach sequence used for every session: the ARM default, which writes nothing to DBGMCU and on detach clears DHCSR.C_DEBUGEN and DEMCR.

Enums§

Driver
Which probe-rs driver drives a base.
Erase
The internal-flash erase that goes with a program.
Progress
Progress during program.

Constants§

DEV_L432
STM32L43x/L44x DBGMCU device ID.
DEV_U375
STM32U37x/U38x DBGMCU device ID.
FLASH_BASE 🔒
Start of internal flash, where every tag image’s vector table sits.
L4_DBGMCU_IDCODE 🔒
Address of DBGMCU_IDCODE on the STM32L4.
L4_FLASH_SR 🔒
Address of the STM32L4 flash status register, FLASH_SR.
L4_FLASH_SR_PEMPTY 🔒
FLASH_SR.PEMPTY (bit 17) on the STM32L4.
PROBE_RS_VERSION
The probe-rs release these tools are built and tested against.
U3_DBGMCU_IDCODE 🔒
Address of DBGMCU_IDCODE on the STM32U3.

Functions§

chip_for
Returns the probe-rs target name for a device, from its ID and the flash size its image was linked for (__flash0_end__ - __flash0_base__).
clear_l4_pempty 🔒
On an STM32L4, clears FLASH_SR.PEMPTY if it is set. Writing 1 toggles the bit, so it is written only when found set, then read back; the rule of embedded/tools/flash_release.py. Does nothing on other parts.
connect_check
Holds the tag in reset, reads its device ID and the supply voltage, and releases it: the connect check. The tag reboots afterwards.
device_name
Returns the family name for a DBGMCU device ID, as STM32CubeProgrammer prints it, or "unknown STM32" for an ID this crate does not know.
identify
Asks a base who it is with the bases’ own F6 99 identify command.
list
Lists the ST-LINK-compatible probes on USB (bases and genuine ST-LINKs alike).
open_probe
Opens usbdev with driver, as a probe-rs [Probe].
operation_name 🔒
Returns the step name reported in Progress::Step for a probe-rs flash operation.
program
Erases as erase says, programs and verifies elf in one session, clears FLASH_SR.PEMPTY on an STM32L4 if it is set, and starts the image with a debugger jump to its vector table (STM32_Programmer_CLI’s -g 0x08000000). One session, so no reset falls between the erase and the program.
read_memory
Reads len bytes of tag memory at addr in a session under reset (the core is held at its reset vector, so nothing runs while it is read).
session 🔒
Opens a session on chip under reset, with TagSequence.