Logging with defmt over RTT
Thursday, 2025-06-05 Comments
How to use the defmt crate to log messages from a Raspberry Pi Pico 2 W over RTT.
Previous post: Introduction to Embassy.
Simple Logging
RTT (Real-Time Transfer) is a logging protocol that can be used on top of an SWD connection. It does not require specifying the baud rate, etc.
The defmt crate is the most popular crate for logging from embedded Rust programs. It exports macros like info! and debug!, similar to the macros in the standard log or tracing crates in Rust.
For the debug probe to actually show the log output from the target, you need to enable a “transport”. In the case of defmt, it is usually the RTT transport using the defmt-rtt crate. The defmt-rtt crate could be compared to tracing-subscriber or other mainstream log consumers.
-
Add
defmtanddefmt-rttas a dependency to yourCargo.tomlfile. Also, enable thedefmtfeatures for all existing dependencies that have it. -
Import the
defmt-rttmodule in your binary or library:use defmt_rtt as _;This may seem useless, but it enables the setup of data necessary to link the binary against the
defmt-rttcrate. -
Add a compiler flag under the current target in the
.cargo/config.tomlfile:-C link-arg=-Tdefmt.x.[target.thumbv8m.main-none-eabihf] rustflags = [ "-C", "link-arg=--nmagic", "-C", "link-arg=-Tlink.x", "-C", "link-arg=-Tdefmt.x", "-C", "target-cpu=cortex-m33", ] -
Specify the log level for
defmtin the.cargo/config.tomlfile:[env] DEFMT_LOG = "debug" -
Enable
rttin theEmbed.tomlfile:[default.rtt] enabled = true -
Add invocations of the
defmtmacros throughout your library or binary code (as necessary). For example, you could write:use defmt::info; async fn main(_spawner: Spawner) -> ! { loop { info!("A new iteration of the loop has started."); } }There is nothing stopping you from adding such statements to library code.
-
Compile, flash, and run your binary on the target Pico 2 W:
cargo runThis should open an RTT console that shows the log messages emitted by the
defmtstatements in your code.