This is the 34th 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!
Highlights 🎉
#[derive(Format)]
now with better support for third party types
A common situation that arises when implementing the Format
trait for a struct or enum is running into fields that don't implement the Format
trait and come from a third party crate.
#[derive(Format)]
pub struct MyStruct {
field0: MyType,
field1: third_party::Type,
//~^ error: `third_party::Type` does not
// implement the Format trait
}
#[derive(Format)]
pub enum MyType { /* .. */ }
Because #[derive(Format)]
requires that all fields implement the Format
trait, the attribute fails in this case, and because the type comes in a third party crate it's not straightforward to implement the Format
trait for it.
To handle these cases one can use the Debug2Format
adapter newtype to get a Format
implementation based on the Debug
implementation of the type.
This, however, required a manual implementation of the Format
trait.
impl defmt::Format for MyStruct {
fn format(&self, f: defmt::Formatter) {
defmt::write!(
f,
"MyStruct {{ field0: {}, field1: {} }}",
&self.field0,
&defmt::Debug2Format(&self.field0),
)
}
}
Thanks to PR #662 such a manual implementation is no longer needed: one can use the #[Debug2Format]
field attribute to the same effect.
#[derive(Format)]
pub struct MyStruct {
field0: MyType,
#[defmt(Debug2Format)] // now it compiles!
field1: third_party::Type,
}
#[derive(Format)]
pub enum MyType { /* .. */ }
Thanks @mattico for the idea and implementation!
defmt-rtt
supports more devices including the RP2040
defmt-rtt
is the main "transport" crate in the defmt ecosystem.
It transports defmt-encoded logs emitted from a microcontroller to a second machine where they'll be decoded and printed (or stored for later use).
Transport crates work by setting up a global logger that must be accessed through a synchronization mechanism.
In the case defmt-rtt
, it used the cortex-m
crate to create a critical section by disabling interrupts.
Although this mechanism works fine on single-core devices it is not appropriate for multi-core devices like the RP2040.
In order to support such devices, defmt-rtt
now uses the critical-section
crate as a synchronization mechanism.
The critical-section
crate allows statically registering a critical section mechanism in order to support vendor-specific implementations like the one the RP2040 chip needs due to its lack of atomic instructions (LDREX, STREX) required to implement a Compare-And-Swap (CAS) operation.
faster --measure-stack
probe-run
gained a runtime stack measurement mechanism last year: --measure-stack
.
--measure-stack
reports the maximum stack usage of a program when it exits.
To do that it works in two stages:
- before the start of the program,
probe-run
fills the entire stack memory with a known bit pattern. we call this process, "stack painting" - on program exit,
probe-run
scans the stack memory until it finds "a spot" (the address) where the program execution undid the stack painting due to its stack usage. subtracting the start address of the stack from this "watermark" level yields the maximum stack usage of the program
although this works fairly well the current implementation uses the probe (debug interface commands) to perform the two phases: this is very slow and adds several seconds to the execution of the program (to both the startup and the exit time).
@Urhengulas has been working on moving the two phases into the target microcontroller itself. The initial results are quite encouraging: performing the "stack painting" on the target is ~170 times faster than the current implementation. We hope that after moving the second phase into the target, the overall time the feature adds to executing programs is small enough that the feature can be enabled by default without the end users noticing the slow down.
Watch this space!
defmt
in the wild
We keep an eye on social media and other chat platforms for cool projects using defmt
.
Like we shared before that the network stack, smoltcp
, started using defmt
some time ago,
this time we want to put pretty-hal-machine in the spotlight.
Pretty-Hal-Machine (PHM) proposes a different approach to developing no_std driver crates. Instead of writing a no_std test application that runs directly on the microcontroller that interacts with the sensor, actuator, lights, etc. you are writing the driver for, you write a desktop application that has the standard library available and use that to test the no_std driver crate. This is accomplished with a dev board that runs the PHM firmware and exposes a USB interface to control its different peripherals: SPI, I2C and UART at the moment. On the desktop side, PHM is a library that implements the embedded-hal traits and, under the hood, commands the PHM dev board via USB commands.
We are glad to see that the PHM developers are using defmt and other knurling tools in the development of their PHM firmware and are looking forward to seeing where they take this project.
Improvements 🦀
defmt
- #662
#[derive(Format)]
now accepts attribute fields to format fields using theDebug2Format
adapter instead of aFormat
implementation. - #656 implement
Format
forCell
andRefCell
- #640 use
critical-section
crate indefmt-rtt
probe-run
- #302 make stack painting faster
- #301 now accepts chip description files (YAML) via
--chip-description-path
, extending device support beyondprobe_rs
' device registry - #303 now tries to decode
defmt
logs when--no-flash
is used, but emits a warning
Internal Improvements 🧽
defmt
probe-run
- #299 refactor
extract_stack_info
Version Update Notification 🆙
defmt 0.3.1
defmt-decoder 0.3.2
defmt-json-schema 0.1.0
(new)defmt-macros 0.3.2
defmt-parser 0.3.1
defmt-print 0.3.2
defmt-rtt 0.3.2
probe-run 0.3.2
Sponsor this work
Knurling-rs is mainly funded through GitHub sponsors. Sponsors get early access to the tools we are building and help us to support and grow the knurling tools and courses. Thank you to all of the people already sponsoring our work through the Knurling project!