From 948e1fd0fbd96f574c31909843b2ed3debabf6fc Mon Sep 17 00:00:00 2001
From: Jorge Aparicio <jorge@japaric.io>
Date: Wed, 22 Nov 2017 09:27:14 +0100
Subject: [PATCH] v0.2.2

---
 CHANGELOG.md                                  |  9 +-
 Cargo.toml                                    |  4 +-
 examples/late-resources.rs                    | 32 ++++---
 gen-examples.sh                               |  1 +
 macros/Cargo.toml                             |  2 +-
 macros/src/lib.rs                             | 78 ++++++++--------
 src/examples/_5_late_resources.rs             | 91 +++++++++++++++++++
 .../{_5_generics.rs => _6_generics.rs}        |  0
 .../{_6_full_syntax.rs => _7_full_syntax.rs}  |  0
 src/examples/mod.rs                           |  5 +-
 10 files changed, 161 insertions(+), 61 deletions(-)
 create mode 100644 src/examples/_5_late_resources.rs
 rename src/examples/{_5_generics.rs => _6_generics.rs} (100%)
 rename src/examples/{_6_full_syntax.rs => _7_full_syntax.rs} (100%)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index fee81f3..405923b 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -5,6 +5,12 @@ This project adheres to [Semantic Versioning](http://semver.org/).
 
 ## [Unreleased]
 
+## [v0.2.2] - 2017-11-22
+
+### Added
+
+- Support for runtime initialized resources ("late" resources).
+
 ## [v0.2.1] - 2017-07-29
 
 ### Fixed
@@ -50,7 +56,8 @@ This project adheres to [Semantic Versioning](http://semver.org/).
 
 - Initial release
 
-[Unreleased]: https://github.com/japaric/cortex-m-rtfm/compare/v0.2.1...HEAD
+[Unreleased]: https://github.com/japaric/cortex-m-rtfm/compare/v0.2.2...HEAD
+[v0.2.2]: https://github.com/japaric/cortex-m-rtfm/compare/v0.2.1...v0.2.2
 [v0.2.1]: https://github.com/japaric/cortex-m-rtfm/compare/v0.2.0...v0.2.1
 [v0.2.0]: https://github.com/japaric/cortex-m-rtfm/compare/v0.1.1...v0.2.0
 [v0.1.1]: https://github.com/japaric/cortex-m-rtfm/compare/v0.1.0...v0.1.1
diff --git a/Cargo.toml b/Cargo.toml
index 3c772ff..3b2aaff 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -10,13 +10,13 @@ keywords = ["arm", "cortex-m"]
 license = "MIT OR Apache-2.0"
 name = "cortex-m-rtfm"
 repository = "https://github.com/japaric/cortex-m-rtfm"
-version = "0.2.1"
+version = "0.2.2"
 
 [dependencies]
 cortex-m = "0.3.1"
 untagged-option = "0.1.1"
 rtfm-core = "0.1.0"
-cortex-m-rtfm-macros = { path = "macros" }
+cortex-m-rtfm-macros = "0.2.1"
 
 [target.'cfg(target_arch = "x86_64")'.dev-dependencies]
 compiletest_rs = "0.2.8"
diff --git a/examples/late-resources.rs b/examples/late-resources.rs
index bc38658..337fbdf 100644
--- a/examples/late-resources.rs
+++ b/examples/late-resources.rs
@@ -16,19 +16,21 @@ app! {
         // Usually, resources are initialized with a constant initializer:
         static ON: bool = false;
 
-        // However, there are cases where this is not possible or not desired. For example, there
-        // may not be a sensible value to use, or the type may not be constructible in a constant
-        // (like `Vec`).
-        // While it is possible to use an `Option` in some cases, that requires you to properly
-        // initialize it and `.unwrap()` it at every use. It also consumes more memory.
+        // However, there are cases where this is not possible or not desired.
+        // For example, there may not be a sensible value to use, or the type may
+        // not be constructible in a constant (like `Vec`).
         //
-        // To solve this, it is possible to defer initialization of resources to `init` by omitting
-        // the initializer. Doing that will require `init` to return the values of all "late"
-        // resources.
+        // While it is possible to use an `Option` in some cases, that requires
+        // you to properly initialize it and `.unwrap()` it at every use. It
+        // also consumes more memory.
+        //
+        // To solve this, it is possible to defer initialization of resources to
+        // `init` by omitting the initializer. Doing that will require `init` to
+        // return the values of all "late" resources.
         static IP_ADDRESS: u32;
 
-        // PORT is used by 2 tasks, making it a shared resource. This just tests another internal
-        // code path and is not important for the example.
+        // PORT is used by 2 tasks, making it a shared resource. This just tests
+        // another internal code path and is not important for the example.
         static PORT: u16;
     },
 
@@ -54,22 +56,24 @@ app! {
 
 // The signature of `init` is now required to have a specific return type.
 fn init(_p: init::Peripherals, _r: init::Resources) -> init::LateResourceValues {
-    // `init::Resources` does not contain `IP_ADDRESS`, since it is not yet initialized.
+    // `init::Resources` does not contain `IP_ADDRESS`, since it is not yet
+    // initialized.
     //_r.IP_ADDRESS;     // doesn't compile
 
     // ...obtain value for IP_ADDRESS from EEPROM/DHCP...
     let ip_address = 0x7f000001;
 
     init::LateResourceValues {
-        // This struct will contain fields for all resources with omitted initializers.
+        // This struct will contain fields for all resources with omitted
+        // initializers.
         IP_ADDRESS: ip_address,
         PORT: 0,
     }
 }
 
 fn sys_tick(_t: &mut Threshold, r: SYS_TICK::Resources) {
-    // Other tasks can access late resources like any other, since they are guaranteed to be
-    // initialized when tasks are run.
+    // Other tasks can access late resources like any other, since they are
+    // guaranteed to be initialized when tasks are run.
 
     r.IP_ADDRESS;
 }
diff --git a/gen-examples.sh b/gen-examples.sh
index d053c95..e6870c4 100644
--- a/gen-examples.sh
+++ b/gen-examples.sh
@@ -10,6 +10,7 @@ main() {
         two-tasks
         preemption
         nested
+        late-resources
         generics
         full-syntax
     )
diff --git a/macros/Cargo.toml b/macros/Cargo.toml
index 748637c..d51cbc2 100644
--- a/macros/Cargo.toml
+++ b/macros/Cargo.toml
@@ -7,7 +7,7 @@ keywords = ["arm", "cortex-m"]
 license = "MIT OR Apache-2.0"
 name = "cortex-m-rtfm-macros"
 repository = "https://github.com/japaric/cortex-m-rtfm"
-version = "0.2.0"
+version = "0.2.1"
 
 [dependencies]
 error-chain = "0.10.0"
diff --git a/macros/src/lib.rs b/macros/src/lib.rs
index bef5dcc..039c19a 100644
--- a/macros/src/lib.rs
+++ b/macros/src/lib.rs
@@ -19,11 +19,9 @@ mod analyze;
 mod check;
 mod trans;
 
-/// The `app!` macro, a macro used to specify the tasks and resources of a
-/// RTFM application.
+/// The `app!` macro, a macro used to specify the tasks and resources of a RTFM application.
 ///
-/// The contents of this macro uses a `key: value` syntax. All the possible keys
-/// are shown below:
+/// The contents of this macro uses a `key: value` syntax. All the possible keys are shown below:
 ///
 /// ``` text
 /// app! {
@@ -41,14 +39,13 @@ mod trans;
 ///
 /// # `device`
 ///
-/// The value of this key is a Rust path, like `foo::bar::baz`, that must point to
-/// a *device crate*, a crate generated using `svd2rust`.
+/// The value of this key is a Rust path, like `foo::bar::baz`, that must point to a *device crate*,
+/// a crate generated using `svd2rust`.
 ///
 /// # `resources`
 ///
-/// This key is optional. Its value is a list of `static` variables. These
-/// variables are the data that can be safely accessed, modified and shared by
-/// tasks.
+/// This key is optional. Its value is a list of `static` variables. These variables are the data
+/// that can be safely accessed, modified and shared by tasks.
 ///
 /// ``` text
 /// resources: {
@@ -56,15 +53,18 @@ mod trans;
 ///     static B: i32 = 0;
 ///     static C: [u8; 16] = [0; 16];
 ///     static D: Thing = Thing::new(..);
+///     static E: Thing;
 /// }
 /// ```
 ///
+/// The initial value of a resource can be omitted. This means that the resource will be runtime
+/// initialized.
+///
 /// If this key is omitted its value defaults to an empty list.
 ///
 /// # `init`
 ///
-/// This key is optional. Its value is a set of key values. All the possible
-/// keys are shown below:
+/// This key is optional. Its value is a set of key values. All the possible keys are shown below:
 ///
 /// ``` text
 /// init: {
@@ -74,15 +74,14 @@ mod trans;
 ///
 /// ## `init.path`
 ///
-/// This key is optional. Its value is a Rust path, like `foo::bar::baz`, that
-/// points to the initialization function.
+/// This key is optional. Its value is a Rust path, like `foo::bar::baz`, that points to the
+/// initialization function.
 ///
 /// If the key is omitted its value defaults to `init`.
 ///
 /// # `idle`
 ///
-/// This key is optional. Its value is a set of key values. All the possible
-/// keys are shown below:
+/// This key is optional. Its value is a set of key values. All the possible keys are shown below:
 ///
 /// ``` text
 /// idle: {
@@ -93,25 +92,24 @@ mod trans;
 ///
 /// ## `idle.path`
 ///
-/// This key is optional. Its value is a Rust path, like `foo::bar::baz`, that
-/// points to the idle loop function.
+/// This key is optional. Its value is a Rust path, like `foo::bar::baz`, that points to the idle
+/// loop function.
 ///
 /// If the key is omitted its value defaults to `idle`.
 ///
 /// ## `idle.resources`
 ///
-/// This key is optional. Its value is a list of resources the `idle` loop has
-/// access to. The resources in this list can refer to the resources listed in
-/// the top `resources` key. If the name doesn't match one of the resources
-/// listed in the top `resources` key the resource is assumed to be a
-/// peripheral.
+/// This key is optional. Its value is a list of resources the `idle` loop has access to. The
+/// resources in this list can refer to the resources listed in the top `resources` key. If the name
+/// doesn't match one of the resources /// listed in the top `resources` key the resource is assumed
+/// to be a peripheral.
 ///
 /// If omitted its value defaults to an empty list.
 ///
 /// # `tasks`
 ///
-/// This key is optional. Its value is a list of tasks. Each task itself is a
-/// set of key value pair. The full syntax is shown below:
+/// This key is optional. Its value is a list of tasks. Each task itself is a set of key value pair.
+/// The full syntax is shown below:
 ///
 /// ``` text
 /// tasks: {
@@ -128,39 +126,37 @@ mod trans;
 ///
 /// ## `tasks.$TASK`
 ///
-/// The key must be either a Cortex-M exception or a device specific interrupt.
-/// `PENDSV`, `SVCALL`, `SYS_TICK` are considered as exceptions. All other names
-/// are assumed to be interrupts.
+/// The key must be either a Cortex-M exception or a device specific interrupt. `PENDSV`, `SVCALL`,
+/// `SYS_TICK` are considered as exceptions. All other names are assumed to be interrupts.
 ///
 /// ## `tasks.$TASK.enabled`
 ///
-/// This key is optional for interrupts and forbidden for exceptions. Its value
-/// must be a boolean and indicates whether the interrupt will be enabled
-/// (`true`) or disabled (`false`) after `init` ends and before `idle` starts.
+/// This key is optional for interrupts and forbidden for exceptions. Its value must be a boolean
+/// and indicates whether the interrupt will be enabled (`true`) or disabled (`false`) after `init`
+/// ends and before `idle` starts.
 ///
 /// If this key is omitted its value defaults to `true`.
 ///
 /// ## `tasks.$TASK.path`
 ///
-/// The value of this key is a Rust path, like `foo::bar::baz`, that points to
-/// the handler of this task.
+/// The value of this key is a Rust path, like `foo::bar::baz`, that points to the handler of this
+/// task.
 ///
 /// ## `tasks.$TASK.priority`
 ///
-/// This key is optional. Its value is an integer with type `u8` that specifies
-/// the priority of this task. The minimum valid priority is 1. The maximum
-/// valid priority depends on the number of the NVIC priority bits the device
-/// has; if the device has 4 priority bits the maximum allowed value would be
-/// 16.
+/// This key is optional. Its value is an integer with type `u8` that specifies the priority of this
+/// task. The minimum valid priority is 1. The maximum valid priority depends on the number of the
+/// NVIC priority bits the device has; if the device has 4 priority bits the maximum allowed value
+/// would be 16.
 ///
 /// If this key is omitted its value defaults to `1`.
 ///
 /// ## `tasks.$TASK.resources`
 ///
-/// This key is optional. Its value is a list of resources this task has access
-/// to. The resources in this list can refer to the resources listed in the top
-/// `resources` key. If the name doesn't match one of the resources listed in
-/// the top `resources` key the resource is assumed to be a peripheral.
+/// This key is optional. Its value is a list of resources this task has access to. The resources in
+/// this list can refer to the resources listed in the top `resources` key. If the name doesn't
+/// match one of the resources listed in the top `resources` key the resource is assumed to be a
+/// peripheral.
 ///
 /// If omitted its value defaults to an empty list.
 #[proc_macro]
diff --git a/src/examples/_5_late_resources.rs b/src/examples/_5_late_resources.rs
new file mode 100644
index 0000000..8a5b6e1
--- /dev/null
+++ b/src/examples/_5_late_resources.rs
@@ -0,0 +1,91 @@
+//! Demonstrates initialization of resources in `init`.
+//!
+//! ```
+//! 
+//! #![deny(unsafe_code)]
+//! #![feature(proc_macro)]
+//! #![no_std]
+//! 
+//! extern crate cortex_m_rtfm as rtfm;
+//! extern crate stm32f103xx;
+//! 
+//! use rtfm::{app, Threshold};
+//! 
+//! app! {
+//!     device: stm32f103xx,
+//! 
+//!     resources: {
+//!         // Usually, resources are initialized with a constant initializer:
+//!         static ON: bool = false;
+//! 
+//!         // However, there are cases where this is not possible or not desired.
+//!         // For example, there may not be a sensible value to use, or the type may
+//!         // not be constructible in a constant (like `Vec`).
+//!         //
+//!         // While it is possible to use an `Option` in some cases, that requires
+//!         // you to properly initialize it and `.unwrap()` it at every use. It
+//!         // also consumes more memory.
+//!         //
+//!         // To solve this, it is possible to defer initialization of resources to
+//!         // `init` by omitting the initializer. Doing that will require `init` to
+//!         // return the values of all "late" resources.
+//!         static IP_ADDRESS: u32;
+//! 
+//!         // PORT is used by 2 tasks, making it a shared resource. This just tests
+//!         // another internal code path and is not important for the example.
+//!         static PORT: u16;
+//!     },
+//! 
+//!     idle: {
+//!         // Test that late resources can be used in idle
+//!         resources: [IP_ADDRESS],
+//!     },
+//! 
+//!     tasks: {
+//!         SYS_TICK: {
+//!             priority: 1,
+//!             path: sys_tick,
+//!             resources: [IP_ADDRESS, PORT, ON],
+//!         },
+//! 
+//!         EXTI0: {
+//!             priority: 2,
+//!             path: exti0,
+//!             resources: [PORT],
+//!         }
+//!     }
+//! }
+//! 
+//! // The signature of `init` is now required to have a specific return type.
+//! fn init(_p: init::Peripherals, _r: init::Resources) -> init::LateResourceValues {
+//!     // `init::Resources` does not contain `IP_ADDRESS`, since it is not yet
+//!     // initialized.
+//!     //_r.IP_ADDRESS;     // doesn't compile
+//! 
+//!     // ...obtain value for IP_ADDRESS from EEPROM/DHCP...
+//!     let ip_address = 0x7f000001;
+//! 
+//!     init::LateResourceValues {
+//!         // This struct will contain fields for all resources with omitted
+//!         // initializers.
+//!         IP_ADDRESS: ip_address,
+//!         PORT: 0,
+//!     }
+//! }
+//! 
+//! fn sys_tick(_t: &mut Threshold, r: SYS_TICK::Resources) {
+//!     // Other tasks can access late resources like any other, since they are
+//!     // guaranteed to be initialized when tasks are run.
+//! 
+//!     r.IP_ADDRESS;
+//! }
+//! 
+//! fn exti0(_t: &mut Threshold, _r: EXTI0::Resources) {}
+//! 
+//! fn idle(_t: &mut Threshold, _r: idle::Resources) -> ! {
+//!     loop {
+//!         rtfm::wfi();
+//!     }
+//! }
+//! ```
+// Auto-generated. Do not modify.
diff --git a/src/examples/_5_generics.rs b/src/examples/_6_generics.rs
similarity index 100%
rename from src/examples/_5_generics.rs
rename to src/examples/_6_generics.rs
diff --git a/src/examples/_6_full_syntax.rs b/src/examples/_7_full_syntax.rs
similarity index 100%
rename from src/examples/_6_full_syntax.rs
rename to src/examples/_7_full_syntax.rs
diff --git a/src/examples/mod.rs b/src/examples/mod.rs
index e0be5a6..53e74ed 100644
--- a/src/examples/mod.rs
+++ b/src/examples/mod.rs
@@ -5,5 +5,6 @@ pub mod _1_one_task;
 pub mod _2_two_tasks;
 pub mod _3_preemption;
 pub mod _4_nested;
-pub mod _5_generics;
-pub mod _6_full_syntax;
+pub mod _5_late_resources;
+pub mod _6_generics;
+pub mod _7_full_syntax;
-- 
GitLab