Blog coding article

Knurling-rs changelog #3


Knurling-rs changelog #3

5 min read
Open Source Project
Knurling icon
A tool set to develop embedded applications faster.

    This is the third changelog for Knurling-rs, our push to sustainably build better tooling for developing and debugging Rust software for embedded systems. Knurling-rs includes a suite of tools that make it easier to develop, log, debug, and test your embedded Rust libraries and applications!

    Knurling-rs is supported by our sponsors on GitHub. If you're interested in seeing more projects like this, consider becoming a sponsor today!

    It has been a while since our last changelog and a lot has happened since then!


    • We have passed 100 sponsors on GitHub sponsors! 🎉 We want to thank each and everyone of them for supporting our work on Knurling!

    • We have launched the knurling website ✨. The website gives you an overview of all the projects under the Knurling umbrella.

    New features

    We want to give the community a round of applause 👏 for submitting several PRs these last few weeks and a special shoutout to @Dirbaio 🏅 for authoring all the PRs in this section!

    • #198 defmt now supports formatting 64-bit integers
    • #197 defmt log messages can now include the @ character. If you are wondering why this didn't work before, the reason is that log messages are stored in the ELF's symbol table as symbols. The @ character is special in symbol names; the text after the @ is treated as the symbol version; this made reconstructing the whole message tricky. The @ character is now escaped to prevent it from adding a version the symbol.
    • #200 defmt now supports formatting the str type. Note that intern!-ing string literals should be preferred as that saves bandwidth but str support is required to use derive(Format) on structs and enums that contain strings (&str).
    • #201 defmt now supports formatting heap-allocated types like Box and Rc. Note that this support is behind an opt-in Cargo feature named "alloc".


    • #184 enhance defmt's bitfield compression. When you log a bitfield view of a register like in info!("M: {:8..12}, E: {:15..16}", u32_val), now 1 byte of register data is transmitted, instead of 2 bytes (this included the Least Significant Byte which is not printed / formatted).


    • #77 in non-defmt mode probe-run now flushes data to stdout more often. Before it would only flush data on newline causing, for example, the first print statement in rprint!("hello"); sleep(5.seconds()); rprintln!("world!") to not be printed until the second one was executed.
    • #204 defmt's ELF parser now skips empty symbol names before parsing them. This increases our compatibility with GNU tools like objcopy, which sometimes inject empty symbol names when used to post-process ELF files produced by rustc.
    • #178 defmt's derive(Format) macro now generates trait bounds like the built-in derive(Debug) macro. Before we were using a more precise way to generate trait bounds but this appears to not be widely used in the ecosystem because we ran into compiler bugs so we decided to switch to the more widely used approach. The difference between the two approaches is pictured below.
    struct S<a, T> { inner: &'a Option<T> }
    // expansion of `derive` using previous approach
    impl<a, T> Format for S<'a, T>
        &'a Option<T>: Format // <- bound on field type
    { /* .. */ }
    // expansion of `derive` using current approach (same as `Debug`)
    impl<a, T> Format for S<'a, T>
       T: Format // <- bound on input type parameter
    { /* .. */ }

    Internal improvements

    We are working hard towards a first release of defmt so that you won't need to juggle several git dependencies in your projects. Most PRs in this section are work towards that goal.

    • #190 prevent using multiple versions of defmt. Once defmt is on it'll be possible to use e.g. v0.1 and v0.2 in the same application (Cargo allows this). The encoder and decoder don't support mixing ABI incompatible logs in the same stream (the stream will appear to be corrupted) so defmt will give you a compiler error if you run into this scenario.
    • #196 extend probe-run version check to support releases. probe-run checks that its defmt decoder supports the defmt version used in the target application. That check relied solely on git hashes but release won't have that git information so the check has been extended to consider the crate version.
    • #197 remove a small implementation detail crate. For the first release of defmt we won't be stabilizing the crates that sit between defmt and probe-run – these include things like the defmt stream decoder and other ELF parsing utilities – so we are trying to reduce the number of those crates (which will also need to be published on

    • #202 mark unstable API as such in the API documentation. This refers to the crates between defmt and probe-run. The defmt crate won't have any unstable API on its first release.

    • #175, #192, #193, #194, #195 use JSON to encode the log messages stored in the ELF symbol table. This has be done with extensibility in mind: it should let users attach custom-metadata to log messages in the future. It also helped implement PR #197.

    Sponsor this work

    probe-run and defmt are Knurling projects and can be funded through GitHub sponsors. Sponsors get early access to the tools we are building. Thank you to all of the people already sponsoring our work through the Knurling project!

    You might be also interested in these.