Skip to content

Commit b6dced0

Browse files
committed
Add a HardFault handler.
This makes sure we indicate fault on an external pin, whether it's a software fault (panic) or a hardware fault (e.g. a bus error). By some careful rearranging, I was able to do this without adding to the size of the compiled program. We are unfortunately still paying for the cortex-m-rt HardFaultTrampoline routine. See: rust-embedded/cortex-m#406
1 parent 293ad3e commit b6dced0

File tree

1 file changed

+20
-4
lines changed

1 file changed

+20
-4
lines changed

src/bin/stage0.rs

+20-4
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
#![no_std]
22
#![no_main]
33

4+
use core::sync::atomic::{compiler_fence, Ordering};
5+
46
use stage0::{romapi, sha256, SLOT_SIZE_WORDS};
57

6-
use cortex_m_rt::entry;
8+
use cortex_m_rt::{entry, exception, ExceptionFrame};
79
use lpc55_pac::interrupt;
810

911
/// Bootloader entry point. These are not the first instructions executed, since
@@ -50,15 +52,29 @@ fn main() -> ! {
5052

5153
#[panic_handler]
5254
fn panic_handler(_: &core::panic::PanicInfo) -> ! {
55+
// We use a BKPT instruction to wake any attached debugger. If no debugger
56+
// is attached, BKPT escalates into a HardFault, falling to the handler
57+
// below. This way we can reuse its fault indication code.
58+
loop {
59+
cortex_m::asm::bkpt();
60+
}
61+
}
62+
63+
#[exception]
64+
unsafe fn HardFault(_ef: &ExceptionFrame) -> ! {
5365
// Safety: the GPIO peripheral is static, and we're not racing anyone by
54-
// definition since we're in the process of panicking to a halt.
66+
// definition since we're handling a HardFault. So we win.
5567
let gpio = unsafe { &*lpc55_pac::GPIO::ptr() };
5668
// Turn on the RED LED on the xpresso board.
5769
gpio.dir[1].write(|w| unsafe { w.bits(1 << 6) });
5870

59-
// Park!
71+
// Spin -- don't use BKPT here because if no debugger is attached it'll
72+
// escalate to another HardFault and lock the processor.
6073
loop {
61-
cortex_m::asm::bkpt();
74+
// This is enough to force LLVM to compile the infinite loop as
75+
// something other than a UDF, but not enough to generate instructions;
76+
// using an explicit nop here costs two bytes more.
77+
compiler_fence(Ordering::SeqCst);
6278
}
6379
}
6480

0 commit comments

Comments
 (0)