aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar homunkulus <homunkulus@gmx.com> 2018-01-25 20:35:56 +0000
committerGravatar homunkulus <homunkulus@gmx.com> 2018-01-25 20:35:56 +0000
commite7618ca3ee577ca7929f7296320d4ad7a8a57a97 (patch)
tree67afff58530513cbf82329a9e90c5bea8f89fa93
parentc921d43f58db6ac4050e53c6b372d530fce073b7 (diff)
parent032af4b2b914f42b5533358cd2f40bbc7a888256 (diff)
downloadcortex-m-e7618ca3ee577ca7929f7296320d4ad7a8a57a97.tar.gz
cortex-m-e7618ca3ee577ca7929f7296320d4ad7a8a57a97.tar.zst
cortex-m-e7618ca3ee577ca7929f7296320d4ad7a8a57a97.zip
Auto merge of #81 - japaric:singleton, r=japaric
[RFC] initialize singletons at runtime This PR changes how the singletons are initialized. The advantage of initializing a singleton at runtime is that the initial value is not constrained to only what works in const context. The disadvantage is that this approach will use up more Flash. With the new approach, `singleton!(_: [u8; 1024] = [0; 1024])` will invoke a memcpy at the caller site; with the old approach, the array would have been initialized (zeroed) during startup. The following code works with the new approach, but doesn't with the old one. ``` rust let x = 0; let y = singleton!(_: u32 = x); ``` cc @therealprof @hannobraun
-rw-r--r--Cargo.toml3
-rw-r--r--src/lib.rs2
-rw-r--r--src/macros.rs52
3 files changed, 51 insertions, 6 deletions
diff --git a/Cargo.toml b/Cargo.toml
index 5885c6b..82712ee 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -13,6 +13,7 @@ version = "0.4.2"
aligned = "0.1.1"
bare-metal = "0.1.0"
volatile-register = "0.2.0"
+untagged-option = "0.1.1"
[features]
-cm7-r0p1 = [] \ No newline at end of file
+cm7-r0p1 = []
diff --git a/src/lib.rs b/src/lib.rs
index 694d1b2..6af60d7 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -15,6 +15,7 @@
extern crate aligned;
extern crate bare_metal;
+extern crate untagged_option;
extern crate volatile_register;
#[macro_use]
@@ -31,3 +32,4 @@ pub mod peripheral;
pub mod register;
pub use peripheral::Peripherals;
+pub use untagged_option::UntaggedOption;
diff --git a/src/macros.rs b/src/macros.rs
index c9a32c2..7d2cf6a 100644
--- a/src/macros.rs
+++ b/src/macros.rs
@@ -52,17 +52,59 @@ macro_rules! iprintln {
#[macro_export]
macro_rules! singleton {
(: $ty:ty = $expr:expr) => {
- $crate::interrupt::free(|_| unsafe {
+ $crate::interrupt::free(|_| {
static mut USED: bool = false;
- static mut VAR: $ty = $expr;
+ static mut VAR: $crate::UntaggedOption<$ty> = $crate::UntaggedOption { none: () };
- if USED {
+
+ #[allow(unsafe_code)]
+ let used = unsafe { USED };
+ if used {
None
} else {
- USED = true;
- let var: &'static mut _ = &mut VAR;
+ #[allow(unsafe_code)]
+ unsafe { USED = true }
+
+ let expr = $expr;
+
+ #[allow(unsafe_code)]
+ unsafe { VAR.some = expr }
+
+ #[allow(unsafe_code)]
+ let var: &'static mut _ = unsafe { &mut VAR.some };
+
Some(var)
}
})
}
}
+
+
+/// ``` compile_fail
+/// #[macro_use(singleton)]
+/// extern crate cortex_m;
+///
+/// fn main() {}
+///
+/// fn foo() {
+/// // check that the call to `uninitialized` requires unsafe
+/// singleton!(: u8 = std::mem::uninitialized());
+/// }
+/// ```
+#[allow(dead_code)]
+const CFAIL: () = ();
+
+/// ```
+/// #![deny(unsafe_code)]
+/// #[macro_use(singleton)]
+/// extern crate cortex_m;
+///
+/// fn main() {}
+///
+/// fn foo() {
+/// // check that calls to `singleton!` don't trip the `unsafe_code` lint
+/// singleton!(: u8 = 0);
+/// }
+/// ```
+#[allow(dead_code)]
+const CPASS: () = ();