aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Cargo.toml9
-rw-r--r--macros/Cargo.toml3
-rw-r--r--macros/src/trans.rs105
-rw-r--r--src/lib.rs3
4 files changed, 89 insertions, 31 deletions
diff --git a/Cargo.toml b/Cargo.toml
index f345689..448282d 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -14,9 +14,10 @@ version = "0.2.1"
[dependencies]
cortex-m = "0.3.1"
-cortex-m-rtfm-macros = "=0.2.0"
-rtfm-core = "0.1.0"
-static-ref = "0.2.1"
+# TODO should this have been a `path` dep all along?
+cortex-m-rtfm-macros = { path = "macros" }
+# TODO revert before merging
+rtfm-core = { git = "https://github.com/jonas-schievink/rtfm-core.git", branch = "init-resources" }
[target.'cfg(target_arch = "x86_64")'.dev-dependencies]
compiletest_rs = "0.2.8"
@@ -30,4 +31,4 @@ features = ["rt"]
version = "0.7.1"
[profile.release]
-lto = true \ No newline at end of file
+lto = true
diff --git a/macros/Cargo.toml b/macros/Cargo.toml
index eda10c5..b825de2 100644
--- a/macros/Cargo.toml
+++ b/macros/Cargo.toml
@@ -12,7 +12,8 @@ version = "0.2.0"
[dependencies]
error-chain = "0.10.0"
quote = "0.3.15"
-rtfm-syntax = "0.1.0"
+# TODO undo change
+rtfm-syntax = { git = "https://github.com/jonas-schievink/rtfm-syntax.git", branch = "init-resources" }
syn = "0.11.11"
[lib]
diff --git a/macros/src/trans.rs b/macros/src/trans.rs
index c65aaa5..ef23aa5 100644
--- a/macros/src/trans.rs
+++ b/macros/src/trans.rs
@@ -157,14 +157,23 @@ fn init(app: &App, main: &mut Vec<Tokens>, root: &mut Vec<Tokens>) {
let mut tys = vec![quote!(#device::Peripherals)];
let mut exprs = vec![quote!(#device::Peripherals::all())];
+ let mut ret = None;
let mut mod_items = vec![];
- if !app.resources.is_empty() {
+ // Write resources usable by `init`, if any
+
+
+ // Are there any resources that have an initializer? Those can be used by `init`.
+ let has_initialized_resources = app.resources.iter()
+ .find(|&(_, res)| res.expr.is_some()).is_some();
+
+ if has_initialized_resources {
let mut fields = vec![];
let mut lifetime = None;
let mut rexprs = vec![];
- for (name, resource) in &app.resources {
+ for (name, resource) in app.resources.iter()
+ .filter(|&(_, res)| res.expr.is_some()) {
let _name = Ident::new(format!("_{}", name.as_ref()));
lifetime = Some(quote!('a));
@@ -204,6 +213,46 @@ fn init(app: &App, main: &mut Vec<Tokens>, root: &mut Vec<Tokens>) {
exprs.push(quote!(init::Resources::new()));
}
+ let mut late_resources = vec![];
+ let has_late_resources = app.resources.iter()
+ .find(|&(_, res)| res.expr.is_none()).is_some();
+
+ if has_late_resources {
+ // `init` must initialize and return resources
+
+ let mut fields = vec![];
+
+ for (name, resource) in app.resources.iter()
+ .filter(|&(_, res)| res.expr.is_none()) {
+ let _name = Ident::new(format!("_{}", name.as_ref()));
+
+ let ty = &resource.ty;
+
+ fields.push(quote! {
+ pub #name: #ty,
+ });
+
+ late_resources.push(quote! {
+ #_name = #krate::LateResource { init: _late_resources.#name };
+ });
+ }
+
+ root.push(quote! {
+ #[allow(non_camel_case_types)]
+ #[allow(non_snake_case)]
+ pub struct _initLateResourceValues {
+ #(#fields)*
+ }
+ });
+
+ mod_items.push(quote! {
+ pub use ::_initLateResourceValues as LateResourceValues;
+ });
+
+ // `init` must return the initialized resources
+ ret = Some(quote!( -> ::init::LateResourceValues));
+ }
+
root.push(quote! {
#[allow(unsafe_code)]
mod init {
@@ -263,10 +312,11 @@ fn init(app: &App, main: &mut Vec<Tokens>, root: &mut Vec<Tokens>) {
let init = &app.init.path;
main.push(quote! {
// type check
- let init: fn(#(#tys,)*) = #init;
+ let init: fn(#(#tys,)*) #ret = #init;
#krate::atomic(unsafe { &mut #krate::Threshold::new(0) }, |_t| unsafe {
- init(#(#exprs,)*);
+ let _late_resources = init(#(#exprs,)*);
+ #(#late_resources)*
#(#exceptions)*
#(#interrupts)*
@@ -281,33 +331,34 @@ fn resources(app: &App, ownerships: &Ownerships, root: &mut Vec<Tokens>) {
let mut items = vec![];
let mut impls = vec![];
for (name, ownership) in ownerships {
+ let _name = Ident::new(format!("_{}", name.as_ref()));
+
+ if let Some(resource) = app.resources.get(name) {
+ // Declare the static that holds the resource
+ let expr = &resource.expr;
+ let ty = &resource.ty;
+
+ root.push(match *expr {
+ Some(ref expr) => quote! {
+ static mut #_name: #ty = #expr;
+ },
+ None => quote! {
+ // Resource initialized in `init`
+ static mut #_name: #krate::LateResource<#ty> = #krate::LateResource { uninit: () };
+ },
+ });
+ }
+
let mut impl_items = vec![];
- let _name = Ident::new(format!("_{}", name.as_ref()));
match *ownership {
Ownership::Owned { .. } => {
- if let Some(resource) = app.resources.get(name) {
- // For owned resources we don't need claim() or borrow()
- let expr = &resource.expr;
- let ty = &resource.ty;
-
- root.push(quote! {
- static mut #_name: #ty = #expr;
- });
- } else {
- // Peripheral
- continue;
- }
+ // For owned resources we don't need claim() or borrow()
}
Ownership::Shared { ceiling } => {
if let Some(resource) = app.resources.get(name) {
- let expr = &resource.expr;
let ty = &resource.ty;
- root.push(quote! {
- static mut #_name: #ty = #expr;
- });
-
impl_items.push(quote! {
type Data = #ty;
@@ -530,8 +581,14 @@ fn tasks(app: &App, ownerships: &Ownerships, root: &mut Vec<Tokens>) {
pub #name: &'a mut ::#krate::Static<#ty>,
});
- exprs.push(quote! {
- #name: ::#krate::Static::ref_mut(&mut ::#_name),
+ exprs.push(if resource.expr.is_some() {
+ quote! {
+ #name: ::#krate::Static::ref_mut(&mut ::#_name),
+ }
+ } else {
+ quote! {
+ #name: ::#krate::Static::ref_mut(&mut ::#_name.init),
+ }
});
} else {
fields.push(quote! {
diff --git a/src/lib.rs b/src/lib.rs
index 3fde2dd..072e635 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -80,11 +80,10 @@
extern crate cortex_m;
extern crate cortex_m_rtfm_macros;
extern crate rtfm_core;
-extern crate static_ref;
use core::u8;
-pub use rtfm_core::{Resource, Static, Threshold};
+pub use rtfm_core::{Resource, LateResource, Static, Threshold};
pub use cortex_m::asm::{bkpt, wfi};
pub use cortex_m_rtfm_macros::app;
use cortex_m::interrupt::{self, Nr};