aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGravatar homunkulus <homunkulus@gmx.com> 2018-01-15 16:05:22 +0000
committerGravatar homunkulus <homunkulus@gmx.com> 2018-01-15 16:05:22 +0000
commitca3d4ef29b8cab72106587908c459da8328a74ea (patch)
treeb90fe78b8ba93fda9e7a005d8477e963ac4a79c6 /src
parent024527b41cdf3f5c9556b5eb94a1a4d2b33758ef (diff)
parent4f9664c54c4dbe5c05cb7a1afa29f2f6952e1ada (diff)
downloadcortex-m-ca3d4ef29b8cab72106587908c459da8328a74ea.tar.gz
cortex-m-ca3d4ef29b8cab72106587908c459da8328a74ea.tar.zst
cortex-m-ca3d4ef29b8cab72106587908c459da8328a74ea.zip
Auto merge of #70 - japaric:safe-static-mut, r=japaric
safe `&'static mut` references through a runtime checked macro runtime checked implementation of japaric/cortex-m-rtfm#59 that doesn't depend on RTFM macros TODO - [ ] bikeshed macro syntax
Diffstat (limited to 'src')
-rw-r--r--src/macros.rs44
1 files changed, 44 insertions, 0 deletions
diff --git a/src/macros.rs b/src/macros.rs
index 465d759..c9a32c2 100644
--- a/src/macros.rs
+++ b/src/macros.rs
@@ -22,3 +22,47 @@ macro_rules! iprintln {
iprint!($channel, concat!($fmt, "\n"), $($arg)*);
};
}
+
+/// Macro to create a mutable reference to a statically allocated value
+///
+/// This macro returns a value with type `Option<&'static mut $ty>`. `Some($expr)` will be returned
+/// the first time the macro is executed; further calls will return `None`. To avoid `unwrap`ping a
+/// `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.
+///
+/// # Example
+///
+/// ``` no_run
+/// #[macro_use(singleton)]
+/// extern crate cortex_m;
+///
+/// fn main() {
+/// // OK if `main` is executed only once
+/// let x: &'static mut bool = singleton!(: bool = false).unwrap();
+///
+/// let y = alias();
+/// // BAD this second call to `alias` will definitively `panic!`
+/// let y_alias = alias();
+/// }
+///
+/// fn alias() -> &'static mut bool {
+/// singleton!(: bool = false).unwrap()
+/// }
+/// ```
+#[macro_export]
+macro_rules! singleton {
+ (: $ty:ty = $expr:expr) => {
+ $crate::interrupt::free(|_| unsafe {
+ static mut USED: bool = false;
+ static mut VAR: $ty = $expr;
+
+ if USED {
+ None
+ } else {
+ USED = true;
+ let var: &'static mut _ = &mut VAR;
+ Some(var)
+ }
+ })
+ }
+}