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