diff --git a/Cargo.toml b/Cargo.toml index 2002d12..acd442b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -14,6 +14,8 @@ features = ["esp32c3", "panic-handler", "exception-handler", "print-uart"] esp-println = { version = "0.7.0", optional = true, default-features = false } [features] +default = [ "colors" ] + # You must enable exactly one of the below features to support the correct chip: esp32 = ["esp-println?/esp32"] esp32c2 = ["esp-println?/esp32c2"] @@ -34,3 +36,4 @@ print-uart = ["esp-println/uart"] exception-handler = ["esp-println"] panic-handler = ["esp-println"] halt-cores = [] +colors = [] diff --git a/README.md b/README.md index 985ab62..f4ca617 100644 --- a/README.md +++ b/README.md @@ -28,6 +28,7 @@ When using this together with `esp-println` make sure to use the same output kin | print-uart | Use UART to print messages\* | | print-jtag-serial | Use JTAG-Serial to print messages\* | | print-rtt | Use RTT to print messages\* | +| colors | Print messages in red\* | | halt-cores | Halt both CPUs on ESP32 / ESP32-S3 in case of a panic or exception | \* _only used for panic and exception handlers_ diff --git a/src/lib.rs b/src/lib.rs index c0b5229..ab3993e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,7 +1,12 @@ #![no_std] #![cfg_attr(target_arch = "xtensa", feature(asm_experimental_arch))] -const MAX_BACKTRACE_ADRESSES: usize = 10; +const MAX_BACKTRACE_ADDRESSES: usize = 10; + +#[cfg(feature = "colors")] +const RESET: &str = "\u{001B}[0m"; +#[cfg(feature = "colors")] +const RED: &str = "\u{001B}[31m"; #[cfg_attr(target_arch = "riscv32", path = "riscv.rs")] #[cfg_attr(target_arch = "xtensa", path = "xtensa.rs")] @@ -12,6 +17,9 @@ pub mod arch; fn panic_handler(info: &core::panic::PanicInfo) -> ! { use esp_println::println; + #[cfg(feature = "colors")] + println!("{}", RED); + println!(" "); println!(" "); @@ -39,6 +47,9 @@ fn panic_handler(info: &core::panic::PanicInfo) -> ! { } } + #[cfg(feature = "colors")] + println!("{}", RESET); + halt(); } @@ -48,6 +59,9 @@ fn panic_handler(info: &core::panic::PanicInfo) -> ! { unsafe fn __user_exception(cause: arch::ExceptionCause, context: arch::Context) { use esp_println::println; + #[cfg(feature = "colors")] + println!("{}", RED); + println!("\n\nException occured '{:?}'", cause); println!("{:?}", context); @@ -62,6 +76,9 @@ unsafe fn __user_exception(cause: arch::ExceptionCause, context: arch::Context) println!(""); println!(""); + #[cfg(feature = "colors")] + println!("{}", RESET); + halt(); } @@ -74,38 +91,51 @@ fn exception_handler(context: &arch::TrapFrame) -> ! { let code = context.mcause & 0xff; let mtval = context.mtval; - let code = match code { - 0 => "Instruction address misaligned", - 1 => "Instruction access fault", - 2 => "Illegal instruction", - 3 => "Breakpoint", - 4 => "Load address misaligned", - 5 => "Load access fault", - 6 => "Store/AMO address misaligned", - 7 => "Store/AMO access fault", - 8 => "Environment call from U-mode", - 9 => "Environment call from S-mode", - 10 => "Reserved", - 11 => "Environment call from M-mode", - 12 => "Instruction page fault", - 13 => "Load page fault", - 14 => "Reserved", - 15 => "Store/AMO page fault", - _ => "UNKNOWN", - }; - println!( - "Exception '{}' mepc=0x{:08x}, mtval=0x{:08x}", - code, mepc, mtval - ); - println!("{:x?}", context); - - let backtrace = crate::arch::backtrace_internal(context.s0 as u32, 0); - if backtrace.iter().filter(|e| e.is_some()).count() == 0 { - println!("No backtrace available - make sure to force frame-pointers. (see https://crates.io/crates/esp-backtrace)"); - } - for e in backtrace { - if let Some(addr) = e { - println!("0x{:x}", addr); + #[cfg(feature = "colors")] + println!("{}", RED); + + if code == 14 { + println!(); + println!( + "Stack overflow detected at 0x{:x} called by 0x{:x}", + mepc, context.ra + ); + println!(); + } else { + let code = match code { + 0 => "Instruction address misaligned", + 1 => "Instruction access fault", + 2 => "Illegal instruction", + 3 => "Breakpoint", + 4 => "Load address misaligned", + 5 => "Load access fault", + 6 => "Store/AMO address misaligned", + 7 => "Store/AMO access fault", + 8 => "Environment call from U-mode", + 9 => "Environment call from S-mode", + 10 => "Reserved", + 11 => "Environment call from M-mode", + 12 => "Instruction page fault", + 13 => "Load page fault", + 14 => "Reserved", + 15 => "Store/AMO page fault", + _ => "UNKNOWN", + }; + + println!( + "Exception '{}' mepc=0x{:08x}, mtval=0x{:08x}", + code, mepc, mtval + ); + println!("{:x?}", context); + + let backtrace = crate::arch::backtrace_internal(context.s0 as u32, 0); + if backtrace.iter().filter(|e| e.is_some()).count() == 0 { + println!("No backtrace available - make sure to force frame-pointers. (see https://crates.io/crates/esp-backtrace)"); + } + for e in backtrace { + if let Some(addr) = e { + println!("0x{:x}", addr); + } } } @@ -113,6 +143,9 @@ fn exception_handler(context: &arch::TrapFrame) -> ! { println!(""); println!(""); + #[cfg(feature = "colors")] + println!("{}", RESET); + halt(); } diff --git a/src/riscv.rs b/src/riscv.rs index 95b1612..fd61b06 100644 --- a/src/riscv.rs +++ b/src/riscv.rs @@ -1,6 +1,6 @@ use core::arch::asm; -use crate::MAX_BACKTRACE_ADRESSES; +use crate::MAX_BACKTRACE_ADDRESSES; /// Registers saved in trap handler #[doc(hidden)] @@ -104,7 +104,7 @@ MTVAL=0x{:08x} /// Get an array of backtrace addresses. /// /// This needs `force-frame-pointers` enabled. -pub fn backtrace() -> [Option; MAX_BACKTRACE_ADRESSES] { +pub fn backtrace() -> [Option; MAX_BACKTRACE_ADDRESSES] { let fp = unsafe { let mut _tmp: u32; asm!("mv {0}, x8", out(reg) _tmp); @@ -117,7 +117,7 @@ pub fn backtrace() -> [Option; MAX_BACKTRACE_ADRESSES] { pub(crate) fn backtrace_internal( fp: u32, suppress: i32, -) -> [Option; MAX_BACKTRACE_ADRESSES] { +) -> [Option; MAX_BACKTRACE_ADDRESSES] { let mut result = [None; 10]; let mut index = 0; @@ -147,7 +147,7 @@ pub(crate) fn backtrace_internal( result[index] = Some(address as usize); index += 1; - if index >= MAX_BACKTRACE_ADRESSES { + if index >= MAX_BACKTRACE_ADDRESSES { break; } } else { diff --git a/src/xtensa.rs b/src/xtensa.rs index b6a850d..d6d2e6c 100644 --- a/src/xtensa.rs +++ b/src/xtensa.rs @@ -1,4 +1,4 @@ -use crate::MAX_BACKTRACE_ADRESSES; +use crate::MAX_BACKTRACE_ADDRESSES; use core::arch::asm; #[doc(hidden)] @@ -236,7 +236,7 @@ F15=0x{:08x} /// Get an array of backtrace addresses. /// -pub fn backtrace() -> [Option; MAX_BACKTRACE_ADRESSES] { +pub fn backtrace() -> [Option; MAX_BACKTRACE_ADDRESSES] { let sp = unsafe { let mut _tmp: u32; asm!("mov {0}, a1", out(reg) _tmp); @@ -253,7 +253,7 @@ pub(crate) fn sanitize_address(address: u32) -> u32 { pub(crate) fn backtrace_internal( sp: u32, suppress: i32, -) -> [Option; MAX_BACKTRACE_ADRESSES] { +) -> [Option; MAX_BACKTRACE_ADDRESSES] { let mut result = [None; 10]; let mut index = 0; @@ -288,7 +288,7 @@ pub(crate) fn backtrace_internal( result[index] = Some(address as usize); index += 1; - if index >= MAX_BACKTRACE_ADRESSES { + if index >= MAX_BACKTRACE_ADDRESSES { break; } } else {