panic! and assert!

NOTE all these macros are available in defmt v0.1.2+

The defmt crate provides its own version of panic!-like and assert!-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]

Because defmt::panic! invokes core::panic! this 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 use the #[defmt::panic_handler] to override the panicking behavior of defmt::panic-like and defmt::assert-like macros. This attribute must be placed on a function with signature fn() -> !. In this function you'll want to 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()
}

#[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.

NOTE: even if you don't run into the "double panic message printed" issue you may still want to use #[defmt::panic_handler] because this way defmt::panic and defmt::assert will not go through the core::panic machinery and that may reduce code size (we recommend you measure the effect of the change).

Inter-operation with built-in attributes

The #[panic_handler] attribute cannot be used together with the export_name or no_mangle attributes