aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGELOG.md9
-rw-r--r--Cargo.toml4
-rw-r--r--examples/late-resources.rs32
-rw-r--r--gen-examples.sh1
-rw-r--r--macros/Cargo.toml2
-rw-r--r--macros/src/lib.rs78
-rw-r--r--src/examples/_5_late_resources.rs91
-rw-r--r--src/examples/_6_generics.rs (renamed from src/examples/_5_generics.rs)0
-rw-r--r--src/examples/_7_full_syntax.rs (renamed from src/examples/_6_full_syntax.rs)0
-rw-r--r--src/examples/mod.rs5
10 files changed, 161 insertions, 61 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index fee81f35..405923bd 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 3c772ff5..3b2aaffa 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 bc386584..337fbdfa 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 d053c95b..e6870c48 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 748637c1..d51cbc26 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 bef5dcc1..039c19a7 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 00000000..8a5b6e16
--- /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
index 82ecdf99..82ecdf99 100644
--- a/src/examples/_5_generics.rs
+++ b/src/examples/_6_generics.rs
diff --git a/src/examples/_6_full_syntax.rs b/src/examples/_7_full_syntax.rs
index 80520657..80520657 100644
--- a/src/examples/_6_full_syntax.rs
+++ b/src/examples/_7_full_syntax.rs
diff --git a/src/examples/mod.rs b/src/examples/mod.rs
index e0be5a6f..53e74ed1 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;