Skip to content

Instantly share code, notes, and snippets.

@therealprof
Created February 15, 2019 12:41
Show Gist options
  • Save therealprof/9b55e15eff37e626265a3af92698e940 to your computer and use it in GitHub Desktop.
Save therealprof/9b55e15eff37e626265a3af92698e940 to your computer and use it in GitHub Desktop.
//! Writes panic messages to the beginning of RAM
//!
//! This crate contains an implementation of `panic_fmt` that logs panic messages to the beginning
//! of RAM, recklessly overwriting the previous contents of that area. After logging the message
//! the panic handler goes into an infinite loop, so a debugging probe can connect and pick up the
//! panic.
//!
//! Unlike other methods this allows to discover the panic reason post-mortem by attaching a
//! debugger probe after the device crashed.
//!
//! Currently this crate was only tested on ARM Cortex-M architecture but should be easily portable
//! to other platforms as required.
//!
//! # Usage
//!
//! ``` ignore
//! #![no_std]
//!
//! extern crate panic_ramdump;
//!
//! fn main() {
//! panic!("FOO")
//! }
//! ```
//!
//! ``` text
//! (gdb) x/s 0x20000000
//! 0x20000000: "panicked at 'FOO!', src/main.rs:6:5\n\276\244\001"
//! ```
//!
#![allow(clippy::empty_loop)]
#![deny(missing_docs)]
#![deny(warnings)]
#![no_std]
use core::fmt::Write;
use core::panic::PanicInfo;
use cortex_m::interrupt;
struct Ram {
offset: u32,
}
/// Internal Write implementation to output the formatted panic string into RAM
impl core::fmt::Write for Ram {
fn write_str(&mut self, s: &str) -> Result<(), core::fmt::Error> {
// Obtain RAM start address from linker symbol _sbss
extern "C" {
static mut __sbss: u8;
}
let data = s.as_bytes();
let len = data.len();
unsafe {
core::ptr::copy(
data.as_ptr() as *mut u8,
(&mut __sbss as *mut u8).offset(self.offset as isize),
len,
)
};
self.offset += len as u32;
Ok(())
}
}
#[panic_handler]
fn panic(info: &PanicInfo) -> ! {
interrupt::disable();
let mut ram = Ram { offset: 0 };
#[cfg(feature = "light")]
{
Ram::write_str(&mut ram, "panicked with '").ok();
let cause = info
.payload()
.downcast_ref::<&'static str>()
.map(|s| *s)
.unwrap_or(&"<cause unknown>");
Ram::write_str(&mut ram, cause).ok();
Ram::write_str(&mut ram, "', ").ok();
if let Some(location) = info.location() {
Ram::write_str(&mut ram, location.file()).ok();
}
Ram::write_str(&mut ram, "\0").ok();
}
#[cfg(not(feature = "light"))]
write!(ram, "{}\0", info).ok();
loop {}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment