I am writing embedded Rust code that uses #[no_std] (with panic = "abort").
I have a custom panic handler like this:
#[inline(never)]
#[panic_handler]
fn panic(info: &PanicInfo) -> ! {
let mut serial = open_serial_port();
if let Some(location) = info.location() {
uwriteln!(&mut serial, "Panic occurred in file '{}' at line {}", location.file(), location.line());
} else {
uwriteln!(&mut serial, "Panic occurred");
}
// I want to to get info.payload(), info.message(), info.to_string() or any other way
// to get some info about why the panic happened
loop {
// blink LED
}
}
This works great for showing the location of the panic, but it doesn't show the reason the panic happened.
I've seen a pattern like:
if let Some(s) = info.payload().downcast_ref::<String>() {
// print s
}
but it seems like I don't have access to String in no_std. Is there another way to extract that information?
I saw someone recommending that I use a custom payload type that I can print, but I can't figure out how. I don't really care about the panic!() macro. I'm more concerned with catching rust's debug checks like arithmetic overflow, etc. Is there a way to tell the compiler how to generate panic payloads for those? I have been looking but haven't been able to find any examples of that.
PanicHandlerimplementsDisplay. You can use that to print the normal panic message as seen on anstdtarget.This is taken from
imxrt-uart-panic(disclaimer: I wrote that crate):The gist is that you create a
structthat implementscore::fmt::Write. With it, you can thencore::writeln!()the error message into whatever peripheral you desire, like UART.An example of what this would print:
Just for reference, if customization is required, this is the current implementation of the
Displayimpl ofPanicInfo: (Important: This might change in the future.)