199199//! won't find it.
200200//!
201201//! - `DefaultHandler`. This is the default handler. If not overridden using `#[exception] fn
202- //! DefaultHandler(..` this will cause a panic with the message "DefaultHandler #`i`", where `i` is
203- //! the number of the interrupt handler.
202+ //! DefaultHandler(..` this will be an infinite loop.
204203//!
205204//! - `HardFaultTrampoline`. This is the real hard fault handler. This function is simply a
206205//! trampoline that jumps into the user defined hard fault handler named `HardFault`. The
207206//! trampoline is required to set up the pointer to the stacked exception frame.
208207//!
209208//! - `HardFault`. This is the user defined hard fault handler. If not overridden using
210- //! `#[exception] fn HardFault(..` it will default to a panic with message "HardFault" .
209+ //! `#[exception] fn HardFault(..` it will default to an infinite loop .
211210//!
212211//! - `__STACK_START`. This is the first entry in the `.vector_table` section. This symbol contains
213212//! the initial value of the stack pointer; this is where the stack will be located -- the stack
@@ -442,6 +441,7 @@ extern crate cortex_m_rt_macros as macros;
442441extern crate r0;
443442
444443use core:: fmt;
444+ use core:: sync:: atomic:: { self , Ordering } ;
445445
446446/// Attribute to declare an interrupt (AKA device-specific exception) handler
447447///
@@ -612,13 +612,13 @@ pub use macros::entry;
612612///
613613/// # Usage
614614///
615- /// `#[exception] fn HardFault(..` sets the hard fault handler. The handler must have signature
616- /// `[ unsafe] fn(&ExceptionFrame) -> !`. This handler is not allowed to return as that can cause
617- /// undefined behavior.
615+ /// `#[exception] unsafe fn HardFault(..` sets the hard fault handler. The handler must have
616+ /// signature ` unsafe fn(&ExceptionFrame) -> !`. This handler is not allowed to return as that can
617+ /// cause undefined behavior.
618618///
619- /// `#[exception] fn DefaultHandler(..` sets the *default* handler. All exceptions which have not
620- /// been assigned a handler will be serviced by this handler. This handler must have signature
621- /// `[ unsafe] fn(irqn: i16) [-> !]`. `irqn` is the IRQ number (See CMSIS); `irqn` will be a negative
619+ /// `#[exception] unsafe fn DefaultHandler(..` sets the *default* handler. All exceptions which have
620+ /// not been assigned a handler will be serviced by this handler. This handler must have signature
621+ /// `unsafe fn(irqn: i16) [-> !]`. `irqn` is the IRQ number (See CMSIS); `irqn` will be a negative
622622/// number when the handler is servicing a core exception; `irqn` will be a positive number when the
623623/// handler is servicing a device specific exception (interrupt).
624624///
@@ -637,31 +637,33 @@ pub use macros::entry;
637637/// the attribute will help by making a transformation to the source code: for this reason a
638638/// variable like `static mut FOO: u32` will become `let FOO: &mut u32;`.
639639///
640- /// # Examples
640+ /// # Safety
641641///
642- /// - Setting the `HardFault` handler
642+ /// It is not generally safe to register handlers for non-maskable interrupts. On Cortex-M,
643+ /// `HardFault` is non-maskable (at least in general), and there is an explicitly non-maskable
644+ /// interrupt `NonMaskableInt`.
643645///
644- /// ```
645- /// # extern crate cortex_m_rt;
646- /// # extern crate cortex_m_rt_macros;
647- /// use cortex_m_rt::{ExceptionFrame, exception};
646+ /// The reason for that is that non-maskable interrupts will preempt any currently running function,
647+ /// even if that function executes within a critical section. Thus, if it was safe to define NMI
648+ /// handlers, critical sections wouldn't work safely anymore.
648649///
649- /// #[exception]
650- /// fn HardFault(ef: &ExceptionFrame) -> ! {
651- /// // prints the exception frame as a panic message
652- /// panic!("{:#?}", ef);
653- /// }
650+ /// This also means that defining a `DefaultHandler` must be unsafe, as that will catch
651+ /// `NonMaskableInt` and `HardFault` if no handlers for those are defined.
654652///
655- /// # fn main() {}
656- /// ```
653+ /// The safety requirements on those handlers is as follows: The handler must not access any data
654+ /// that is protected via a critical section and shared with other interrupts that may be preempted
655+ /// by the NMI while holding the critical section. As long as this requirement is fulfilled, it is
656+ /// safe to handle NMIs.
657+ ///
658+ /// # Examples
657659///
658660/// - Setting the default handler
659661///
660662/// ```
661663/// use cortex_m_rt::exception;
662664///
663665/// #[exception]
664- /// fn DefaultHandler(irqn: i16) {
666+ /// unsafe fn DefaultHandler(irqn: i16) {
665667/// println!("IRQn = {}", irqn);
666668/// }
667669///
@@ -990,17 +992,21 @@ pub unsafe extern "C" fn Reset() -> ! {
990992#[ link_section = ".HardFault.default" ]
991993#[ no_mangle]
992994pub unsafe extern "C" fn HardFault_ ( ef : & ExceptionFrame ) -> ! {
993- panic ! ( "HardFault" ) ;
995+ loop {
996+ // add some side effect to prevent this from turning into a UDF instruction
997+ // see rust-lang/rust#28728 for details
998+ atomic:: compiler_fence ( Ordering :: SeqCst ) ;
999+ }
9941000}
9951001
9961002#[ doc( hidden) ]
9971003#[ no_mangle]
9981004pub unsafe extern "C" fn DefaultHandler_ ( ) -> ! {
999- const SCB_ICSR : * const u32 = 0xE000_ED04 as * const u32 ;
1000-
1001- let irqn = core :: ptr :: read ( SCB_ICSR ) as u8 as i16 - 16 ;
1002-
1003- panic ! ( "DefaultHandler #{}" , irqn ) ;
1005+ loop {
1006+ // add some side effect to prevent this from turning into a UDF instruction
1007+ // see rust-lang/rust#28728 for details
1008+ atomic :: compiler_fence ( Ordering :: SeqCst ) ;
1009+ }
10041010}
10051011
10061012#[ doc( hidden) ]
0 commit comments