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
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
#![no_std]
#![cfg(target_os = "none")]
#[cfg(not(cortex_m))]
compile_error!("`panic-probe` only supports Cortex-M targets (thumbvN-none-eabi[hf])");
#[cfg(target_os = "none")]
mod imp {
use core::panic::PanicInfo;
use core::sync::atomic::{AtomicBool, Ordering};
use cortex_m::asm;
#[cfg(feature = "print-rtt")]
use crate::print_rtt::print;
#[cfg(feature = "print-defmt")]
use crate::print_defmt::print;
#[cfg(not(any(feature = "print-rtt", feature = "print-defmt")))]
fn print(_: &core::panic::PanicInfo) {}
#[panic_handler]
fn panic(info: &PanicInfo) -> ! {
static PANICKED: AtomicBool = AtomicBool::new(false);
cortex_m::interrupt::disable();
if PANICKED.load(Ordering::Relaxed) {
loop {
asm::bkpt();
}
}
PANICKED.store(true, Ordering::Relaxed);
print(info);
#[cfg(not(any(armv6m, armv8m_base)))]
{
const SHCSR: *mut u32 = 0xE000ED24usize as _;
const USGFAULTENA: usize = 18;
unsafe {
let mut shcsr = core::ptr::read_volatile(SHCSR);
shcsr &= !(1 << USGFAULTENA);
core::ptr::write_volatile(SHCSR, shcsr);
}
}
asm::udf();
}
}
#[cfg(feature = "print-rtt")]
mod print_rtt {
use core::panic::PanicInfo;
use rtt_target::rprintln;
pub fn print(info: &PanicInfo) {
rprintln!("{}", info);
}
}
#[cfg(feature = "print-defmt")]
mod print_defmt {
use core::{
cmp,
fmt::{self, Write},
mem,
panic::PanicInfo,
str,
};
const DEFMT_BUF_SIZE: usize = 128;
const OVERFLOW_MARK: &str = "…";
struct Sink<'a> {
buf: &'a mut [u8],
pos: usize,
overflowed: bool,
}
impl<'a> fmt::Write for Sink<'a> {
fn write_str(&mut self, s: &str) -> fmt::Result {
if self.overflowed {
return Ok(());
}
let buf = mem::replace(&mut self.buf, &mut []);
let buf_unused = &mut buf[self.pos..];
if buf_unused.len() < s.len() {
self.overflowed = true;
}
let lim = cmp::min(buf_unused.len(), s.len());
buf_unused[..lim].copy_from_slice(&s.as_bytes()[..lim]);
self.buf = buf;
self.pos += lim;
Ok(())
}
}
pub fn print(info: &PanicInfo) {
let mut buf = [0; DEFMT_BUF_SIZE];
let mut sink = Sink {
buf: &mut buf,
pos: 0,
overflowed: false,
};
write!(sink, "{}", info).ok();
let msg = str::from_utf8(&sink.buf[..sink.pos]).unwrap_or("<utf-8 error>");
let overflow = if sink.overflowed { OVERFLOW_MARK } else { "" };
defmt::error!("{:str}{:str}", msg, overflow);
}
}