diff options
author | 2023-08-16 22:28:08 +0000 | |
---|---|---|
committer | 2023-08-16 22:28:08 +0000 | |
commit | 1746a63ca16b68514ea23dcca1543aed00165452 (patch) | |
tree | fbed40673119c9a2e1148721e85fcd1449d2b9da /cortex-m-rt/src | |
parent | 4651808e1de360e01b3e734c655aeb5310881b7c (diff) | |
parent | faf7bd3cf37343dec23f61c185e0ae22f684e991 (diff) | |
download | cortex-m-1746a63ca16b68514ea23dcca1543aed00165452.tar.gz cortex-m-1746a63ca16b68514ea23dcca1543aed00165452.tar.zst cortex-m-1746a63ca16b68514ea23dcca1543aed00165452.zip |
Merge pull request #476 from diondokter/optional-hardfault-trampoline
Hardfault trampoline is now optional
Diffstat (limited to 'cortex-m-rt/src')
-rw-r--r-- | cortex-m-rt/src/lib.rs | 66 |
1 files changed, 26 insertions, 40 deletions
diff --git a/cortex-m-rt/src/lib.rs b/cortex-m-rt/src/lib.rs index a6d946c..920c989 100644 --- a/cortex-m-rt/src/lib.rs +++ b/cortex-m-rt/src/lib.rs @@ -225,12 +225,15 @@ //! - `DefaultHandler`. This is the default handler. If not overridden using `#[exception] fn //! DefaultHandler(..` this will be an infinite loop. //! -//! - `HardFaultTrampoline`. This is the real hard fault handler. This function is simply a -//! trampoline that jumps into the user defined hard fault handler named `HardFault`. The -//! trampoline is required to set up the pointer to the stacked exception frame. -//! -//! - `HardFault`. This is the user defined hard fault handler. If not overridden using -//! `#[exception] fn HardFault(..` it will default to an infinite loop. +//! - `HardFault` and `_HardFault`. These function handle the hard fault handling and what they +//! do depends on whether the hard fault is overridden and whether the trampoline is enabled (which it is by default). +//! - No override: Both are the same function. The function is an infinite loop defined in the cortex-m-rt crate. +//! - Trampoline enabled: `HardFault` is the real hard fault handler defined in assembly. This function is simply a +//! trampoline that jumps into the rust defined `_HardFault` function. This second function jumps to the user-defined +//! handler with the exception frame as parameter. This second jump is usually optimised away with inlining. +//! - Trampoline disabled: `HardFault` is the user defined function. This means the user function is called directly +//! from the vector table. `_HardFault` still exists, but is an empty function that is purely there for compiler +//! diagnostics. //! //! - `__STACK_START`. This is the first entry in the `.vector_table` section. This symbol contains //! the initial value of the stack pointer; this is where the stack will be located -- the stack @@ -455,31 +458,6 @@ extern crate cortex_m_rt_macros as macros; use core::arch::global_asm; use core::fmt; -// HardFault exceptions are bounced through this trampoline which grabs the stack pointer at -// the time of the exception and passes it to the user's HardFault handler in r0. -// Depending on the stack mode in EXC_RETURN, fetches stack from either MSP or PSP. -#[cfg(cortex_m)] -global_asm!( - ".cfi_sections .debug_frame - .section .HardFaultTrampoline, \"ax\" - .global HardFaultTrampline - .type HardFaultTrampline,%function - .thumb_func - .cfi_startproc - HardFaultTrampoline:", - "mov r0, lr - movs r1, #4 - tst r0, r1 - bne 0f - mrs r0, MSP - b HardFault - 0: - mrs r0, PSP - b HardFault", - ".cfi_endproc - .size HardFaultTrampoline, . - HardFaultTrampoline", -); - /// Parse cfg attributes inside a global_asm call. #[cfg(cortex_m)] macro_rules! cfg_global_asm { @@ -749,9 +727,18 @@ pub use macros::entry; /// /// # Usage /// -/// `#[exception] unsafe fn HardFault(..` sets the hard fault handler. The handler must have -/// signature `unsafe fn(&ExceptionFrame) -> !`. This handler is not allowed to return as that can -/// cause undefined behavior. +/// ## HardFault handler +/// +/// `#[exception(trampoline = true)] unsafe fn HardFault(..` sets the hard fault handler. +/// If the trampoline parameter is set to true, the handler must have signature `unsafe fn(&ExceptionFrame) -> !`. +/// If set to false, the handler must have signature `unsafe fn() -> !`. +/// +/// This handler is not allowed to return as that can cause undefined behavior. +/// +/// To maintain backwards compatibility the attribute can be used without trampoline parameter (`#[exception]`), +/// which sets the trampoline to true. +/// +/// ## Default handler /// /// `#[exception] unsafe fn DefaultHandler(..` sets the *default* handler. All exceptions which have /// not been assigned a handler will be serviced by this handler. This handler must have signature @@ -759,6 +746,8 @@ pub use macros::entry; /// number when the handler is servicing a core exception; `irqn` will be a positive number when the /// handler is servicing a device specific exception (interrupt). /// +/// ## Other handlers +/// /// `#[exception] fn Name(..` overrides the default handler for the exception with the given `Name`. /// These handlers must have signature `[unsafe] fn() [-> !]`. When overriding these other exception /// it's possible to add state to them by declaring `static mut` variables at the beginning of the @@ -1058,11 +1047,10 @@ pub fn heap_start() -> *mut u32 { #[no_mangle] pub static __RESET_VECTOR: unsafe extern "C" fn() -> ! = Reset; -#[allow(unused_variables)] #[doc(hidden)] #[cfg_attr(cortex_m, link_section = ".HardFault.default")] #[no_mangle] -pub unsafe extern "C" fn HardFault_(ef: &ExceptionFrame) -> ! { +pub unsafe extern "C" fn HardFault_() -> ! { #[allow(clippy::empty_loop)] loop {} } @@ -1115,7 +1103,7 @@ extern "C" { fn NonMaskableInt(); - fn HardFaultTrampoline(); + fn HardFault(); #[cfg(not(armv6m))] fn MemoryManagement(); @@ -1154,9 +1142,7 @@ pub static __EXCEPTIONS: [Vector; 14] = [ handler: NonMaskableInt, }, // Exception 3: Hard Fault Interrupt. - Vector { - handler: HardFaultTrampoline, - }, + Vector { handler: HardFault }, // Exception 4: Memory Management Interrupt [not on Cortex-M0 variants]. #[cfg(not(armv6m))] Vector { |