#![allow(clippy::empty_loop)]
#![deny(missing_docs)]
#![deny(warnings)]
#![no_std]
use core::cmp::min;
use core::fmt::Write;
use core::mem::size_of;
use core::panic::PanicInfo;
struct Ram {
offset: usize,
}
impl core::fmt::Write for Ram {
fn write_str(&mut self, s: &str) -> Result<(), core::fmt::Error> {
extern "C" {
static mut _panic_dump_start: u8;
static mut _panic_dump_end: u8;
}
let data = s.as_bytes();
let len = data.len();
let start_ptr = unsafe { &mut _panic_dump_start as *mut u8 };
let end_ptr = unsafe { &mut _panic_dump_end as *mut u8 };
let max_len = end_ptr as usize - start_ptr as usize;
let max_len_str = max_len - size_of::<usize>() - size_of::<usize>();
if self.offset >= max_len_str {
return Ok(());
}
let str_len = min(max_len_str - self.offset, len);
unsafe {
start_ptr.cast::<usize>().write_unaligned(0x0FACADE0);
core::ptr::copy(
data.as_ptr() as *mut u8,
start_ptr.offset(8).offset(self.offset as isize),
str_len,
);
self.offset += str_len;
start_ptr
.offset(4)
.cast::<usize>()
.write_unaligned(self.offset);
};
Ok(())
}
}
pub fn get_panic_message_bytes() -> Option<&'static [u8]> {
extern "C" {
static mut _panic_dump_start: u8;
static mut _panic_dump_end: u8;
}
let start_ptr = unsafe { &mut _panic_dump_start as *mut u8 };
if 0x0FACADE0 != unsafe { core::ptr::read_unaligned(start_ptr.cast::<usize>()) } {
return None;
}
unsafe {
start_ptr.cast::<usize>().write_unaligned(0x00000000);
}
let end_ptr = unsafe { &mut _panic_dump_end as *mut u8 };
let max_len = end_ptr as usize - start_ptr as usize;
let max_len_str = max_len - size_of::<usize>() - size_of::<usize>();
let len = unsafe { core::ptr::read_unaligned(start_ptr.offset(4).cast::<usize>()) };
if len > max_len_str {
return None;
}
let byte_slice = unsafe { core::slice::from_raw_parts(start_ptr.offset(8), len) };
Some(byte_slice)
}
#[cfg(feature = "utf8")]
pub fn get_panic_message_utf8() -> Option<&'static str> {
let bytes = get_panic_message_bytes()?;
use core::str::from_utf8;
match from_utf8(bytes) {
Ok(stir) => Some(stir),
Err(utf_err) => {
match from_utf8(&bytes[..utf_err.valid_up_to()]) {
Ok(stir) => Some(stir),
Err(_) => {
None
}
}
}
}
}
#[cfg(feature = "custom-panic-handler")]
pub fn report_panic_info(info: &PanicInfo) {
writeln!(Ram { offset: 0 }, "{}", info).ok();
}
#[cfg(not(feature = "custom-panic-handler"))]
#[panic_handler]
fn panic(info: &PanicInfo) -> ! {
cortex_m::interrupt::disable();
#[cfg(feature = "min-panic")]
if let Some(location) = info.location() {
writeln!(Ram { offset: 0 }, "Panicked at {}", location).ok();
} else {
writeln!(Ram { offset: 0 }, "Panic occured!").ok();
}
#[cfg(not(feature = "min-panic"))]
writeln!(Ram { offset: 0 }, "{}", info).ok();
cortex_m::peripheral::SCB::sys_reset();
}