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, seeembedded/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
listandidentifynever touch nRST or SWD, so the tag keeps running.connect_check,programandread_memoryall hold the tag in reset to attach. A running log is ended, and the tag reboots its firmware afterwards.programalso 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_IDCODEon 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_IDCODEon 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 99identify command. - list
- Lists the ST-LINK-compatible probes on USB (bases and genuine ST-LINKs alike).
- open_
probe - Opens
usbdevwithdriver, as a probe-rs [Probe]. - operation_
name 🔒 - Returns the step name reported in
Progress::Stepfor a probe-rs flash operation. - program
- Erases as
erasesays, programs and verifieselfin 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
lenbytes of tag memory ataddrin a session under reset (the core is held at its reset vector, so nothing runs while it is read). - session 🔒
- Opens a session on
chipunder reset, withTagSequence.