1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73
//! Logs panic messages over RTT. A companion crate for rtt-target.
//!
//! RTT must have been initialized by using one of the `rtt_init` macros. Otherwise you will get a
//! linker error at compile time.
//!
//! Panics are always logged on channel 0. Upon panicking the channel mode is also automatically set
//! to `BlockIfFull`, so that the full message will always be logged. If the code somehow manages to
//! panic at runtime before RTT is initialized (quite unlikely), or if channel 0 doesn't exist,
//! nothing is logged.
//!
//! A platform feature such as `cortex-m` is required to use this crate.
//!
//! # Usage
//!
//! Cargo.toml:
//!
//! ```toml
//! [dependencies]
//! panic-rtt-target = { version = "x.y.z", features = ["cortex-m"] }
//! ```
//!
//! main.rs:
//!
//! ```no_run
//! #![no_std]
//!
//! use panic_rtt_target as _;
//! use rtt_target::rtt_init_default;
//!
//! fn main() -> ! {
//! // you can use any init macro as long as it creates channel 0
//! rtt_init_default!();
//!
//! panic!("Something has gone terribly wrong");
//! }
//! ```
#![no_std]
// allow(unused) is used so that warnings when no platform feature is defined don't drown out the
// compile_error
#[allow(unused)]
use core::{
fmt::Write,
panic::PanicInfo,
sync::atomic::{compiler_fence, Ordering::SeqCst},
};
#[allow(unused)]
use rtt_target::{ChannelMode, UpChannel};
#[inline(never)]
#[panic_handler]
fn panic(info: &PanicInfo) -> ! {
critical_section::with(|_| {
if let Some(mut channel) = unsafe { UpChannel::conjure(0) } {
channel.set_mode(ChannelMode::BlockIfFull);
writeln!(channel, "{}", info).ok();
} else {
// failed to get channel, but not much else we can do but spin
loop {
compiler_fence(SeqCst);
}
}
// we should never leave critical section
loop {
compiler_fence(SeqCst);
}
})
}