defmt
defmt
("de format", short for "deferred formatting") is a highly efficient logging framework that targets resource-constrained devices, like microcontrollers.
Features
println!
-like formatting- Multiple logging levels:
error
,info
,warn
,debug
,trace
- Compile-time
RUST_LOG
-like filtering of logs: include/omit logging levels with module-level granularity - Timestamped logs
Current limitations
- Output object format must be ELF
- Custom linking (linker script) is required
- Single, global logger instance (but using multiple channels is possible)
Intended use
In its current iteration defmt
mainly targets tiny embedded devices that have no mean to display information to the developer, e.g. a screen.
In this scenario logs need to be transferred to a second machine, usually a PC/laptop, before they can be displayed to the developer/end-user.
defmt
operating principles, however, are applicable to beefier machines and could be use to improve the logging performance of x86 web server applications and the like.
Operating principle
defmt
achieves high performance using deferred formatting and string compression.
Deferred formatting means that formatting is not done on the machine that's logging data but on a second machine.
That is, instead of formatting 255u8
into "255"
and sending the string, the single-byte binary data is sent to a second machine, the host, and the formatting happens there.
defmt
's string compression consists of building a table of string literals, like "Hello, world"
or "The answer is {:?}"
, at compile time.
At runtime the logging machine sends indices instead of complete strings.
Components
Fundamentally, defmt
is comprised of multiple packages - some run on your microcontroller :pager:, some run on your host machine :computer:, and some are macros that generate code (for either of those scenarios) :construction:.
defmt
📟
The defmt
crate runs on your microcontroller or other target device. It
exports macros, like info!
that libraries can use to emit logging messages,
and the #[no_mangle]
infrastructure those macros use to send log messages to
the registered logging transport.
The defmt
crate requires a transport to be registered within your firmware.
Example transports include defmt-rtt
and defmt-itm
. The transport is handed
a log frame every time a line of code like defmt::info!("...")
is executed.
That log frame describes which interned format string to use, and what arguments
to print with it.
defmt-rtt
📟
This library is a logging transport for defmt
that sends data over
SEGGER's RTT transport protocol.
This is a good choice when using probe-rs
because support is built-in to that
runner.
defmt-itm
📟
This library is a logging transport for defmt that sends data over Arm's Instruction Trace Macrocell.
This might be a good choice if you are using a commercial debugger with ITM support but not RTT support.
defmt-semihosting
📟
This library is a logging transport for defmt that sends data over semihosting calls (i.e. breakpoints that wake up your debugger).
You should only use this when running firmware inside QEMU, because otherwise it's very slow.
defmt-test
📟
This library is for running unit tests with our deprecated runner probe-run
.
You might want to look at embedded-test
, which integrates a bit better with
probe-rs
.
panic-probe
📟
This library can be added to an Embedded Rust application to provide an
implementation of #[panic_handler]
. It can optionally route the
core::panic::PanicInfo
structure over RTT (using the rtt_target
crate) or
over defmt (using the defmt
crate).
defmt-decoder
🖥️
The defmt-decoder
library turns log frames into human-readable Unicode text.
The popular probe-rs
runner uses this library to decode defmt
log frames
emitted by your firmware.
defmt-parser
🖥️
This library turns defmt log frames into Rust structures. You probably want to
use defmt-decoder
instead, which actually decodes the log frames instead of
just parsing them.
defmt-print
🖥️
The defmt-print
CLI program uses defmt-decoder
to turn defmt
log frames into
human-readable Unicode text. You can use this if your log frames aren't coming
via probe-rs
but instead come in through some other mechanism (e.g. a network
connection).
defmt-macros
🚧
This crate contains the procedural macros used and/or exported by the defmt
crate. It is an internal implementation detail and should be not used
standalone.
Support
defmt
is part of the Knurling project, Ferrous Systems' effort at
improving tooling used to develop for embedded systems.
If you think that our work is useful, consider sponsoring it via GitHub Sponsors.
commit dc64101 on 2025-01-27 16:58:35