aboutsummaryrefslogtreecommitdiff
path: root/src/exception.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/exception.rs')
-rw-r--r--src/exception.rs165
1 files changed, 163 insertions, 2 deletions
diff --git a/src/exception.rs b/src/exception.rs
index 7046080..f5c8c28 100644
--- a/src/exception.rs
+++ b/src/exception.rs
@@ -1,4 +1,9 @@
-/// Kind of exception
+//! Exceptions
+
+use ctxt::Context;
+use Reserved;
+
+/// Enumeration of all exceptions
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum Exception {
/// i.e. currently not servicing an exception
@@ -29,7 +34,7 @@ pub enum Exception {
impl Exception {
/// Returns the kind of exception that's currently being serviced
pub fn current() -> Exception {
- match ::peripheral::scb().icsr.read() as u8 {
+ match unsafe { (*::peripheral::SCB.get()).icsr.read() } as u8 {
0 => Exception::ThreadMode,
2 => Exception::Nmi,
3 => Exception::HardFault,
@@ -41,7 +46,163 @@ 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: extern "C" fn(Nmi),
+ /// All class of fault
+ pub hard_fault: extern "C" fn(HardFault),
+ /// Memory management
+ pub mem_manage: extern "C" fn(MemManage),
+ /// Pre-fetch fault, memory access fault
+ pub bus_fault: extern "C" fn(BusFault),
+ /// Undefined instruction or illegal state
+ pub usage_fault: extern "C" fn(UsageFault),
+ /// Reserved spots in the vector table
+ pub _reserved0: [Reserved; 4],
+ /// System service call via SWI instruction
+ pub svcall: extern "C" fn(Svcall),
+ /// Reserved spots in the vector table
+ pub _reserved1: [Reserved; 2],
+ /// Pendable request for system service
+ pub pendsv: extern "C" fn(Pendsv),
+ /// System tick timer
+ pub sys_tick: extern "C" fn(SysTick),
+}
+
+/// Non-maskable interrupt
+pub struct Nmi {
+ _0: (),
+}
+
+/// All class of fault
+pub struct HardFault {
+ _0: (),
+}
+
+/// Memory management
+pub struct MemManage {
+ _0: (),
+}
+
+/// Pre-fetch fault, memory access fault
+pub struct BusFault {
+ _0: (),
+}
+
+/// Undefined instruction or illegal state
+pub struct UsageFault {
+ _0: (),
+}
+
+/// System service call via SWI instruction
+pub struct Svcall {
+ _0: (),
+}
+
+/// Pendable request for system service
+pub struct Pendsv {
+ _0: (),
+}
+
+/// System tick timer
+pub struct SysTick {
+ _0: (),
+}
+
+unsafe impl Context for Nmi {}
+
+unsafe impl Context for HardFault {}
+
+unsafe impl Context for MemManage {}
+
+unsafe impl Context for BusFault {}
+
+unsafe impl Context for UsageFault {}
+
+unsafe impl Context for Svcall {}
+
+unsafe impl Context for Pendsv {}
+
+unsafe impl Context for SysTick {}
+
+/// 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 stacked registers
+#[naked]
+pub extern "C" fn default_handler<T>(_token: T)
+where
+ T: Context,
+{
+ // This is the actual exception handler. `_sf` is a pointer to the previous
+ // stack frame
+ #[cfg(target_arch = "arm")]
+ extern "C" fn handler(_sr: &StackedRegisters) -> ! {
+ ::asm::bkpt();
+
+ loop {}
+ }
+
+ match () {
+ #[cfg(target_arch = "arm")]
+ () => {
+ unsafe {
+ // "trampoline" to get to the real exception handler.
+ asm!("mrs r0, MSP
+ ldr r1, [r0, #20]
+ b $0"
+ :
+ : "i"(handler as extern "C" fn(&StackedRegisters) -> !)
+ :
+ : "volatile");
+
+ ::core::intrinsics::unreachable()
+ }
}
+ #[cfg(not(target_arch = "arm"))]
+ () => {}
}
}
+
+/// Registers stacked during an exception
+#[repr(C)]
+pub struct StackedRegisters {
+ /// (General purpose) Register 0
+ pub r0: u32,
+ /// (General purpose) Register 1
+ pub r1: u32,
+ /// (General purpose) Register 2
+ pub r2: u32,
+ /// (General purpose) Register 3
+ pub r3: u32,
+ /// (General purpose) Register 12
+ pub r12: u32,
+ /// Linker Register
+ pub lr: u32,
+ /// Program Counter
+ pub pc: u32,
+ /// Program Status Register
+ pub xpsr: u32,
+}