diff options
-rw-r--r-- | cortex-m-rt/.github/bors.toml | 16 | ||||
-rw-r--r-- | cortex-m-rt/.github/workflows/ci.yml | 67 | ||||
-rw-r--r-- | cortex-m-rt/CHANGELOG.md | 23 | ||||
-rw-r--r-- | cortex-m-rt/examples/divergent-default-handler.rs | 3 | ||||
-rw-r--r-- | cortex-m-rt/examples/override-exception.rs | 5 | ||||
-rw-r--r-- | cortex-m-rt/link.x.in | 23 | ||||
-rw-r--r-- | cortex-m-rt/macros/src/lib.rs | 42 | ||||
-rw-r--r-- | cortex-m-rt/src/lib.rs | 99 | ||||
-rw-r--r-- | cortex-m-rt/tests/compile-fail/default-handler-bad-signature-1.rs | 4 | ||||
-rw-r--r-- | cortex-m-rt/tests/compile-fail/default-handler-bad-signature-2.rs | 4 | ||||
-rw-r--r-- | cortex-m-rt/tests/compile-fail/default-handler-hidden.rs | 2 | ||||
-rw-r--r-- | cortex-m-rt/tests/compile-fail/default-handler-twice.rs | 4 | ||||
-rw-r--r-- | cortex-m-rt/tests/compile-fail/exception-nmi-unsafe.rs | 24 | ||||
-rw-r--r-- | cortex-m-rt/tests/compile-fail/hard-fault-bad-signature-1.rs | 4 | ||||
-rw-r--r-- | cortex-m-rt/tests/compile-fail/hard-fault-twice.rs | 4 | ||||
-rw-r--r-- | cortex-m-rt/tests/compile-fail/unsafe-init-static.rs | 4 |
16 files changed, 235 insertions, 93 deletions
diff --git a/cortex-m-rt/.github/bors.toml b/cortex-m-rt/.github/bors.toml index 1972ab0..9b9d884 100644 --- a/cortex-m-rt/.github/bors.toml +++ b/cortex-m-rt/.github/bors.toml @@ -2,17 +2,9 @@ block_labels = ["needs-decision"] delete_merged_branches = true required_approvals = 1 status = [ - "ci-linux (stable, x86_64-unknown-linux-gnu)", - "ci-linux (stable, thumbv6m-none-eabi)", - "ci-linux (stable, thumbv7m-none-eabi)", - "ci-linux (stable, thumbv7em-none-eabi)", - "ci-linux (stable, thumbv7em-none-eabihf)", - "ci-linux (stable, thumbv8m.main-none-eabi)", - "ci-linux (1.39.0, x86_64-unknown-linux-gnu)", - "ci-linux (1.39.0, thumbv6m-none-eabi)", - "ci-linux (1.39.0, thumbv7m-none-eabi)", - "ci-linux (1.39.0, thumbv7em-none-eabi)", - "ci-linux (1.39.0, thumbv7em-none-eabihf)", - "ci-linux (1.39.0, thumbv8m.main-none-eabi)", + "ci-linux (stable)", + "ci-linux (1.39.0)", + "build-other (macOS-latest)", + "build-other (windows-latest)", "Rustfmt" ] diff --git a/cortex-m-rt/.github/workflows/ci.yml b/cortex-m-rt/.github/workflows/ci.yml index 6905827..35abd15 100644 --- a/cortex-m-rt/.github/workflows/ci.yml +++ b/cortex-m-rt/.github/workflows/ci.yml @@ -7,33 +7,74 @@ name: Continuous integration jobs: ci-linux: - runs-on: ubuntu-latest + runs-on: ubuntu-20.04 strategy: matrix: # All generated code should be running on stable now rust: [nightly, stable, 1.39.0] - # The default target we're compiling on and for - TARGET: [x86_64-unknown-linux-gnu, thumbv6m-none-eabi, thumbv7m-none-eabi, thumbv7em-none-eabi, thumbv7em-none-eabihf, thumbv8m.main-none-eabi] - include: # Nightly is only for reference and allowed to fail - rust: nightly experimental: true steps: - - uses: fiam/arm-none-eabi-gcc@v1 - with: - release: '7-2018-q2' - uses: actions/checkout@v2 - uses: actions-rs/toolchain@v1 with: profile: minimal toolchain: ${{ matrix.rust }} - target: ${{ matrix.TARGET }} override: true - components: rustfmt - - name: Install qemu - run: sudo apt-get install qemu-system-arm - - name: Run CI script for ${{ matrix.TARGET }} under ${{ matrix.rust }} - run: TARGET=${{ matrix.TARGET }} TRAVIS_RUST_VERSION=${{ matrix.rust }} bash ci/script.sh + - name: Install all Rust targets for ${{ matrix.rust }} + run: rustup target install --toolchain=${{ matrix.rust }} thumbv6m-none-eabi thumbv7m-none-eabi thumbv7em-none-eabi thumbv7em-none-eabihf thumbv8m.base-none-eabi thumbv8m.main-none-eabi thumbv8m.main-none-eabihf + - name: Install qemu and gcc + run: sudo apt-get update && sudo apt-get install qemu-system-arm gcc-arm-none-eabi + - name: Run CI script for x86_64-unknown-linux-gnu under ${{ matrix.rust }} + run: TARGET=x86_64-unknown-linux-gnu TRAVIS_RUST_VERSION=${{ matrix.rust }} bash ci/script.sh + - name: Run CI script for thumbv6m-none-eabi under ${{ matrix.rust }} + run: TARGET=thumbv6m-none-eabi TRAVIS_RUST_VERSION=${{ matrix.rust }} bash ci/script.sh + - name: Run CI script for thumbv7m-none-eabi under ${{ matrix.rust }} + run: TARGET=thumbv7m-none-eabi TRAVIS_RUST_VERSION=${{ matrix.rust }} bash ci/script.sh + - name: Run CI script for thumbv7em-none-eabi under ${{ matrix.rust }} + run: TARGET=thumbv7em-none-eabi TRAVIS_RUST_VERSION=${{ matrix.rust }} bash ci/script.sh + - name: Run CI script for thumbv7em-none-eabihf under ${{ matrix.rust }} + run: TARGET=thumbv7em-none-eabihf TRAVIS_RUST_VERSION=${{ matrix.rust }} bash ci/script.sh + - name: Run CI script for thumbv8m.base-none-eabi under ${{ matrix.rust }} + run: TARGET=thumbv8m.base-none-eabi TRAVIS_RUST_VERSION=${{ matrix.rust }} bash ci/script.sh + - name: Run CI script for thumbv8m.main-none-eabi under ${{ matrix.rust }} + run: TARGET=thumbv8m.main-none-eabi TRAVIS_RUST_VERSION=${{ matrix.rust }} bash ci/script.sh + - name: Run CI script for thumbv8m.main-none-eabihf under ${{ matrix.rust }} + run: TARGET=thumbv8m.main-none-eabihf TRAVIS_RUST_VERSION=${{ matrix.rust }} bash ci/script.sh + + # On macOS and Windows, we at least make sure that all examples build and link. + build-other: + strategy: + matrix: + os: + - macOS-latest + - windows-latest + runs-on: ${{ matrix.os }} + + steps: + - uses: actions/checkout@v2 + - uses: actions-rs/toolchain@v1 + with: + profile: minimal + toolchain: stable + override: true + - name: Install all Rust targets + run: rustup target install thumbv6m-none-eabi thumbv7m-none-eabi thumbv7em-none-eabi thumbv7em-none-eabihf thumbv8m.base-none-eabi thumbv8m.main-none-eabi thumbv8m.main-none-eabihf + - name: Build crate for thumbv6m-none-eabi + run: cargo build --target=thumbv6m-none-eabi --examples + - name: Build crate for thumbv7m-none-eabi + run: cargo build --target=thumbv7m-none-eabi --examples + - name: Build crate for thumbv7em-none-eabi + run: cargo build --target=thumbv7em-none-eabi --examples + - name: Build crate for thumbv7em-none-eabihf + run: cargo build --target=thumbv7em-none-eabihf --examples + - name: Build crate for thumbv8m.base-none-eabi + run: cargo build --target=thumbv8m.base-none-eabi --examples + - name: Build crate for thumbv8m.main-none-eabi + run: cargo build --target=thumbv8m.main-none-eabi --examples + - name: Build crate for thumbv8m.main-none-eabihf + run: cargo build --target=thumbv8m.main-none-eabihf --examples diff --git a/cortex-m-rt/CHANGELOG.md b/cortex-m-rt/CHANGELOG.md index b6ca176..e04c9c9 100644 --- a/cortex-m-rt/CHANGELOG.md +++ b/cortex-m-rt/CHANGELOG.md @@ -7,6 +7,29 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ## [Unreleased] +### Fixes + +- Various fixes to the linker script ([#265], [#286]). +- Use the correct ABI for the `main` symbol ([#278]). +- Add barriers after FPU enabling ([#279]). + +[#265]: https://github.com/rust-embedded/cortex-m-rt/pull/265 +[#278]: https://github.com/rust-embedded/cortex-m-rt/pull/278 +[#279]: https://github.com/rust-embedded/cortex-m-rt/pull/279 +[#286]: https://github.com/rust-embedded/cortex-m-rt/pull/286 + +### Breaking Changes + +- Make `ExceptionFrame`s fields private, adding setters and getters instead + ([#239]). +- Only allow certain attributes on handlers, and apply them to the trampoline + too ([#228]). +- Make it unsafe to define exception handlers for NMIs ([#289]). + +[#239]: https://github.com/rust-embedded/cortex-m-rt/pull/239 +[#228]: https://github.com/rust-embedded/cortex-m-rt/pull/228 +[#289]: https://github.com/rust-embedded/cortex-m-rt/pull/289 + ## [v0.6.11] - 2019-12-04 ### Changed diff --git a/cortex-m-rt/examples/divergent-default-handler.rs b/cortex-m-rt/examples/divergent-default-handler.rs index 22fa437..3290254 100644 --- a/cortex-m-rt/examples/divergent-default-handler.rs +++ b/cortex-m-rt/examples/divergent-default-handler.rs @@ -1,4 +1,3 @@ -#![deny(unsafe_code)] #![deny(warnings)] #![no_main] #![no_std] @@ -14,6 +13,6 @@ fn foo() -> ! { } #[exception] -fn DefaultHandler(_irqn: i16) -> ! { +unsafe fn DefaultHandler(_irqn: i16) -> ! { loop {} } diff --git a/cortex-m-rt/examples/override-exception.rs b/cortex-m-rt/examples/override-exception.rs index 6da6c5e..3190b77 100644 --- a/cortex-m-rt/examples/override-exception.rs +++ b/cortex-m-rt/examples/override-exception.rs @@ -1,6 +1,5 @@ //! How to override the hard fault exception handler and the default exception handler -#![deny(unsafe_code)] #![deny(warnings)] #![no_main] #![no_std] @@ -18,12 +17,12 @@ fn main() -> ! { } #[exception] -fn DefaultHandler(_irqn: i16) { +unsafe fn DefaultHandler(_irqn: i16) { asm::bkpt(); } #[exception] -fn HardFault(_ef: &ExceptionFrame) -> ! { +unsafe fn HardFault(_ef: &ExceptionFrame) -> ! { asm::bkpt(); loop {} diff --git a/cortex-m-rt/link.x.in b/cortex-m-rt/link.x.in index a502a03..f5e582e 100644 --- a/cortex-m-rt/link.x.in +++ b/cortex-m-rt/link.x.in @@ -88,9 +88,10 @@ SECTIONS *(.text .text.*); *(.HardFaultTrampoline); *(.HardFault.*); - . = ALIGN(4); - __etext = .; + . = ALIGN(4); /* Pad .text to the alignment to workaround overlapping load section bug in old lld */ } > FLASH + . = ALIGN(4); /* Ensure __etext is aligned if something unaligned is inserted after .text */ + __etext = .; /* Define outside of .text to allow using INSERT AFTER .text */ /* ### .rodata */ .rodata __etext : ALIGN(4) @@ -101,32 +102,36 @@ SECTIONS This is required by LLD to ensure the LMA of the following .data section will have the correct alignment. */ . = ALIGN(4); - __erodata = .; } > FLASH + . = ALIGN(4); /* Ensure __erodata is aligned if something unaligned is inserted after .rodata */ + __erodata = .; /* ## Sections in RAM */ /* ### .data */ - .data : AT(__erodata) ALIGN(4) + .data : ALIGN(4) { . = ALIGN(4); __sdata = .; *(.data .data.*); . = ALIGN(4); /* 4-byte align the end (VMA) of this section */ - __edata = .; - } > RAM + } > RAM AT>FLASH + . = ALIGN(4); /* Ensure __edata is aligned if something unaligned is inserted after .data */ + __edata = .; /* LMA of .data */ __sidata = LOADADDR(.data); /* ### .bss */ + . = ALIGN(4); + __sbss = .; /* Define outside of section to include INSERT BEFORE/AFTER symbols */ .bss (NOLOAD) : ALIGN(4) { - . = ALIGN(4); - __sbss = .; *(.bss .bss.*); + *(COMMON); /* Uninitialized C statics */ . = ALIGN(4); /* 4-byte align the end (VMA) of this section */ - __ebss = .; } > RAM + . = ALIGN(4); /* Ensure __ebss is aligned if something unaligned is inserted after .bss */ + __ebss = .; /* ### .uninit */ .uninit (NOLOAD) : ALIGN(4) diff --git a/cortex-m-rt/macros/src/lib.rs b/cortex-m-rt/macros/src/lib.rs index 3c532c0..7e54a5c 100644 --- a/cortex-m-rt/macros/src/lib.rs +++ b/cortex-m-rt/macros/src/lib.rs @@ -113,6 +113,14 @@ pub fn entry(args: TokenStream, input: TokenStream) -> TokenStream { .into() } +#[derive(Debug, PartialEq)] +enum Exception { + DefaultHandler, + HardFault, + NonMaskableInt, + Other, +} + #[proc_macro_attribute] pub fn exception(args: TokenStream, input: TokenStream) -> TokenStream { let mut f = parse_macro_input!(input as ItemFn); @@ -130,20 +138,15 @@ pub fn exception(args: TokenStream, input: TokenStream) -> TokenStream { let fspan = f.span(); let ident = f.sig.ident.clone(); - enum Exception { - DefaultHandler, - HardFault, - Other, - } - let ident_s = ident.to_string(); let exn = match &*ident_s { "DefaultHandler" => Exception::DefaultHandler, "HardFault" => Exception::HardFault, + "NonMaskableInt" => Exception::NonMaskableInt, // NOTE that at this point we don't check if the exception is available on the target (e.g. // MemoryManagement is not available on Cortex-M0) - "NonMaskableInt" | "MemoryManagement" | "BusFault" | "UsageFault" | "SecureFault" - | "SVCall" | "DebugMonitor" | "PendSV" | "SysTick" => Exception::Other, + "MemoryManagement" | "BusFault" | "UsageFault" | "SecureFault" | "SVCall" + | "DebugMonitor" | "PendSV" | "SysTick" => Exception::Other, _ => { return parse::Error::new(ident.span(), "This is not a valid exception name") .to_compile_error() @@ -151,7 +154,22 @@ pub fn exception(args: TokenStream, input: TokenStream) -> TokenStream { } }; - // XXX should we blacklist other attributes? + if f.sig.unsafety.is_none() { + match exn { + Exception::DefaultHandler | Exception::HardFault | Exception::NonMaskableInt => { + // These are unsafe to define. + let name = if exn == Exception::DefaultHandler { + format!("`DefaultHandler`") + } else { + format!("`{:?}` handler", exn) + }; + return parse::Error::new(ident.span(), format_args!("defining a {} is unsafe and requires an `unsafe fn` (see the cortex-m-rt docs)", name)) + .to_compile_error() + .into(); + } + Exception::Other => {} + } + } match exn { Exception::DefaultHandler => { @@ -174,7 +192,7 @@ pub fn exception(args: TokenStream, input: TokenStream) -> TokenStream { if !valid_signature { return parse::Error::new( fspan, - "`DefaultHandler` must have signature `[unsafe] fn(i16) [-> !]`", + "`DefaultHandler` must have signature `unsafe fn(i16) [-> !]`", ) .to_compile_error() .into(); @@ -231,7 +249,7 @@ pub fn exception(args: TokenStream, input: TokenStream) -> TokenStream { if !valid_signature { return parse::Error::new( fspan, - "`HardFault` handler must have signature `[unsafe] fn(&ExceptionFrame) -> !`", + "`HardFault` handler must have signature `unsafe fn(&ExceptionFrame) -> !`", ) .to_compile_error() .into(); @@ -257,7 +275,7 @@ pub fn exception(args: TokenStream, input: TokenStream) -> TokenStream { ) .into() } - Exception::Other => { + Exception::NonMaskableInt | Exception::Other => { let valid_signature = f.sig.constness.is_none() && f.vis == Visibility::Inherited && f.sig.abi.is_none() diff --git a/cortex-m-rt/src/lib.rs b/cortex-m-rt/src/lib.rs index bab2844..524b161 100644 --- a/cortex-m-rt/src/lib.rs +++ b/cortex-m-rt/src/lib.rs @@ -199,15 +199,14 @@ //! won't find it. //! //! - `DefaultHandler`. This is the default handler. If not overridden using `#[exception] fn -//! DefaultHandler(..` this will cause a panic with the message "DefaultHandler #`i`", where `i` is -//! the number of the interrupt handler. +//! 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 a panic with message "HardFault". +//! `#[exception] fn HardFault(..` it will default to an infinite loop. //! //! - `__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 @@ -387,6 +386,41 @@ //! undefined behavior. At some point in the future we may add an attribute to safely place static //! variables in this section. //! +//! ## Extra Sections +//! +//! Some microcontrollers provide additional memory regions beyond RAM and FLASH. +//! For example, some STM32 devices provide "CCM" or core-coupled RAM that is +//! only accessible from the core. In order to access these using +//! [`link_section`] attributes from your code, you need to modify `memory.x` +//! to declare the additional sections: +//! +//! [`link_section`]: https://doc.rust-lang.org/reference/abi.html#the-link_section-attribute +//! +//! ```text +//! MEMORY +//! { +//! FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 1024K +//! RAM (rw) : ORIGIN = 0x20000000, LENGTH = 128K +//! CCMRAM (rw) : ORIGIN = 0x10000000, LENGTH = 64K +//! } +//! +//! SECTIONS +//! { +//! .ccmram (NOLOAD) : ALIGN(4) +//! { +//! *(.ccmram .ccmram.*); +//! . = ALIGN(4); +//! } > CCMRAM +//! } INSERT AFTER .bss; +//! ``` +//! +//! You can then use something like this to place a variable into this specific section of memory: +//! +//! ```no_run,edition2018 +//! #[link_section=".ccmram.BUFFERS"] +//! static mut BUF: [u8; 1024] = [0u8; 1024]; +//! ``` +//! //! [attr-entry]: attr.entry.html //! [attr-exception]: attr.exception.html //! [attr-pre_init]: attr.pre_init.html @@ -407,6 +441,7 @@ extern crate cortex_m_rt_macros as macros; extern crate r0; use core::fmt; +use core::sync::atomic::{self, Ordering}; /// Attribute to declare an interrupt (AKA device-specific exception) handler /// @@ -577,13 +612,13 @@ pub use macros::entry; /// /// # Usage /// -/// `#[exception] 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. +/// `#[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. /// -/// `#[exception] 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 -/// `[unsafe] fn(irqn: i16) [-> !]`. `irqn` is the IRQ number (See CMSIS); `irqn` will be a negative +/// `#[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 +/// `unsafe fn(irqn: i16) [-> !]`. `irqn` is the IRQ number (See CMSIS); `irqn` will be a negative /// 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). /// @@ -602,23 +637,25 @@ pub use macros::entry; /// the attribute will help by making a transformation to the source code: for this reason a /// variable like `static mut FOO: u32` will become `let FOO: &mut u32;`. /// -/// # Examples +/// # Safety /// -/// - Setting the `HardFault` handler +/// It is not generally safe to register handlers for non-maskable interrupts. On Cortex-M, +/// `HardFault` is non-maskable (at least in general), and there is an explicitly non-maskable +/// interrupt `NonMaskableInt`. /// -/// ``` -/// # extern crate cortex_m_rt; -/// # extern crate cortex_m_rt_macros; -/// use cortex_m_rt::{ExceptionFrame, exception}; +/// The reason for that is that non-maskable interrupts will preempt any currently running function, +/// even if that function executes within a critical section. Thus, if it was safe to define NMI +/// handlers, critical sections wouldn't work safely anymore. /// -/// #[exception] -/// fn HardFault(ef: &ExceptionFrame) -> ! { -/// // prints the exception frame as a panic message -/// panic!("{:#?}", ef); -/// } +/// This also means that defining a `DefaultHandler` must be unsafe, as that will catch +/// `NonMaskableInt` and `HardFault` if no handlers for those are defined. /// -/// # fn main() {} -/// ``` +/// The safety requirements on those handlers is as follows: The handler must not access any data +/// that is protected via a critical section and shared with other interrupts that may be preempted +/// by the NMI while holding the critical section. As long as this requirement is fulfilled, it is +/// safe to handle NMIs. +/// +/// # Examples /// /// - Setting the default handler /// @@ -626,7 +663,7 @@ pub use macros::entry; /// use cortex_m_rt::exception; /// /// #[exception] -/// fn DefaultHandler(irqn: i16) { +/// unsafe fn DefaultHandler(irqn: i16) { /// println!("IRQn = {}", irqn); /// } /// @@ -955,17 +992,21 @@ pub unsafe extern "C" fn Reset() -> ! { #[link_section = ".HardFault.default"] #[no_mangle] pub unsafe extern "C" fn HardFault_(ef: &ExceptionFrame) -> ! { - panic!("HardFault"); + loop { + // add some side effect to prevent this from turning into a UDF instruction + // see rust-lang/rust#28728 for details + atomic::compiler_fence(Ordering::SeqCst); + } } #[doc(hidden)] #[no_mangle] pub unsafe extern "C" fn DefaultHandler_() -> ! { - const SCB_ICSR: *const u32 = 0xE000_ED04 as *const u32; - - let irqn = core::ptr::read(SCB_ICSR) as u8 as i16 - 16; - - panic!("DefaultHandler #{}", irqn); + loop { + // add some side effect to prevent this from turning into a UDF instruction + // see rust-lang/rust#28728 for details + atomic::compiler_fence(Ordering::SeqCst); + } } #[doc(hidden)] diff --git a/cortex-m-rt/tests/compile-fail/default-handler-bad-signature-1.rs b/cortex-m-rt/tests/compile-fail/default-handler-bad-signature-1.rs index 5436115..b590883 100644 --- a/cortex-m-rt/tests/compile-fail/default-handler-bad-signature-1.rs +++ b/cortex-m-rt/tests/compile-fail/default-handler-bad-signature-1.rs @@ -12,5 +12,5 @@ fn foo() -> ! { } #[exception] -fn DefaultHandler(_irqn: i16, undef: u32) {} -//~^ ERROR `DefaultHandler` must have signature `[unsafe] fn(i16) [-> !]` +unsafe fn DefaultHandler(_irqn: i16, undef: u32) {} +//~^ ERROR `DefaultHandler` must have signature `unsafe fn(i16) [-> !]` diff --git a/cortex-m-rt/tests/compile-fail/default-handler-bad-signature-2.rs b/cortex-m-rt/tests/compile-fail/default-handler-bad-signature-2.rs index 1cca10c..0dadd6a 100644 --- a/cortex-m-rt/tests/compile-fail/default-handler-bad-signature-2.rs +++ b/cortex-m-rt/tests/compile-fail/default-handler-bad-signature-2.rs @@ -12,7 +12,7 @@ fn foo() -> ! { } #[exception] -fn DefaultHandler(_irqn: i16) -> u32 { - //~^ ERROR `DefaultHandler` must have signature `[unsafe] fn(i16) [-> !]` +unsafe fn DefaultHandler(_irqn: i16) -> u32 { + //~^ ERROR `DefaultHandler` must have signature `unsafe fn(i16) [-> !]` 0 } diff --git a/cortex-m-rt/tests/compile-fail/default-handler-hidden.rs b/cortex-m-rt/tests/compile-fail/default-handler-hidden.rs index e57cb31..c658e2b 100644 --- a/cortex-m-rt/tests/compile-fail/default-handler-hidden.rs +++ b/cortex-m-rt/tests/compile-fail/default-handler-hidden.rs @@ -18,5 +18,5 @@ mod hidden { use cortex_m_rt::exception; #[exception] - fn DefaultHandler(_irqn: i16) {} + unsafe fn DefaultHandler(_irqn: i16) {} } diff --git a/cortex-m-rt/tests/compile-fail/default-handler-twice.rs b/cortex-m-rt/tests/compile-fail/default-handler-twice.rs index ad1c3f9..bbf2edd 100644 --- a/cortex-m-rt/tests/compile-fail/default-handler-twice.rs +++ b/cortex-m-rt/tests/compile-fail/default-handler-twice.rs @@ -12,11 +12,11 @@ fn foo() -> ! { } #[exception] -fn DefaultHandler(_irqn: i16) {} +unsafe fn DefaultHandler(_irqn: i16) {} pub mod reachable { use cortex_m_rt::exception; #[exception] //~ ERROR symbol `DefaultHandler` is already defined - fn DefaultHandler(_irqn: i16) {} + unsafe fn DefaultHandler(_irqn: i16) {} } diff --git a/cortex-m-rt/tests/compile-fail/exception-nmi-unsafe.rs b/cortex-m-rt/tests/compile-fail/exception-nmi-unsafe.rs new file mode 100644 index 0000000..f5de2f8 --- /dev/null +++ b/cortex-m-rt/tests/compile-fail/exception-nmi-unsafe.rs @@ -0,0 +1,24 @@ +#![no_main] +#![no_std] + +extern crate cortex_m_rt; +extern crate panic_halt; + +use cortex_m_rt::{entry, exception}; + +#[entry] +fn foo() -> ! { + loop {} +} + +#[exception] +fn DefaultHandler(_irq: i16) {} +//~^ ERROR defining a `DefaultHandler` is unsafe and requires an `unsafe fn` + +#[exception] +fn HardFault() {} +//~^ ERROR defining a `HardFault` handler is unsafe and requires an `unsafe fn` + +#[exception] +fn NonMaskableInt() {} +//~^ ERROR defining a `NonMaskableInt` handler is unsafe and requires an `unsafe fn` diff --git a/cortex-m-rt/tests/compile-fail/hard-fault-bad-signature-1.rs b/cortex-m-rt/tests/compile-fail/hard-fault-bad-signature-1.rs index d3b4392..11b53dc 100644 --- a/cortex-m-rt/tests/compile-fail/hard-fault-bad-signature-1.rs +++ b/cortex-m-rt/tests/compile-fail/hard-fault-bad-signature-1.rs @@ -12,7 +12,7 @@ fn foo() -> ! { } #[exception] -fn HardFault(_ef: &ExceptionFrame, undef: u32) -> ! { - //~^ ERROR `HardFault` handler must have signature `[unsafe] fn(&ExceptionFrame) -> !` +unsafe fn HardFault(_ef: &ExceptionFrame, undef: u32) -> ! { + //~^ ERROR `HardFault` handler must have signature `unsafe fn(&ExceptionFrame) -> !` loop {} } diff --git a/cortex-m-rt/tests/compile-fail/hard-fault-twice.rs b/cortex-m-rt/tests/compile-fail/hard-fault-twice.rs index 030b54c..03b79a5 100644 --- a/cortex-m-rt/tests/compile-fail/hard-fault-twice.rs +++ b/cortex-m-rt/tests/compile-fail/hard-fault-twice.rs @@ -12,7 +12,7 @@ fn foo() -> ! { } #[exception] -fn HardFault(_ef: &ExceptionFrame) -> ! { +unsafe fn HardFault(_ef: &ExceptionFrame) -> ! { loop {} } @@ -20,7 +20,7 @@ pub mod reachable { use cortex_m_rt::{exception, ExceptionFrame}; #[exception] //~ ERROR symbol `HardFault` is already defined - fn HardFault(_ef: &ExceptionFrame) -> ! { + unsafe fn HardFault(_ef: &ExceptionFrame) -> ! { loop {} } } diff --git a/cortex-m-rt/tests/compile-fail/unsafe-init-static.rs b/cortex-m-rt/tests/compile-fail/unsafe-init-static.rs index c040173..23105f1 100644 --- a/cortex-m-rt/tests/compile-fail/unsafe-init-static.rs +++ b/cortex-m-rt/tests/compile-fail/unsafe-init-static.rs @@ -29,12 +29,12 @@ fn SVCall() { } #[exception] -fn DefaultHandler(_irq: i16) { +unsafe fn DefaultHandler(_irq: i16) { static mut X: u32 = init(); //~ ERROR requires unsafe } #[exception] -fn HardFault(_frame: &cortex_m_rt::ExceptionFrame) -> ! { +unsafe fn HardFault(_frame: &cortex_m_rt::ExceptionFrame) -> ! { static mut X: u32 = init(); //~ ERROR requires unsafe loop {} } |