aboutsummaryrefslogtreecommitdiff
path: root/src
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 /src
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
Diffstat (limited to 'src')
-rw-r--r--src/lib.rs2
-rw-r--r--src/macros.rs52
2 files changed, 49 insertions, 5 deletions
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: () = ();