From 6a650bc02e4a0807298ba5eeab420a99f9f7785f Mon Sep 17 00:00:00 2001 From: Adam Greig Date: Sun, 15 May 2022 22:09:34 +0100 Subject: [PATCH 1/4] Permit using inline-asm feature on stable Rust compilers --- CHANGELOG.md | 7 +++++++ src/lib.rs | 4 ++-- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ddc03a74..a406a057 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,10 +7,17 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ## [Unreleased] +## [v0.7.5] - 2022-05-15 + ### Deprecated - the `ptr()` function on all peripherals register blocks in favor of the associated constant `PTR` (#386). +### Changed + +- The `inline-asm` feature no longer requires a nightly Rust compiler, but + does require Rust 1.59 or above. + ## [v0.7.4] - 2021-12-31 ### Added diff --git a/src/lib.rs b/src/lib.rs index beff6e8f..4790f980 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -22,7 +22,8 @@ //! - 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. +//! The disadvantage is that `inline-asm` requires a Rust version at least 1.59 to use the `asm!()` +//! macro. In the future 0.8 and above versions of `cortex-m`, this feature will always be enabled. //! //! ## `cm7-r0p1` //! @@ -55,7 +56,6 @@ //! This crate is guaranteed to compile on stable Rust 1.38 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)] From ed00f507084b17765a8387b209eb48e33d32cb17 Mon Sep 17 00:00:00 2001 From: "bors[bot]" <26634292+bors[bot]@users.noreply.github.com> Date: Tue, 4 Jan 2022 16:42:26 +0000 Subject: [PATCH 2/4] Merge #380 380: Improve singleton!() macro r=adamgreig a=Rahix This PR addresses two shortcomings of the `cortex_m::singleton!()` macro, which I raised in #364. For review, I think it is best to look at the two commits implementing these changes individually. I think this changeset should also be backported to `0.7.x` where it applies cleanly and which is also the place where I tested it. The static is always initialized to a "zero" value with `Option::None` which means it should end up in `.bss`. However, if the enclosed type has a niche, `Option::None` can become a non-zero bitpattern which moves the whole singleton from `.bss` to `.data`. This is especially problematic when storing large buffers in the `singleton!()` as this starts eating lots of flash space unnecessarily. To prevent this, I switched to using an explicit boolean flag instead. This is not quite as nice but at least there is no chance for the `singleton!()` to end up in `.data`... For reference and as an example, the faulty behavior can be triggered with ```rust cortex_m::singleton!(: Option = None) ``` (the inner option has a non-zero niche which the outer option will occupy) Due to the static always being named `VAR` right now, all `singleton!()` instances end up having non-descriptive symbol names like `__cortex_m_rt_main::{{closure}}::VAR` which makes them hard to tell apart in a debugger or when looking at an objdump. I added the ability to set an explicit name which end up becoming part of the symbol name. This does not affect Rust code at all - the new name is not visible anywhere. It works like this: ```rust let value = singleton!(FOO_BUFFER: [u8; 1024] = [0u8; 1024]); ``` Of course the old syntax also still works and keeps the old behavior of calling the static `VAR`. Fixes #364. Co-authored-by: Rahix --- CHANGELOG.md | 4 ++++ src/macros.rs | 32 ++++++++++++++++++++++---------- 2 files changed, 26 insertions(+), 10 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a406a057..9b36a5a2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,6 +18,10 @@ and this project adheres to [Semantic Versioning](http://semver.org/). - The `inline-asm` feature no longer requires a nightly Rust compiler, but does require Rust 1.59 or above. +### Fixed +- Fixed `singleton!()` statics sometimes ending up in `.data` instead of `.bss` (#364, #380). + (Backported from upcoming 0.8 release). + ## [v0.7.4] - 2021-12-31 ### Added diff --git a/src/macros.rs b/src/macros.rs index 66b75b17..512c9323 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -30,9 +30,12 @@ macro_rules! iprintln { /// `None` variant the caller must ensure that the macro is called from a function that's executed /// at most once in the whole lifetime of the program. /// -/// # Note +/// # Notes /// This macro is unsound on multi core systems. /// +/// For debuggability, you can set an explicit name for a singleton. This name only shows up the +/// the debugger and is not referencable from other code. See example below. +/// /// # Example /// /// ``` no_run @@ -50,15 +53,24 @@ macro_rules! iprintln { /// fn alias() -> &'static mut bool { /// singleton!(: bool = false).unwrap() /// } +/// +/// fn singleton_with_name() { +/// // A name only for debugging purposes +/// singleton!(FOO_BUFFER: [u8; 1024] = [0u8; 1024]); +/// } /// ``` #[macro_export] macro_rules! singleton { - (: $ty:ty = $expr:expr) => { + ($name:ident: $ty:ty = $expr:expr) => { $crate::interrupt::free(|_| { - static mut VAR: Option<$ty> = None; + // this is a tuple of a MaybeUninit and a bool because using an Option here is + // problematic: Due to niche-optimization, an Option could end up producing a non-zero + // initializer value which would move the entire static from `.bss` into `.data`... + static mut $name: (::core::mem::MaybeUninit<$ty>, bool) = + (::core::mem::MaybeUninit::uninit(), false); #[allow(unsafe_code)] - let used = unsafe { VAR.is_some() }; + let used = unsafe { $name.1 }; if used { None } else { @@ -66,16 +78,16 @@ macro_rules! singleton { #[allow(unsafe_code)] unsafe { - VAR = Some(expr) - } - - #[allow(unsafe_code)] - unsafe { - VAR.as_mut() + $name.1 = true; + $name.0 = ::core::mem::MaybeUninit::new(expr); + Some(&mut *$name.0.as_mut_ptr()) } } }) }; + (: $ty:ty = $expr:expr) => { + $crate::singleton!(VAR: $ty = $expr) + }; } /// ``` compile_fail From 45406f6a667f11b459dad51cf45e2739d23a381b Mon Sep 17 00:00:00 2001 From: Adam Greig Date: Sun, 15 May 2022 22:16:18 +0100 Subject: [PATCH 3/4] Prepare for cortex-m v0.7.5 --- CHANGELOG.md | 3 ++- Cargo.toml | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9b36a5a2..95ed2030 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -746,7 +746,8 @@ fn main() { - Functions to get the vector table - Wrappers over miscellaneous instructions like `bkpt` -[Unreleased]: https://github.com/rust-embedded/cortex-m/compare/v0.7.4...HEAD +[Unreleased]: https://github.com/rust-embedded/cortex-m/compare/v0.7.5...HEAD +[v0.7.5]: https://github.com/rust-embedded/cortex-m/compare/v0.7.4...v0.7.5 [v0.7.4]: https://github.com/rust-embedded/cortex-m/compare/v0.7.3...v0.7.4 [v0.7.3]: https://github.com/rust-embedded/cortex-m/compare/v0.7.2...v0.7.3 [v0.7.2]: https://github.com/rust-embedded/cortex-m/compare/v0.7.1...v0.7.2 diff --git a/Cargo.toml b/Cargo.toml index dcbd3bdb..dc0678ee 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -11,7 +11,7 @@ license = "MIT OR Apache-2.0" name = "cortex-m" readme = "README.md" repository = "https://github.com/rust-embedded/cortex-m" -version = "0.7.4" +version = "0.7.5" edition = "2018" links = "cortex-m" # prevent multiple versions of this crate to be linked together From bba4f0f83287b2c642f074cbcc96312ca7688135 Mon Sep 17 00:00:00 2001 From: Adam Greig Date: Mon, 16 May 2022 00:06:43 +0100 Subject: [PATCH 4/4] Swap cortex-m-semihosting to use asm instead of llvm_asm --- cortex-m-semihosting/src/lib.rs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/cortex-m-semihosting/src/lib.rs b/cortex-m-semihosting/src/lib.rs index a67b84d8..721ac45d 100644 --- a/cortex-m-semihosting/src/lib.rs +++ b/cortex-m-semihosting/src/lib.rs @@ -153,8 +153,7 @@ //! //! ## `inline-asm` //! -//! When this feature is enabled semihosting is implemented using inline assembly (`llvm_asm!`) and -//! compiling this crate requires nightly. +//! When this feature is enabled semihosting is implemented using inline assembly (`asm!`). //! //! 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. @@ -179,7 +178,6 @@ //! //! [pdf]: http://infocenter.arm.com/help/topic/com.arm.doc.dui0471e/DUI0471E_developing_for_arm_processors.pdf -#![cfg_attr(feature = "inline-asm", feature(llvm_asm))] #![deny(missing_docs)] #![no_std] @@ -213,7 +211,7 @@ pub unsafe fn syscall1(_nr: usize, _arg: usize) -> usize { #[cfg(all(thumb, feature = "inline-asm", not(feature = "no-semihosting")))] () => { let mut nr = _nr; - llvm_asm!("bkpt 0xAB" : "+{r0}"(nr) : "{r1}"(_arg) :: "volatile"); + core::arch::asm!("bkpt #0xab", inout("r0") nr, in("r1") _arg, options(nostack, preserves_flags)); nr }