aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Jorge Aparicio <jorge@japaric.io> 2017-12-09 17:14:51 +0100
committerGravatar Jorge Aparicio <jorge@japaric.io> 2017-12-09 17:17:56 +0100
commitd30bdcb096774c1f56d9823fb2fbb78bf5cd3584 (patch)
tree0a781ee30567a2f13de11d03f25736bf60d3866f
parenta6dd004113fcbc03ffacacc519d742ee84886c1d (diff)
downloadrtic-d30bdcb096774c1f56d9823fb2fbb78bf5cd3584.tar.gz
rtic-d30bdcb096774c1f56d9823fb2fbb78bf5cd3584.tar.zst
rtic-d30bdcb096774c1f56d9823fb2fbb78bf5cd3584.zip
safe `&'static mut` references via init.resources
-rw-r--r--examples/safe-static-mut-ref.rs32
-rw-r--r--macros/Cargo.toml3
-rw-r--r--macros/src/check.rs31
-rw-r--r--macros/src/trans.rs30
-rw-r--r--tests/cfail/init-resource-share-idle.rs31
-rw-r--r--tests/cfail/init-resource-share-task.rs36
6 files changed, 153 insertions, 10 deletions
diff --git a/examples/safe-static-mut-ref.rs b/examples/safe-static-mut-ref.rs
new file mode 100644
index 00000000..bb872122
--- /dev/null
+++ b/examples/safe-static-mut-ref.rs
@@ -0,0 +1,32 @@
+//! Safe creation of `&'static mut` references
+#![deny(unsafe_code)]
+#![deny(warnings)]
+#![feature(proc_macro)]
+#![no_std]
+
+extern crate cortex_m_rtfm as rtfm;
+extern crate stm32f103xx;
+
+use rtfm::app;
+
+app! {
+ device: stm32f103xx,
+
+ resources: {
+ static BUFFER: [u8; 16] = [0; 16];
+ },
+
+ init: {
+ resources: [BUFFER],
+ },
+}
+
+fn init(_p: init::Peripherals, r: init::Resources) {
+ let _buf: &'static mut [u8] = r.BUFFER;
+}
+
+fn idle() -> ! {
+ loop {
+ rtfm::wfi();
+ }
+}
diff --git a/macros/Cargo.toml b/macros/Cargo.toml
index d51cbc26..d2e4da5b 100644
--- a/macros/Cargo.toml
+++ b/macros/Cargo.toml
@@ -12,7 +12,8 @@ version = "0.2.1"
[dependencies]
error-chain = "0.10.0"
quote = "0.3.15"
-rtfm-syntax = "0.2.0"
+# rtfm-syntax = "0.2.0"
+rtfm-syntax = { git = "https://github.com/japaric/rtfm-syntax", branch = "init-resources" }
syn = "0.11.11"
[lib]
diff --git a/macros/src/check.rs b/macros/src/check.rs
index 63cac1fa..f6fd9cc6 100644
--- a/macros/src/check.rs
+++ b/macros/src/check.rs
@@ -77,7 +77,38 @@ pub fn app(app: check::App) -> Result<App> {
}
fn resources(app: &App) -> Result<()> {
+ for name in &app.init.resources {
+ if let Some(resource) = app.resources.get(name) {
+ ensure!(
+ resource.expr.is_some(),
+ "resource `{}`, allocated to `init`, must have an initial value",
+ name
+ );
+ } else {
+ bail!(
+ "resource `{}`, allocated to `init`, must be a data resource",
+ name
+ );
+ }
+
+ ensure!(
+ !app.idle.resources.contains(name),
+ "resources assigned to `init` can't be shared with `idle`"
+ );
+
+ ensure!(
+ app.tasks
+ .iter()
+ .all(|(_, task)| !task.resources.contains(name)),
+ "resources assigned to `init` can't be shared with tasks"
+ )
+ }
+
for resource in app.resources.keys() {
+ if app.init.resources.contains(resource) {
+ continue;
+ }
+
if app.idle.resources.contains(resource) {
continue;
}
diff --git a/macros/src/trans.rs b/macros/src/trans.rs
index 1008dfed..b540fd1d 100644
--- a/macros/src/trans.rs
+++ b/macros/src/trans.rs
@@ -249,18 +249,30 @@ fn init(app: &App, main: &mut Vec<Tokens>, root: &mut Vec<Tokens>) {
let mut rexprs = vec![];
for (name, resource) in init_resources {
- let _name = Ident::new(format!("_{}", name.as_ref()));
- lifetime = Some(quote!('a));
-
let ty = &resource.ty;
- fields.push(quote! {
- pub #name: &'a mut #ty,
- });
+ if app.init.resources.contains(name) {
+ fields.push(quote! {
+ pub #name: &'static mut #ty,
+ });
- rexprs.push(quote! {
- #name: &mut ::#_name,
- });
+ let expr = &resource.expr;
+ rexprs.push(quote!(#name: {
+ static mut #name: #ty = #expr;
+ &mut #name
+ }));
+ } else {
+ let _name = Ident::new(format!("_{}", name.as_ref()));
+ lifetime = Some(quote!('a));
+
+ fields.push(quote! {
+ pub #name: &'a mut #ty,
+ });
+
+ rexprs.push(quote! {
+ #name: &mut ::#_name,
+ });
+ }
}
root.push(quote! {
diff --git a/tests/cfail/init-resource-share-idle.rs b/tests/cfail/init-resource-share-idle.rs
new file mode 100644
index 00000000..d8332469
--- /dev/null
+++ b/tests/cfail/init-resource-share-idle.rs
@@ -0,0 +1,31 @@
+#![deny(warnings)]
+#![feature(proc_macro)]
+#![no_std]
+
+extern crate cortex_m_rtfm as rtfm;
+extern crate stm32f103xx;
+
+use rtfm::app;
+
+app! { //~ proc macro panicked
+ device: stm32f103xx,
+
+ resources: {
+ static BUFFER: [u8; 16] = [0; 16];
+ },
+
+ init: {
+ resources: [BUFFER],
+ },
+
+ idle: {
+ // ERROR resources assigned to `init` can't be shared with `idle`
+ resources: [BUFFER],
+ },
+}
+
+fn init(_p: init::Peripherals, _r: init::Resources) {}
+
+fn idle(_r: init::Resources) -> ! {
+ loop {}
+}
diff --git a/tests/cfail/init-resource-share-task.rs b/tests/cfail/init-resource-share-task.rs
new file mode 100644
index 00000000..8fe68899
--- /dev/null
+++ b/tests/cfail/init-resource-share-task.rs
@@ -0,0 +1,36 @@
+#![deny(warnings)]
+#![feature(proc_macro)]
+#![no_std]
+
+extern crate cortex_m_rtfm as rtfm;
+extern crate stm32f103xx;
+
+use rtfm::app;
+
+app! { //~ proc macro panicked
+ device: stm32f103xx,
+
+ resources: {
+ static BUFFER: [u8; 16] = [0; 16];
+ },
+
+ init: {
+ resources: [BUFFER],
+ },
+
+ tasks: {
+ SYS_TICK: {
+ path: sys_tick,
+ // ERROR resources assigned to `init` can't be shared with tasks
+ resources: [BUFFER],
+ },
+ },
+}
+
+fn init(_p: init::Peripherals) {}
+
+fn idle() -> ! {
+ loop {}
+}
+
+fn sys_tick() {}