diff --git a/CHANGELOG.md b/CHANGELOG.md index 4b5a837a..d7cae7a1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,17 @@ and this project adheres to [Semantic Versioning](http://semver.org/). - Associated const `PTR` is introduced to Core Peripherals to eventually replace the existing `ptr()` API. - A delay driver based on SysTick. +- You can now use LTO to inline assembly calls, even on stable Rust. + See the `asm/lib.rs` documentation for more details. + +### Changed + +- Previously, asm calls without the `inline-asm` feature enabled used pre-built + objects which were built by a GCC compiler, while `inline-asm` enabled the + use of `llvm_asm!` calls. The asm system has been replaced with a new + technique which generates Rust static libs for stable calling, and uses the + new `asm!` macro with `inline-asm`. See the `asm/lib.rs` documentation for + more details. ## [v0.6.3] - 2020-07-20 diff --git a/asm/inline.rs b/asm/inline.rs index 67e4925f..3fbba92e 100644 --- a/asm/inline.rs +++ b/asm/inline.rs @@ -6,6 +6,8 @@ //! All of these functions should be blanket-`unsafe`. `cortex-m` provides safe wrappers where //! applicable. +use core::sync::atomic::{Ordering, compiler_fence}; + #[inline(always)] pub unsafe fn __bkpt() { asm!("bkpt"); @@ -20,45 +22,62 @@ pub unsafe fn __control_r() -> u32 { #[inline(always)] pub unsafe fn __control_w(w: u32) { - asm!("msr CONTROL, {}", in(reg) w); + // ISB is required after writing to CONTROL, + // per ARM architectural requirements (see Application Note 321). + asm!( + "msr CONTROL, {}", + "isb", + in(reg) w + ); + + // Ensure memory accesses are not reordered around the CONTROL update. + compiler_fence(Ordering::SeqCst); } #[inline(always)] pub unsafe fn __cpsid() { asm!("cpsid i"); + + // 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"); } #[inline(always)] pub unsafe fn __delay(cyc: u32) { - asm!(" - 1: - nop - subs {}, #1 - bne 1b - // Branch to 1 instead of delay does not generate R_ARM_THM_JUMP8 relocation, which breaks - // linking on the thumbv6m-none-eabi target - ", in(reg) cyc); + // Use local labels to avoid R_ARM_THM_JUMP8 relocations which fail on thumbv6m. + asm!( + "1:", + "nop", + "subs {}, #1", + "bne 1b", + in(reg) cyc + ); } -// FIXME do we need compiler fences here or should we expect them in the caller? #[inline(always)] pub unsafe fn __dmb() { - asm!("dmb 0xF"); + asm!("dmb"); + compiler_fence(Ordering::SeqCst); } #[inline(always)] pub unsafe fn __dsb() { - asm!("dsb 0xF"); + asm!("dsb"); + compiler_fence(Ordering::SeqCst); } #[inline(always)] pub unsafe fn __isb() { - asm!("isb 0xF"); + asm!("isb"); + compiler_fence(Ordering::SeqCst); } #[inline(always)] @@ -93,28 +112,28 @@ pub unsafe fn __nop() { #[inline(always)] pub unsafe fn __pc_r() -> u32 { let r; - asm!("mov {}, R15", out(reg) r); + asm!("mov {}, pc", out(reg) r); r } // NOTE: No FFI shim, this requires inline asm. #[inline(always)] pub unsafe fn __pc_w(val: u32) { - asm!("mov R15, {}", in(reg) val); + asm!("mov pc, {}", in(reg) val); } // NOTE: No FFI shim, this requires inline asm. #[inline(always)] pub unsafe fn __lr_r() -> u32 { let r; - asm!("mov {}, R14", out(reg) r); + asm!("mov {}, lr", out(reg) r); r } // NOTE: No FFI shim, this requires inline asm. #[inline(always)] pub unsafe fn __lr_w(val: u32) { - asm!("mov R14, {}", in(reg) val); + asm!("mov lr, {}", in(reg) val); } #[inline(always)] @@ -161,6 +180,8 @@ pub unsafe fn __wfi() { pub use self::v7m::*; #[cfg(any(armv7m, armv8m_main))] mod v7m { + use core::sync::atomic::{Ordering, compiler_fence}; + #[inline(always)] pub unsafe fn __basepri_max(val: u8) { asm!("msr BASEPRI_MAX, {}", in(reg) val); @@ -185,45 +206,42 @@ mod v7m { r } - // FIXME: compiler_fences necessary? #[inline(always)] pub unsafe fn __enable_icache() { asm!( - " - ldr r0, =0xE000ED14 @ CCR - mrs r2, PRIMASK @ save critical nesting info - cpsid i @ mask interrupts - ldr r1, [r0] @ read CCR - orr.w r1, r1, #(1 << 17) @ Set bit 17, IC - str r1, [r0] @ write it back - dsb @ ensure store completes - isb @ synchronize pipeline - msr PRIMASK, r2 @ unnest critical section - ", - out("r0") _, - out("r1") _, - out("r2") _, + "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) _, ); + compiler_fence(Ordering::SeqCst); } #[inline(always)] pub unsafe fn __enable_dcache() { asm!( - " - ldr r0, =0xE000ED14 @ CCR - mrs r2, PRIMASK @ save critical nesting info - cpsid i @ mask interrupts - ldr r1, [r0] @ read CCR - orr.w r1, r1, #(1 << 16) @ Set bit 16, DC - str r1, [r0] @ write it back - dsb @ ensure store completes - isb @ synchronize pipeline - msr PRIMASK, r2 @ unnest critical section - ", - out("r0") _, - out("r1") _, - out("r2") _, + "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) _, ); + compiler_fence(Ordering::SeqCst); } } @@ -234,34 +252,30 @@ mod v7em { #[inline(always)] pub unsafe fn __basepri_max_cm7_r0p1(val: u8) { asm!( - " - mrs r1, PRIMASK - cpsid i - tst.w r1, #1 - msr BASEPRI_MAX, {} - it ne - bxne lr - cpsie i - ", + "mrs {1}, PRIMASK", + "cpsid i", + "tst.w {1}, #1", + "msr BASEPRI_MAX, {0}", + "it ne", + "bxne lr", + "cpsie i", in(reg) val, - out("r1") _, + out(reg) _, ); } #[inline(always)] pub unsafe fn __basepri_w_cm7_r0p1(val: u8) { asm!( - " - mrs r1, PRIMASK - cpsid i - tst.w r1, #1 - msr BASEPRI, {} - it ne - bxne lr - cpsie i - ", + "mrs {1}, PRIMASK", + "cpsid i", + "tst.w {1}, #1", + "msr BASEPRI, {0}", + "it ne", + "bxne lr", + "cpsie i", in(reg) val, - out("r1") _, + out(reg) _, ); } } diff --git a/bin/thumbv6m-none-eabi-lto.a b/bin/thumbv6m-none-eabi-lto.a index 32667b18..f2451c0f 100644 Binary files a/bin/thumbv6m-none-eabi-lto.a and b/bin/thumbv6m-none-eabi-lto.a differ diff --git a/bin/thumbv6m-none-eabi.a b/bin/thumbv6m-none-eabi.a index 5c8c7587..12677003 100644 Binary files a/bin/thumbv6m-none-eabi.a and b/bin/thumbv6m-none-eabi.a differ diff --git a/bin/thumbv7em-none-eabi-lto.a b/bin/thumbv7em-none-eabi-lto.a index c405e9ef..2258d432 100644 Binary files a/bin/thumbv7em-none-eabi-lto.a and b/bin/thumbv7em-none-eabi-lto.a differ diff --git a/bin/thumbv7em-none-eabi.a b/bin/thumbv7em-none-eabi.a index ec56934c..9a47ef0b 100644 Binary files a/bin/thumbv7em-none-eabi.a and b/bin/thumbv7em-none-eabi.a differ diff --git a/bin/thumbv7em-none-eabihf-lto.a b/bin/thumbv7em-none-eabihf-lto.a index bd5ad837..67cb2eab 100644 Binary files a/bin/thumbv7em-none-eabihf-lto.a and b/bin/thumbv7em-none-eabihf-lto.a differ diff --git a/bin/thumbv7em-none-eabihf.a b/bin/thumbv7em-none-eabihf.a index 75a7e5dc..28a091a5 100644 Binary files a/bin/thumbv7em-none-eabihf.a and b/bin/thumbv7em-none-eabihf.a differ diff --git a/bin/thumbv7m-none-eabi-lto.a b/bin/thumbv7m-none-eabi-lto.a index a95b0699..81bdbe40 100644 Binary files a/bin/thumbv7m-none-eabi-lto.a and b/bin/thumbv7m-none-eabi-lto.a differ diff --git a/bin/thumbv7m-none-eabi.a b/bin/thumbv7m-none-eabi.a index ae9db609..d215f5f8 100644 Binary files a/bin/thumbv7m-none-eabi.a and b/bin/thumbv7m-none-eabi.a differ diff --git a/bin/thumbv8m.base-none-eabi-lto.a b/bin/thumbv8m.base-none-eabi-lto.a index dd7553ed..d0fdb57a 100644 Binary files a/bin/thumbv8m.base-none-eabi-lto.a and b/bin/thumbv8m.base-none-eabi-lto.a differ diff --git a/bin/thumbv8m.base-none-eabi.a b/bin/thumbv8m.base-none-eabi.a index e8bb7a6a..60164eb5 100644 Binary files a/bin/thumbv8m.base-none-eabi.a and b/bin/thumbv8m.base-none-eabi.a differ diff --git a/bin/thumbv8m.main-none-eabi-lto.a b/bin/thumbv8m.main-none-eabi-lto.a index 1f5b29dd..0a4faa1b 100644 Binary files a/bin/thumbv8m.main-none-eabi-lto.a and b/bin/thumbv8m.main-none-eabi-lto.a differ diff --git a/bin/thumbv8m.main-none-eabi.a b/bin/thumbv8m.main-none-eabi.a index af9179ab..43af099b 100644 Binary files a/bin/thumbv8m.main-none-eabi.a and b/bin/thumbv8m.main-none-eabi.a differ diff --git a/bin/thumbv8m.main-none-eabihf-lto.a b/bin/thumbv8m.main-none-eabihf-lto.a index c243d5d4..23d26630 100644 Binary files a/bin/thumbv8m.main-none-eabihf-lto.a and b/bin/thumbv8m.main-none-eabihf-lto.a differ diff --git a/bin/thumbv8m.main-none-eabihf.a b/bin/thumbv8m.main-none-eabihf.a index 3189a29c..399b4099 100644 Binary files a/bin/thumbv8m.main-none-eabihf.a and b/bin/thumbv8m.main-none-eabihf.a differ