From 689259bfb370ee769a14c2169d79003574986836 Mon Sep 17 00:00:00 2001 From: Adam Greig Date: Sat, 29 Jan 2022 17:55:08 +0000 Subject: [PATCH 01/12] Exclude c-m-rt from cron test of cortex-m, fixes #417 --- .github/workflows/cron.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/cron.yml b/.github/workflows/cron.yml index d765dbab..24b547d6 100644 --- a/.github/workflows/cron.yml +++ b/.github/workflows/cron.yml @@ -16,7 +16,7 @@ jobs: toolchain: stable override: true - name: Run tests - run: cargo test --all + run: cargo test --all --exclude cortex-m-rt - uses: imjohnbo/issue-bot@v2 if: failure() with: From 9e8dd294b04510d727d50039a7f84292789aed0e Mon Sep 17 00:00:00 2001 From: Adam Greig Date: Thu, 3 Feb 2022 20:07:43 +0000 Subject: [PATCH 02/12] Allow #[naked] attribute on interrupt handlers and pre_init --- cortex-m-rt/macros/src/lib.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/cortex-m-rt/macros/src/lib.rs b/cortex-m-rt/macros/src/lib.rs index fbcf4fad..0641c736 100644 --- a/cortex-m-rt/macros/src/lib.rs +++ b/cortex-m-rt/macros/src/lib.rs @@ -612,6 +612,7 @@ fn check_attr_whitelist(attrs: &[Attribute], caller: WhiteListCaller) -> Result< "deny", "forbid", "cold", + "naked", ]; 'o: for attr in attrs { From 894f2aabdbd65f85eecf25debc2326f0387863c7 Mon Sep 17 00:00:00 2001 From: Adam Greig Date: Mon, 21 Feb 2022 19:57:18 +0000 Subject: [PATCH 03/12] Remove outlined asm, replace with stable inline asm. --- .github/bors.toml | 2 +- .github/workflows/ci.yml | 2 +- CHANGELOG.md | 4 + Cargo.toml | 1 - README.md | 2 +- asm-toolchain | 1 - asm/inline.rs | 448 ---------------------------- asm/lib.rs | 143 --------- bin/thumbv6m-none-eabi-lto.a | Bin 11196 -> 0 bytes bin/thumbv6m-none-eabi.a | Bin 14576 -> 0 bytes bin/thumbv7em-none-eabi-lto.a | Bin 15280 -> 0 bytes bin/thumbv7em-none-eabi.a | Bin 19336 -> 0 bytes bin/thumbv7em-none-eabihf-lto.a | Bin 16104 -> 0 bytes bin/thumbv7em-none-eabihf.a | Bin 20480 -> 0 bytes bin/thumbv7m-none-eabi-lto.a | Bin 14244 -> 0 bytes bin/thumbv7m-none-eabi.a | Bin 18068 -> 0 bytes bin/thumbv8m.base-none-eabi-lto.a | Bin 14280 -> 0 bytes bin/thumbv8m.base-none-eabi.a | Bin 18680 -> 0 bytes bin/thumbv8m.main-none-eabi-lto.a | Bin 18672 -> 0 bytes bin/thumbv8m.main-none-eabi.a | Bin 24408 -> 0 bytes bin/thumbv8m.main-none-eabihf-lto.a | Bin 19508 -> 0 bytes bin/thumbv8m.main-none-eabihf.a | Bin 25524 -> 0 bytes build.rs | 24 +- cortex-m-semihosting/CHANGELOG.md | 2 + cortex-m-semihosting/README.md | 2 +- cortex-m-semihosting/bin | 1 - cortex-m-semihosting/build.rs | 16 +- cortex-m-semihosting/src/lib.rs | 18 +- panic-semihosting/CHANGELOG.md | 2 + panic-semihosting/Cargo.toml | 2 +- panic-semihosting/README.md | 2 +- panic-semihosting/src/lib.rs | 8 - src/asm.rs | 139 +++++++-- src/call_asm.rs | 24 -- src/interrupt.rs | 19 +- src/lib.rs | 40 +-- src/peripheral/mod.rs | 2 + src/register/apsr.rs | 9 +- src/register/basepri.rs | 24 +- src/register/basepri_max.rs | 23 +- src/register/control.rs | 23 +- src/register/faultmask.rs | 7 +- src/register/fpscr.rs | 7 +- src/register/lr.rs | 15 +- src/register/mod.rs | 5 - src/register/msp.rs | 21 +- src/register/msplim.rs | 8 +- src/register/pc.rs | 15 +- src/register/primask.rs | 7 +- src/register/psp.rs | 13 +- src/register/psplim.rs | 8 +- xtask/src/lib.rs | 195 +----------- xtask/src/main.rs | 6 +- xtask/tests/ci.rs | 16 +- 54 files changed, 301 insertions(+), 1005 deletions(-) delete mode 100644 asm-toolchain delete mode 100644 asm/inline.rs delete mode 100644 asm/lib.rs delete mode 100644 bin/thumbv6m-none-eabi-lto.a delete mode 100644 bin/thumbv6m-none-eabi.a delete mode 100644 bin/thumbv7em-none-eabi-lto.a delete mode 100644 bin/thumbv7em-none-eabi.a delete mode 100644 bin/thumbv7em-none-eabihf-lto.a delete mode 100644 bin/thumbv7em-none-eabihf.a delete mode 100644 bin/thumbv7m-none-eabi-lto.a delete mode 100644 bin/thumbv7m-none-eabi.a delete mode 100644 bin/thumbv8m.base-none-eabi-lto.a delete mode 100644 bin/thumbv8m.base-none-eabi.a delete mode 100644 bin/thumbv8m.main-none-eabi-lto.a delete mode 100644 bin/thumbv8m.main-none-eabi.a delete mode 100644 bin/thumbv8m.main-none-eabihf-lto.a delete mode 100644 bin/thumbv8m.main-none-eabihf.a delete mode 120000 cortex-m-semihosting/bin delete mode 100644 src/call_asm.rs diff --git a/.github/bors.toml b/.github/bors.toml index 4402e952..c12731ab 100644 --- a/.github/bors.toml +++ b/.github/bors.toml @@ -3,7 +3,7 @@ delete_merged_branches = true required_approvals = 1 status = [ "ci-linux (stable)", - "ci-linux (1.42.0)", + "ci-linux (1.59.0)", "rt-ci-linux (stable)", "rt-ci-linux (1.42.0)", "rt-ci-other-os (macOS-latest)", diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 8caebd00..701e46a8 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -16,7 +16,7 @@ jobs: include: # Test MSRV - - rust: 1.42.0 + - rust: 1.59.0 # Test nightly but don't fail - rust: nightly diff --git a/CHANGELOG.md b/CHANGELOG.md index 421dce79..23496078 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -21,8 +21,12 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ### Fixed - Fixed `singleton!()` statics sometimes ending up in `.data` instead of `.bss` (#364, #380). +### Changed +- Inline assembly is now always used, requiring Rust 1.59. + ### Removed - removed all peripherals `ptr()` functions in favor of the associated constant `PTR` (#385). +- removed `inline-asm` feature which is now always enabled ## [v0.7.4] - 2021-12-31 diff --git a/Cargo.toml b/Cargo.toml index 8527a89d..ebbfdfee 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -29,7 +29,6 @@ optional = true [features] cm7 = [] cm7-r0p1 = ["cm7"] -inline-asm = [] linker-plugin-lto = [] std = [] diff --git a/README.md b/README.md index df9fd52f..a0457651 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@ This project is developed and maintained by the [Cortex-M team][team]. ## Minimum Supported Rust Version (MSRV) -This crate is guaranteed to compile on stable Rust 1.42 and up. It might compile with older versions but that may change in any new patch release. +This crate is guaranteed to compile on stable Rust 1.59 and up. It might compile with older versions but that may change in any new patch release. ## License diff --git a/asm-toolchain b/asm-toolchain deleted file mode 100644 index cc5dbb24..00000000 --- a/asm-toolchain +++ /dev/null @@ -1 +0,0 @@ -nightly-2021-12-16 diff --git a/asm/inline.rs b/asm/inline.rs deleted file mode 100644 index bbc04d2b..00000000 --- a/asm/inline.rs +++ /dev/null @@ -1,448 +0,0 @@ -//! Inline assembly implementing the routines exposed in `cortex_m::asm`. -//! -//! If the `inline-asm` feature is enabled, these functions will be directly called by the -//! `cortex-m` wrappers. Otherwise, `cortex-m` links against them via prebuilt archives. -//! -//! All of these functions should be blanket-`unsafe`. `cortex-m` provides safe wrappers where -//! applicable. - -use core::arch::asm; -use core::sync::atomic::{compiler_fence, Ordering}; - -#[inline(always)] -pub unsafe fn __bkpt() { - asm!("bkpt", options(nomem, nostack, preserves_flags)); -} - -#[inline(always)] -pub unsafe fn __control_r() -> u32 { - let r; - asm!("mrs {}, CONTROL", out(reg) r, options(nomem, nostack, preserves_flags)); - r -} - -#[inline(always)] -pub unsafe fn __control_w(w: u32) { - // ISB is required after writing to CONTROL, - // per ARM architectural requirements (see Application Note 321). - asm!( - "msr CONTROL, {}", - "isb", - in(reg) w, - options(nomem, nostack, preserves_flags), - ); - - // Ensure memory accesses are not reordered around the CONTROL update. - compiler_fence(Ordering::SeqCst); -} - -#[inline(always)] -pub unsafe fn __cpsid() { - asm!("cpsid i", options(nomem, nostack, preserves_flags)); - - // Ensure no subsequent memory accesses are reordered to before interrupts are disabled. - compiler_fence(Ordering::SeqCst); -} - -#[inline(always)] -pub unsafe fn __cpsie() { - // Ensure no preceeding memory accesses are reordered to after interrupts are enabled. - compiler_fence(Ordering::SeqCst); - - asm!("cpsie i", options(nomem, nostack, preserves_flags)); -} - -#[inline(always)] -pub unsafe fn __delay(cyc: u32) { - // The loop will normally take 3 to 4 CPU cycles per iteration, but superscalar cores - // (eg. Cortex-M7) can potentially do it in 2, so we use that as the lower bound, since delaying - // for more cycles is okay. - // Add 1 to prevent an integer underflow which would cause a long freeze - let real_cyc = 1 + cyc / 2; - asm!( - // Use local labels to avoid R_ARM_THM_JUMP8 relocations which fail on thumbv6m. - "1:", - "subs {}, #1", - "bne 1b", - inout(reg) real_cyc => _, - options(nomem, nostack), - ); -} - -#[inline(always)] -pub unsafe fn __dmb() { - compiler_fence(Ordering::SeqCst); - asm!("dmb", options(nomem, nostack, preserves_flags)); - compiler_fence(Ordering::SeqCst); -} - -#[inline(always)] -pub unsafe fn __dsb() { - compiler_fence(Ordering::SeqCst); - asm!("dsb", options(nomem, nostack, preserves_flags)); - compiler_fence(Ordering::SeqCst); -} - -#[inline(always)] -pub unsafe fn __isb() { - compiler_fence(Ordering::SeqCst); - asm!("isb", options(nomem, nostack, preserves_flags)); - compiler_fence(Ordering::SeqCst); -} - -#[inline(always)] -pub unsafe fn __msp_r() -> u32 { - let r; - asm!("mrs {}, MSP", out(reg) r, options(nomem, nostack, preserves_flags)); - r -} - -#[inline(always)] -pub unsafe fn __msp_w(val: u32) { - // Technically is writing to the stack pointer "not pushing any data to the stack"? - // In any event, if we don't set `nostack` here, this method is useless as the new - // stack value is immediately mutated by returning. Really this is just not a good - // method and its higher-level use is marked as deprecated in cortex-m. - asm!("msr MSP, {}", in(reg) val, options(nomem, nostack, preserves_flags)); -} - -// NOTE: No FFI shim, this requires inline asm. -#[inline(always)] -pub unsafe fn __apsr_r() -> u32 { - let r; - asm!("mrs {}, APSR", out(reg) r, options(nomem, nostack, preserves_flags)); - r -} - -#[inline(always)] -pub unsafe fn __nop() { - // NOTE: This is a `pure` asm block, but applying that option allows the compiler to eliminate - // the nop entirely (or to collapse multiple subsequent ones). Since the user probably wants N - // nops when they call `nop` N times, let's not add that option. - asm!("nop", options(nomem, nostack, preserves_flags)); -} - -// NOTE: No FFI shim, this requires inline asm. -#[inline(always)] -pub unsafe fn __pc_r() -> u32 { - let r; - asm!("mov {}, pc", out(reg) r, options(nomem, nostack, preserves_flags)); - r -} - -// NOTE: No FFI shim, this requires inline asm. -#[inline(always)] -pub unsafe fn __pc_w(val: u32) { - asm!("mov pc, {}", in(reg) val, options(nomem, nostack, preserves_flags)); -} - -// NOTE: No FFI shim, this requires inline asm. -#[inline(always)] -pub unsafe fn __lr_r() -> u32 { - let r; - asm!("mov {}, lr", out(reg) r, options(nomem, nostack, preserves_flags)); - r -} - -// NOTE: No FFI shim, this requires inline asm. -#[inline(always)] -pub unsafe fn __lr_w(val: u32) { - asm!("mov lr, {}", in(reg) val, options(nomem, nostack, preserves_flags)); -} - -#[inline(always)] -pub unsafe fn __primask_r() -> u32 { - let r; - asm!("mrs {}, PRIMASK", out(reg) r, options(nomem, nostack, preserves_flags)); - r -} - -#[inline(always)] -pub unsafe fn __psp_r() -> u32 { - let r; - asm!("mrs {}, PSP", out(reg) r, options(nomem, nostack, preserves_flags)); - r -} - -#[inline(always)] -pub unsafe fn __psp_w(val: u32) { - // See comment on __msp_w. Unlike MSP, there are legitimate use-cases for modifying PSP - // if MSP is currently being used as the stack pointer. - asm!("msr PSP, {}", in(reg) val, options(nomem, nostack, preserves_flags)); -} - -#[inline(always)] -pub unsafe fn __sev() { - asm!("sev", options(nomem, nostack, preserves_flags)); -} - -#[inline(always)] -pub unsafe fn __udf() -> ! { - asm!("udf #0", options(noreturn, nomem, nostack, preserves_flags)); -} - -#[inline(always)] -pub unsafe fn __wfe() { - asm!("wfe", options(nomem, nostack, preserves_flags)); -} - -#[inline(always)] -pub unsafe fn __wfi() { - asm!("wfi", options(nomem, nostack, preserves_flags)); -} - -/// Semihosting syscall. -#[inline(always)] -pub unsafe fn __sh_syscall(mut nr: u32, arg: u32) -> u32 { - asm!("bkpt #0xab", inout("r0") nr, in("r1") arg, options(nomem, nostack, preserves_flags)); - nr -} - -/// Set CONTROL.SPSEL to 0, write `msp` to MSP, branch to `rv`. -#[inline(always)] -pub unsafe fn __bootstrap(msp: u32, rv: u32) -> ! { - asm!( - "mrs {tmp}, CONTROL", - "bics {tmp}, {spsel}", - "msr CONTROL, {tmp}", - "isb", - "msr MSP, {msp}", - "bx {rv}", - // `out(reg) _` is not permitted in a `noreturn` asm! call, - // so instead use `in(reg) 0` and don't restore it afterwards. - tmp = in(reg) 0, - spsel = in(reg) 2, - msp = in(reg) msp, - rv = in(reg) rv, - options(noreturn, nomem, nostack), - ); -} - -// v7m *AND* v8m.main, but *NOT* v8m.base -#[cfg(any(armv7m, armv8m_main))] -pub use self::v7m::*; -#[cfg(any(armv7m, armv8m_main))] -mod v7m { - use core::arch::asm; - use core::sync::atomic::{compiler_fence, Ordering}; - - #[inline(always)] - pub unsafe fn __basepri_max(val: u8) { - asm!("msr BASEPRI_MAX, {}", in(reg) val, options(nomem, nostack, preserves_flags)); - } - - #[inline(always)] - pub unsafe fn __basepri_r() -> u8 { - let r; - asm!("mrs {}, BASEPRI", out(reg) r, options(nomem, nostack, preserves_flags)); - r - } - - #[inline(always)] - pub unsafe fn __basepri_w(val: u8) { - asm!("msr BASEPRI, {}", in(reg) val, options(nomem, nostack, preserves_flags)); - } - - #[inline(always)] - pub unsafe fn __faultmask_r() -> u32 { - let r; - asm!("mrs {}, FAULTMASK", out(reg) r, options(nomem, nostack, preserves_flags)); - r - } - - #[inline(always)] - pub unsafe fn __enable_icache() { - asm!( - "ldr {0}, =0xE000ED14", // CCR - "mrs {2}, PRIMASK", // save critical nesting info - "cpsid i", // mask interrupts - "ldr {1}, [{0}]", // read CCR - "orr.w {1}, {1}, #(1 << 17)", // Set bit 17, IC - "str {1}, [{0}]", // write it back - "dsb", // ensure store completes - "isb", // synchronize pipeline - "msr PRIMASK, {2}", // unnest critical section - out(reg) _, - out(reg) _, - out(reg) _, - options(nostack), - ); - compiler_fence(Ordering::SeqCst); - } - - #[inline(always)] - pub unsafe fn __enable_dcache() { - asm!( - "ldr {0}, =0xE000ED14", // CCR - "mrs {2}, PRIMASK", // save critical nesting info - "cpsid i", // mask interrupts - "ldr {1}, [{0}]", // read CCR - "orr.w {1}, {1}, #(1 << 16)", // Set bit 16, DC - "str {1}, [{0}]", // write it back - "dsb", // ensure store completes - "isb", // synchronize pipeline - "msr PRIMASK, {2}", // unnest critical section - out(reg) _, - out(reg) _, - out(reg) _, - options(nostack), - ); - compiler_fence(Ordering::SeqCst); - } -} - -#[cfg(armv7em)] -pub use self::v7em::*; -#[cfg(armv7em)] -mod v7em { - use core::arch::asm; - - #[inline(always)] - pub unsafe fn __basepri_max_cm7_r0p1(val: u8) { - asm!( - "mrs {1}, PRIMASK", - "cpsid i", - "tst.w {1}, #1", - "msr BASEPRI_MAX, {0}", - "it ne", - "bxne lr", - "cpsie i", - in(reg) val, - out(reg) _, - options(nomem, nostack, preserves_flags), - ); - } - - #[inline(always)] - pub unsafe fn __basepri_w_cm7_r0p1(val: u8) { - asm!( - "mrs {1}, PRIMASK", - "cpsid i", - "tst.w {1}, #1", - "msr BASEPRI, {0}", - "it ne", - "bxne lr", - "cpsie i", - in(reg) val, - out(reg) _, - options(nomem, nostack, preserves_flags), - ); - } -} - -#[cfg(armv8m)] -pub use self::v8m::*; -/// Baseline and Mainline. -#[cfg(armv8m)] -mod v8m { - use core::arch::asm; - - #[inline(always)] - pub unsafe fn __tt(mut target: u32) -> u32 { - asm!( - "tt {target}, {target}", - target = inout(reg) target, - options(nomem, nostack, preserves_flags), - ); - target - } - - #[inline(always)] - pub unsafe fn __ttt(mut target: u32) -> u32 { - asm!( - "ttt {target}, {target}", - target = inout(reg) target, - options(nomem, nostack, preserves_flags), - ); - target - } - - #[inline(always)] - pub unsafe fn __tta(mut target: u32) -> u32 { - asm!( - "tta {target}, {target}", - target = inout(reg) target, - options(nomem, nostack, preserves_flags), - ); - target - } - - #[inline(always)] - pub unsafe fn __ttat(mut target: u32) -> u32 { - asm!( - "ttat {target}, {target}", - target = inout(reg) target, - options(nomem, nostack, preserves_flags), - ); - target - } - - #[inline(always)] - pub unsafe fn __msp_ns_r() -> u32 { - let r; - asm!("mrs {}, MSP_NS", out(reg) r, options(nomem, nostack, preserves_flags)); - r - } - - #[inline(always)] - pub unsafe fn __msp_ns_w(val: u32) { - asm!("msr MSP_NS, {}", in(reg) val, options(nomem, nostack, preserves_flags)); - } - - #[inline(always)] - pub unsafe fn __bxns(val: u32) { - asm!("BXNS {}", in(reg) val, options(nomem, nostack, preserves_flags)); - } -} - -#[cfg(armv8m_main)] -pub use self::v8m_main::*; -/// Mainline only. -#[cfg(armv8m_main)] -mod v8m_main { - use core::arch::asm; - - #[inline(always)] - pub unsafe fn __msplim_r() -> u32 { - let r; - asm!("mrs {}, MSPLIM", out(reg) r, options(nomem, nostack, preserves_flags)); - r - } - - #[inline(always)] - pub unsafe fn __msplim_w(val: u32) { - asm!("msr MSPLIM, {}", in(reg) val, options(nomem, nostack, preserves_flags)); - } - - #[inline(always)] - pub unsafe fn __psplim_r() -> u32 { - let r; - asm!("mrs {}, PSPLIM", out(reg) r, options(nomem, nostack, preserves_flags)); - r - } - - #[inline(always)] - pub unsafe fn __psplim_w(val: u32) { - asm!("msr PSPLIM, {}", in(reg) val, options(nomem, nostack, preserves_flags)); - } -} - -#[cfg(has_fpu)] -pub use self::fpu::*; -/// All targets with FPU. -#[cfg(has_fpu)] -mod fpu { - use core::arch::asm; - - #[inline(always)] - pub unsafe fn __fpscr_r() -> u32 { - let r; - asm!("vmrs {}, fpscr", out(reg) r, options(nomem, nostack, preserves_flags)); - r - } - - #[inline(always)] - pub unsafe fn __fpscr_w(val: u32) { - asm!("vmsr fpscr, {}", in(reg) val, options(nomem, nostack)); - } -} diff --git a/asm/lib.rs b/asm/lib.rs deleted file mode 100644 index 48f3dc21..00000000 --- a/asm/lib.rs +++ /dev/null @@ -1,143 +0,0 @@ -//! FFI shim around the inline assembly in `inline.rs`. -//! -//! We use this file to precompile some assembly stubs into the static libraries you can find in -//! `bin`. Apps using the `cortex-m` crate then link against those static libraries and don't need -//! to build this file themselves. -//! -//! Nowadays the assembly stubs are no longer actual assembly files, but actually just this small -//! Rust crate that uses unstable inline assembly, coupled with the `xtask` tool to invoke rustc -//! and build the files. -//! -//! Precompiling this to a static lib allows users to call assembly routines from stable Rust, but -//! also perform [linker plugin LTO] with the precompiled artifacts to completely inline the -//! assembly routines into their code, which brings the "outline assembly" on par with "real" inline -//! assembly. -//! -//! For developers and contributors to `cortex-m`, this setup means that they don't have to install -//! any binutils, assembler, or C compiler to hack on the crate. All they need is to run `cargo -//! xtask assemble` to rebuild the archives from this file. -//! -//! Cool, right? -//! -//! # Rust version management -//! -//! Since inline assembly is still unstable, and we want to ensure that the created blobs are -//! up-to-date in CI, we have to pin the nightly version we use for this. The nightly toolchain is -//! stored in `asm-toolchain`. -//! -//! The `cargo xtask` automation will automatically install the `asm-toolchain` as well as all -//! Cortex-M targets needed to generate the blobs. -//! -//! [linker plugin LTO]: https://doc.rust-lang.org/stable/rustc/linker-plugin-lto.html - -#![feature(asm)] -#![no_std] -#![crate_type = "staticlib"] -#![deny(warnings)] -// Don't warn about feature(asm) being stable on Rust >= 1.59.0 -#![allow(stable_features)] - -mod inline; - -macro_rules! shims { - ( - $( fn $name:ident( $($arg:ident: $argty:ty),* ) $(-> $ret:ty)?; )+ - ) => { - $( - #[no_mangle] - pub unsafe extern "C" fn $name( - $($arg: $argty),* - ) $(-> $ret)? { - crate::inline::$name($($arg),*) - } - )+ - }; -} - -shims! { - fn __bkpt(); - fn __control_r() -> u32; - fn __control_w(w: u32); - fn __cpsid(); - fn __cpsie(); - fn __delay(cyc: u32); - fn __dmb(); - fn __dsb(); - fn __isb(); - fn __msp_r() -> u32; - fn __msp_w(val: u32); - fn __nop(); - fn __primask_r() -> u32; - fn __psp_r() -> u32; - fn __psp_w(val: u32); - fn __sev(); - fn __udf() -> !; - fn __wfe(); - fn __wfi(); - fn __sh_syscall(nr: u32, arg: u32) -> u32; - fn __bootstrap(msp: u32, rv: u32) -> !; -} - -// v7m *AND* v8m.main, but *NOT* v8m.base -#[cfg(any(armv7m, armv8m_main))] -shims! { - fn __basepri_max(val: u8); - fn __basepri_r() -> u8; - fn __basepri_w(val: u8); - fn __faultmask_r() -> u32; - fn __enable_icache(); - fn __enable_dcache(); -} - -#[cfg(armv7em)] -shims! { - fn __basepri_max_cm7_r0p1(val: u8); - fn __basepri_w_cm7_r0p1(val: u8); -} - -// Baseline and Mainline. -#[cfg(armv8m)] -shims! { - fn __tt(target: u32) -> u32; - fn __ttt(target: u32) -> u32; - fn __tta(target: u32) -> u32; - fn __ttat(target: u32) -> u32; - fn __msp_ns_r() -> u32; - fn __msp_ns_w(val: u32); - fn __bxns(val: u32); -} - -// Mainline only. -#[cfg(armv8m_main)] -shims! { - fn __msplim_r() -> u32; - fn __msplim_w(val: u32); - fn __psplim_r() -> u32; - fn __psplim_w(val: u32); -} - -// All targets with FPU. -#[cfg(has_fpu)] -shims! { - fn __fpscr_r() -> u32; - fn __fpscr_w(val: u32); -} - -/// We *must* define a panic handler here, even though nothing here should ever be able to panic. -/// -/// We prove that nothing will ever panic by calling a function that doesn't exist. If the panic -/// handler gets linked in, this causes a linker error. We always build this file with optimizations -/// enabled, but even without them the panic handler should never be linked in. -#[panic_handler] -#[link_section = ".text.asm_panic_handler"] -fn panic(_: &core::panic::PanicInfo) -> ! { - extern "C" { - #[link_name = "cortex-m internal error: panic handler not optimized out, please file an \ - issue at https://github.com/rust-embedded/cortex-m"] - fn __cortex_m_should_not_panic() -> !; - } - - unsafe { - __cortex_m_should_not_panic(); - } -} diff --git a/bin/thumbv6m-none-eabi-lto.a b/bin/thumbv6m-none-eabi-lto.a deleted file mode 100644 index a203d7ae88015d7f659eb1f17053906bff22e8af..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 11196 zcmcgy3v?URnZBdfD6%|O5+{)z*%>(rxJew39@ZmvK(doyAQUB#V5o~Vdc`Jw$dVn$ zVV909+j78V1t&dqx9P48p-W4;h&E+YHWbNrf*ZWlu#|df4r_-bIAEwDSx(x`q5I#F z#;@2L_O#tO(%hNnM*o(J^M`4I-M@n-l=fa z)E72YH`loinCc4Z8|u9UUe;ApP}|h7xuLWy{(ey=LKH&CrDQar*A>T|X+Kes!7-U1 zej~Ea9T`__8FebM-a)qVlux77ha7b^PW^%2M(CwTt3>GH5`@x3S|oyTR>GeQt$oTq zB)L&euvhf~(A z%8p}E=Wb6Wz0TXlWfKh1%iMuvx2U&uBUzTATPOb>(QSW(j;lD`j=Cq2u3s&=hd84S zuY>V+sS(-)1SY=grBEuaC1DRLxM@BTqQi=UEwq7A9z(X%Ta zpFgFa#h}HUDSh4%ofTGXsQD-gP8SP$j%N=JV zW!c*uvh}arf9#$P&7LoJbyV#c`$orIdj~!1@7??MzUN-p`%Inp%e~LEtXHZXKYWsS zE>tyzvQdI;%1XE|a=iH_fAIX-%Z@NUU=TzHm{-j(h6a~>>BFRT2!2#9t8!_`^-r<8udfAxeE<%NVDrN#KIc&pDUK?YHN?t<{_h<(?Y@LzMFok?T|Mvc$@^91Rx_ zJJzKbaYkAWk_UTs?YtVzzzF0%l6#ibOlWi7PvksCVM1JC>3D$Y0NdB-@4zM<0e zkXufdbt$u!1oY+f+EDjXPrbFRSC#K6(dkQ{jB20ll6mMdX#Y4;EU~M*{F(@>Y>TQo z8r7Xlxsx$Eol5&>3g_5Z0wFe7S6Ex)+8hXOE_Bzj_50|ZJNMp0=LedDO>X*tHxR68 zsHb(Ci>#ZOg8G_$)lIdnbiTXD>vrpk%nYq(^tu9_zCc&>wXc;l*YB@yXsN%=-4O5w zTkG9yQ$t;i``&=Z8>p$@*KFDCtz{2-Jy3Yrpx5qhY_1950tokc8_R-CzPhGB(*d2m zwq{>_owvSer`OlC8$YxRZoGj#$?;+E=Gvy+{Q2Jf+XI1ZURU!z`p$Y^1HCsnW1rEj z^B8olA}hn{eLkJeXw-WcozH0Y89hF$9$3bl*VNb6)O&$>vyS!piVSYnWnm45q9QkR zcI&+suTSrD>n+}7!)Aj%(15uqA zH&EsC*1Nq`4}IN;2QuP8OvyoXK$+b}XRbErEC7L9XE3@9UQ>~A`vJBVq0Unv7;rFc zOvPIHKvCP&I|;|$_%9M*W!;DP)YKQXE2%4m)Xf? zC)vW0YxjskrwE!1ax{{+(ML%9XoTW;yk9%TF>=Hyj+1ZUUd!=dqV;$%$5K34#TjM$ zn(IVB;YC=QHQ5!8k%rn5xES@NWUZpbJt9OY({+v^RANeX_Q=}f*q)0td z8P4q%Z5U>bC4MNw>`BhSB$^D8_|A58Ld1v}2XU};D&2&RBiR)V%4#Rnh-Av>G{aI6 zlNN6Z>B4BJ9~zH}plOs)9ZC2PkI39y+VceycHU>?4sVlln~_2C3x5;xA60W5kDLsx z?jo{#iF~-gKVsuGDcoi!Z@IRrUQEosCe6VuLlns+PYThMsCkXTzljJ4u zj-lu-#UKs`(2i_`s;XT3{Y{`A2GBQCQe{m^BItt-G}`4hvu>l=>$Vu#?Pz&B@s0I4 z$4AoQ8{(mjae^c0e%XuYln5Pv`pJq3X%*LTW<@q9wza1}OdOP=kybjS)apI!u4=Yj z7dgwO(hyoJlPqm>sw4(k$9?T#3)_tL~hI5wbT3)1q<;nJ-l*VihqVg zJ$oeMDDA$!D>hM9sb{Es!rFCB8t)uib!L5=rHk0K^QQ<6cJ^v+kq_kH`6aQj0XEV- zT>}=lzk_IVj&z46VJnbv0#3I_@dkl$I}m5-7RM6Zb~{N~kjbAEfKXwXfnO3oYLLh8?kU+U{90NT2e1VI zG#9xIdb7s}Cu~z0EI;<|)5_m%xa{nB80{sfdV)eqwA6G^I;KI+?=%gT7G4)^^88Db z(4f59DTQqd;@%W5@yMUjuI>Af&eNcKWYY6C3d47;f5TvClLW=IOr-HJL;Vt^eUHDj zMbbqOXG+)@h6FGq5s%@=7{i~R`(o4LOlPc6xu>1F#+L z1;lbJW3XY;0bh&B?&8?=eMM}r@1JGdQrLI_8xzC~MvKK_wip;UAM*=7QfW8 zC^ipKv$5fIx66LzzcC7UyPp)3gk`pv05DyIy`5G|cwOEOTZhH4>7S$5&48Pr*BNka zyo)>U_o^xzd&#pU??A9GR!0-J#qGDp2z9qzlYbs^4@lNXQ+KcF36;bMO)PZ#B#z>5 zPwKh}#^B{^nFMy02)*7blUG%FAOLN3x4LhDk*@$48IxOYHdSagpYnNQ2aZX2*}`F=WL=*d^%wSfXHzh$meN=Qza|zp_PXO8xSRU8}L(DirbICiMON3I&A|yacl#`ybZXB8(|v&9vz*d$GYur zkv-O&CiHLt9Amo*g@GY?s$VnX(1EFPHMRz*Fa%yG%u}eswNv2izV{k=b3u z>KWE$GFg(cu2t^6liYY!6jS)e6n^APMyxL)^un>VD-R`BIkhV)wJRWL$Q$St$o64K zqHiCHJ~a|leU`@U?GX7@D%wyarPeOymDa=3i1^nP*)7Oj<7cw%Yg_2Cy4W z{OZ_NN5zbXR>!;TpS{=r8`%XkG2`-P*^T}?ZjRrjo8cE+0KXu{kFgr{X4YgdSy_Wi z$E572{bu+PD=UeWi{kerkKfj`KNCM~+W!xJurOBW4OueU+c{3UIEWJ$lD-*wK4Q!Sb2u?tHDQ8e~-;!og|F&#wF)CZ^*BG&0B ze{p}mXBKYwK~0@c0B$%|<>8u+Qbnyv%y2G$Va(=*rYX#DRO<0TIAqfMideJNr8DBN z9^%rz8O;1Mm|d8$g?*a(KFthf^K4<`VMJBO6peHmfokPv*vhET*AUEdZs8IzKxe?bw2Yu4I_W&GjjG57obKwoSzTU64t^ zrzCJv59rvZ+9S@$(Cj^;KTuQ02KUd` zJ-kPpuEN6PhV+=v;&NGyRujWw1zg@fK7+x+`e(nj+J5VdEG6}Ca@(T%H`%_p{@weR z)W4mxFkHlLp_O0BZuu9qTRatDvziS$vq`TrK;qABbeWQ}L!?i~BMalE-BhjJG#|IF z?Tg~p)v+jUrz`%FxGiqCc(}fz-NNYHXt#JOV8)tRtH;PP9+L-BpO(~qMLUDp!gh-& zs3!_$F#Ae&OZ3oR*KVDDXueW|+|B6q&FvPOdlrny|7N#>-UBz-EuaC8MwidSdaQc4 z%TxrZ?v&lK&)~SQ-5M{b92amLyCD|7!EQ+_=d(D&-`w1md6v#e;Cfx>-J)l6hZ35& zQ#qF6aV?ZL#{114-wiwh4a-WA+vhTyOhsPC=e05^9@!gsY;(rvrthS$_@%Gl?X8`0 zh95u=6R1geb+VOQ`Wga9CW5)l+V_7G^NH?N^BeiacwET$jOW6ev=n~}`<@oxyxlwO zXMhI$Sxi=Qkrg=98N61HKIOwhH}Hou@U!T}pB3;Y~wrn`-kUy&A6ZFirh36~jSxq48SBo-Xl&D&!3NsR>9w zoPiy2$cWPqINkUfN;{@a6QNqwJ8X_gGS1l5lg>8gTtdPQVKtbSbKvui(>Vu@kMjte zcl5+??jSsqbJ(dCw$Z6{MGS|C(_P~h*bpZ-%jsFiae{4%Pd@Nz$mOzlR|qGQ=mZV9 zi|2OD%2ysqd<2a%Uc#gGz=_{pX0&+CE{|2`(R;zrxM8OX z@m%^Xa(>T|SGwOQnQ-DQZF7p0}5#y^5$JV*{yLwcLT>FpP^ zu)6@sY`P|`s7U7}6TW(gCEyDmH5tf0<+=V@1yX{D6-nt2D_flCM&T_^QW~RqK*fOOm~kRf#qQ zYJ>;y->t!v+tD?tdg>8Q^rg(=e2kO)L|$S0J5KiTl7q1qIQbK4J+W6g#gCLH(I}@p znLZkw;HckH*T(+HsV-%xKU)%7_FI+ZGj%94x(uNw6mK2*@b=tG*2y;>U>4f8LQ0{vm2;qir1pnFqvp%mz~K*!??r9f{?(S=f=A4t)KQlLMYq6?)!=YS3( zgM?C`cLNR2Unm9ocY%g;2||hK@=ZX1Cb|M;*;xonbQrpXcC@QVQmNsx$W!+SKmG;(+BqZ=k2(c{eY|lL-B(y>Z9hP7v1QHmtnro%C_R{REjv#{~ zAQ6Oc_ywL~%OJoGigCD1Y>WvIKN5IA97voO;b07o?Z7h*u@#d%8Rtyv(? zC3S!QU;kD0S9MiS^)6VND;IX0-*iT_JCTM7GpeHYCVdxCx=HM4s9+Zq6 zIMHyZVYTDM$<_a&&?id>m!*0MO}OgR39I)W5W3V*{0I?!)alFX!eNxXH-Ja&ePgo%<~6aJ{OI}Kr~Kv1_XEgXw6qE zWcbz#5<-{owwbppa0|bJ+fBGEtF8c0bvwz_jo}`uy9W1g-9c8X`a9tDMO@(*nyg8$ zIYbg7l+YJ=yNkC!#Z5c?CI~n^0#J4LlBs(D_fXwKxQB76(6gl2fbZdg?(+au_aYfw zleh6^h5iW;dJVURH*sr%DAZ~-P6MtWJ-r_NwwjtZl9@pU!+t54>sc|^YQ0UP7Bu__ zbQ5N7sKaWQ4qQgswpvyJM@eU_*1a03-_*RH^fJe3!;N4bV#Qjk;c?&(N%vX}{|anD zk3w6l#_7Oiq_3utX;z=(p=A{$qm-5qMxz!q><9f-^1H3Z2Z8@W`iouF0Em*3~ZEy3Qrll#4-MOa3LR^=6G!Z@twem72=ofM;cG;mBF`w6|D;f}|-c zK21$0Gl|R=j;CeQ$FyIt7DbyvOZ(xHWo_ZOTJ{X9mji1>sXmhrK1%~GIGttn&PL75 zKB=N8w5a}+xX;@E=^D>02%wk$gx+>n8y%&*<@C4K^~w zm?$!oXk?qN@idapG8%cRXqraObIrE!35UjFzc26O$mbp!v49Ux6s`u)I6t7FM?yDl z3)cvzld~^GY%UW{re|0ixll;j*ZDo5M^~a|mbI~@1-jX%!rt1#)kNom%ZclX3yQef z1q;SLh3fi2|GeYskandeZ$Ppq*Quu_P^_KrfbR47D~X}djU$D&=)SXVT8_Sq^oHq<>hkdKtdRHR!K zM#?2Mwr{wga+Q&xfr1*(s7|?OHijQJ0j9rSib= zcGW*rQRRx-9aZZ~{S~!|@zu)GaHUjMmksY69@#UjRtyeoA09%TDwoE_2VuQattyuh zLUU-38W0$!6Xgra(y&m?c zJ+w|RiwR~ixj$;2w8-m9WUn9o34(rE1H z*gz5X8T2EOh!%==yx;E6$8<9&t8K!NsdO@$$Ye6_;+XXZuUJT&C2Y z#4s@qBms5K%+d0|P;P9eZe6jE?oae*^7(8co3eAdb*?;Mi%yM7r?TmIG@Xh?=|5TM&!j=OL|S_Pf4@z-U(W-t>Yw41>+>e3LEHiU8YC8QzVrtc zv2#$RcM}_g>?p5;l*K)ygK=(Lgi5o&+zVRvi$z+2v*Alr&|685qpG*01E8_j@aHnO zog0DJcb*4uH@Qfx2h=^fhtA6NbBD${v=w@?do9)D#MS1HHN}PG+uFQ3z>h**wkuF- zC9di~^H;a*Ui@wD?uPu8#BJpjRAMi^8BpE)z^D~b+;TjvQ`T7^SH>cCR!wS|yrDrg zT5W2YHPf1`~Uh2+W)RRU$3sjB&kyeLE-fDw{5KiJlH%RvGB&Ey7jwOxBE_&h+|cX z#*?W`-pL;+@Im5>7rZ)8gfPyNLPk%p zdVLRfTXmuO`lj&JR-IMf7G4~|4;C~kAT2u5_H{L-gH~O*es=g9vkqz>KmD9lQ*EE4 z_Ghyq6RE*VQ}~`)x=CTUq28n#Et=C5Znf%XPKwmmPwLjrcAwNTpRW(#i%q;?*1As= z`}&=Z{)aO^nf}e9|Ng}KI?J|`$IU0TR!f&S(si|^FXGINL-gczH8O$`d{^X$ud8i; zLgaT$Apfn%Z<;`U0B3rPf5QavZ?vos){c|r&dp-?n`>*g`!|R`-}A}2PgP4;b*d4cyt66<6;@rU=#zH^ zD>cRT-Z=8;~zmT|W8JfPA^S-6vljkY5ns zFAVUj0{q$l|LFkFcdKd%tIg_LVENc^Z<~%Dm%)(dOrMVX0FXTQ>gky8PhiWa>bIza zK7I;jq*s4B-Y>lVW~mQF-|;_3@u_O(B*?)LF1)#c-}>H}Z=rRrtjxwlVO&iHl0hNY81h_Y;S z@-Uk`lS!22pc7xxG|v|>lumifJ7)^dvoVxTd3-zNoThWW)XQVp*)IG-!9{|L1v>=s z7_n&~#OD)3TtkGMO%0)vO$*_1VN-}~LMVnKYvCCp)U6bsSjx{8WWLES5nLg-T9D&O z`K5yVWJP|PU{P>LaKGU13;u!NZGv|R9ud4x@R;CZg5MGRuHXxTuL>R){Gs5F1%D>^ z?}EP)2!|P#3eR;5uO{ldQva&(ZxAu*-%;p**jeZU`Dub3g3E|gabiz|-X`Jmg8Kw-CE}qzOoZP3!hb{XMZq5tvHrY6gx-G( zUyt(uylSZ_MAYM}w#Kuhekl>_)J0OiQTVHgSUh$}{T|_OAYvWUpBUlq%ff$+h;{98 zBI^H2@MWogi`cHz&!zr-;lmiK&_aB(B(ipsu~HkQ{wm=Ih*%HD zr2bkW#_OQ)w+Y@&gx-@xtgFvS{oe`xK=2)rPnrxpv zo^Mdq^Cv^Z{OKWL{MQg++)KoGZY5&8wh=KtJBV;PN<`lG5|QTvMCA1lv0bU#iOAPs zBJy*TxLB!U#15q%A);R_Y$uwiv4IE%P0~1(h)!|KA|kYIKSFA3C*nCk2#s*9`-7Bf zw2A0fLNG&w)1`tvMD+7Q!8Jq#TQAs4M87u+ZY81-R|#$-A`eBu9Yi#4P;iupyi^4D z65Ey9FL;26Jl!C8h=|VIB6vFydHWN=!$frQh~QBo^7s`&q)3myK{Qo`uz8|MI=?X0 zyv|RZQW@cw5@EDPc-{X78GqPc#d_p2)*NMpU+rqy~oR9TG_z#H4a|8Dg#MAp{JLZe<^NGl_ z-ZvpXmpt;E5xL$sk!QVMLcX5$9q7NvuOcGP`uza&^)DC?`Fn|oy#0#UfN${BL!Oos zTa?oKEb?+EdF117h{(gQiRk|f_+r1KMD%wf5&hgnME~v}qF;{^(Vtg|3$cC@(f-CT z5bZvji1zY#nSQP!<+Zg{RzDG%hwD)_mD!IbW2@Lo_qIPH=c6);AZ=4>!zl_9BV9HN_6Ulf)UOS-vVCV}uQkX!M zhu*cF@L+rb3C__Y82d_&xNnHKs1k{0dDpjShNQkl(2Xg5mKI&U zj5}#8Pr4)o4Pg1wlnKy0^>P%Zfx^eT4o*Q=!WVAQBChpbH^TuuW#Kr588@B-38@CrcmTb3}{_-~@ z^xU{tfoEJ3!^FMJQwLIYc;eEp>F;B3?2TI#8Esfh++&WO8+Qj}jEn6=7Zdj@&@*kJ z!1ly#1#jZ=Zxg+7M@2>(7894hfxP{#K*qS{^w7i|4#drP;$n+)I>cR%=AdB!WY zFYY1mjEikj7ZaDhy#4L*#Kqsgx^buBS@6ca9Wpal=+N|cvZLqb`7mURYfd{&+%WXK zao2d_V(WI}{+E+KH`YF;XL-ng%TuN8Nhqvysw4xVur;9@axdAjP2yTcQAq3F@>>rOx1 zSZ|69pbOHb3;%c!|J}GhK`reUIbt{N-B9wz9reUL6S}6qw*=zy-M3bM4+i4?C-fK> z+k-Bqzt;xh?)Aj&fToGdGbQ|YV}0PE>Cp7IGZ2@5RnEAbR6;Rv7o*@J0aL5L3miQ+&oiONxLvqdOk9NV#XaPS8xcL)U60Efm%kZ|4~X3U?sN3qxa|_x zrV@&=83*m{@9mzr_=(~6cLfsZjmzIC#s~eGJo9V|A~){264!iPFg833^Ts{wiOY8Y z>ao9v193Ut#s|c1+*<>2`J0LMDJr2Do0|i1k9y*!MUQqoyMqgNOnWAXds-mwg%X#~ zD~pLcHxT!jC+-r_V_cpwdgHF2Anv=4o||W`bF^QIi^ar!8};5iKjMkIO!R2SKmNsk zx4-;NiJy3GLGyKa%F%P0HVe7!MopFq7g?h~H4J`+Ctnljlv4oAzxC_{-o$?P@f{6ythBz~9lu&bbrww;7l5cP4D1 T>XyTp^amiMpExe+O~v(p7qD$b diff --git a/bin/thumbv7em-none-eabi-lto.a b/bin/thumbv7em-none-eabi-lto.a deleted file mode 100644 index b34ac64f16c45cfe042eeb0e60f53b2942b9bae6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 15280 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 diff --git a/bin/thumbv7em-none-eabihf.a b/bin/thumbv7em-none-eabihf.a deleted file mode 100644 index cf91a7a59012c7d74c13c0c6b75f40928440d285..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 20480 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
c$3D^&q%6Ob2dWPRJ5&w)Ea$pK|SmvW* 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 C*LS@D diff --git a/bin/thumbv8m.base-none-eabi-lto.a b/bin/thumbv8m.base-none-eabi-lto.a deleted file mode 100644 index f62acafd374083db4a588cd102fd56abb083f910..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 14280 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 VA24`r7OS1!38RAF$`CqUMIlKS> diff --git a/bin/thumbv8m.base-none-eabi.a b/bin/thumbv8m.base-none-eabi.a deleted file mode 100644 index c0cc96c4a440876c4b514f593aba2540390bccf2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 18680 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 diff --git a/bin/thumbv8m.main-none-eabi-lto.a b/bin/thumbv8m.main-none-eabi-lto.a deleted file mode 100644 index 1a5151522ce7d8929706dd441bc495c91e2343e5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 18672 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 Xev{s#aheQ9GhOK1v1=uEztR5yXTuH` diff --git a/bin/thumbv8m.main-none-eabi.a b/bin/thumbv8m.main-none-eabi.a deleted file mode 100644 index d017a15b7b61a5cd6b006561d34521470f79040e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 24408 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 diff --git a/bin/thumbv8m.main-none-eabihf.a b/bin/thumbv8m.main-none-eabihf.a deleted file mode 100644 index 223ff1df388e198bef9c760e63a65ede3e27df07..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 25524 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 diff --git a/build.rs b/build.rs index 23ceebad..f81072bd 100644 --- a/build.rs +++ b/build.rs @@ -1,33 +1,13 @@ -use std::path::PathBuf; -use std::{env, fs}; +use std::env; fn main() { let target = env::var("TARGET").unwrap(); let host_triple = env::var("HOST").unwrap(); - let out_dir = PathBuf::from(env::var("OUT_DIR").unwrap()); - let name = env::var("CARGO_PKG_NAME").unwrap(); if host_triple == target { println!("cargo:rustc-cfg=native"); } - if target.starts_with("thumb") { - let suffix = if env::var_os("CARGO_FEATURE_LINKER_PLUGIN_LTO").is_some() { - "-lto" - } else { - "" - }; - - fs::copy( - format!("bin/{}{}.a", target, suffix), - out_dir.join(format!("lib{}.a", name)), - ) - .unwrap(); - - println!("cargo:rustc-link-lib=static={}", name); - println!("cargo:rustc-link-search={}", out_dir.display()); - } - if target.starts_with("thumbv6m-") { println!("cargo:rustc-cfg=cortex_m"); println!("cargo:rustc-cfg=armv6m"); @@ -37,7 +17,7 @@ fn main() { } else if target.starts_with("thumbv7em-") { println!("cargo:rustc-cfg=cortex_m"); println!("cargo:rustc-cfg=armv7m"); - println!("cargo:rustc-cfg=armv7em"); // (not currently used) + println!("cargo:rustc-cfg=armv7em"); } else if target.starts_with("thumbv8m.base") { println!("cargo:rustc-cfg=cortex_m"); println!("cargo:rustc-cfg=armv8m"); diff --git a/cortex-m-semihosting/CHANGELOG.md b/cortex-m-semihosting/CHANGELOG.md index 0a942cfc..38ee835e 100644 --- a/cortex-m-semihosting/CHANGELOG.md +++ b/cortex-m-semihosting/CHANGELOG.md @@ -5,6 +5,8 @@ This project adheres to [Semantic Versioning](http://semver.org/). ## [Unreleased] +- Always use inline-asm, requiring Rust 1.59. + ## [v0.4.1] - 2020-10-20 0.4.1 was yanked because the pre-built binaries contain conflicting symbols diff --git a/cortex-m-semihosting/README.md b/cortex-m-semihosting/README.md index bfbfb44a..6036d4e2 100644 --- a/cortex-m-semihosting/README.md +++ b/cortex-m-semihosting/README.md @@ -11,7 +11,7 @@ This project is developed and maintained by the [Cortex-M team][team]. # Minimum Supported Rust Version (MSRV) -This crate is guaranteed to compile on stable Rust 1.33.0 and up. It *might* +This crate is guaranteed to compile on stable Rust 1.59.0 and up. It *might* compile with older versions but that may change in any new patch release. ## License diff --git a/cortex-m-semihosting/bin b/cortex-m-semihosting/bin deleted file mode 120000 index 19f285ac..00000000 --- a/cortex-m-semihosting/bin +++ /dev/null @@ -1 +0,0 @@ -../bin \ No newline at end of file diff --git a/cortex-m-semihosting/build.rs b/cortex-m-semihosting/build.rs index 315035e9..ed0d0697 100644 --- a/cortex-m-semihosting/build.rs +++ b/cortex-m-semihosting/build.rs @@ -1,23 +1,9 @@ -use std::path::PathBuf; -use std::{env, fs}; +use std::env; fn main() { let target = env::var("TARGET").unwrap(); - let out_dir = PathBuf::from(env::var("OUT_DIR").unwrap()); - let name = env::var("CARGO_PKG_NAME").unwrap(); if target.starts_with("thumbv") { - if env::var_os("CARGO_FEATURE_INLINE_ASM").is_none() { - fs::copy( - format!("bin/{}.a", target), - out_dir.join(format!("lib{}.a", name)), - ) - .unwrap(); - - println!("cargo:rustc-link-lib=static={}", name); - println!("cargo:rustc-link-search={}", out_dir.display()); - } - println!("cargo:rustc-cfg=thumb"); } } diff --git a/cortex-m-semihosting/src/lib.rs b/cortex-m-semihosting/src/lib.rs index 3bc23ea3..4ff975de 100644 --- a/cortex-m-semihosting/src/lib.rs +++ b/cortex-m-semihosting/src/lib.rs @@ -151,14 +151,6 @@ //! //! # Optional features //! -//! ## `inline-asm` -//! -//! When this feature is enabled semihosting is implemented using inline assembly and -//! compiling this crate requires nightly. -//! -//! When this feature is disabled semihosting is implemented using FFI calls into an external -//! assembly file and compiling this crate works on stable and beta. -//! //! ## `jlink-quirks` //! //! When this feature is enabled, return values above `0xfffffff0` from semihosting operation @@ -191,11 +183,6 @@ pub mod export; pub mod hio; pub mod nr; -#[cfg(all(thumb, not(feature = "inline-asm")))] -extern "C" { - fn __sh_syscall(nr: usize, arg: usize) -> usize; -} - /// Performs a semihosting operation, takes a pointer to an argument block #[inline(always)] pub unsafe fn syscall(nr: usize, arg: &T) -> usize { @@ -206,10 +193,7 @@ pub unsafe fn syscall(nr: usize, arg: &T) -> usize { #[inline(always)] pub unsafe fn syscall1(_nr: usize, _arg: usize) -> usize { match () { - #[cfg(all(thumb, not(feature = "inline-asm"), not(feature = "no-semihosting")))] - () => __sh_syscall(_nr, _arg), - - #[cfg(all(thumb, feature = "inline-asm", not(feature = "no-semihosting")))] + #[cfg(all(thumb, not(feature = "no-semihosting")))] () => { let mut nr = _nr; core::arch::asm!( diff --git a/panic-semihosting/CHANGELOG.md b/panic-semihosting/CHANGELOG.md index 95c38901..c7a2e78d 100644 --- a/panic-semihosting/CHANGELOG.md +++ b/panic-semihosting/CHANGELOG.md @@ -7,6 +7,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ## [Unreleased] +- Always use inline-asm, requiring Rust 1.59. + ## [v0.5.6] - 2020-11-14 - Fix update to docs.rs to build for an embedded target diff --git a/panic-semihosting/Cargo.toml b/panic-semihosting/Cargo.toml index 46a3d2f1..dd3511eb 100644 --- a/panic-semihosting/Cargo.toml +++ b/panic-semihosting/Cargo.toml @@ -18,7 +18,7 @@ cortex-m-semihosting = { path = "../cortex-m-semihosting", version = ">= 0.3, < [features] exit = [] -inline-asm = ["cortex-m-semihosting/inline-asm", "cortex-m/inline-asm"] +inline-asm = [] jlink-quirks = ["cortex-m-semihosting/jlink-quirks"] [package.metadata.docs.rs] diff --git a/panic-semihosting/README.md b/panic-semihosting/README.md index baacf1af..f8057d32 100644 --- a/panic-semihosting/README.md +++ b/panic-semihosting/README.md @@ -8,7 +8,7 @@ This project is developed and maintained by the [Cortex-M team][team]. ## Minimum Supported Rust Version (MSRV) -This crate is guaranteed to compile on stable Rust 1.32.0 and up. It *might* +This crate is guaranteed to compile on stable Rust 1.59.0 and up. It *might* compile with older versions but that may change in any new patch release. ## License diff --git a/panic-semihosting/src/lib.rs b/panic-semihosting/src/lib.rs index 1db7b72d..1d7379e9 100644 --- a/panic-semihosting/src/lib.rs +++ b/panic-semihosting/src/lib.rs @@ -47,14 +47,6 @@ //! //! We discourage using this feature when the program will run on hardware as the exit call can //! leave the hardware debugger in an inconsistent state. -//! -//! ## `inline-asm` -//! -//! When this feature is enabled semihosting is implemented using inline assembly (`asm!`) and -//! compiling this crate requires nightly. -//! -//! When this feature is disabled semihosting is implemented using FFI calls into an external -//! assembly file and compiling this crate works on stable and beta. #![cfg(all(target_arch = "arm", target_os = "none"))] #![deny(missing_docs)] diff --git a/src/asm.rs b/src/asm.rs index 4dc1ab07..0434b5ff 100644 --- a/src/asm.rs +++ b/src/asm.rs @@ -1,18 +1,17 @@ //! Miscellaneous assembly instructions -// When inline assembly is enabled, pull in the assembly routines here. `call_asm!` will invoke -// these routines. -#[cfg(feature = "inline-asm")] -#[path = "../asm/inline.rs"] -pub(crate) mod inline; +#[cfg(cortex_m)] +use core::arch::asm; +use core::sync::atomic::{compiler_fence, Ordering}; /// Puts the processor in Debug state. Debuggers can pick this up as a "breakpoint". /// /// **NOTE** calling `bkpt` when the processor is not connected to a debugger will cause an /// exception. +#[cfg(cortex_m)] #[inline(always)] pub fn bkpt() { - call_asm!(__bkpt()); + unsafe { asm!("bkpt", options(nomem, nostack, preserves_flags)) }; } /// Blocks the program for *at least* `cycles` CPU cycles. @@ -24,41 +23,66 @@ pub fn bkpt() { /// and the execution time may vary with other factors. This delay is mainly useful for simple /// timer-less initialization of peripherals if and only if accurate timing is not essential. In /// any other case please use a more accurate method to produce a delay. +#[cfg(cortex_m)] #[inline] pub fn delay(cycles: u32) { - call_asm!(__delay(cycles: u32)); + // The loop will normally take 3 to 4 CPU cycles per iteration, but superscalar cores + // (eg. Cortex-M7) can potentially do it in 2, so we use that as the lower bound, since delaying + // for more cycles is okay. + // Add 1 to prevent an integer underflow which would cause a long freeze + let real_cycles = 1 + cycles / 2; + unsafe { + asm!( + // Use local labels to avoid R_ARM_THM_JUMP8 relocations which fail on thumbv6m. + "1:", + "subs {}, #1", + "bne 1b", + inout(reg) real_cycles => _, + options(nomem, nostack), + ) + }; } /// A no-operation. Useful to prevent delay loops from being optimized away. #[inline] pub fn nop() { - call_asm!(__nop()); + // NOTE: This is a `pure` asm block, but applying that option allows the compiler to eliminate + // the nop entirely (or to collapse multiple subsequent ones). Since the user probably wants N + // nops when they call `nop` N times, let's not add that option. + #[cfg(cortex_m)] + unsafe { + asm!("nop", options(nomem, nostack, preserves_flags)) + }; } /// Generate an Undefined Instruction exception. /// /// Can be used as a stable alternative to `core::intrinsics::abort`. +#[cfg(cortex_m)] #[inline] pub fn udf() -> ! { - call_asm!(__udf() -> !) + unsafe { asm!("udf #0", options(noreturn, nomem, nostack, preserves_flags)) }; } /// Wait For Event +#[cfg(cortex_m)] #[inline] pub fn wfe() { - call_asm!(__wfe()) + unsafe { asm!("wfe", options(nomem, nostack, preserves_flags)) }; } /// Wait For Interrupt +#[cfg(cortex_m)] #[inline] pub fn wfi() { - call_asm!(__wfi()) + unsafe { asm!("wfi", options(nomem, nostack, preserves_flags)) }; } /// Send Event +#[cfg(cortex_m)] #[inline] pub fn sev() { - call_asm!(__sev()) + unsafe { asm!("sev", options(nomem, nostack, preserves_flags)) }; } /// Instruction Synchronization Barrier @@ -67,7 +91,12 @@ pub fn sev() { /// from cache or memory, after the instruction has been completed. #[inline] pub fn isb() { - call_asm!(__isb()) + compiler_fence(Ordering::SeqCst); + #[cfg(cortex_m)] + unsafe { + asm!("isb", options(nomem, nostack, preserves_flags)) + }; + compiler_fence(Ordering::SeqCst); } /// Data Synchronization Barrier @@ -79,7 +108,12 @@ pub fn isb() { /// * all cache and branch predictor maintenance operations before this instruction complete #[inline] pub fn dsb() { - call_asm!(__dsb()) + compiler_fence(Ordering::SeqCst); + #[cfg(cortex_m)] + unsafe { + asm!("dsb", options(nomem, nostack, preserves_flags)) + }; + compiler_fence(Ordering::SeqCst); } /// Data Memory Barrier @@ -89,7 +123,12 @@ pub fn dsb() { /// after the `DMB` instruction. #[inline] pub fn dmb() { - call_asm!(__dmb()) + compiler_fence(Ordering::SeqCst); + #[cfg(cortex_m)] + unsafe { + asm!("dmb", options(nomem, nostack, preserves_flags)) + }; + compiler_fence(Ordering::SeqCst); } /// Test Target @@ -102,8 +141,15 @@ pub fn dmb() { // The __tt function does not dereference the pointer received. #[allow(clippy::not_unsafe_ptr_arg_deref)] pub fn tt(addr: *mut u32) -> u32 { - let addr = addr as u32; - call_asm!(__tt(addr: u32) -> u32) + let mut target = addr as u32; + unsafe { + asm!( + "tt {target}, {target}", + target = inout(reg) target, + options(nomem, nostack, preserves_flags), + ) + }; + target } /// Test Target Unprivileged @@ -117,8 +163,15 @@ pub fn tt(addr: *mut u32) -> u32 { // The __ttt function does not dereference the pointer received. #[allow(clippy::not_unsafe_ptr_arg_deref)] pub fn ttt(addr: *mut u32) -> u32 { - let addr = addr as u32; - call_asm!(__ttt(addr: u32) -> u32) + let mut target = addr as u32; + unsafe { + asm!( + "ttt {target}, {target}", + target = inout(reg) target, + options(nomem, nostack, preserves_flags), + ) + }; + target } /// Test Target Alternate Domain @@ -133,8 +186,15 @@ pub fn ttt(addr: *mut u32) -> u32 { // The __tta function does not dereference the pointer received. #[allow(clippy::not_unsafe_ptr_arg_deref)] pub fn tta(addr: *mut u32) -> u32 { - let addr = addr as u32; - call_asm!(__tta(addr: u32) -> u32) + let mut target = addr as u32; + unsafe { + asm!( + "tta {target}, {target}", + target = inout(reg) target, + options(nomem, nostack, preserves_flags), + ) + }; + target } /// Test Target Alternate Domain Unprivileged @@ -149,8 +209,15 @@ pub fn tta(addr: *mut u32) -> u32 { // The __ttat function does not dereference the pointer received. #[allow(clippy::not_unsafe_ptr_arg_deref)] pub fn ttat(addr: *mut u32) -> u32 { - let addr = addr as u32; - call_asm!(__ttat(addr: u32) -> u32) + let mut target = addr as u32; + unsafe { + asm!( + "ttat {target}, {target}", + target = inout(reg) target, + options(nomem, nostack, preserves_flags), + ) + }; + target } /// Branch and Exchange Non-secure @@ -160,15 +227,17 @@ pub fn ttat(addr: *mut u32) -> u32 { #[inline] #[cfg(armv8m)] pub unsafe fn bx_ns(addr: u32) { - call_asm!(__bxns(addr: u32)); + asm!("bxns {}", in(reg) addr, options(nomem, nostack, preserves_flags)); } /// Semihosting syscall. /// /// This method is used by cortex-m-semihosting to provide semihosting syscalls. +#[cfg(cortex_m)] #[inline] -pub unsafe fn semihosting_syscall(nr: u32, arg: u32) -> u32 { - call_asm!(__sh_syscall(nr: u32, arg: u32) -> u32) +pub unsafe fn semihosting_syscall(mut nr: u32, arg: u32) -> u32 { + asm!("bkpt #0xab", inout("r0") nr, in("r1") arg, options(nomem, nostack, preserves_flags)); + nr } /// Bootstrap. @@ -181,12 +250,27 @@ pub unsafe fn semihosting_syscall(nr: u32, arg: u32) -> u32 { /// /// `msp` and `rv` must point to valid stack memory and executable code, /// respectively. +#[cfg(cortex_m)] #[inline] pub unsafe fn bootstrap(msp: *const u32, rv: *const u32) -> ! { // Ensure thumb mode is set. let rv = (rv as u32) | 1; let msp = msp as u32; - call_asm!(__bootstrap(msp: u32, rv: u32) -> !); + asm!( + "mrs {tmp}, CONTROL", + "bics {tmp}, {spsel}", + "msr CONTROL, {tmp}", + "isb", + "msr MSP, {msp}", + "bx {rv}", + // `out(reg) _` is not permitted in a `noreturn` asm! call, + // so instead use `in(reg) 0` and don't restore it afterwards. + tmp = in(reg) 0, + spsel = in(reg) 2, + msp = in(reg) msp, + rv = in(reg) rv, + options(noreturn, nomem, nostack), + ); } /// Bootload. @@ -201,6 +285,7 @@ pub unsafe fn bootstrap(msp: *const u32, rv: *const u32) -> ! { /// The provided `vector_table` must point to a valid vector /// table, with a valid stack pointer as the first word and /// a valid reset vector as the second word. +#[cfg(cortex_m)] #[inline] pub unsafe fn bootload(vector_table: *const u32) -> ! { let msp = core::ptr::read_volatile(vector_table); diff --git a/src/call_asm.rs b/src/call_asm.rs deleted file mode 100644 index 295277f3..00000000 --- a/src/call_asm.rs +++ /dev/null @@ -1,24 +0,0 @@ -/// An internal macro to invoke an assembly routine. -/// -/// Depending on whether the unstable `inline-asm` feature is enabled, this will either call into -/// the inline assembly implementation directly, or through the FFI shim (see `asm/lib.rs`). -macro_rules! call_asm { - ( $func:ident ( $($args:ident: $tys:ty),* ) $(-> $ret:ty)? ) => {{ - #[allow(unused_unsafe)] - unsafe { - match () { - #[cfg(feature = "inline-asm")] - () => crate::asm::inline::$func($($args),*), - - #[cfg(not(feature = "inline-asm"))] - () => { - extern "C" { - fn $func($($args: $tys),*) $(-> $ret)?; - } - - $func($($args),*) - }, - } - } - }}; -} diff --git a/src/interrupt.rs b/src/interrupt.rs index 68719ecf..06b91f17 100644 --- a/src/interrupt.rs +++ b/src/interrupt.rs @@ -1,6 +1,10 @@ //! Interrupts pub use bare_metal::{CriticalSection, Mutex}; +#[cfg(cortex_m)] +use core::arch::asm; +#[cfg(cortex_m)] +use core::sync::atomic::{compiler_fence, Ordering}; /// Trait for enums of external interrupt numbers. /// @@ -24,9 +28,15 @@ pub unsafe trait InterruptNumber: Copy { } /// Disables all interrupts +#[cfg(cortex_m)] #[inline] pub fn disable() { - call_asm!(__cpsid()); + unsafe { + asm!("cpsid i", options(nomem, nostack, preserves_flags)); + } + + // Ensure no subsequent memory accesses are reordered to before interrupts are disabled. + compiler_fence(Ordering::SeqCst); } /// Enables all the interrupts @@ -34,14 +44,19 @@ pub fn disable() { /// # Safety /// /// - Do not call this function inside an `interrupt::free` critical section +#[cfg(cortex_m)] #[inline] pub unsafe fn enable() { - call_asm!(__cpsie()); + // Ensure no preceeding memory accesses are reordered to after interrupts are enabled. + compiler_fence(Ordering::SeqCst); + + asm!("cpsie i", options(nomem, nostack, preserves_flags)); } /// Execute closure `f` in an interrupt-free context. /// /// This as also known as a "critical section". +#[cfg(cortex_m)] #[inline] pub fn free(f: F) -> R where diff --git a/src/lib.rs b/src/lib.rs index dd46fd7a..7286f06a 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -9,53 +9,17 @@ //! //! # Optional features //! -//! ## `inline-asm` -//! -//! When this feature is enabled the implementation of all the functions inside the `asm` and -//! `register` modules use inline assembly (`asm!`) instead of external assembly (FFI into separate -//! assembly files pre-compiled using `arm-none-eabi-gcc`). The advantages of enabling `inline-asm` -//! are: -//! -//! - Reduced overhead. FFI eliminates the possibility of inlining so all operations include a -//! function call overhead when `inline-asm` is not enabled. -//! -//! - Some of the `register` API only becomes available only when `inline-asm` is enabled. Check the -//! API docs for details. -//! -//! The disadvantage is that `inline-asm` requires a nightly toolchain. -//! //! ## `cm7-r0p1` //! //! This feature enables workarounds for errata found on Cortex-M7 chips with revision r0p1. Some //! functions in this crate only work correctly on those chips if this Cargo feature is enabled //! (the functions are documented accordingly). //! -//! ## `linker-plugin-lto` -//! -//! This feature links against prebuilt assembly blobs that are compatible with [Linker-Plugin LTO]. -//! This allows inlining assembly routines into the caller, even without the `inline-asm` feature, -//! and works on stable Rust (but note the drawbacks below!). -//! -//! If you want to use this feature, you need to be aware of a few things: -//! -//! - You need to make sure that `-Clinker-plugin-lto` is passed to rustc. Please refer to the -//! [Linker-Plugin LTO] documentation for details. -//! -//! - You have to use a Rust version whose LLVM version is compatible with the toolchain in -//! `asm-toolchain`. -//! -//! - Due to a [Rust bug][rust-lang/rust#75940] in compiler versions **before 1.49**, this option -//! does not work with optimization levels `s` and `z`. -//! -//! [Linker-Plugin LTO]: https://doc.rust-lang.org/stable/rustc/linker-plugin-lto.html -//! [rust-lang/rust#75940]: https://github.com/rust-lang/rust/issues/75940 -//! //! # Minimum Supported Rust Version (MSRV) //! -//! This crate is guaranteed to compile on stable Rust 1.42 and up. It *might* +//! This crate is guaranteed to compile on stable Rust 1.59 and up. It *might* //! compile with older versions but that may change in any new patch release. -#![cfg_attr(feature = "inline-asm", feature(asm))] #![deny(missing_docs)] #![no_std] #![allow(clippy::identity_op)] @@ -82,8 +46,6 @@ extern crate bare_metal; extern crate volatile_register; -#[macro_use] -mod call_asm; #[macro_use] mod macros; diff --git a/src/peripheral/mod.rs b/src/peripheral/mod.rs index af922b1c..d1dfb6a3 100644 --- a/src/peripheral/mod.rs +++ b/src/peripheral/mod.rs @@ -60,6 +60,7 @@ use core::marker::PhantomData; use core::ops; +#[cfg(cortex_m)] use crate::interrupt; #[cfg(cm7)] @@ -163,6 +164,7 @@ static mut TAKEN: bool = false; impl Peripherals { /// Returns all the core peripherals *once* + #[cfg(cortex_m)] #[inline] pub fn take() -> Option { interrupt::free(|_| { diff --git a/src/register/apsr.rs b/src/register/apsr.rs index e83435ce..edb87373 100644 --- a/src/register/apsr.rs +++ b/src/register/apsr.rs @@ -1,5 +1,8 @@ //! Application Program Status Register +#[cfg(cortex_m)] +use core::arch::asm; + /// Application Program Status Register #[derive(Clone, Copy, Debug)] pub struct Apsr { @@ -45,10 +48,10 @@ impl Apsr { } /// Reads the CPU register -/// -/// **NOTE** This function is available if `cortex-m` is built with the `"inline-asm"` feature. +#[cfg(cortex_m)] #[inline] pub fn read() -> Apsr { - let bits: u32 = call_asm!(__apsr_r() -> u32); + let bits; + unsafe { asm!("mrs {}, APSR", out(reg) bits, options(nomem, nostack, preserves_flags)) }; Apsr { bits } } diff --git a/src/register/basepri.rs b/src/register/basepri.rs index 07084cd2..cffb3791 100644 --- a/src/register/basepri.rs +++ b/src/register/basepri.rs @@ -1,24 +1,42 @@ //! Base Priority Mask Register +#[cfg(cortex_m)] +use core::arch::asm; + /// Reads the CPU register +#[cfg(cortex_m)] #[inline] pub fn read() -> u8 { - call_asm!(__basepri_r() -> u8) + let r; + unsafe { asm!("mrs {}, BASEPRI", out(reg) r, options(nomem, nostack, preserves_flags)) }; + r } /// Writes to the CPU register /// /// **IMPORTANT** If you are using a Cortex-M7 device with revision r0p1 you MUST enable the /// `cm7-r0p1` Cargo feature or this function WILL misbehave. +#[cfg(cortex_m)] #[inline] pub unsafe fn write(basepri: u8) { #[cfg(feature = "cm7-r0p1")] { - call_asm!(__basepri_w_cm7_r0p1(basepri: u8)); + asm!( + "mrs {1}, PRIMASK", + "cpsid i", + "tst.w {1}, #1", + "msr BASEPRI, {0}", + "it ne", + "bxne lr", + "cpsie i", + in(reg) basepri, + out(reg) _, + options(nomem, nostack, preserves_flags), + ); } #[cfg(not(feature = "cm7-r0p1"))] { - call_asm!(__basepri_w(basepri: u8)); + asm!("msr BASEPRI, {}", in(reg) basepri, options(nomem, nostack, preserves_flags)); } } diff --git a/src/register/basepri_max.rs b/src/register/basepri_max.rs index cea38383..2881c4fe 100644 --- a/src/register/basepri_max.rs +++ b/src/register/basepri_max.rs @@ -1,5 +1,8 @@ //! Base Priority Mask Register (conditional write) +#[cfg(cortex_m)] +use core::arch::asm; + /// Writes to BASEPRI *if* /// /// - `basepri != 0` AND `basepri::read() == 0`, OR @@ -7,15 +10,31 @@ /// /// **IMPORTANT** If you are using a Cortex-M7 device with revision r0p1 you MUST enable the /// `cm7-r0p1` Cargo feature or this function WILL misbehave. +#[cfg(cortex_m)] #[inline] pub fn write(basepri: u8) { #[cfg(feature = "cm7-r0p1")] { - call_asm!(__basepri_max_cm7_r0p1(basepri: u8)); + unsafe { + asm!( + "mrs {1}, PRIMASK", + "cpsid i", + "tst.w {1}, #1", + "msr BASEPRI_MAX, {0}", + "it ne", + "bxne lr", + "cpsie i", + in(reg) basepri, + out(reg) _, + options(nomem, nostack, preserves_flags), + ); + } } #[cfg(not(feature = "cm7-r0p1"))] { - call_asm!(__basepri_max(basepri: u8)); + unsafe { + asm!("msr BASEPRI_MAX, {}", in(reg) basepri, options(nomem, nostack, preserves_flags)); + } } } diff --git a/src/register/control.rs b/src/register/control.rs index a991625b..d7819139 100644 --- a/src/register/control.rs +++ b/src/register/control.rs @@ -1,5 +1,10 @@ //! Control register +#[cfg(cortex_m)] +use core::arch::asm; +#[cfg(cortex_m)] +use core::sync::atomic::{compiler_fence, Ordering}; + /// Control register #[derive(Clone, Copy, Debug)] pub struct Control { @@ -150,15 +155,29 @@ impl Fpca { } /// Reads the CPU register +#[cfg(cortex_m)] #[inline] pub fn read() -> Control { - let bits: u32 = call_asm!(__control_r() -> u32); + let bits; + unsafe { asm!("mrs {}, CONTROL", out(reg) bits, options(nomem, nostack, preserves_flags)) }; Control { bits } } /// Writes to the CPU register. +#[cfg(cortex_m)] #[inline] pub unsafe fn write(control: Control) { let control = control.bits(); - call_asm!(__control_w(control: u32)); + + // ISB is required after writing to CONTROL, + // per ARM architectural requirements (see Application Note 321). + asm!( + "msr CONTROL, {}", + "isb", + in(reg) control, + options(nomem, nostack, preserves_flags), + ); + + // Ensure memory accesses are not reordered around the CONTROL update. + compiler_fence(Ordering::SeqCst); } diff --git a/src/register/faultmask.rs b/src/register/faultmask.rs index e57fa28d..1d327095 100644 --- a/src/register/faultmask.rs +++ b/src/register/faultmask.rs @@ -1,5 +1,8 @@ //! Fault Mask Register +#[cfg(cortex_m)] +use core::arch::asm; + /// All exceptions are ... #[derive(Clone, Copy, Debug, Eq, PartialEq)] pub enum Faultmask { @@ -24,9 +27,11 @@ impl Faultmask { } /// Reads the CPU register +#[cfg(cortex_m)] #[inline] pub fn read() -> Faultmask { - let r: u32 = call_asm!(__faultmask_r() -> u32); + let r: u32; + unsafe { asm!("mrs {}, FAULTMASK", out(reg) r, options(nomem, nostack, preserves_flags)) }; if r & (1 << 0) == (1 << 0) { Faultmask::Inactive } else { diff --git a/src/register/fpscr.rs b/src/register/fpscr.rs index 68692c73..bffed6cd 100644 --- a/src/register/fpscr.rs +++ b/src/register/fpscr.rs @@ -1,5 +1,7 @@ //! Floating-point Status Control Register +use core::arch::asm; + /// Floating-point Status Control Register #[derive(Clone, Copy, Debug)] pub struct Fpscr { @@ -293,7 +295,8 @@ impl RMode { /// Read the FPSCR register #[inline] pub fn read() -> Fpscr { - let r: u32 = call_asm!(__fpscr_r() -> u32); + let r; + unsafe { asm!("vmrs {}, fpscr", out(reg) r, options(nomem, nostack, preserves_flags)) }; Fpscr::from_bits(r) } @@ -301,5 +304,5 @@ pub fn read() -> Fpscr { #[inline] pub unsafe fn write(fpscr: Fpscr) { let fpscr = fpscr.bits(); - call_asm!(__fpscr_w(fpscr: u32)); + asm!("vmsr fpscr, {}", in(reg) fpscr, options(nomem, nostack)); } diff --git a/src/register/lr.rs b/src/register/lr.rs index 1aa546c8..02708ae4 100644 --- a/src/register/lr.rs +++ b/src/register/lr.rs @@ -1,17 +1,20 @@ //! Link register +#[cfg(cortex_m)] +use core::arch::asm; + /// Reads the CPU register -/// -/// **NOTE** This function is available if `cortex-m` is built with the `"inline-asm"` feature. +#[cfg(cortex_m)] #[inline] pub fn read() -> u32 { - call_asm!(__lr_r() -> u32) + let r; + unsafe { asm!("mov {}, lr", out(reg) r, options(nomem, nostack, preserves_flags)) }; + r } /// Writes `bits` to the CPU register -/// -/// **NOTE** This function is available if `cortex-m` is built with the `"inline-asm"` feature. +#[cfg(cortex_m)] #[inline] pub unsafe fn write(bits: u32) { - call_asm!(__lr_w(bits: u32)); + asm!("mov lr, {}", in(reg) bits, options(nomem, nostack, preserves_flags)); } diff --git a/src/register/mod.rs b/src/register/mod.rs index 48d157a5..aee7d213 100644 --- a/src/register/mod.rs +++ b/src/register/mod.rs @@ -56,13 +56,8 @@ pub mod msplim; #[cfg(armv8m_main)] pub mod psplim; -// Accessing these registers requires inline assembly because their contents are tied to the current -// stack frame -#[cfg(feature = "inline-asm")] pub mod apsr; -#[cfg(feature = "inline-asm")] pub mod lr; -#[cfg(feature = "inline-asm")] pub mod pc; diff --git a/src/register/msp.rs b/src/register/msp.rs index bccc2ae8..22ce7d97 100644 --- a/src/register/msp.rs +++ b/src/register/msp.rs @@ -1,16 +1,27 @@ //! Main Stack Pointer +#[cfg(cortex_m)] +use core::arch::asm; + /// Reads the CPU register +#[cfg(cortex_m)] #[inline] pub fn read() -> u32 { - call_asm!(__msp_r() -> u32) + let r; + unsafe { asm!("mrs {}, MSP", out(reg) r, options(nomem, nostack, preserves_flags)) }; + r } /// Writes `bits` to the CPU register +#[cfg(cortex_m)] #[inline] #[deprecated = "calling this function invokes Undefined Behavior, consider asm::bootstrap as an alternative"] pub unsafe fn write(bits: u32) { - call_asm!(__msp_w(bits: u32)); + // Technically is writing to the stack pointer "not pushing any data to the stack"? + // In any event, if we don't set `nostack` here, this method is useless as the new + // stack value is immediately mutated by returning. Really this is just not a good + // method and its use is marked as deprecated. + asm!("msr MSP, {}", in(reg) bits, options(nomem, nostack, preserves_flags)); } /// Reads the Non-Secure CPU register from Secure state. @@ -19,7 +30,9 @@ pub unsafe fn write(bits: u32) { #[cfg(armv8m)] #[inline] pub fn read_ns() -> u32 { - call_asm!(__msp_ns_r() -> u32) + let r; + unsafe { asm!("mrs {}, MSP_NS", out(reg) r, options(nomem, nostack, preserves_flags)) }; + r } /// Writes `bits` to the Non-Secure CPU register from Secure state. @@ -28,5 +41,5 @@ pub fn read_ns() -> u32 { #[cfg(armv8m)] #[inline] pub unsafe fn write_ns(bits: u32) { - call_asm!(__msp_ns_w(bits: u32)); + asm!("msr MSP_NS, {}", in(reg) bits, options(nomem, nostack, preserves_flags)); } diff --git a/src/register/msplim.rs b/src/register/msplim.rs index ac6f9ed6..7b45b33a 100644 --- a/src/register/msplim.rs +++ b/src/register/msplim.rs @@ -1,13 +1,17 @@ //! Main Stack Pointer Limit Register +use core::arch::asm; + /// Reads the CPU register #[inline] pub fn read() -> u32 { - call_asm!(__msplim_r() -> u32) + let r; + unsafe { asm!("mrs {}, MSPLIM", out(reg) r, options(nomem, nostack, preserves_flags)) }; + r } /// Writes `bits` to the CPU register #[inline] pub unsafe fn write(bits: u32) { - call_asm!(__msplim_w(bits: u32)) + asm!("msr MSPLIM, {}", in(reg) bits, options(nomem, nostack, preserves_flags)); } diff --git a/src/register/pc.rs b/src/register/pc.rs index 0b33629a..34606641 100644 --- a/src/register/pc.rs +++ b/src/register/pc.rs @@ -1,17 +1,20 @@ //! Program counter +#[cfg(cortex_m)] +use core::arch::asm; + /// Reads the CPU register -/// -/// **NOTE** This function is available if `cortex-m` is built with the `"inline-asm"` feature. +#[cfg(cortex_m)] #[inline] pub fn read() -> u32 { - call_asm!(__pc_r() -> u32) + let r; + unsafe { asm!("mov {}, pc", out(reg) r, options(nomem, nostack, preserves_flags)) }; + r } /// Writes `bits` to the CPU register -/// -/// **NOTE** This function is available if `cortex-m` is built with the `"inline-asm"` feature. +#[cfg(cortex_m)] #[inline] pub unsafe fn write(bits: u32) { - call_asm!(__pc_w(bits: u32)); + asm!("mov pc, {}", in(reg) bits, options(nomem, nostack, preserves_flags)); } diff --git a/src/register/primask.rs b/src/register/primask.rs index 842ca49a..e95276fa 100644 --- a/src/register/primask.rs +++ b/src/register/primask.rs @@ -1,5 +1,8 @@ //! Priority mask register +#[cfg(cortex_m)] +use core::arch::asm; + /// All exceptions with configurable priority are ... #[derive(Clone, Copy, Debug, Eq, PartialEq)] pub enum Primask { @@ -24,9 +27,11 @@ impl Primask { } /// Reads the CPU register +#[cfg(cortex_m)] #[inline] pub fn read() -> Primask { - let r: u32 = call_asm!(__primask_r() -> u32); + let r: u32; + unsafe { asm!("mrs {}, PRIMASK", out(reg) r, options(nomem, nostack, preserves_flags)) }; if r & (1 << 0) == (1 << 0) { Primask::Inactive } else { diff --git a/src/register/psp.rs b/src/register/psp.rs index 0bca22c3..c8f53b98 100644 --- a/src/register/psp.rs +++ b/src/register/psp.rs @@ -1,13 +1,22 @@ //! Process Stack Pointer +#[cfg(cortex_m)] +use core::arch::asm; + /// Reads the CPU register +#[cfg(cortex_m)] #[inline] pub fn read() -> u32 { - call_asm!(__psp_r() -> u32) + let r; + unsafe { asm!("mrs {}, PSP", out(reg) r, options(nomem, nostack, preserves_flags)) }; + r } /// Writes `bits` to the CPU register +#[cfg(cortex_m)] #[inline] pub unsafe fn write(bits: u32) { - call_asm!(__psp_w(bits: u32)) + // See comment on msp_w. Unlike MSP, there are legitimate use-cases for modifying PSP + // if MSP is currently being used as the stack pointer. + asm!("msr PSP, {}", in(reg) bits, options(nomem, nostack, preserves_flags)); } diff --git a/src/register/psplim.rs b/src/register/psplim.rs index 8ee1e945..832f9c67 100644 --- a/src/register/psplim.rs +++ b/src/register/psplim.rs @@ -1,13 +1,17 @@ //! Process Stack Pointer Limit Register +use core::arch::asm; + /// Reads the CPU register #[inline] pub fn read() -> u32 { - call_asm!(__psplim_r() -> u32) + let r; + unsafe { asm!("mrs {}, PSPLIM", out(reg) r, options(nomem, nostack, preserves_flags)) }; + r } /// Writes `bits` to the CPU register #[inline] pub unsafe fn write(bits: u32) { - call_asm!(__psplim_w(bits: u32)) + asm!("msr PSPLIM, {}", in(reg) bits, options(nomem, nostack, preserves_flags)); } diff --git a/xtask/src/lib.rs b/xtask/src/lib.rs index f6a57b3f..9d966868 100644 --- a/xtask/src/lib.rs +++ b/xtask/src/lib.rs @@ -1,117 +1,8 @@ //! `cargo xtask` automation. //! //! Please refer to for an explanation of the concept. -//! -//! Also see the docs in `asm.rs`. - -use std::collections::BTreeMap; -use std::env::current_dir; -use std::fs::{self, File}; -use std::process::{Command, Stdio}; - -fn toolchain() -> String { - fs::read_to_string("asm-toolchain") - .unwrap() - .trim() - .to_string() -} - -fn rustc() -> Command { - let mut cmd = Command::new("rustc"); - cmd.arg(format!("+{}", toolchain())); - cmd -} - -fn assemble_really(target: &str, cfgs: &[&str], plugin_lto: bool) { - let mut cmd = rustc(); - - // Set the codegen target. - cmd.arg("--target").arg(target); - // Set all the `--cfg` directives for the target. - cmd.args(cfgs.iter().map(|cfg| format!("--cfg={}", cfg))); - - // We want some level of debuginfo to allow unwinding through the functions. - cmd.arg("-g"); - // We always optimize the assembly shims. There's not really any reason not to. - cmd.arg("-O"); - - // We use LTO on the archive to ensure the (unused) panic handler is removed, preventing - // a linker error when the archives are linked into final crates with two panic handlers. - cmd.arg("-Clto=yes"); - - // rustc will usually add frame pointers by default to aid with debugging, but that is a high - // overhead for the tiny assembly routines. - cmd.arg("-Cforce-frame-pointers=no"); - // We don't want any system-specific paths to show up since we ship the result to other users. - // Add `--remap-path-prefix $(pwd)=.`. - let mut dir = current_dir().unwrap().as_os_str().to_os_string(); - dir.push("=."); - cmd.arg("--remap-path-prefix").arg(dir); - - // We let rustc build a single object file, not a staticlib, since the latter pulls in loads of - // code that will never be used (`compiler_builtins` and `core::fmt`, etc.). We build the static - // archive by hand after compiling. - cmd.arg("--emit=obj"); - - if plugin_lto { - // Make artifacts compatible with Linker-Plugin LTO (and incompatible with everything else). - cmd.arg("-Clinker-plugin-lto"); - } - - let file_stub = if plugin_lto { - format!("{}-lto", target) - } else { - target.to_string() - }; - - let obj_file = format!("bin/{}.o", file_stub); - - // Pass output and input file. - cmd.arg("-o").arg(&obj_file); - cmd.arg("asm/lib.rs"); - - println!("{:?}", cmd); - let status = cmd.status().unwrap(); - assert!(status.success()); - - // Archive `target.o` -> `bin/target.a`. - let mut builder = ar::Builder::new(File::create(format!("bin/{}.a", file_stub)).unwrap()); - - // Use `append`, not `append_path`, to avoid adding any filesystem metadata (modification times, - // etc.). - let file = fs::read(&obj_file).unwrap(); - builder - .append( - &ar::Header::new(obj_file.as_bytes().to_vec(), file.len() as u64), - &*file, - ) - .unwrap(); - - fs::remove_file(&obj_file).unwrap(); -} - -fn assemble(target: &str, cfgs: &[&str]) { - assemble_really(target, cfgs, false); - assemble_really(target, cfgs, true); -} - -// `--target` -> `--cfg` list (mirrors what `build.rs` does). -static TARGETS: &[(&str, &[&str])] = &[ - ("thumbv6m-none-eabi", &[]), - ("thumbv7m-none-eabi", &["armv7m"]), - ("thumbv7em-none-eabi", &["armv7m", "armv7em"]), - ("thumbv7em-none-eabihf", &["armv7m", "armv7em", "has_fpu"]), - ("thumbv8m.base-none-eabi", &["armv8m", "armv8m_base"]), - ( - "thumbv8m.main-none-eabi", - &["armv7m", "armv8m", "armv8m_main"], - ), - ( - "thumbv8m.main-none-eabihf", - &["armv7m", "armv8m", "armv8m_main", "has_fpu"], - ), -]; +use std::process::Command; pub fn install_targets(targets: &mut dyn Iterator, toolchain: Option<&str>) { let mut rustup = Command::new("rustup"); @@ -125,90 +16,6 @@ pub fn install_targets(targets: &mut dyn Iterator, toolchain: Optio assert!(status.success(), "rustup command failed: {:?}", rustup); } -pub fn assemble_blobs() { - let mut cmd = rustc(); - cmd.arg("-V"); - cmd.stdout(Stdio::null()); - let status = cmd.status().unwrap(); - let toolchain = toolchain(); - - if !status.success() { - println!( - "asm toolchain {} does not seem to be installed. installing it now.", - toolchain - ); - - let mut rustup = Command::new("rustup"); - let status = rustup.arg("install").arg(&toolchain).status().unwrap(); - assert!(status.success(), "rustup command failed: {:?}", rustup); - } - - install_targets( - &mut TARGETS.iter().map(|(target, _)| *target), - Some(&*toolchain), - ); - - for (target, cfgs) in TARGETS { - println!("building artifacts for {}", target); - assemble(target, cfgs); - } -} - -pub fn check_blobs() { - // Load each `.a` file in `bin` into memory. - let mut files_before = BTreeMap::new(); - for entry in fs::read_dir("bin").unwrap() { - let entry = entry.unwrap(); - if entry.path().extension().unwrap() == "a" { - files_before.insert( - entry - .path() - .file_name() - .unwrap() - .to_str() - .unwrap() - .to_string(), - fs::read(entry.path()).unwrap(), - ); - } - } - - assemble_blobs(); - - let mut files_after = BTreeMap::new(); - for entry in fs::read_dir("bin").unwrap() { - let entry = entry.unwrap(); - if entry.path().extension().unwrap() == "a" { - files_after.insert( - entry - .path() - .file_name() - .unwrap() - .to_str() - .unwrap() - .to_string(), - fs::read(entry.path()).unwrap(), - ); - } - } - - // Ensure they contain the same files. - let before = files_before.keys().collect::>(); - let after = files_after.keys().collect::>(); - assert_eq!(before, after); - - for ((file, before), (_, after)) in files_before.iter().zip(files_after.iter()) { - if before != after { - panic!( - "{} is not up-to-date, please run `cargo xtask assemble`", - file - ); - } - } - - println!("Blobs identical."); -} - // Check that serde and PartialOrd works with VectActive pub fn check_host_side() { use cortex_m::peripheral::{itm::LocalTimestampOptions, scb::VectActive}; diff --git a/xtask/src/main.rs b/xtask/src/main.rs index 26dce31b..4673a455 100644 --- a/xtask/src/main.rs +++ b/xtask/src/main.rs @@ -1,18 +1,14 @@ use std::{env, process}; -use xtask::{assemble_blobs, check_blobs, check_host_side}; +use xtask::check_host_side; fn main() { let subcommand = env::args().nth(1); match subcommand.as_deref() { - Some("assemble") => assemble_blobs(), - Some("check-blobs") => check_blobs(), Some("check-host-side") => check_host_side(), _ => { eprintln!("usage: cargo xtask "); eprintln!(); eprintln!("subcommands:"); - eprintln!(" assemble Reassemble the pre-built artifacts"); - eprintln!(" check-blobs Check that the pre-built artifacts are up-to-date and reproducible"); eprintln!(" check-host-side Build the crate in a non-Cortex-M host application and check host side usage of certain types"); process::exit(1); } diff --git a/xtask/tests/ci.rs b/xtask/tests/ci.rs index 37466e92..603491c7 100644 --- a/xtask/tests/ci.rs +++ b/xtask/tests/ci.rs @@ -1,6 +1,6 @@ use std::process::Command; use std::{env, str}; -use xtask::{check_blobs, check_host_side, install_targets}; +use xtask::{check_host_side, install_targets}; /// List of all compilation targets we support. /// @@ -44,13 +44,13 @@ fn build(package: &str, target: &str, features: &[&str]) { #[rustfmt::skip] static PACKAGE_FEATURES: &[(&str, &[&str], &[&str])] = &[ - ("cortex-m", ALL_TARGETS, &["inline-asm", "cm7-r0p1"]), // no `linker-plugin-lto` since it's experimental - ("cortex-m-semihosting", ALL_TARGETS, &["inline-asm", "no-semihosting", "jlink-quirks"]), - ("panic-semihosting", ALL_TARGETS, &["inline-asm", "exit", "jlink-quirks"]), + ("cortex-m", ALL_TARGETS, &["cm7-r0p1"]), + ("cortex-m-semihosting", ALL_TARGETS, &["no-semihosting", "jlink-quirks"]), + ("panic-semihosting", ALL_TARGETS, &["exit", "jlink-quirks"]), ("panic-itm", NON_BASE_TARGETS, &[]), ]; -fn check_crates_build(is_nightly: bool) { +fn check_crates_build(_is_nightly: bool) { // Build all crates for each supported target. for (package, targets, all_features) in PACKAGE_FEATURES { for target in *targets { @@ -58,11 +58,8 @@ fn check_crates_build(is_nightly: bool) { // Relies on all crates in this repo to use the same convention. let should_use_feature = |feat: &str| { match feat { - // This is nightly-only, so don't use it on stable. - "inline-asm" => is_nightly, // This only affects thumbv7em targets. "cm7-r0p1" => target.starts_with("thumbv7em"), - _ => true, } }; @@ -98,9 +95,6 @@ fn main() { install_targets(&mut ALL_TARGETS.iter().cloned(), None); - // Check that the ASM blobs are up-to-date. - check_blobs(); - let output = Command::new("rustc").arg("-V").output().unwrap(); let is_nightly = str::from_utf8(&output.stdout).unwrap().contains("nightly"); From 2810f97fe909bc68f1052de1c6a92b7817d86783 Mon Sep 17 00:00:00 2001 From: Adam Greig Date: Tue, 22 Feb 2022 02:47:31 +0000 Subject: [PATCH 04/12] Remove prebuilt cortex-m-rt binaries, replace with global_asm --- .github/bors.toml | 2 +- .github/workflows/rt-ci.yml | 3 +- cortex-m-rt/CHANGELOG.md | 2 + cortex-m-rt/README.md | 2 +- cortex-m-rt/asm.S | 113 ------------------ cortex-m-rt/assemble.sh | 33 ------ cortex-m-rt/bin/thumbv6m-none-eabi.a | Bin 2738 -> 0 bytes cortex-m-rt/bin/thumbv7em-none-eabi.a | Bin 2746 -> 0 bytes cortex-m-rt/bin/thumbv7em-none-eabihf.a | Bin 2778 -> 0 bytes cortex-m-rt/bin/thumbv7m-none-eabi.a | Bin 2746 -> 0 bytes cortex-m-rt/bin/thumbv8m.base-none-eabi.a | Bin 2742 -> 0 bytes cortex-m-rt/bin/thumbv8m.main-none-eabi.a | Bin 2750 -> 0 bytes cortex-m-rt/bin/thumbv8m.main-none-eabihf.a | Bin 2782 -> 0 bytes cortex-m-rt/build.rs | 15 +-- cortex-m-rt/check-blobs.sh | 21 ---- cortex-m-rt/ci/script.sh | 4 - cortex-m-rt/src/lib.rs | 123 +++++++++++++++++++- 17 files changed, 132 insertions(+), 186 deletions(-) delete mode 100644 cortex-m-rt/asm.S delete mode 100755 cortex-m-rt/assemble.sh delete mode 100644 cortex-m-rt/bin/thumbv6m-none-eabi.a delete mode 100644 cortex-m-rt/bin/thumbv7em-none-eabi.a delete mode 100644 cortex-m-rt/bin/thumbv7em-none-eabihf.a delete mode 100644 cortex-m-rt/bin/thumbv7m-none-eabi.a delete mode 100644 cortex-m-rt/bin/thumbv8m.base-none-eabi.a delete mode 100644 cortex-m-rt/bin/thumbv8m.main-none-eabi.a delete mode 100644 cortex-m-rt/bin/thumbv8m.main-none-eabihf.a delete mode 100755 cortex-m-rt/check-blobs.sh diff --git a/.github/bors.toml b/.github/bors.toml index c12731ab..218ec03a 100644 --- a/.github/bors.toml +++ b/.github/bors.toml @@ -5,7 +5,7 @@ status = [ "ci-linux (stable)", "ci-linux (1.59.0)", "rt-ci-linux (stable)", - "rt-ci-linux (1.42.0)", + "rt-ci-linux (1.59.0)", "rt-ci-other-os (macOS-latest)", "rt-ci-other-os (windows-latest)", "rustfmt", diff --git a/.github/workflows/rt-ci.yml b/.github/workflows/rt-ci.yml index 8b956123..f1eee816 100644 --- a/.github/workflows/rt-ci.yml +++ b/.github/workflows/rt-ci.yml @@ -11,8 +11,7 @@ jobs: continue-on-error: ${{ matrix.experimental || false }} strategy: matrix: - # All generated code should be running on stable now - rust: [nightly, stable, 1.42.0] + rust: [nightly, stable, 1.59.0] include: # Nightly is only for reference and allowed to fail diff --git a/cortex-m-rt/CHANGELOG.md b/cortex-m-rt/CHANGELOG.md index c66b5c0e..68a15790 100644 --- a/cortex-m-rt/CHANGELOG.md +++ b/cortex-m-rt/CHANGELOG.md @@ -7,6 +7,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ## [Unreleased] +- Moved precompiled assembly blobs to `global_asm!`, requiring Rust 1.59. + ## Fixes - Fix `cortex_m_rt::exception` macro no longer being usable fully-qualified ([#414]) diff --git a/cortex-m-rt/README.md b/cortex-m-rt/README.md index 34b0f170..b62dbb53 100644 --- a/cortex-m-rt/README.md +++ b/cortex-m-rt/README.md @@ -11,7 +11,7 @@ This project is developed and maintained by the [Cortex-M team][team]. # Minimum Supported Rust Version (MSRV) -This crate is guaranteed to compile on stable Rust 1.42.0 and up. It *might* +This crate is guaranteed to compile on stable Rust 1.59.0 and up. It *might* compile with older versions but that may change in any new patch release. # License diff --git a/cortex-m-rt/asm.S b/cortex-m-rt/asm.S deleted file mode 100644 index 0d078b37..00000000 --- a/cortex-m-rt/asm.S +++ /dev/null @@ -1,113 +0,0 @@ - .cfi_sections .debug_frame - - # Notes for function attributes: - # .type and .thumb_func are _both_ required, otherwise the Thumb mode bit - # will not be set and an invalid vector table is generated. - # LLD requires that section flags are set explicitly. - - .section .HardFaultTrampoline, "ax" - .global HardFaultTrampoline - .type HardFaultTrampoline,%function - .thumb_func - .cfi_startproc - # 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. -HardFaultTrampoline: - # Depending on the stack mode in EXC_RETURN, fetch stack pointer from - # PSP or MSP. - mov r0, lr - mov r1, #4 - tst r0, r1 - bne 0f - mrs r0, MSP - b HardFault -0: - mrs r0, PSP - b HardFault - .cfi_endproc - .size HardFaultTrampoline, . - HardFaultTrampoline - - .section .Reset, "ax" - .global Reset - .type Reset,%function - .thumb_func - .cfi_startproc - # Main entry point after reset. This jumps to the user __pre_init function, - # which cannot be called from Rust code without invoking UB, then - # initialises RAM. If the target has an FPU, it is enabled. Finally, jumps - # to the user main function. -Reset: - # ARMv6-M does not initialise LR, but many tools expect it to be 0xFFFF_FFFF - # when reaching the first call frame, so we set it at startup. - # ARMv7-M and above initialise LR to 0xFFFF_FFFF at reset. - ldr r4,=0xffffffff - mov lr,r4 - - # Run user pre-init code, which must be executed immediately after startup, - # before the potentially time-consuming memory initialisation takes place. - # Example use cases include disabling default watchdogs or enabling RAM. - bl __pre_init - - # Restore LR after calling __pre_init (r4 is preserved by subroutines). - mov lr,r4 - - # Initialise .bss memory. `__sbss` and `__ebss` come from the linker script. - ldr r0,=__sbss - ldr r1,=__ebss - mov r2,#0 -0: - cmp r1, r0 - beq 1f - stm r0!, {r2} - b 0b -1: - - # Initialise .data memory. `__sdata`, `__sidata`, and `__edata` come from the - # linker script. Copy from r2 into r0 until r0 reaches r1. - ldr r0,=__sdata - ldr r1,=__edata - ldr r2,=__sidata -2: - cmp r1, r0 - beq 3f - # load 1 word from r2 to r3, inc r2 - ldm r2!, {r3} - # store 1 word from r3 to r0, inc r0 - stm r0!, {r3} - b 2b -3: - -#ifdef HAS_FPU - # Conditionally enable the FPU. - # Address of SCB.CPACR. - ldr r0, =0xE000ED88 - # Enable access to CP10 and CP11 from both privileged and unprivileged mode. - ldr r1, =(0b1111 << 20) - # RMW. - ldr r2, [r0] - orr r2, r2, r1 - str r2, [r0] - # Barrier is required on some processors. - dsb - isb -#endif - -4: - # Preserve `lr` and emit debuginfo that lets external tools restore it. - # This fixes unwinding past the `Reset` handler. - # See https://sourceware.org/binutils/docs/as/CFI-directives.html for an - # explanation of the directives. -.cfi_def_cfa sp, 0 - push {lr} -.cfi_offset lr, 0 - - # Jump to user main function. We use bl for the extended range, but the - # user main function may not return. - bl main - - # Trap on return. - udf - - .cfi_endproc - .size Reset, . - Reset diff --git a/cortex-m-rt/assemble.sh b/cortex-m-rt/assemble.sh deleted file mode 100755 index 9b1f15c4..00000000 --- a/cortex-m-rt/assemble.sh +++ /dev/null @@ -1,33 +0,0 @@ -#!/usr/bin/env bash - -set -euxo pipefail - -# cflags taken from cc 1.0.22 - -crate=cortex-m-rt - -# remove existing blobs because otherwise this will append object files to the old blobs -rm -f bin/*.a - -arm-none-eabi-gcc -g -c -march=armv6s-m asm.S -o bin/$crate.o -ar crs bin/thumbv6m-none-eabi.a bin/$crate.o - -arm-none-eabi-gcc -g -c -march=armv7-m asm.S -o bin/$crate.o -ar crs bin/thumbv7m-none-eabi.a bin/$crate.o - -arm-none-eabi-gcc -g -c -march=armv7e-m asm.S -o bin/$crate.o -ar crs bin/thumbv7em-none-eabi.a bin/$crate.o - -arm-none-eabi-gcc -g -c -march=armv7e-m asm.S -DHAS_FPU -o bin/$crate.o -ar crs bin/thumbv7em-none-eabihf.a bin/$crate.o - -arm-none-eabi-gcc -g -c -march=armv8-m.base asm.S -o bin/$crate.o -ar crs bin/thumbv8m.base-none-eabi.a bin/$crate.o - -arm-none-eabi-gcc -g -c -march=armv8-m.main asm.S -o bin/$crate.o -ar crs bin/thumbv8m.main-none-eabi.a bin/$crate.o - -arm-none-eabi-gcc -g -c -march=armv8-m.main -DHAS_FPU asm.S -o bin/$crate.o -ar crs bin/thumbv8m.main-none-eabihf.a bin/$crate.o - -rm bin/$crate.o diff --git a/cortex-m-rt/bin/thumbv6m-none-eabi.a b/cortex-m-rt/bin/thumbv6m-none-eabi.a deleted file mode 100644 index c145cc612cc7348062f3c5cf0b891805a5e65e96..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2738 zcmb7G&re)c6h7}gpu+$oQYzGHn3*z>Sb0+@(wbCLh($1r zqx2sz#+6ImbmhX0dltqRSM5L0=!#_*HPP6l_0nT zw3d1bnMM2FgNK=e$43ty_TxLSdS~hQkH^P%ma@y)6)E0cwC?sCK03-Q_pkK7eS6Wq zoB1Vk_}7vAKrgv}48$qB#3x|A(jzZJ+LrYwHzb%IXM_f2!c5M#ChTYI7dW!WkMy!k z;*3}Ypj<557M!*BoK+~zoGlcJu$3r^#ey@MFU>fMd1ufqI|FXHY}*)7-fhVahVKda!a1}pgie|pO#9c z75J4}qZUe~(yq4K5Pl@uTVCjq#AO5Lk9kdNnX8>JbEC3iK8W6FD-MM35u?dL=; zQI3gRrW_Z!LU~$*YqXz_E|ZO5uaHB|#PT&t1bvqhM}WI(V=KAaHjV&y(FWnou(4$b zY2=Hs*e-7S<9g^-A;Tb&yQ<+)4#hQ9 zaal7r@b}y&6;3?k#t^;bM&0tO`#Tl$!n+;4g1AwPsIS)8ZX&$#^{Umtzm>Flf!Ema zku-8hjSU(*d$o2L&na@*#_x(R?!vV-*9*g-R^1OV{(peyoab6^B=B0_f4UBd4{m%=8VzyKK7IM3&+sBDWE3b3S=_gGB}%pe#BL@ zWV~G%c%B)LHPCn)&~;5va{9a?g|!}xU`Mj!L?-O#*0Lf0`+ z30S5`%Rr7)$eZsF%fG3 diff --git a/cortex-m-rt/bin/thumbv7em-none-eabi.a b/cortex-m-rt/bin/thumbv7em-none-eabi.a deleted file mode 100644 index 2d6b6a1f2054164d6d452c4bf71d7e65c1e7e9bd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2746 zcmb7G%}*R<7=LC4=mKSnlnS*PcDE3TEwkmr7L#fU5nP(mnijm7Wws2k4f~PVp=vad z{sX4*Kk(9c@ZiO(;o!*=y?HY6#Ia3!FtMie_j_j^c9>L+zvP|gbDrmUpXZ%-H-FU& z?rwe1Q_LO5rGyyq$!9J%J*y6DJtAUb-Qy~G!TO@NvmLGkUai^KuGW3I?YI0;?lywZ z|9ql05rl37>HaCh<(U~1dg|TT*k!Hf>xCPOmSrJ91WU%HEs0$0GWyOLL&oK-3`=vd zBcGYKA3u4P*?n>Fb^Tpw##qLtik`x}yTl*b*&kr)C%u@ID2lMuR z=GV;LUkCCNz2x^eVTybPxl=mi9Z=h{o@e_6<*_0xFe9co+ZwS?*>CdQ0w2=JHi78++i)*#HEMqGUZd`{itGOU zVxq0$wQBC2_&LISVs$X1spcd(fUROV)~@xM^bf5LIoWgBvFzzi=ti+jjo6!FFlI`s z0F4s;TPYviT+Pkh$xXS_SL6)dV7G`9d<>c=0e*Taqm5zF&OHsF{tKWA+ApgBO8Nbi{9#JIk&;(Z@~0_TMnf50msedZN4ofm zDVLjpU#`}xp_I$5N~;CpN2Imxg&xJ2wyK7ydDS}d@f>cT0Ru7RlzLvry+Vo)nDeuT zL}p2cMXr*b6}d+Gh6wj)qjCJMY>bfakxs_+JyINw zg8M6?Z^e}L*cd(g%Qz^(#4+zf=2RJ%Gqe%R*r6Yd|H98&KF_08>SD~xN3TsH9g;)^?Xd)f8EFsN2`LcIS!z;n)X&E686aT0owE^C~24P4LOQ`$)vt%*)$U^X`IYT*W64_a{16Fds!^qnY9rNC6~2vc~_wP2<8vH?GUVg>gmyfu^olnKr>hW0T_Vci+1+j~CQwgr2D4~(^FF_^u+Y|M3AG&knorU4DKv^&orn$IGJ!*<`MFK{9vejQzH~7YB)4Vj=nQ z-8pl=^Ow%OzYcnG%fHtQbF=#cv+(F}`TnEB>V5fa+Ke{9x ziBn5mLHW>~MAorWg)IqJt9>nKqGX|J)x4&%)fcKPbo02qL#>mw1{C0&hN}Bbfcd9e z0Fot%819T=Ud9$#!qvCPlD-yzWJxlH&&2RKwIf^ud)<%f*;-AEHiSVt*VK>tN5D1F zKCJ;b@q01+VGJ+E@M;Wy7Q-^=%ix-v^zbxw;S-e4*XmxrR4MtA&o_#V2ACJH#+vK9 zgduN~lu&j{73AYNTt@@?L(V(W{i?_{a$IEYpE-bci2S_BC*&7ISiAX}$fx9J9PgEh zEqpuV;~{^C97kuF9KpG(CbpitZ6Y~$(Zp8qrkK5g_buSBhn)48*n0MtaZrMaqviv1 zR~eUkXd;-hLq8be;m|I2X*Q7$$7*LVg$NUWxa~<%GWIx>)uY(>ek)LhKHnqLu_unvawZa_+d?f%Q}94 zJh5kQEZMH_*Gt81AM^hQ@tpHqv$v$FfHlARAxT3+Km9Vq{b(b-iNSsSFTXMP#Pf3B zH0iuNLtPlxLc=chllzZjsooesm2Uw&8jokSfT4+gq3abjH_t}fcIOIwtWkQmT9{O5Ur1EA>n7|Sl$$VFnQ0Im#?hO`yFJ))9ZZ* zU;}HSjpJd+wf+f|y!V>uL;3+Dy51S&?Sqba`EKaEKS9=WAj+Qr++R)fBkf^CoZH!BEUYBcrKgqSTA!TUXv~%QL%|ywR25T MzfIKl>j{2;1H@b%oB#j- diff --git a/cortex-m-rt/bin/thumbv7m-none-eabi.a b/cortex-m-rt/bin/thumbv7m-none-eabi.a deleted file mode 100644 index 3d1783c6ec9ecbdc55bb069de390005aa42c9ec8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2746 zcmb7F%}*R<7=LC4=(3b8rBtZZu)BpwY?&<|wwP2?h{eT}*0kWwEVE^RZP<^@4ppOx z^dB&d|ACjrg9k5O4F^x2=*^RfCyq7g!Ni*4@Au9;>@cYsf5|(~=RD8zKF>Sv6s~!} zy{&h%rTlSRPKXhoeCG2rbLy~`6%iZjK3CZb))&2aFH>t>McZzwL)|uNj2? zr<3)`Aat8Z_fHwF%+8w7({IhiE^FB@Z`@q8EDH%DSTZ3UN#s(G(Ra@pG9l+=L|Tho zh0KEe@8=Pr1)^b+V9$Xevm0=mU=&UxM1&R ze$MRuc_2T~OMZEIrv1%e_(cP`wn+u~UOl#Jg2z2bv@tRBf7fr0n#CDhJ&> zZtpSsWUUb*IXairL22uY-PzCK*Q~;&?PD*|+CErZRD=GQolq_SRjIGPdE|w!* ze8p5Mt-!C;8nsX=m3Fn=2Js`(UiU(eVocjL!_>W61NnFkH_(8=m~u+lS8%V8;sfUV z>|v2P(h-qsq~}Dglj1CLk2V^|@5;sq`5x(1Oy4HO(YZ~E;GC+B(R121l5>hSM#V41 zJ|(!nBKmqvS&xm;v%idk5=f7?CkaN;^QhUiW=?7Cmw*{qnG-tF)e#EoJ^x>{qSiSWkPt5yU5LDK34 zUSrco(#Rq8ZqV4=uC>FsrpRRj{}*4}`8&(57luKtx)b94{{fzJo@@4&;Ea>do1_3G z{q$x?`_V?cfyKH0m)~Xhr1Nra3eC$i)QfdJHmqTuoIj4Gxnm%jd`qCocxA|33i=T@ zu#)jwFz`Gx9($niR>13?z{(@6&&kA4+lP>o@xDa>o-@W{A2i+?c)r7Z6MYcqr=X21 zjH&8ppuC_$!qx(x%)5_7jLp2fO*QW>c*a$H1cBeTLTz6|p*(F{5R&zAF9d!&$MWKr zX1+7#VJfi-@Sr9#CKT9{f;2-0CddDdqea71YX|( zE5AVCd=>N~_OO!iCJ-+V9pmvH(Rfe5<1Dv83@j+&}ccu5Oy9@UH z%ukv9KM&-4ddV+`pg83T_AyYmbjeHLwq-re4G5OU6=6UaGmEpWG5Z<&dCn~IBi$^M zI73zeR4SHi3(l&&XcZ==FBA$z*e1w|#ey@OpO|(Q@=m{7a{Am-$+j`0w9{(%rQ5Bh z*C|!~JEcTr#p^WO_4qr+lwx%;saa4zB@nB{6u;cre-o2JPI#5cYQwT#5Es1>nT5rSSC>UQOYR6#gKEWjvJes{GTVa-@r& zmvXrs_~lx&7D~C?sdPGEe#AOeFZ2jw-l-X(;nkYR$KKmQX@+9XQ_Z58c(=1C$PBps ztjHYsh{!eaQIR*u&xvr4_H)sNvJvcMV({shze1$c@!0Q=X* zks+kvFT|W(WA{e&WgMh7am;*Ro+{(=3~d~Ou|q!|tZNC8Uv z=}VCIqmA?;2G8}s{CJPjd3kP1nwLFMFc~byQz7_Cfyk%exCHj#T zF_Q7>FtDE)k2TPE8<2HR5akPuPbtKtws(P(@xDO-_8H@`4jOM0GUssLq#OYKlxX7! zW3KvHC@&~T*xHbjd4EPC#%5l=rkZyTGUF<}2f+KSq_!`iP?@$iKyrQD3kkoP6M6qa zBHlCRIIKGRy>VJfi_g;xUq;D~j`yIv~dJsD1<-4JIe}JrW zAj+=*JYOaHk@hi?@x~D^4;|z29np9XAfuPtV1`D~nE6;H(_G}*v((Q4>_drX($t&r fxL)Sey8%)D0H{!iN#k)(Nx$n@-*4&!u6}<5fbJ5d diff --git a/cortex-m-rt/bin/thumbv8m.main-none-eabi.a b/cortex-m-rt/bin/thumbv8m.main-none-eabi.a deleted file mode 100644 index 40a5c512dbfd6a91a2dedd85ca010e363f1e5053..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2750 zcmb7F&u`pR5FXo`bT?_XNt%+D7G-yv6%lRh{GtS@pl(D%f|3-q2{*LycAaFa>~3T` z1q2f5KY%L!11>%Fz=bQyffJ`x;=l=sQ;x0F0}_=QzVF#D>sT#_k)CJ1neoiLndj%? zb=SYU^A{?FklBB6m|e&&=015a zXC7pK&F=qwC_m9l{)iK%*cZTEl96}7O~ZJR?-P{Aim)JzsNzgx#5`kO;=3h2q>F75 zYtSfyoRVW2aMs!@hEtxrTr8GgE0dKoU`cvIC0vG%v1Ns@)iRRfQeo!(Go zp`$15-DXH%E$K_)Yzp&(>yRY_9RSIa{uIuq@YxhTr>4R^ zu-}8I{$j#|(aKn~b5Db){|dM!+OKH#TFA$08Zms5f_mfuFcUzkt zl12`xcm3Apb|VPmnj)7C{9`<^E4Pqcy-W1gHpj-|R|09C$4@MOFNU@lGcBi+PG z#tUKKd1gHJK*w8!toH;_9%6k>Atr766gV00F#_^lHa{1`j8%DCHH#?dHbPbUfvrz?=O(` zI}qh}0M1tv{Yd**$#_>0uK*q6@gC9fo~K~T>r+_`<+huIE}|(D969)^yG|oD0GU5iE)!--u2gW?#_0w=DX!ub-PsY4%_#hA3Qniz<1@3qp5qjqd%V?-OHusdln>nd(L>+vj6O$d%k-i z_3`aF^I`kX?fZWpbj`0ktr_N4=Lcrt!Qsl?2ZzK2sEN--b|s-jI}(Cjf^)x&t+jep5WqURH4l=J8EzGQ{ z>Y@bVRU?TAb*dG*Aq-V3)~M-pBowp)JWTX&rF^t}Jw3aczGzRr zBWEy!yGA;}&uR57h_I$3kRj$5sjhB?=|Ey$otrp^k%!Oh*CMlAo$I;9k{Bxb%-E8> zG`p}YZG9(}IxPCXjI3iP3vG#3to42HYp6QV z0GNNW2_RY0oxtr0%nR8hOZu7sk|n(foJ!zR34BI%g=^q`_oMprF%L!?#-N>R>PP*f z;F@Tk)&QLNy#)R+ffo~aErCBxU>OQzXkA|P_%w9UGnCKQd@o&1E<%nMn4 z-3?sAh}TO>D7&Q!^6@NgU<3Li&U@1NipXVhTxRyq91vmc=2^T+=C?iA%8vMtj9#_xxb8q5>y;D zADCTbT=vjJFlC2+D8eI=UF`bj<-je12Y$%6w1fvd5L@kv%{{YyZ`*F{aO}xfhVb22 z;<{Jd+03iIf!&nzh#STTb*0Ki72%byTP*tCZrtknZe`O$($FC>*RO1Dm+C=OQ|PjR ze~>5k?6oD^4FbPZ+zBxMe-O_(&o%d!G!?SOH+&04GSJXZzYIw~+DLC=u&@8+Hx8d< zUiM9s&dW2@fpIx9e1(3p|2UTFjR92o7Qo~2cvcG-n&?Nmf)S7REetczF&_6o$6JG} z*91|%$M}*$MB2tX5Rdl@0`QzM9``}VD?sKPuA4LpKtD~iaRd?9`c)_|Xb`j2Ajk7Q zMIy##UcRO}?;d2v)wB!1`>jdazJWr^wA}%S*T=Px@as92cL+aC-ZSRqE35N<2buBo zdhY|+z?x{|xF2z?e+(t>y(apQe!z&Y_Y(5w_%)c4y9{Qdzi1|IAH diff --git a/cortex-m-rt/build.rs b/cortex-m-rt/build.rs index 96a8560d..2b65cdfb 100644 --- a/cortex-m-rt/build.rs +++ b/cortex-m-rt/build.rs @@ -1,4 +1,4 @@ -use std::fs::{self, File}; +use std::fs::File; use std::io::Write; use std::path::{Path, PathBuf}; use std::{env, ffi::OsStr}; @@ -16,15 +16,6 @@ fn main() { .map_or(target.clone(), |stem| stem.to_str().unwrap().to_string()); } - let out_dir = PathBuf::from(env::var("OUT_DIR").unwrap()); - - if target.starts_with("thumbv") { - let lib_path = format!("bin/{}.a", target); - fs::copy(&lib_path, out_dir.join("libcortex-m-rt.a")).unwrap(); - println!("cargo:rustc-link-lib=static=cortex-m-rt"); - println!("cargo:rerun-if-changed={}", lib_path); - } - // Put the linker script somewhere the linker can find it let out = &PathBuf::from(env::var_os("OUT_DIR").unwrap()); let link_x = include_bytes!("link.x.in"); @@ -69,6 +60,10 @@ INCLUDE device.x"# 240 }; + if target.ends_with("-eabihf") { + println!("cargo:rustc-cfg=has_fpu"); + } + // checking the size of the interrupts portion of the vector table is sub-architecture dependent writeln!( f, diff --git a/cortex-m-rt/check-blobs.sh b/cortex-m-rt/check-blobs.sh deleted file mode 100755 index 166b4a4c..00000000 --- a/cortex-m-rt/check-blobs.sh +++ /dev/null @@ -1,21 +0,0 @@ -#!/usr/bin/env bash - -# Checks that the blobs are up to date with the committed assembly files - -set -euxo pipefail - -for lib in bin/*.a; do - filename=$(basename "$lib") - arm-none-eabi-objdump -Cd "$lib" > "bin/${filename%.a}.before" -done - -./assemble.sh - -for lib in bin/*.a; do - filename=$(basename "$lib") - arm-none-eabi-objdump -Cd "$lib" > "bin/${filename%.a}.after" -done - -for cksum in bin/*.after; do - diff -u "$cksum" "${cksum%.after}.before" -done diff --git a/cortex-m-rt/ci/script.sh b/cortex-m-rt/ci/script.sh index 08ff863e..a9c2b195 100755 --- a/cortex-m-rt/ci/script.sh +++ b/cortex-m-rt/ci/script.sh @@ -71,10 +71,6 @@ main() { ;; esac - - if [ "$TARGET" = x86_64-unknown-linux-gnu ]; then - ./check-blobs.sh - fi } main diff --git a/cortex-m-rt/src/lib.rs b/cortex-m-rt/src/lib.rs index 752d3d7d..0cfed4df 100644 --- a/cortex-m-rt/src/lib.rs +++ b/cortex-m-rt/src/lib.rs @@ -418,7 +418,7 @@ //! //! # Minimum Supported Rust Version (MSRV) //! -//! The MSRV of this release is Rust 1.42.0. +//! The MSRV of this release is Rust 1.59.0. // # Developer notes // @@ -430,9 +430,130 @@ extern crate cortex_m_rt_macros as macros; +use core::arch::global_asm; use core::fmt; use core::sync::atomic::{self, Ordering}; +// HardFault exceptions are bounced through this trampoline which grabs the stack pointer at +// the time of the exception and passes it to th euser's HardFault handler in r0. +// Depending on the stack mode in EXC_RETURN, fetches stack from either MSP or PSP. +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. +macro_rules! cfg_global_asm { + {@inner, [$($x:tt)*], } => { + global_asm!{$($x)*} + }; + (@inner, [$($x:tt)*], #[cfg($meta:meta)] $asm:literal, $($rest:tt)*) => { + #[cfg($meta)] + cfg_global_asm!{@inner, [$($x)* $asm,], $($rest)*} + #[cfg(not($meta))] + cfg_global_asm!{@inner, [$($x)*], $($rest)*} + }; + {@inner, [$($x:tt)*], $asm:literal, $($rest:tt)*} => { + cfg_global_asm!{@inner, [$($x)* $asm,], $($rest)*} + }; + {$($asms:tt)*} => { + cfg_global_asm!{@inner, [], $($asms)*} + }; +} + +// This reset vector is the initial entry point after a system reset. +// Calls an optional user-provided __pre_init and then initialises RAM. +// If the target has an FPU, it is enabled. +// Finally jumsp to the user main function. +cfg_global_asm! { + ".cfi_sections .debug_frame + .section .Reset, \"ax\" + .global Reset + .type Reset,%function + .thumb_func", + ".cfi_startproc + Reset:", + + // Ensure LR is loaded with 0xFFFF_FFFF at startup to help debuggers find the first call frame. + // On ARMv6-M LR is not initialised at all, while other platforms should initialise it. + "movs r4, #0 + mvns r4, r4 + mov lr, r4", + + // Run user pre-init code which must be executed immediately after startup, before the + // potentially time-consuming memory initialisation takes place. + // Example use cases include disabling default watchdogs or enabling RAM. + // Reload LR after returning from pre-init (r4 is preserved by subroutines). + "bl __pre_init + mov lr, r4", + + // Initialise .bss memory. `__sbss` and `__ebss` come from the linker script. + "ldr r0, =__sbss + ldr r1, =__ebss + movs r2, #0 + 0: + cmp r1, r0 + beq 1f + stm r0!, {{r2}} + b 0b + 1:", + + // Initialise .data memory. `__sdata`, `__sidata`, and `__edata` come from the linker script. + "ldr r0, =__sdata + ldr r1, =__edata + ldr r2, =__sidata + 2: + cmp r0, r0 + beq 3f + ldm r2!, {{r3}} + stm r0!, {{r3}} + b 2b + 3:", + + // Potentially enable an FPU. + // SCB.CPACR is 0xE000_ED88. + // We enable access to CP10 and CP11 from priviliged and unprivileged mode. + #[cfg(has_fpu)] + "ldr r0, =0xE000ED88 + ldr r1, =(0b1111 << 20) + ldr r2, [r0] + orr r2, r2, r1 + str r2, [r0] + dsb + isb", + + // Push `lr` to the stack for debuggers, to prevent them unwinding past Reset. + // See https://sourceware.org/binutils/docs/as/CFI-directives.html. + ".cfi_def_cfa sp, 0 + push {{lr}} + .cfi_offset lr, 0", + + // Jump to user main function. + // `bl` is used for the extended range, but the user main function should not return, + // so trap on any unexpected return. + "bl main + udf #0", + + ".cfi_endproc + .size Reset, . - Reset", +} + /// Attribute to declare an interrupt (AKA device-specific exception) handler /// /// **IMPORTANT**: If you are using Rust 1.30 this attribute must be used on reachable items (i.e. From 7813e4d5572199f345a081fc7b217c4ba607c686 Mon Sep 17 00:00:00 2001 From: Adam Greig Date: Tue, 22 Feb 2022 03:11:12 +0000 Subject: [PATCH 05/12] Add set-sp and set-vtor features to cortex-m-rt. --- cortex-m-rt/Cargo.toml | 2 ++ cortex-m-rt/ci/script.sh | 5 +++++ cortex-m-rt/src/lib.rs | 30 ++++++++++++++++++++++++++++++ 3 files changed, 37 insertions(+) diff --git a/cortex-m-rt/Cargo.toml b/cortex-m-rt/Cargo.toml index 52890575..ae4eb9f8 100644 --- a/cortex-m-rt/Cargo.toml +++ b/cortex-m-rt/Cargo.toml @@ -42,6 +42,8 @@ required-features = ["device"] [features] device = [] +set-sp = [] +set-vtor = [] [package.metadata.docs.rs] features = ["device"] diff --git a/cortex-m-rt/ci/script.sh b/cortex-m-rt/ci/script.sh index a9c2b195..4683566e 100755 --- a/cortex-m-rt/ci/script.sh +++ b/cortex-m-rt/ci/script.sh @@ -57,6 +57,11 @@ main() { done cargo rustc --target "$TARGET" --example device --features device -- $linker cargo rustc --target "$TARGET" --example device --features device --release -- $linker + + cargo rustc --target "$TARGET" --example minimal --features set-sp -- $linker + cargo rustc --target "$TARGET" --example minimal --features set-sp --release -- $linker + cargo rustc --target "$TARGET" --example minimal --features set-vtor -- $linker + cargo rustc --target "$TARGET" --example minimal --features set-vtor --release -- $linker done fi diff --git a/cortex-m-rt/src/lib.rs b/cortex-m-rt/src/lib.rs index 0cfed4df..7a3f7e0b 100644 --- a/cortex-m-rt/src/lib.rs +++ b/cortex-m-rt/src/lib.rs @@ -158,6 +158,19 @@ //! conjunction with crates generated using `svd2rust`. Those *device crates* will populate the //! missing part of the vector table when their `"rt"` feature is enabled. //! +//! ## `set-sp` +//! +//! If this feature is enabled, the stack pointer (SP) is initialised in the reset handler to the +//! `_stack_start` value from the linker script. This is not usually required, but some debuggers +//! do not initialise SP when performing a soft reset, which can lead to stack corruption. +//! +//! ## `set-vtor` +//! +//! If this feature is enabled, the vector table offset register (VTOR) is initialised in the reset +//! handler to the start of the vector table defined in the linker script. This is not usually +//! required, but some bootloaders do not set VTOR before jumping to application code, leading to +//! your main function executing but interrupt handlers not being used. +//! //! # Inspection //! //! This section covers how to inspect a binary that builds on top of `cortex-m-rt`. @@ -496,6 +509,23 @@ cfg_global_asm! { mvns r4, r4 mov lr, r4", + // If enabled, initialise the SP. This is normally initialised by the CPU itself or by a + // bootloader, but some debuggers fail to set it when resetting the target, leading to + // stack corruptions. + #[cfg(feature = "set-sp")] + "ldr r0, =_stack_start + msr msp, r0", + + // If enabled, initialise VTOR to the start of the vector table. This is normally initialised + // by a bootloader when the non-reset value is required, but some bootloaders do not set it, + // leading to frustrating issues where everything seems to work but interrupts are never + // handled. The VTOR register is optional on ARMv6-M, but when not present is RAZ,WI and + // therefore safe to write to. + #[cfg(feature = "set-vtor")] + "ldr r0, =0xe000ed08 + ldr r1, =__vector_table + str r1, [r0]", + // Run user pre-init code which must be executed immediately after startup, before the // potentially time-consuming memory initialisation takes place. // Example use cases include disabling default watchdogs or enabling RAM. From 37de64ae532889421a938660e1c2ced87a3bd77a Mon Sep 17 00:00:00 2001 From: Adam Greig Date: Thu, 24 Feb 2022 01:39:13 +0000 Subject: [PATCH 06/12] Remove references to unsupported Rust versions in cortex-m-rt --- cortex-m-rt/src/lib.rs | 49 ++++++++---------------------------------- 1 file changed, 9 insertions(+), 40 deletions(-) diff --git a/cortex-m-rt/src/lib.rs b/cortex-m-rt/src/lib.rs index 7a3f7e0b..5034983f 100644 --- a/cortex-m-rt/src/lib.rs +++ b/cortex-m-rt/src/lib.rs @@ -322,14 +322,10 @@ //! //! We want to provide a default handler for all the interrupts while still letting the user //! individually override each interrupt handler. In C projects, this is usually accomplished using -//! weak aliases declared in external assembly files. In Rust, we could achieve something similar -//! using `global_asm!`, but that's an unstable feature. -//! -//! A solution that doesn't require `global_asm!` or external assembly files is to use the `PROVIDE` -//! command in a linker script to create the weak aliases. This is the approach that `cortex-m-rt` -//! uses; when the `"device"` feature is enabled `cortex-m-rt`'s linker script (`link.x`) depends on -//! a linker script named `device.x`. The crate that provides `__INTERRUPTS` must also provide this -//! file. +//! weak aliases declared in external assembly files. We use a similar solution via the `PROVIDE` +//! command in the linker script: when the `"device"` feature is enabled, `cortex-m-rt`'s linker +//! script (`link.x`) includes a linker script named `device.x`, which must be provided by +//! whichever crate provides `__INTERRUPTS`. //! //! For our running example the `device.x` linker script looks like this: //! @@ -343,8 +339,8 @@ //! that the core exceptions use unless overridden. //! //! Because this linker script is provided by a dependency of the final application the dependency -//! must contain build script that puts `device.x` somewhere the linker can find. An example of such -//! build script is shown below: +//! must contain a build script that puts `device.x` somewhere the linker can find. An example of +//! such build script is shown below: //! //! ```ignore //! use std::env; @@ -586,11 +582,6 @@ cfg_global_asm! { /// Attribute to declare an interrupt (AKA device-specific exception) handler /// -/// **IMPORTANT**: If you are using Rust 1.30 this attribute must be used on reachable items (i.e. -/// there must be no private modules between the item and the root of the crate); if the item is in -/// the root of the crate you'll be fine. This reachability restriction doesn't apply to Rust 1.31 -/// and newer releases. -/// /// **NOTE**: This attribute is exposed by `cortex-m-rt` only when the `device` feature is enabled. /// However, that export is not meant to be used directly -- using it will result in a compilation /// error. You should instead use the device crate (usually generated using `svd2rust`) re-export of @@ -657,11 +648,6 @@ pub use macros::interrupt; /// Attribute to declare the entry point of the program /// -/// **IMPORTANT**: This attribute must appear exactly *once* in the dependency graph. Also, if you -/// are using Rust 1.30 the attribute must be used on a reachable item (i.e. there must be no -/// private modules between the item and the root of the crate); if the item is in the root of the -/// crate you'll be fine. This reachability restriction doesn't apply to Rust 1.31 and newer releases. -/// /// The specified function will be called by the reset handler *after* RAM has been initialized. In /// the case of the `thumbv7em-none-eabihf` target the FPU will also be enabled before the function /// is called. @@ -716,11 +702,6 @@ pub use macros::entry; /// Attribute to declare an exception handler /// -/// **IMPORTANT**: If you are using Rust 1.30 this attribute must be used on reachable items (i.e. -/// there must be no private modules between the item and the root of the crate); if the item is in -/// the root of the crate you'll be fine. This reachability restriction doesn't apply to Rust 1.31 -/// and newer releases. -/// /// # Syntax /// /// ``` @@ -832,11 +813,7 @@ pub use macros::exception; /// Attribute to mark which function will be called at the beginning of the reset handler. /// -/// **IMPORTANT**: This attribute can appear at most *once* in the dependency graph. Also, if you -/// are using Rust 1.30 the attribute must be used on a reachable item (i.e. there must be no -/// private modules between the item and the root of the crate); if the item is in the root of the -/// crate you'll be fine. This reachability restriction doesn't apply to Rust 1.31 and newer -/// releases. +/// **IMPORTANT**: This attribute can appear at most *once* in the dependency graph. /// /// The function must have the signature of `unsafe fn()`. /// @@ -1071,21 +1048,13 @@ pub static __RESET_VECTOR: unsafe extern "C" fn() -> ! = Reset; #[cfg_attr(cortex_m, link_section = ".HardFault.default")] #[no_mangle] pub unsafe extern "C" fn HardFault_(ef: &ExceptionFrame) -> ! { - 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); - } + loop {} } #[doc(hidden)] #[no_mangle] pub unsafe extern "C" fn DefaultHandler_() -> ! { - 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); - } + loop {} } #[doc(hidden)] From c39dfb32f2c8a03a2d94c63fb8a9d0771d7c8c82 Mon Sep 17 00:00:00 2001 From: Adam Greig Date: Thu, 24 Feb 2022 01:41:36 +0000 Subject: [PATCH 07/12] Bump to Edition 2021 and rust-version 1.59 --- Cargo.toml | 3 ++- cortex-m-rt/Cargo.toml | 3 ++- cortex-m-rt/macros/Cargo.toml | 3 ++- cortex-m-semihosting/Cargo.toml | 3 ++- panic-semihosting/Cargo.toml | 2 ++ 5 files changed, 10 insertions(+), 4 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index ebbfdfee..914bd629 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,7 +12,8 @@ name = "cortex-m" readme = "README.md" repository = "https://github.com/rust-embedded/cortex-m" version = "0.7.4" -edition = "2018" +edition = "2021" +rust-version = "1.59" links = "cortex-m" # prevent multiple versions of this crate to be linked together [dependencies] diff --git a/cortex-m-rt/Cargo.toml b/cortex-m-rt/Cargo.toml index ae4eb9f8..c292cfee 100644 --- a/cortex-m-rt/Cargo.toml +++ b/cortex-m-rt/Cargo.toml @@ -15,7 +15,8 @@ repository = "https://github.com/rust-embedded/cortex-m" version = "0.7.1" autoexamples = true links = "cortex-m-rt" # Prevent multiple versions of cortex-m-rt being linked -edition = "2018" +edition = "2021" +rust-version = "1.59" [dependencies] cortex-m-rt-macros = { path = "macros", version = "=0.7.0" } diff --git a/cortex-m-rt/macros/Cargo.toml b/cortex-m-rt/macros/Cargo.toml index c73ebc1c..e95cc7d5 100644 --- a/cortex-m-rt/macros/Cargo.toml +++ b/cortex-m-rt/macros/Cargo.toml @@ -8,7 +8,8 @@ license = "MIT OR Apache-2.0" name = "cortex-m-rt-macros" repository = "https://github.com/rust-embedded/cortex-m" version = "0.7.0" -edition = "2018" +edition = "2021" +rust-version = "1.59" [lib] proc-macro = true diff --git a/cortex-m-semihosting/Cargo.toml b/cortex-m-semihosting/Cargo.toml index 58940296..b539e134 100644 --- a/cortex-m-semihosting/Cargo.toml +++ b/cortex-m-semihosting/Cargo.toml @@ -12,7 +12,8 @@ name = "cortex-m-semihosting" readme = "README.md" repository = "https://github.com/rust-embedded/cortex-m" version = "0.4.1" -edition = "2018" +edition = "2021" +rust-version = "1.59" [features] inline-asm = [] diff --git a/panic-semihosting/Cargo.toml b/panic-semihosting/Cargo.toml index dd3511eb..0e9749ae 100644 --- a/panic-semihosting/Cargo.toml +++ b/panic-semihosting/Cargo.toml @@ -11,6 +11,8 @@ license = "MIT OR Apache-2.0" name = "panic-semihosting" repository = "https://github.com/rust-embedded/cortex-m" version = "0.5.6" +rust-version = "1.59" +edition = "2021" [dependencies] cortex-m = { path = "..", version = ">= 0.5.6, < 0.8" } From db8bea29e61d4659942539f8da7fe4f39c02729f Mon Sep 17 00:00:00 2001 From: Adam Greig Date: Thu, 24 Feb 2022 17:31:00 +0000 Subject: [PATCH 08/12] Add a free() method for non-cortex-m build targets that panics, to allow checking code that uses it on native platform. --- src/interrupt.rs | 12 ++++++++++++ src/peripheral/tpiu.rs | 1 - 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/src/interrupt.rs b/src/interrupt.rs index 06b91f17..72450c4b 100644 --- a/src/interrupt.rs +++ b/src/interrupt.rs @@ -77,3 +77,15 @@ where r } + +// Make a `free()` function available to allow checking dependencies without specifying a target, +// but that will panic at runtime if executed. +#[doc(hidden)] +#[cfg(not(cortex_m))] +#[inline] +pub fn free(_: F) -> R +where + F: FnOnce(&CriticalSection) -> R, +{ + panic!("cortex_m::interrupt::free() is only functional on cortex-m platforms"); +} diff --git a/src/peripheral/tpiu.rs b/src/peripheral/tpiu.rs index 07624951..14dd35ca 100644 --- a/src/peripheral/tpiu.rs +++ b/src/peripheral/tpiu.rs @@ -118,7 +118,6 @@ impl TPIU { /// [`trace_output_protocol`](Self::set_trace_output_protocol). #[inline] pub fn trace_output_protocol(&self) -> Option { - use core::convert::TryInto; self.sppr.read().txmode().try_into().ok() } From f2feeb2595fe8f281a50d63055c65d6ac064ae11 Mon Sep 17 00:00:00 2001 From: Adam Greig Date: Thu, 24 Feb 2022 23:26:09 +0000 Subject: [PATCH 09/12] Tweaks to enable building and doctesting on host platform --- cortex-m-rt/src/lib.rs | 9 +++++++-- src/peripheral/mod.rs | 3 --- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/cortex-m-rt/src/lib.rs b/cortex-m-rt/src/lib.rs index 5034983f..793b9281 100644 --- a/cortex-m-rt/src/lib.rs +++ b/cortex-m-rt/src/lib.rs @@ -439,13 +439,14 @@ extern crate cortex_m_rt_macros as macros; -use core::arch::global_asm; use core::fmt; -use core::sync::atomic::{self, Ordering}; +#[cfg(cortex_m)] +use core::arch::global_asm; // HardFault exceptions are bounced through this trampoline which grabs the stack pointer at // the time of the exception and passes it to th euser'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\" @@ -468,6 +469,7 @@ global_asm!( ); /// Parse cfg attributes inside a global_asm call. +#[cfg(cortex_m)] macro_rules! cfg_global_asm { {@inner, [$($x:tt)*], } => { global_asm!{$($x)*} @@ -490,6 +492,7 @@ macro_rules! cfg_global_asm { // Calls an optional user-provided __pre_init and then initialises RAM. // If the target has an FPU, it is enabled. // Finally jumsp to the user main function. +#[cfg(cortex_m)] cfg_global_asm! { ".cfi_sections .debug_frame .section .Reset, \"ax\" @@ -1048,12 +1051,14 @@ pub static __RESET_VECTOR: unsafe extern "C" fn() -> ! = Reset; #[cfg_attr(cortex_m, link_section = ".HardFault.default")] #[no_mangle] pub unsafe extern "C" fn HardFault_(ef: &ExceptionFrame) -> ! { + #[allow(clippy::empty_loop)] loop {} } #[doc(hidden)] #[no_mangle] pub unsafe extern "C" fn DefaultHandler_() -> ! { + #[allow(clippy::empty_loop)] loop {} } diff --git a/src/peripheral/mod.rs b/src/peripheral/mod.rs index d1dfb6a3..56b663e0 100644 --- a/src/peripheral/mod.rs +++ b/src/peripheral/mod.rs @@ -59,8 +59,6 @@ use core::marker::PhantomData; use core::ops; - -#[cfg(cortex_m)] use crate::interrupt; #[cfg(cm7)] @@ -164,7 +162,6 @@ static mut TAKEN: bool = false; impl Peripherals { /// Returns all the core peripherals *once* - #[cfg(cortex_m)] #[inline] pub fn take() -> Option { interrupt::free(|_| { From 3e8a5beec5f96a3c219b840dc26df34f76e4ab1e Mon Sep 17 00:00:00 2001 From: Adam Greig Date: Fri, 25 Feb 2022 01:19:34 +0000 Subject: [PATCH 10/12] Fix cortex-m-rt qemu test by removing 'nomem' from semihosting_syscall asm, add inline to most cortex_m::asm methods --- cortex-m-rt/examples/qemu.rs | 30 +++++++++++++----------------- cortex-m-rt/link.x.in | 2 ++ cortex-m-rt/src/lib.rs | 2 +- cortex-m-semihosting/src/lib.rs | 13 +------------ src/asm.rs | 30 +++++++++++++++--------------- src/peripheral/mod.rs | 2 +- 6 files changed, 33 insertions(+), 46 deletions(-) diff --git a/cortex-m-rt/examples/qemu.rs b/cortex-m-rt/examples/qemu.rs index e903404a..a8ffd208 100644 --- a/cortex-m-rt/examples/qemu.rs +++ b/cortex-m-rt/examples/qemu.rs @@ -1,28 +1,24 @@ -// #![feature(stdsimd)] #![no_main] #![no_std] -extern crate cortex_m; -extern crate cortex_m_rt as rt; -extern crate cortex_m_semihosting as semihosting; +use core::fmt::Write; -extern crate panic_halt; - -use cortex_m::asm; -use rt::entry; - -#[entry] +#[cortex_m_rt::entry] fn main() -> ! { - use core::fmt::Write; let x = 42; loop { - asm::nop(); - - // write something through semihosting interface - let mut hstdout = semihosting::hio::hstdout().unwrap(); + let mut hstdout = cortex_m_semihosting::hio::hstdout().unwrap(); write!(hstdout, "x = {}\n", x).unwrap(); - // exit from qemu - semihosting::debug::exit(semihosting::debug::EXIT_SUCCESS); + cortex_m_semihosting::debug::exit(cortex_m_semihosting::debug::EXIT_SUCCESS); + } +} + +// Define a panic handler that uses semihosting to exit immediately, +// so that any panics cause qemu to quit instead of hang. +#[panic_handler] +fn panic(_: &core::panic::PanicInfo) -> ! { + loop { + cortex_m_semihosting::debug::exit(cortex_m_semihosting::debug::EXIT_FAILURE); } } diff --git a/cortex-m-rt/link.x.in b/cortex-m-rt/link.x.in index 92004b7f..deff3769 100644 --- a/cortex-m-rt/link.x.in +++ b/cortex-m-rt/link.x.in @@ -66,6 +66,8 @@ SECTIONS /* ### Vector table */ .vector_table ORIGIN(FLASH) : { + __vector_table = .; + /* Initial Stack Pointer (SP) value */ LONG(_stack_start); diff --git a/cortex-m-rt/src/lib.rs b/cortex-m-rt/src/lib.rs index 793b9281..1e977c66 100644 --- a/cortex-m-rt/src/lib.rs +++ b/cortex-m-rt/src/lib.rs @@ -439,9 +439,9 @@ extern crate cortex_m_rt_macros as macros; -use core::fmt; #[cfg(cortex_m)] 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 th euser's HardFault handler in r0. diff --git a/cortex-m-semihosting/src/lib.rs b/cortex-m-semihosting/src/lib.rs index 4ff975de..186e7e77 100644 --- a/cortex-m-semihosting/src/lib.rs +++ b/cortex-m-semihosting/src/lib.rs @@ -194,20 +194,9 @@ pub unsafe fn syscall(nr: usize, arg: &T) -> usize { pub unsafe fn syscall1(_nr: usize, _arg: usize) -> usize { match () { #[cfg(all(thumb, not(feature = "no-semihosting")))] - () => { - let mut nr = _nr; - core::arch::asm!( - "bkpt #0xab", - inout("r0") nr, - in("r1") _arg, - options(nomem, nostack, preserves_flags) - ); - nr - } - + () => cortex_m::asm::semihosting_syscall(_nr as u32, _arg as u32) as usize, #[cfg(all(thumb, feature = "no-semihosting"))] () => 0, - #[cfg(not(thumb))] () => unimplemented!(), } diff --git a/src/asm.rs b/src/asm.rs index 0434b5ff..3a3485a1 100644 --- a/src/asm.rs +++ b/src/asm.rs @@ -44,7 +44,7 @@ pub fn delay(cycles: u32) { } /// A no-operation. Useful to prevent delay loops from being optimized away. -#[inline] +#[inline(always)] pub fn nop() { // NOTE: This is a `pure` asm block, but applying that option allows the compiler to eliminate // the nop entirely (or to collapse multiple subsequent ones). Since the user probably wants N @@ -59,28 +59,28 @@ pub fn nop() { /// /// Can be used as a stable alternative to `core::intrinsics::abort`. #[cfg(cortex_m)] -#[inline] +#[inline(always)] pub fn udf() -> ! { unsafe { asm!("udf #0", options(noreturn, nomem, nostack, preserves_flags)) }; } /// Wait For Event #[cfg(cortex_m)] -#[inline] +#[inline(always)] pub fn wfe() { unsafe { asm!("wfe", options(nomem, nostack, preserves_flags)) }; } /// Wait For Interrupt #[cfg(cortex_m)] -#[inline] +#[inline(always)] pub fn wfi() { unsafe { asm!("wfi", options(nomem, nostack, preserves_flags)) }; } /// Send Event #[cfg(cortex_m)] -#[inline] +#[inline(always)] pub fn sev() { unsafe { asm!("sev", options(nomem, nostack, preserves_flags)) }; } @@ -89,7 +89,7 @@ pub fn sev() { /// /// Flushes the pipeline in the processor, so that all instructions following the `ISB` are fetched /// from cache or memory, after the instruction has been completed. -#[inline] +#[inline(always)] pub fn isb() { compiler_fence(Ordering::SeqCst); #[cfg(cortex_m)] @@ -106,7 +106,7 @@ pub fn isb() { /// /// * any explicit memory access made before this instruction is complete /// * all cache and branch predictor maintenance operations before this instruction complete -#[inline] +#[inline(always)] pub fn dsb() { compiler_fence(Ordering::SeqCst); #[cfg(cortex_m)] @@ -121,7 +121,7 @@ pub fn dsb() { /// Ensures that all explicit memory accesses that appear in program order before the `DMB` /// instruction are observed before any explicit memory accesses that appear in program order /// after the `DMB` instruction. -#[inline] +#[inline(always)] pub fn dmb() { compiler_fence(Ordering::SeqCst); #[cfg(cortex_m)] @@ -136,7 +136,7 @@ pub fn dmb() { /// Queries the Security state and access permissions of a memory location. /// Returns a Test Target Response Payload (cf section D1.2.215 of /// Armv8-M Architecture Reference Manual). -#[inline] +#[inline(always)] #[cfg(armv8m)] // The __tt function does not dereference the pointer received. #[allow(clippy::not_unsafe_ptr_arg_deref)] @@ -158,7 +158,7 @@ pub fn tt(addr: *mut u32) -> u32 { /// access to that location. /// Returns a Test Target Response Payload (cf section D1.2.215 of /// Armv8-M Architecture Reference Manual). -#[inline] +#[inline(always)] #[cfg(armv8m)] // The __ttt function does not dereference the pointer received. #[allow(clippy::not_unsafe_ptr_arg_deref)] @@ -181,7 +181,7 @@ pub fn ttt(addr: *mut u32) -> u32 { /// undefined if used from Non-Secure state. /// Returns a Test Target Response Payload (cf section D1.2.215 of /// Armv8-M Architecture Reference Manual). -#[inline] +#[inline(always)] #[cfg(armv8m)] // The __tta function does not dereference the pointer received. #[allow(clippy::not_unsafe_ptr_arg_deref)] @@ -204,7 +204,7 @@ pub fn tta(addr: *mut u32) -> u32 { /// state and is undefined if used from Non-Secure state. /// Returns a Test Target Response Payload (cf section D1.2.215 of /// Armv8-M Architecture Reference Manual). -#[inline] +#[inline(always)] #[cfg(armv8m)] // The __ttat function does not dereference the pointer received. #[allow(clippy::not_unsafe_ptr_arg_deref)] @@ -224,7 +224,7 @@ pub fn ttat(addr: *mut u32) -> u32 { /// /// See section C2.4.26 of Armv8-M Architecture Reference Manual for details. /// Undefined if executed in Non-Secure state. -#[inline] +#[inline(always)] #[cfg(armv8m)] pub unsafe fn bx_ns(addr: u32) { asm!("bxns {}", in(reg) addr, options(nomem, nostack, preserves_flags)); @@ -234,9 +234,9 @@ pub unsafe fn bx_ns(addr: u32) { /// /// This method is used by cortex-m-semihosting to provide semihosting syscalls. #[cfg(cortex_m)] -#[inline] +#[inline(always)] pub unsafe fn semihosting_syscall(mut nr: u32, arg: u32) -> u32 { - asm!("bkpt #0xab", inout("r0") nr, in("r1") arg, options(nomem, nostack, preserves_flags)); + asm!("bkpt #0xab", inout("r0") nr, in("r1") arg, options(nostack, preserves_flags)); nr } diff --git a/src/peripheral/mod.rs b/src/peripheral/mod.rs index 56b663e0..c3168863 100644 --- a/src/peripheral/mod.rs +++ b/src/peripheral/mod.rs @@ -57,9 +57,9 @@ //! //! - ARMv7-M Architecture Reference Manual (Issue E.b) - Chapter B3 +use crate::interrupt; use core::marker::PhantomData; use core::ops; -use crate::interrupt; #[cfg(cm7)] pub mod ac; From b49bcbe9fd6bbc36874a6d763c07b97aca8df71f Mon Sep 17 00:00:00 2001 From: Adam Greig Date: Fri, 25 Feb 2022 01:56:50 +0000 Subject: [PATCH 11/12] Remove inline-asm features from cortex-m-semihosting and panic-semihosting entirely --- cortex-m-semihosting/CHANGELOG.md | 1 + cortex-m-semihosting/Cargo.toml | 1 - panic-semihosting/CHANGELOG.md | 1 + panic-semihosting/Cargo.toml | 1 - 4 files changed, 2 insertions(+), 2 deletions(-) diff --git a/cortex-m-semihosting/CHANGELOG.md b/cortex-m-semihosting/CHANGELOG.md index 38ee835e..2b9c780d 100644 --- a/cortex-m-semihosting/CHANGELOG.md +++ b/cortex-m-semihosting/CHANGELOG.md @@ -6,6 +6,7 @@ This project adheres to [Semantic Versioning](http://semver.org/). ## [Unreleased] - Always use inline-asm, requiring Rust 1.59. +- Removed inline-asm feature. ## [v0.4.1] - 2020-10-20 diff --git a/cortex-m-semihosting/Cargo.toml b/cortex-m-semihosting/Cargo.toml index b539e134..32e980e7 100644 --- a/cortex-m-semihosting/Cargo.toml +++ b/cortex-m-semihosting/Cargo.toml @@ -16,7 +16,6 @@ edition = "2021" rust-version = "1.59" [features] -inline-asm = [] jlink-quirks = [] no-semihosting = [] diff --git a/panic-semihosting/CHANGELOG.md b/panic-semihosting/CHANGELOG.md index c7a2e78d..5f7bf7bd 100644 --- a/panic-semihosting/CHANGELOG.md +++ b/panic-semihosting/CHANGELOG.md @@ -8,6 +8,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ## [Unreleased] - Always use inline-asm, requiring Rust 1.59. +- Remove inline-asm feature. ## [v0.5.6] - 2020-11-14 diff --git a/panic-semihosting/Cargo.toml b/panic-semihosting/Cargo.toml index 0e9749ae..4aaadb43 100644 --- a/panic-semihosting/Cargo.toml +++ b/panic-semihosting/Cargo.toml @@ -20,7 +20,6 @@ cortex-m-semihosting = { path = "../cortex-m-semihosting", version = ">= 0.3, < [features] exit = [] -inline-asm = [] jlink-quirks = ["cortex-m-semihosting/jlink-quirks"] [package.metadata.docs.rs] From ac2a8365721b453f005feb7fe1fb25615f76af7c Mon Sep 17 00:00:00 2001 From: Adam Greig Date: Fri, 25 Feb 2022 01:57:16 +0000 Subject: [PATCH 12/12] Put inline asm directly into cortex-m-semihosting so it doesn't need to depend on cortex-m 0.8 --- cortex-m-semihosting/src/lib.rs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/cortex-m-semihosting/src/lib.rs b/cortex-m-semihosting/src/lib.rs index 186e7e77..83063072 100644 --- a/cortex-m-semihosting/src/lib.rs +++ b/cortex-m-semihosting/src/lib.rs @@ -194,7 +194,13 @@ pub unsafe fn syscall(nr: usize, arg: &T) -> usize { pub unsafe fn syscall1(_nr: usize, _arg: usize) -> usize { match () { #[cfg(all(thumb, not(feature = "no-semihosting")))] - () => cortex_m::asm::semihosting_syscall(_nr as u32, _arg as u32) as usize, + () => { + use core::arch::asm; + let mut nr = _nr as u32; + let arg = _arg as u32; + asm!("bkpt #0xab", inout("r0") nr, in("r1") arg, options(nostack, preserves_flags)); + nr as usize + } #[cfg(all(thumb, feature = "no-semihosting"))] () => 0, #[cfg(not(thumb))]