panic! and assert!
The
defmtcrate provides its own version ofpanic!-like andassert!-like macros.
The defmt version of these macros will log the panic message using defmt and then call core::panic! (by default).
Because the panic message is formatted using defmt! the format string must use the same syntax as the logging macros (e.g. info!).
#[defmt::panic_handler]
You can use the
#[defmt::panic_handler]to override the panicking behavior of thedefmt::panic!anddefmt::assert!macros.
This attribute must be placed on a function with signature fn() -> !.
This is for example useful, because defmt::panic! invokes core::panic! which can result in the panic message being printed twice if your #[core::panic_handler] also prints the panic message.
This is the case if you use panic-probe with the print-defmt feature enabled but not an issue if you are using the panic-abort crate, for example.
To avoid this issue you can replicate the panicking behavior of the Rust #[panic_handler] but leave out the part that prints the panic message.
For example:
#[panic_handler] // built-in ("core") attribute
fn core_panic(info: &core::panic::PanicInfo) -> ! {
print(info); // e.g. using RTT
reset()
}
#![allow(unused)] fn main() { extern crate defmt; fn reset() -> ! { todo!() } #[defmt::panic_handler] // defmt's attribute fn defmt_panic() -> ! { // leave out the printing part here reset() } }
If you are using the panic-probe crate then you should "abort" (call cortex_m::asm::udf) from #[defmt::panic_handler] to match its behavior.
💡 Even if you don't run into the "double panic message printed" issue you may still want to use
#[defmt::panic_handler]because this waydefmt::panicanddefmt::assertwill not go through thecore::panicmachinery and that may reduce code size (we recommend you measure the effect of the change).
⚠️ The
#[panic_handler]attribute cannot be used together with theexport_nameorno_mangleattributes