aboutsummaryrefslogtreecommitdiff
path: root/src/exception.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/exception.rs')
-rw-r--r--src/exception.rs73
1 files changed, 73 insertions, 0 deletions
diff --git a/src/exception.rs b/src/exception.rs
index 7046080..fad3ea9 100644
--- a/src/exception.rs
+++ b/src/exception.rs
@@ -1,3 +1,7 @@
+//! Exceptions
+
+use {Handler, Reserved, StackFrame};
+
/// Kind of exception
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum Exception {
@@ -41,7 +45,76 @@ impl Exception {
15 => Exception::Systick,
n if n >= 16 => Exception::Interrupt(n - 16),
_ => Exception::Reserved,
+ }
+ }
+}
+/// Exception handlers
+#[repr(C)]
+pub struct Handlers {
+ /// Non-maskable interrupt
+ pub nmi: Handler,
+ /// All class of fault
+ pub hard_fault: Handler,
+ /// Memory management
+ pub mem_manage: Handler,
+ /// Pre-fetch fault, memory access fault
+ pub bus_fault: Handler,
+ /// Undefined instruction or illegal state
+ pub usage_fault: Handler,
+ /// Reserved spots in the vector table
+ pub _reserved0: [Reserved; 4],
+ /// System service call via SWI instruction
+ pub svcall: Handler,
+ /// Reserved spots in the vector table
+ pub _reserved1: [Reserved; 2],
+ /// Pendable request for system service
+ pub pendsv: Handler,
+ /// System tick timer
+ pub sys_tick: Handler,
+}
+
+/// Default exception handlers
+pub const DEFAULT_HANDLERS: Handlers = Handlers {
+ _reserved0: [Reserved::Vector; 4],
+ _reserved1: [Reserved::Vector; 2],
+ bus_fault: default_handler,
+ hard_fault: default_handler,
+ mem_manage: default_handler,
+ nmi: default_handler,
+ pendsv: default_handler,
+ svcall: default_handler,
+ sys_tick: default_handler,
+ usage_fault: default_handler,
+};
+
+/// The default exception handler
+///
+/// This handler triggers a breakpoint (`bkpt`) and gives you access, within a
+/// GDB session, to the stack frame (`_sf`) where the exception occurred.
+// This needs asm!, #[naked] and unreachable() to avoid modifying the stack
+// pointer (MSP), that way it points to the previous stack frame
+#[naked]
+pub unsafe extern "C" fn default_handler() {
+ // This is the actual exception handler. `_sf` is a pointer to the previous
+ // stack frame
+ extern "C" fn handler(_sf: &StackFrame) -> ! {
+ #[cfg(feature = "semihosting")]
+ hprintln!("EXCEPTION {:?} @ PC=0x{:08x}", Exception::current(), _sf.pc);
+
+ unsafe {
+ bkpt!();
}
+
+ loop {}
}
+
+ // "trampoline" to get to the real exception handler.
+ asm!("mrs r0, MSP
+ ldr r1, [r0, #20]
+ b $0"
+ :
+ : "i"(handler as extern "C" fn(&StackFrame) -> !) :: "volatile");
+
+ ::core::intrinsics::unreachable()
}