use ctxt::Context;
use Reserved;
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum Exception {
ThreadMode,
Nmi,
HardFault,
MemoryManagementFault,
BusFault,
UsageFault,
SVCall,
PendSV,
Systick,
Interrupt(u8),
#[doc(hidden)]
Reserved,
}
impl Exception {
pub fn current() -> Exception {
match unsafe { (*::peripheral::SCB.get()).icsr.read() } as u8 {
0 => Exception::ThreadMode,
2 => Exception::Nmi,
3 => Exception::HardFault,
4 => Exception::MemoryManagementFault,
5 => Exception::BusFault,
6 => Exception::UsageFault,
11 => Exception::SVCall,
14 => Exception::PendSV,
15 => Exception::Systick,
n if n >= 16 => Exception::Interrupt(n - 16),
_ => Exception::Reserved,
}
}
}
#[repr(C)]
pub struct Handlers {
pub nmi: extern "C" fn(Nmi),
pub hard_fault: extern "C" fn(HardFault),
pub mem_manage: extern "C" fn(MemManage),
pub bus_fault: extern "C" fn(BusFault),
pub usage_fault: extern "C" fn(UsageFault),
pub _reserved0: [Reserved; 4],
pub svcall: extern "C" fn(Svcall),
pub _reserved1: [Reserved; 2],
pub pendsv: extern "C" fn(Pendsv),
pub sys_tick: extern "C" fn(SysTick),
}
pub struct Nmi {
_0: (),
}
pub struct HardFault {
_0: (),
}
pub struct MemManage {
_0: (),
}
pub struct BusFault {
_0: (),
}
pub struct UsageFault {
_0: (),
}
pub struct Svcall {
_0: (),
}
pub struct Pendsv {
_0: (),
}
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 {}
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,
};
#[naked]
pub extern "C" fn default_handler<T>(_token: T)
where
T: Context,
{
#[cfg(target_arch = "arm")]
extern "C" fn handler(_sr: &StackedRegisters) -> ! {
let _e = Exception::current();
::asm::bkpt();
loop {}
}
match () {
#[cfg(target_arch = "arm")]
() => {
unsafe {
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"))]
() => {}
}
}
#[repr(C)]
pub struct StackedRegisters {
pub r0: u32,
pub r1: u32,
pub r2: u32,
pub r3: u32,
pub r12: u32,
pub lr: u32,
pub pc: u32,
pub xpsr: u32,
}