defmt

repository·main·Indexed 22 days ago

https://github.com/knurling-rs/defmt

A highly efficient, deferred-formatting logging framework optimized for resource-constrained embedded devices like microcontrollers. It reduces CPU and memory overhead by deferring string formatting to the host machine. The ecosystem includes transport implementations for RTT (defmt-rtt), ITM (defmt-itm), and Semihosting (defmt-semihosting), as well as tools for decoding logs (defmt-decoder, defmt-print) and an embedded test harness (defmt-test).

Tokens
42.5K
Snippets
152
Records
215
Agent score
76%

What's inside defmt

  1. What is defmt-macros?

    main

    defmt-macros provides the procedural macros used by the defmt logging framework.

    defmt ("de format", short for "deferred formatting") is a highly efficient logging framework designed specifically for resource-constrained devices, such as microcontrollers. Instead of formatting strings on the device, it defers the formatting to the host machine, significantly reducing the CPU and memory overhead on the embedded target.

  2. What is `defmt-test`?

    main
    defmt-test is a test harness for embedded devices that allows you to write and run unit tests directly on your hardware using a syntax similar to the standard Rust #[test] attribute. It is compatible with rust-analyzer, enabling you to flash and run tests directly from VS Code by clicking the ▶ Run Test button above a defmt_test::tests module.
  3. What is defmt?

    main
    defmt ("de format", short for "deferred formatting") is a highly efficient logging framework designed specifically for resource-constrained devices, such as microcontrollers. It minimizes the amount of data sent over the wire by deferring the formatting of log messages to the host side.
  4. Use `panic-probe` to exit `probe-run` with error codes

    main

    panic-probe is a panic handler designed to work with probe-run. When a panic occurs, it causes probe-run to exit with an error code, which is useful for automated testing and debugging workflows.

    Key constraints and features:

    • Target Support: This firmware only supports Cortex-M targets.
    • Logging: You can optionally log the panic message using the defmt logging framework by enabling the print-defmt Cargo feature.
  5. Use `defmt-print` to decode and print `defmt` logs

    main
    defmt-print is a tool designed to decode defmt log frames and print them to the console. Because there is no stable library API for decoding defmt log frames, this tool serves as the primary utility for developers to view human-readable logs from their embedded devices.
  6. Use defmt-semihosting for logging over Cortex-M Semihosting

    main

    The defmt-semihosting crate allows you to transmit defmt log messages using the Cortex-M Debugger Semihosting protocol.

    When to use it: Semihosting operations are significantly slower than RTT (Real-Time Transfer). You should primarily use defmt-semihosting when running in an emulator like QEMU where RTT might not be available or supported.

    For a concrete implementation example using QEMU, refer to the QEMU Thumbv7em example.

  7. Understand the purpose of defmt-json-schema

    main

    defmt-json-schema is a library that provides the JSON schema definition for the output produced by defmt-decoder.

    defmt (deferred formatting) is a highly efficient logging framework designed for resource-constrained devices like microcontrollers. This schema allows tools and developers to validate or parse the JSON logs generated when decoding defmt telemetry.

  8. Use `defmt-itm` to transmit logs over ITM stimulus port 0

    main
    defmt-itm is a transport implementation for the defmt logging framework. It allows you to transmit defmt log messages over the ITM (Instrumentation Trace Macrocell) stimulus port 0. This is typically used in embedded systems development to provide high-efficiency logging via hardware trace capabilities.
    defmt-itm
  9. What is defmt and how does it work?

    main

    Overview

    defmt ("de format") is a highly efficient logging framework designed for resource-constrained devices like microcontrollers. It uses deferred formatting and string compression to minimize the overhead on the target device.

    Operating Principle

    1. Deferred Formatting: Instead of formatting data (e.g., converting 255u8 to the string "255") on the microcontroller, the device sends raw binary data to a host machine. The host performs the expensive string formatting.
    2. String Compression: At compile time, defmt builds a table of string literals (e.g., "Hello, world"). At runtime, the microcontroller sends only the indices of these strings rather than the full text, significantly reducing bandwidth and memory usage.

    Key Features

    • println!-like formatting syntax.
    • Multiple logging levels: error, info, warn, debug, trace.
    • Compile-time filtering: Include or omit logging levels with module-level granularity (similar to RUST_LOG).
    • Timestamped logs.
  10. Overview of defmt components

    main

    The defmt ecosystem consists of several packages categorized by their role in the logging pipeline:

    On-target (Firmware) Components

    • defmt: The core on-target code for efficient logging.
    • defmt-rtt: Sends logs over RTT (Real Time Transfer).
    • defmt-itm: Sends logs over ITM (Instrumentation Trace Macrocell).
    • defmt-semihosting: Sends logs over semihosting.
    • panic-probe: Sends panic! messages over defmt.
    • defmt-test: A framework for running tests directly on-target.
    • defmt-test-macros: Procedural macros used by defmt-test.

    Host-side (Tooling) Components

    • defmt-macros: Procedural macros used by the on-target defmt crate.
    • defmt-print: A CLI utility to decode and print defmt logs to standard output.
    • defmt-decoder: A host library for decoding defmt log frames.
    • defmt-parser: A host library for parsing defmt log frames.
    • defmt-json-schema: Defines the JSON schema emitted by defmt-decoder.
  11. Single vs. Multiple logging channels

    main

    When implementing a global_logger, you must choose between a single-channel or multi-channel architecture depending on your concurrency requirements.

    Single Logging Channel

    All execution contexts (e.g., main and all interrupt handlers) share one channel.

    • Synchronization: To prevent corruption, acquire must disable interrupts and release must re-enable them. This synchronizes access across different priority levels.
    • Example: defmt-semihosting uses this approach.

    Multiple Logging Channels

    Each priority level (or interrupt level) can have its own dedicated channel.

    • Benefits: Allows for lock-free logging; interrupts do not need to be disabled during logging.
    • Trade-offs: Higher memory usage on the target (for per-channel buffering) and potentially lower throughput (due to channel multiplexing or tagging).
    • Transport Requirements: Requires a transport that supports multiplexing. RTT supports this natively. Other transports (like ITM) require log frames to be tagged with their channel ID.