Today we are pleased to announce the public release of probe-run
, a custom Cargo runner for embedded development.
This host application integrates into your Cargo workflow and lets you cargo run
embedded applications.
Let's see how to use it for ARM Cortex-M application development.
Setup
First, start by installing the Cargo runner.
$ cargo install probe-run
Now set probe-run
as the Cargo runner for your embedded application.
You do this in .cargo/config
; if you are using the cortex-m-quickstart
template then extend it like this:
# file: .cargo/config
# under this section
[target.'cfg(all(target_arch = "arm", target_os = "none"))']
# (we removed the commented out runners that were here)
runner = "probe-run --chip nRF52840_xxAA" # <- add this
Instead of nRF52840_xxAA
use the name of your microcontroller; you should find it in the output of the probe-run --list-chips
command.
Now you are all set to cargo run
embedded applications!
Run it
Let's say you have this program.
#![no_std]
use cortex_m::asm;
use cortex_m_rt::entry;
use rtt_target::{rprintln, rtt_init_print};
#[entry]
fn main() -> ! {
rtt_init_print!();
rprintln!("Hello, world!");
loop {
asm::bkpt()
}
}
cargo run
-ing this program produces the following output:
$ cargo run --bin hello
Running `probe-run --chip nrf52 target/thumbv7em-none-eabi/debug/hello`
flashing program ..
DONE
resetting device
Hello, world!
stack backtrace:
0: 0x0000167c - __bkpt
1: 0x0000055e - hello::__cortex_m_rt_main
2: 0x00000432 - main
3: 0x00001e28 - Reset
As you can see, text printed by the device over RTT (rprintln!
) is shown in the output of probe-run
.
Stack backtraces
When the firmware reaches a BKPT (BreaKPoinT) instruction the device halts.
The probe-run
tool treats this halted state as the "end" of the application and exits.
Before exiting probe-run
prints the stack backtrace of the halted program.
This backtrace follows the format of the std
backtraces you get from std::panic!
but includes <exception entry>
lines to indicate where an exception/interrupt occurred.
We find it quite useful to "exit" embedded applications with a backtrace on panics.
See the #[panic_handler]
function in the example below:
#![no_std]
use cortex_m::{asm, peripheral::SCB};
use cortex_m_rt::{entry, exception};
use rtt_target::{rprintln, rtt_init_print};
#[entry]
fn main() -> ! {
rtt_init_print!();
rprintln!("main");
SCB::set_pendsv(); // trigger PendSV exception
rprintln!("after PendSV");
exit()
}
#[exception]
fn PendSV() {
rprintln!("PendSV");
panic!()
}
#[panic_handler]
fn panic(info: &core::panic::PanicInfo) -> ! {
rprintln!("{}", info);
exit()
}
fn exit() -> ! {
loop {
asm::bkpt() // halt = exit probe-run
}
}
Now we have the same panicking behavior as std
programs!
$ cargo run --bin panic
flashing program ..
DONE
resetting device
main
PendSV
panicked at 'explicit panic', src/main.rs:21:5
stack backtrace:
0: 0x00001f58 - __bkpt
1: 0x00000490 - nrf52::exit
2: 0x00000484 - rust_begin_unwind
3: 0x00002134 - core::panicking::panic_fmt
4: 0x000020cc - core::panicking::panic
5: 0x00000616 - nrf52::__cortex_m_rt_PendSV
6: 0x000005e6 - PendSV
<exception entry>
7: 0x00001e00 - core::ptr::write_volatile
8: 0x000006d2 - cortex_m::peripheral::scb::SCB::set_pendsv
9: 0x000005c4 - nrf52::__cortex_m_rt_main
10: 0x0000049a - main
11: 0x00002de6 - Reset
Device support
probe-run
is built on top of the probe-rs
library so it inherits its device and probe support.
Currently, probe-run
does not support the (hard-float) thumbv7em-none-eabihf
target; you'll get a CLI error if you try to cargo run
a program compiled for that target.
You can work around this limitation by compiling your application to the (soft-float) thumbv7em-none-eabi
target (note: no hf
).
Hard float support is on the TODO list.
What's next?
In follow-up blog posts we'll cover:
- how to use custom panic handler and
probe-run
to run unit tests on the embedded device - how the
defmt
("deferred formatting") logging framework – introduced in a previous post asbinfmt
– plugs intoprobe-run
Sponsor this work
probe-run
is a Knurling project and can be funded through GitHub sponsors. Sponsors get early access to defmt
and other tools we are building. Thank you to all of the people already sponsoring our work through the Knurling project!