Skip to content

Commit 7d19e64

Browse files
Document NMI handler unsafety
1 parent ac74bff commit 7d19e64

File tree

1 file changed

+24
-6
lines changed

1 file changed

+24
-6
lines changed

cortex-m-rt/src/lib.rs

Lines changed: 24 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -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,6 +637,24 @@ 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+
/// # Safety
641+
///
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`.
645+
///
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.
649+
///
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.
652+
///
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+
///
640658
/// # Examples
641659
///
642660
/// - Setting the `HardFault` handler

0 commit comments

Comments
 (0)