aboutsummaryrefslogtreecommitdiff
path: root/src/exception.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/exception.rs')
-rw-r--r--src/exception.rs93
1 files changed, 76 insertions, 17 deletions
diff --git a/src/exception.rs b/src/exception.rs
index cd38366..b944d6c 100644
--- a/src/exception.rs
+++ b/src/exception.rs
@@ -1,8 +1,7 @@
//! Exceptions
-use {Handler, Reserved};
-#[cfg(target_arch = "arm")]
-use StackFrame;
+use ctxt::Token;
+use Reserved;
/// Kind of exception
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
@@ -35,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,
@@ -55,27 +54,65 @@ impl Exception {
#[repr(C)]
pub struct Handlers {
/// Non-maskable interrupt
- pub nmi: Handler,
+ pub nmi: unsafe extern "C" fn(&NmiCtxt),
/// All class of fault
- pub hard_fault: Handler,
+ pub hard_fault: unsafe extern "C" fn(&HardFaultCtxt),
/// Memory management
- pub mem_manage: Handler,
+ pub mem_manage: unsafe extern "C" fn(&MemManageCtxt),
/// Pre-fetch fault, memory access fault
- pub bus_fault: Handler,
+ pub bus_fault: unsafe extern "C" fn(&BusFaultCtxt),
/// Undefined instruction or illegal state
- pub usage_fault: Handler,
+ pub usage_fault: unsafe extern "C" fn(&UsageFaultCtxt),
/// Reserved spots in the vector table
pub _reserved0: [Reserved; 4],
/// System service call via SWI instruction
- pub svcall: Handler,
+ pub svcall: unsafe extern "C" fn(&SvcallCtxt),
/// Reserved spots in the vector table
pub _reserved1: [Reserved; 2],
/// Pendable request for system service
- pub pendsv: Handler,
+ pub pendsv: unsafe extern "C" fn(&PendsvCtxt),
/// System tick timer
- pub sys_tick: Handler,
+ pub sys_tick: unsafe extern "C" fn (&SysTickCtxt),
}
+/// Identifies the Nmi exception
+pub struct NmiCtxt { _0: () }
+
+/// Identifies the HardFault exception
+pub struct HardFaultCtxt { _0: () }
+
+/// Identifies the MemManage exception
+pub struct MemManageCtxt { _0: () }
+
+/// Identifies the BusFault exception
+pub struct BusFaultCtxt { _0: () }
+
+/// Identifies the UsageFault exception
+pub struct UsageFaultCtxt { _0: () }
+
+/// Identifies the Svcall exception
+pub struct SvcallCtxt { _0: () }
+
+/// Identifies the Pendsv exception
+pub struct PendsvCtxt { _0: () }
+
+/// Identifies the Systick exception
+pub struct SysTickCtxt { _0: () }
+
+unsafe impl Token for NmiCtxt {}
+
+unsafe impl Token for HardFaultCtxt {}
+
+unsafe impl Token for MemManageCtxt {}
+
+unsafe impl Token for BusFaultCtxt {}
+
+unsafe impl Token for SvcallCtxt {}
+
+unsafe impl Token for PendsvCtxt {}
+
+unsafe impl Token for SysTickCtxt {}
+
/// Default exception handlers
pub const DEFAULT_HANDLERS: Handlers = Handlers {
_reserved0: [Reserved::Vector; 4],
@@ -95,15 +132,16 @@ pub const DEFAULT_HANDLERS: Handlers = Handlers {
/// 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
+// pointer (MSP), that way it points to the stacked registers
#[naked]
-pub unsafe extern "C" fn default_handler() {
+pub unsafe extern "C" fn default_handler<T>(_token: &T)
+{
// This is the actual exception handler. `_sf` is a pointer to the previous
// stack frame
#[cfg(target_arch = "arm")]
- extern "C" fn handler(_sf: &StackFrame) -> ! {
+ extern "C" fn handler(_sr: &StackedRegisters) -> ! {
#[cfg(feature = "semihosting")]
- hprintln!("EXCEPTION {:?} @ PC=0x{:08x}", Exception::current(), _sf.pc);
+ hprintln!("EXCEPTION {:?} @ PC=0x{:08x}", Exception::current(), _sr.pc);
unsafe {
bkpt!();
@@ -120,7 +158,7 @@ pub unsafe extern "C" fn default_handler() {
ldr r1, [r0, #20]
b $0"
:
- : "i"(handler as extern "C" fn(&StackFrame) -> !)
+ : "i"(handler as extern "C" fn(&StackedRegisters) -> !)
:
: "volatile");
@@ -130,3 +168,24 @@ pub unsafe extern "C" fn default_handler() {
() => {}
}
}
+
+/// 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,
+}