199
199
//! won't find it.
200
200
//!
201
201
//! - `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.
204
203
//!
205
204
//! - `HardFaultTrampoline`. This is the real hard fault handler. This function is simply a
206
205
//! trampoline that jumps into the user defined hard fault handler named `HardFault`. The
207
206
//! trampoline is required to set up the pointer to the stacked exception frame.
208
207
//!
209
208
//! - `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 .
211
210
//!
212
211
//! - `__STACK_START`. This is the first entry in the `.vector_table` section. This symbol contains
213
212
//! 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;
442
441
extern crate r0;
443
442
444
443
use core:: fmt;
444
+ use core:: sync:: atomic:: { self , Ordering } ;
445
445
446
446
/// Attribute to declare an interrupt (AKA device-specific exception) handler
447
447
///
@@ -612,13 +612,13 @@ pub use macros::entry;
612
612
///
613
613
/// # Usage
614
614
///
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.
618
618
///
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
622
622
/// number when the handler is servicing a core exception; `irqn` will be a positive number when the
623
623
/// handler is servicing a device specific exception (interrupt).
624
624
///
@@ -637,31 +637,33 @@ pub use macros::entry;
637
637
/// the attribute will help by making a transformation to the source code: for this reason a
638
638
/// variable like `static mut FOO: u32` will become `let FOO: &mut u32;`.
639
639
///
640
- /// # Examples
640
+ /// # Safety
641
641
///
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`.
643
645
///
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.
648
649
///
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.
654
652
///
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
657
659
///
658
660
/// - Setting the default handler
659
661
///
660
662
/// ```
661
663
/// use cortex_m_rt::exception;
662
664
///
663
665
/// #[exception]
664
- /// fn DefaultHandler(irqn: i16) {
666
+ /// unsafe fn DefaultHandler(irqn: i16) {
665
667
/// println!("IRQn = {}", irqn);
666
668
/// }
667
669
///
@@ -990,17 +992,21 @@ pub unsafe extern "C" fn Reset() -> ! {
990
992
#[ link_section = ".HardFault.default" ]
991
993
#[ no_mangle]
992
994
pub 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
+ }
994
1000
}
995
1001
996
1002
#[ doc( hidden) ]
997
1003
#[ no_mangle]
998
1004
pub 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
+ }
1004
1010
}
1005
1011
1006
1012
#[ doc( hidden) ]
0 commit comments