aboutsummaryrefslogtreecommitdiff
path: root/examples
diff options
context:
space:
mode:
authorJorge Aparicio <jorge@japaric.io>2018-11-03 17:02:41 +0100
committerJorge Aparicio <jorge@japaric.io>2018-11-03 17:16:55 +0100
commitc631049efcadca8b07940c794cce2be58fa48444 (patch)
treef6bd73e5c396fc06072557ee965cc59e9c8e3e9f /examples
parent653338e7997a0cdc5deaed98b1bb5f60006717ed (diff)
v0.4.0
closes #32 closes #33
Diffstat (limited to 'examples')
-rw-r--r--examples/baseline.rs61
-rw-r--r--examples/capacity.rs57
-rw-r--r--examples/custom-type.rs49
-rw-r--r--examples/full-syntax.rs83
-rw-r--r--examples/generics.rs73
-rw-r--r--examples/idle.rs43
-rw-r--r--examples/init.rs44
-rw-r--r--examples/interrupt.rs61
-rw-r--r--examples/late-resources.rs86
-rw-r--r--examples/late.rs65
-rw-r--r--examples/lock.rs71
-rw-r--r--examples/message.rs61
-rw-r--r--examples/nested.rs128
-rw-r--r--examples/not-send.rs58
-rw-r--r--examples/not-sync.rs41
-rw-r--r--examples/one-task.rs96
-rw-r--r--examples/periodic.rs43
-rw-r--r--examples/preemption.rs67
-rw-r--r--examples/ramfunc.rs53
-rw-r--r--examples/resource.rs60
-rw-r--r--examples/safe-static-mut-ref.rs31
-rw-r--r--examples/schedule.rs51
-rw-r--r--examples/singleton.rs69
-rw-r--r--examples/smallest.rs17
-rw-r--r--examples/static.rs47
-rw-r--r--examples/task.rs61
-rw-r--r--examples/two-tasks.rs58
-rw-r--r--examples/types.rs54
-rw-r--r--examples/zero-tasks.rs43
29 files changed, 1017 insertions, 714 deletions
diff --git a/examples/baseline.rs b/examples/baseline.rs
new file mode 100644
index 0000000..73ef4c9
--- /dev/null
+++ b/examples/baseline.rs
@@ -0,0 +1,61 @@
+//! examples/baseline.rs
+
+#![deny(unsafe_code)]
+#![deny(warnings)]
+#![no_main]
+#![no_std]
+
+extern crate panic_semihosting;
+
+use cortex_m_semihosting::debug;
+use lm3s6965::Interrupt;
+use rtfm::app;
+
+macro_rules! println {
+ ($($tt:tt)*) => {
+ if let Ok(mut stdout) = cortex_m_semihosting::hio::hstdout() {
+ use core::fmt::Write;
+
+ writeln!(stdout, $($tt)*).ok();
+ }
+ };
+}
+
+// NOTE: does NOT properly work on QEMU
+#[app(device = lm3s6965)]
+const APP: () = {
+ #[init(spawn = [foo])]
+ fn init() {
+ println!("init(baseline = {:?})", start);
+
+ // `foo` inherits the baseline of `init`: `Instant(0)`
+ spawn.foo().unwrap();
+ }
+
+ #[task(schedule = [foo])]
+ fn foo() {
+ static mut ONCE: bool = true;
+
+ println!("foo(baseline = {:?})", scheduled);
+
+ if *ONCE {
+ *ONCE = false;
+
+ rtfm::pend(Interrupt::UART0);
+ } else {
+ debug::exit(debug::EXIT_SUCCESS);
+ }
+ }
+
+ #[interrupt(spawn = [foo])]
+ fn UART0() {
+ println!("UART0(baseline = {:?})", start);
+
+ // `foo` inherits the baseline of `UART0`: its `start` time
+ spawn.foo().unwrap();
+ }
+
+ extern "C" {
+ fn UART1();
+ }
+};
diff --git a/examples/capacity.rs b/examples/capacity.rs
new file mode 100644
index 0000000..2dea2c3
--- /dev/null
+++ b/examples/capacity.rs
@@ -0,0 +1,57 @@
+//! examples/capacity.rs
+
+#![deny(unsafe_code)]
+#![deny(warnings)]
+#![no_main]
+#![no_std]
+
+extern crate panic_semihosting;
+
+use cortex_m_semihosting::debug;
+use lm3s6965::Interrupt;
+use rtfm::app;
+
+macro_rules! println {
+ ($($tt:tt)*) => {
+ if let Ok(mut stdout) = cortex_m_semihosting::hio::hstdout() {
+ use core::fmt::Write;
+
+ writeln!(stdout, $($tt)*).ok();
+ }
+ };
+}
+
+#[app(device = lm3s6965)]
+const APP: () = {
+ #[init(spawn = [foo])]
+ fn init() {
+ rtfm::pend(Interrupt::UART0);
+ }
+
+ #[interrupt(spawn = [foo, bar])]
+ fn UART0() {
+ spawn.foo(0).unwrap();
+ spawn.foo(1).unwrap();
+ spawn.foo(2).unwrap();
+ spawn.foo(3).unwrap();
+
+ spawn.bar().unwrap();
+ }
+
+ #[task(capacity = 4)]
+ fn foo(x: u32) {
+ println!("foo({})", x);
+ }
+
+ #[task]
+ fn bar() {
+ println!("bar");
+
+ debug::exit(debug::EXIT_SUCCESS);
+ }
+
+ // Interrupt handlers used to dispatch software tasks
+ extern "C" {
+ fn UART1();
+ }
+};
diff --git a/examples/custom-type.rs b/examples/custom-type.rs
deleted file mode 100644
index 826e9dd..0000000
--- a/examples/custom-type.rs
+++ /dev/null
@@ -1,49 +0,0 @@
-#![deny(unsafe_code)]
-#![deny(warnings)]
-#![no_std]
-
-extern crate cortex_m_rtfm as rtfm;
-extern crate stm32f103xx;
-
-use rtfm::{app, Threshold};
-
-pub struct Foo;
-
-app! {
- device: stm32f103xx,
-
- resources: {
- static CO_OWNED: Foo = Foo;
- static ON: Foo = Foo;
- static OWNED: Foo = Foo;
- static SHARED: Foo = Foo;
- },
-
- idle: {
- resources: [OWNED, SHARED],
- },
-
- tasks: {
- SYS_TICK: {
- path: sys_tick,
- resources: [CO_OWNED, ON, SHARED],
- },
-
- TIM2: {
- enabled: false,
- path: tim2,
- priority: 1,
- resources: [CO_OWNED],
- },
- },
-}
-
-fn init(_p: ::init::Peripherals, _r: ::init::Resources) {}
-
-fn idle(_t: &mut Threshold, _r: ::idle::Resources) -> ! {
- loop {}
-}
-
-fn sys_tick(_t: &mut Threshold, _r: SYS_TICK::Resources) {}
-
-fn tim2(_t: &mut Threshold, _r: TIM2::Resources) {}
diff --git a/examples/full-syntax.rs b/examples/full-syntax.rs
deleted file mode 100644
index 9bdcd7b..0000000
--- a/examples/full-syntax.rs
+++ /dev/null
@@ -1,83 +0,0 @@
-//! A showcase of the `app!` macro syntax
-#![deny(unsafe_code)]
-#![deny(warnings)]
-#![no_std]
-
-extern crate cortex_m_rtfm as rtfm;
-extern crate stm32f103xx;
-
-use rtfm::{app, Threshold};
-
-app! {
- device: stm32f103xx,
-
- resources: {
- static CO_OWNED: u32 = 0;
- static ON: bool = false;
- static OWNED: bool = false;
- static SHARED: bool = false;
- },
-
- init: {
- // This is the path to the `init` function
- //
- // `init` doesn't necessarily has to be in the root of the crate
- path: main::init,
- },
-
- idle: {
- // This is a path to the `idle` function
- //
- // `idle` doesn't necessarily has to be in the root of the crate
- path: main::idle,
- resources: [OWNED, SHARED],
- },
-
- tasks: {
- SYS_TICK: {
- path: sys_tick,
- // If omitted priority is assumed to be 1
- // priority: 1,
- resources: [CO_OWNED, ON, SHARED],
- },
-
- TIM2: {
- // Tasks are enabled, between `init` and `idle`, by default but they
- // can start disabled if `false` is specified here
- enabled: false,
- path: tim2,
- priority: 1,
- resources: [CO_OWNED],
- },
- },
-}
-
-mod main {
- use rtfm::{self, Resource, Threshold};
-
- pub fn init(_p: ::init::Peripherals, _r: ::init::Resources) {}
-
- pub fn idle(t: &mut Threshold, mut r: ::idle::Resources) -> ! {
- loop {
- *r.OWNED = !*r.OWNED;
-
- if *r.OWNED {
- if r.SHARED.claim(t, |shared, _| *shared) {
- rtfm::wfi();
- }
- } else {
- r.SHARED.claim_mut(t, |shared, _| *shared = !*shared);
- }
- }
- }
-}
-
-fn sys_tick(_t: &mut Threshold, mut r: SYS_TICK::Resources) {
- *r.ON = !*r.ON;
-
- *r.CO_OWNED += 1;
-}
-
-fn tim2(_t: &mut Threshold, mut r: TIM2::Resources) {
- *r.CO_OWNED += 1;
-}
diff --git a/examples/generics.rs b/examples/generics.rs
deleted file mode 100644
index aceba1a..0000000
--- a/examples/generics.rs
+++ /dev/null
@@ -1,73 +0,0 @@
-//! Working with resources in a generic fashion
-#![deny(unsafe_code)]
-#![deny(warnings)]
-#![no_std]
-
-extern crate cortex_m_rtfm as rtfm;
-extern crate stm32f103xx;
-
-use rtfm::{app, Resource, Threshold};
-use stm32f103xx::{GPIOA, SPI1};
-
-app! {
- device: stm32f103xx,
-
- resources: {
- static GPIOA: GPIOA;
- static SPI1: SPI1;
- },
-
- tasks: {
- EXTI0: {
- path: exti0,
- priority: 1,
- resources: [GPIOA, SPI1],
- },
-
- EXTI1: {
- path: exti1,
- priority: 2,
- resources: [GPIOA, SPI1],
- },
- },
-}
-
-fn init(p: init::Peripherals) -> init::LateResources {
- init::LateResources {
- GPIOA: p.device.GPIOA,
- SPI1: p.device.SPI1,
- }
-}
-
-fn idle() -> ! {
- loop {
- rtfm::wfi();
- }
-}
-
-// A generic function that uses some resources
-fn work<G, S>(t: &mut Threshold, gpioa: &G, spi1: &S)
-where
- G: Resource<Data = GPIOA>,
- S: Resource<Data = SPI1>,
-{
- gpioa.claim(t, |_gpioa, t| {
- // drive NSS low
-
- spi1.claim(t, |_spi1, _| {
- // transfer data
- });
-
- // drive NSS high
- });
-}
-
-// This task needs critical sections to access the resources
-fn exti0(t: &mut Threshold, r: EXTI0::Resources) {
- work(t, &r.GPIOA, &r.SPI1);
-}
-
-// This task has direct access to the resources
-fn exti1(t: &mut Threshold, r: EXTI1::Resources) {
- work(t, &r.GPIOA, &r.SPI1);
-}
diff --git a/examples/idle.rs b/examples/idle.rs
new file mode 100644
index 0000000..013ccce
--- /dev/null
+++ b/examples/idle.rs
@@ -0,0 +1,43 @@
+//! examples/idle.rs
+
+#![deny(unsafe_code)]
+#![deny(warnings)]
+#![no_main]
+#![no_std]
+
+extern crate panic_semihosting;
+
+use cortex_m_semihosting::debug;
+use rtfm::app;
+
+macro_rules! println {
+ ($($tt:tt)*) => {
+ if let Ok(mut stdout) = cortex_m_semihosting::hio::hstdout() {
+ use core::fmt::Write;
+
+ writeln!(stdout, $($tt)*).ok();
+ }
+ };
+}
+
+#[app(device = lm3s6965)]
+const APP: () = {
+ #[init]
+ fn init() {
+ println!("init");
+ }
+
+ #[idle]
+ fn idle() -> ! {
+ static mut X: u32 = 0;
+
+ // Safe access to local `static mut` variable
+ let _x: &'static mut u32 = X;
+
+ println!("idle");
+
+ debug::exit(debug::EXIT_SUCCESS);
+
+ loop {}
+ }
+};
diff --git a/examples/init.rs b/examples/init.rs
new file mode 100644
index 0000000..d6caa60
--- /dev/null
+++ b/examples/init.rs
@@ -0,0 +1,44 @@
+//! examples/init.rs
+
+#![deny(unsafe_code)]
+#![deny(warnings)]
+#![no_main]
+#![no_std]
+
+extern crate panic_semihosting;
+
+use cortex_m_semihosting::debug;
+use rtfm::app;
+
+// NOTE: This convenience macro will appear in all the other examples and
+// will always look the same
+macro_rules! println {
+ ($($tt:tt)*) => {
+ if let Ok(mut stdout) = cortex_m_semihosting::hio::hstdout() {
+ use core::fmt::Write;
+
+ writeln!(stdout, $($tt)*).ok();
+ }
+ };
+}
+
+#[app(device = lm3s6965)]
+const APP: () = {
+ #[init]
+ fn init() {
+ static mut X: u32 = 0;
+
+ // Cortex-M peripherals
+ let _core: rtfm::Peripherals = core;
+
+ // Device specific peripherals
+ let _device: lm3s6965::Peripherals = device;
+
+ // Safe access to local `static mut` variable
+ let _x: &'static mut u32 = X;
+
+ println!("init");
+
+ debug::exit(debug::EXIT_SUCCESS);
+ }
+};
diff --git a/examples/interrupt.rs b/examples/interrupt.rs
new file mode 100644
index 0000000..19b1fed
--- /dev/null
+++ b/examples/interrupt.rs
@@ -0,0 +1,61 @@
+//! examples/interrupt.rs
+
+#![deny(unsafe_code)]
+#![deny(warnings)]
+#![no_main]
+#![no_std]
+
+extern crate panic_semihosting;
+
+use cortex_m_semihosting::debug;
+use lm3s6965::Interrupt;
+use rtfm::app;
+
+macro_rules! println {
+ ($($tt:tt)*) => {
+ if let Ok(mut stdout) = cortex_m_semihosting::hio::hstdout() {
+ use core::fmt::Write;
+
+ writeln!(stdout, $($tt)*).ok();
+ }
+ };
+}
+
+#[app(device = lm3s6965)]
+const APP: () = {
+ #[init]
+ fn init() {
+ // Pends the UART0 interrupt but its handler won't run until *after*
+ // `init` returns because interrupts are disabled
+ rtfm::pend(Interrupt::UART0);
+
+ println!("init");
+ }
+
+ #[idle]
+ fn idle() -> ! {
+ // interrupts are enabled again; the `UART0` handler runs at this point
+
+ println!("idle");
+
+ rtfm::pend(Interrupt::UART0);
+
+ debug::exit(debug::EXIT_SUCCESS);
+
+ loop {}
+ }
+
+ #[interrupt]
+ fn UART0() {
+ static mut TIMES: u32 = 0;
+
+ // Safe access to local `static mut` variable
+ *TIMES += 1;
+
+ println!(
+ "UART0 called {} time{}",
+ *TIMES,
+ if *TIMES > 1 { "s" } else { "" }
+ );
+ }
+};
diff --git a/examples/late-resources.rs b/examples/late-resources.rs
deleted file mode 100644
index 3bfc388..0000000
--- a/examples/late-resources.rs
+++ /dev/null
@@ -1,86 +0,0 @@
-//! Demonstrates initialization of resources in `init`.
-#![deny(unsafe_code)]
-#![deny(warnings)]
-#![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::LateResources {
- // `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::LateResources {
- // 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();
- }
-}
diff --git a/examples/late.rs b/examples/late.rs
new file mode 100644
index 0000000..6d76c58
--- /dev/null
+++ b/examples/late.rs
@@ -0,0 +1,65 @@
+//! examples/late.rs
+
+#![deny(unsafe_code)]
+#![deny(warnings)]
+#![no_main]
+#![no_std]
+
+extern crate panic_semihosting;
+
+use cortex_m_semihosting::debug;
+use heapless::{
+ consts::*,
+ spsc::{Consumer, Producer, Queue},
+};
+use lm3s6965::Interrupt;
+use rtfm::app;
+
+macro_rules! println {
+ ($($tt:tt)*) => {
+ if let Ok(mut stdout) = cortex_m_semihosting::hio::hstdout() {
+ use core::fmt::Write;
+
+ writeln!(stdout, $($tt)*).ok();
+ }
+ };
+}
+
+#[app(device = lm3s6965)]
+const APP: () = {
+ // Late resources
+ static mut P: Producer<'static, u32, U4> = ();
+ static mut C: Consumer<'static, u32, U4> = ();
+
+ #[init]
+ fn init() {
+ // NOTE: we use `Option` here to work around the lack of
+ // a stable `const` constructor
+ static mut Q: Option<Queue<u32, U4>> = None;
+
+ *Q = Some(Queue::new());
+ let (p, c) = Q.as_mut().unwrap().split();
+
+ // Initialization of late resources
+ P = p;
+ C = c;
+ }
+
+ #[idle(resources = [C])]
+ fn idle() -> ! {
+ loop {
+ if let Some(byte) = resources.C.dequeue() {
+ println!("received message: {}", byte);
+
+ debug::exit(debug::EXIT_SUCCESS);
+ } else {
+ rtfm::pend(Interrupt::UART0);
+ }
+ }
+ }
+
+ #[interrupt(resources = [P])]
+ fn UART0() {
+ resources.P.enqueue(42).unwrap();
+ }
+};
diff --git a/examples/lock.rs b/examples/lock.rs
new file mode 100644
index 0000000..097bd5c
--- /dev/null
+++ b/examples/lock.rs
@@ -0,0 +1,71 @@
+//! examples/lock.rs
+
+#![deny(unsafe_code)]
+#![deny(warnings)]
+#![no_main]
+#![no_std]
+
+extern crate panic_semihosting;
+
+use cortex_m_semihosting::debug;
+use lm3s6965::Interrupt;
+use rtfm::app;
+
+macro_rules! println {
+ ($($tt:tt)*) => {
+ if let Ok(mut stdout) = cortex_m_semihosting::hio::hstdout() {
+ use core::fmt::Write;
+
+ writeln!(stdout, $($tt)*).ok();
+ }
+ };
+}
+
+#[app(device = lm3s6965)]
+const APP: () = {
+ static mut SHARED: u32 = 0;
+
+ #[init]
+ fn init() {
+ rtfm::pend(Interrupt::GPIOA);
+ }
+
+ // when omitted priority is assumed to be `1`
+ #[interrupt(resources = [SHARED])]
+ fn GPIOA() {
+ println!("A");
+
+ // the lower priority task requires a critical section to access the data
+ resources.SHARED.lock(|shared| {
+ // data can only be modified within this critical section (closure)
+ *shared += 1;
+
+ // GPIOB will *not* run right now due to the critical section
+ rtfm::pend(Interrupt::GPIOB);
+
+ println!("B - SHARED = {}", *shared);
+
+ // GPIOC does not contend for `SHARED` so it's allowed to run now
+ rtfm::pend(Interrupt::GPIOC);
+ });
+
+ // critical section is over: GPIOB can now start
+
+ println!("E");
+
+ debug::exit(debug::EXIT_SUCCESS);
+ }
+
+ #[interrupt(priority = 2, resources = [SHARED])]
+ fn GPIOB() {
+ // the higher priority task does *not* need a critical section
+ *resources.SHARED += 1;
+
+ println!("D - SHARED = {}", *resources.SHARED);
+ }
+
+ #[interrupt(priority = 3)]
+ fn GPIOC() {
+ println!("C");
+ }
+};
diff --git a/examples/message.rs b/examples/message.rs
new file mode 100644
index 0000000..1ff08b2
--- /dev/null
+++ b/examples/message.rs
@@ -0,0 +1,61 @@
+//! examples/message.rs
+
+#![deny(unsafe_code)]
+#![deny(warnings)]
+#![no_main]
+#![no_std]
+
+extern crate panic_semihosting;
+
+use cortex_m_semihosting::debug;
+use rtfm::app;
+
+macro_rules! println {
+ ($($tt:tt)*) => {
+ if let Ok(mut stdout) = cortex_m_semihosting::hio::hstdout() {
+ use core::fmt::Write;
+
+ writeln!(stdout, $($tt)*).ok();
+ }
+ };
+}
+
+#[app(device = lm3s6965)]
+const APP: () = {
+ #[init(spawn = [foo])]
+ fn init() {
+ spawn.foo(/* no message */).unwrap();
+ }
+
+ #[task(spawn = [bar])]
+ fn foo() {
+ static mut COUNT: u32 = 0;
+
+ println!("foo");
+
+ spawn.bar(*COUNT).unwrap();
+ *COUNT += 1;
+ }
+
+ #[task(spawn = [baz])]
+ fn bar(x: u32) {
+ println!("bar({})", x);
+
+ spawn.baz(x + 1, x + 2).unwrap();
+ }
+
+ #[task(spawn = [foo])]
+ fn baz(x: u32, y: u32) {
+ println!("baz({}, {})", x, y);
+
+ if x + y > 4 {
+ debug::exit(debug::EXIT_SUCCESS);
+ }
+
+ spawn.foo().unwrap();
+ }
+
+ extern "C" {
+ fn UART0();
+ }
+};
diff --git a/examples/nested.rs b/examples/nested.rs
deleted file mode 100644
index 46c00b2..0000000
--- a/examples/nested.rs
+++ /dev/null
@@ -1,128 +0,0 @@
-//! Nesting claims and how the preemption threshold works
-//!
-//! If you run this program you'll hit the breakpoints as indicated by the
-//! letters in the comments: A, then B, then C, etc.
-#![deny(unsafe_code)]
-#![deny(warnings)]
-#![no_std]
-
-extern crate cortex_m_rtfm as rtfm;
-extern crate stm32f103xx;
-
-use rtfm::{app, Resource, Threshold};
-use stm32f103xx::Interrupt;
-
-app! {
- device: stm32f103xx,
-
- resources: {
- static LOW: u64 = 0;
- static HIGH: u64 = 0;
- },
-
- tasks: {
- EXTI0: {
- path: exti0,
- priority: 1,
- resources: [LOW, HIGH],
- },
-
- EXTI1: {
- path: exti1,
- priority: 2,
- resources: [LOW],
- },
-
- EXTI2: {
- path: exti2,
- priority: 3,
- resources: [HIGH],
- },
- },
-}
-
-fn init(_p: init::Peripherals, _r: init::Resources) {}
-
-fn idle() -> ! {
- // A
- rtfm::bkpt();
-
- // Sets task `exti0` as pending
- //
- // Because `exti0` has higher priority than `idle` it will be executed
- // immediately
- rtfm::set_pending(Interrupt::EXTI0); // ~> exti0
-
- loop {
- rtfm::wfi();
- }
-}
-
-#[allow(non_snake_case)]
-fn exti0(
- t: &mut Threshold,
- EXTI0::Resources {
- LOW: mut low,
- HIGH: mut high,
- }: EXTI0::Resources,
-) {
- // Because this task has a priority of 1 the preemption threshold `t` also
- // starts at 1
-
- // B
- rtfm::bkpt();
-
- // Because `exti1` has higher priority than `exti0` it can preempt it
- rtfm::set_pending(Interrupt::EXTI1); // ~> exti1
-
- // A claim creates a critical section
- low.claim_mut(t, |_low, t| {
- // This claim increases the preemption threshold to 2
- //
- // 2 is just high enough to not race with task `exti1` for access to the
- // `LOW` resource
-
- // D
- rtfm::bkpt();
-
- // Now `exti1` can't preempt this task because its priority is equal to
- // the current preemption threshold
- rtfm::set_pending(Interrupt::EXTI1);
-
- // But `exti2` can, because its priority is higher than the current
- // preemption threshold
- rtfm::set_pending(Interrupt::EXTI2); // ~> exti2
-
- // F
- rtfm::bkpt();
-
- // Claims can be nested
- high.claim_mut(t, |_high, _| {
- // This claim increases the preemption threshold to 3
-
- // Now `exti2` can't preempt this task
- rtfm::set_pending(Interrupt::EXTI2);
-
- // G
- rtfm::bkpt();
- });
-
- // Upon leaving the critical section the preemption threshold drops back
- // to 2 and `exti2` immediately preempts this task
- // ~> exti2
- });
-
- // Once again the preemption threshold drops but this time to 1. Now the
- // pending `exti1` task can preempt this task
- // ~> exti1
-}
-
-fn exti1(_t: &mut Threshold, _r: EXTI1::Resources) {
- // C, I
- rtfm::bkpt();
-}
-
-fn exti2(_t: &mut Threshold, _r: EXTI2::Resources) {
- // E, H
- rtfm::bkpt();
-}
diff --git a/examples/not-send.rs b/examples/not-send.rs
new file mode 100644
index 0000000..be78c33
--- /dev/null
+++ b/examples/not-send.rs
@@ -0,0 +1,58 @@
+//! `examples/not-send.rs`
+
+#![deny(unsafe_code)]
+#![deny(warnings)]
+#![no_main]
+#![no_std]
+
+extern crate panic_halt;
+
+use core::marker::PhantomData;
+
+use cortex_m_semihosting::debug;
+use rtfm::app;
+
+pub struct NotSend {
+ _0: PhantomData<*const ()>,
+}
+
+#[app(device = lm3s6965)]
+const APP: () = {
+ static mut SHARED: Option<NotSend> = None;
+
+ #[init(spawn = [baz, quux])]
+ fn init() {
+ spawn.baz().unwrap();
+ spawn.quux().unwrap();
+ }
+
+ #[task(spawn = [bar])]
+ fn foo() {
+ // scenario 1: message passed to task that runs at the same priority
+ spawn.bar(NotSend { _0: PhantomData }).ok();
+ }
+
+ #[task]
+ fn bar(_x: NotSend) {
+ // scenario 1
+ }
+
+ #[task(priority = 2, resources = [SHARED])]
+ fn baz() {
+ // scenario 2: resource shared between tasks that run at the same priority
+ *resources.SHARED = Some(NotSend { _0: PhantomData });
+ }
+
+ #[task(priority = 2, resources = [SHARED])]
+ fn quux() {
+ // scenario 2
+ let _not_send = resources.SHARED.take().unwrap();
+
+ debug::exit(debug::EXIT_SUCCESS);
+ }
+
+ extern "C" {
+ fn UART0();
+ fn UART1();
+ }
+};
diff --git a/examples/not-sync.rs b/examples/not-sync.rs
new file mode 100644
index 0000000..d94e0a0
--- /dev/null
+++ b/examples/not-sync.rs
@@ -0,0 +1,41 @@
+//! `examples/not-sync.rs`
+
+#![deny(unsafe_code)]
+#![deny(warnings)]
+#![no_main]
+#![no_std]
+
+extern crate panic_halt;
+
+use core::marker::PhantomData;
+
+use cortex_m_semihosting::debug;
+use rtfm::app;
+
+pub struct NotSync {
+ _0: PhantomData<*const ()>,
+}
+
+#[app(device = lm3s6965)]
+const APP: () = {
+ static SHARED: NotSync = NotSync { _0: PhantomData };
+
+ #[init]
+ fn init() {
+ debug::exit(debug::EXIT_SUCCESS);
+ }
+
+ #[task(resources = [SHARED])]
+ fn foo() {
+ let _: &NotSync = resources.SHARED;
+ }
+
+ #[task(resources = [SHARED])]
+ fn bar() {
+ let _: &NotSync = resources.SHARED;
+ }
+
+ extern "C" {
+ fn UART0();
+ }
+};
diff --git a/examples/one-task.rs b/examples/one-task.rs
deleted file mode 100644
index dc2bfd2..0000000
--- a/examples/one-task.rs
+++ /dev/null
@@ -1,96 +0,0 @@
-//! An application with one task
-#![deny(unsafe_code)]
-#![deny(warnings)]
-#![no_std]
-
-extern crate cortex_m;
-extern crate cortex_m_rtfm as rtfm;
-extern crate stm32f103xx;
-
-use cortex_m::peripheral::syst::SystClkSource;
-use rtfm::{app, Threshold};
-use stm32f103xx::GPIOC;
-
-app! {
- device: stm32f103xx,
-
- // Here data resources are declared
- //
- // Data resources are static variables that are safe to share across tasks
- resources: {
- // Declaration of resources looks exactly like declaration of static
- // variables
- static ON: bool = false;
- },
-
- // Here tasks are declared
- //
- // Each task corresponds to an interrupt or an exception. Every time the
- // interrupt or exception becomes *pending* the corresponding task handler
- // will be executed.
- tasks: {
- // Here we declare that we'll use the SYS_TICK exception as a task
- SYS_TICK: {
- // Path to the task handler
- path: sys_tick,
-
- // These are the resources this task has access to.
- //
- // The resources listed here must also appear in `app.resources`
- resources: [ON],
- },
- }
-}
-
-fn init(mut p: init::Peripherals, r: init::Resources) {
- // `init` can modify all the `resources` declared in `app!`
- r.ON;
-
- // power on GPIOC
- p.device.RCC.apb2enr.modify(|_, w| w.iopcen().enabled());
-
- // configure PC13 as output
- p.device.GPIOC.bsrr.write(|w| w.bs13().set());
- p.device
- .GPIOC
- .crh
- .modify(|_, w| w.mode13().output().cnf13().push());
-
- // configure the system timer to generate one interrupt every second
- p.core.SYST.set_clock_source(SystClkSource::Core);
- p.core.SYST.set_reload(8_000_000); // 1s
- p.core.SYST.enable_interrupt();
- p.core.SYST.enable_counter();
-}
-
-fn idle() -> ! {
- loop {
- rtfm::wfi();
- }
-}
-
-// This is the task handler of the SYS_TICK exception
-//
-// `_t` is the preemption threshold token. We won't use it in this program.
-//
-// `r` is the set of resources this task has access to. `SYS_TICK::Resources`
-// has one field per resource declared in `app!`.
-#[allow(unsafe_code)]
-fn sys_tick(_t: &mut Threshold, mut r: SYS_TICK::Resources) {
- // toggle state
- *r.ON = !*r.ON;
-
- if *r.ON {
- // set the pin PC13 high
- // NOTE(unsafe) atomic write to a stateless register
- unsafe {
- (*GPIOC::ptr()).bsrr.write(|w| w.bs13().set());
- }
- } else {
- // set the pin PC13 low
- // NOTE(unsafe) atomic write to a stateless register
- unsafe {
- (*GPIOC::ptr()).bsrr.write(|w| w.br13().reset());
- }
- }
-}
diff --git a/examples/periodic.rs b/examples/periodic.rs
new file mode 100644
index 0000000..0fb8bdf
--- /dev/null
+++ b/examples/periodic.rs
@@ -0,0 +1,43 @@
+//! examples/periodic.rs
+
+#![deny(unsafe_code)]
+#![deny(warnings)]
+#![no_main]
+#![no_std]
+
+extern crate panic_semihosting;
+
+use rtfm::{app, Instant};
+
+macro_rules! println {
+ ($($tt:tt)*) => {
+ if let Ok(mut stdout) = cortex_m_semihosting::hio::hstdout() {
+ use core::fmt::Write;
+
+ writeln!(stdout, $($tt)*).ok();
+ }
+ };
+}
+
+const PERIOD: u32 = 8_000_000;
+
+// NOTE: does NOT work on QEMU!
+#[app(device = lm3s6965)]
+const APP: () = {
+ #[init(schedule = [foo])]
+ fn init() {
+ schedule.foo(Instant::now() + PERIOD.cycles()).unwrap();
+ }
+
+ #[task(schedule = [foo])]
+ fn foo() {
+ let now = Instant::now();
+ println!("foo(scheduled = {:?}, now = {:?})", scheduled, now);
+
+ schedule.foo(scheduled + PERIOD.cycles()).unwrap();
+ }
+
+ extern "C" {
+ fn UART0();
+ }
+};
diff --git a/examples/preemption.rs b/examples/preemption.rs
deleted file mode 100644
index 340b976..0000000
--- a/examples/preemption.rs
+++ /dev/null
@@ -1,67 +0,0 @@
-//! Two tasks running at *different* priorities with access to the same resource
-#![deny(unsafe_code)]
-#![deny(warnings)]
-#![no_std]
-
-extern crate cortex_m_rtfm as rtfm;
-extern crate stm32f103xx;
-
-use rtfm::{app, Resource, Threshold};
-
-app! {
- device: stm32f103xx,
-
- resources: {
- static COUNTER: u64 = 0;
- },
-
- tasks: {
- // The `SYS_TICK` task has higher priority than `TIM2`
- SYS_TICK: {
- path: sys_tick,
- priority: 2,
- resources: [COUNTER],
- },
-
- TIM2: {
- path: tim2,
- priority: 1,
- resources: [COUNTER],
- },
- },
-}
-
-fn init(_p: init::Peripherals, _r: init::Resources) {
- // ..
-}
-
-fn idle() -> ! {
- loop {
- rtfm::wfi();
- }
-}
-
-fn sys_tick(_t: &mut Threshold, mut r: SYS_TICK::Resources) {
- // ..
-
- // This task can't be preempted by `tim2` so it has direct access to the
- // resource data
- *r.COUNTER += 1;
-
- // ..
-}
-
-fn tim2(t: &mut Threshold, mut r: TIM2::Resources) {
- // ..
-
- // As this task runs at lower priority it needs a critical section to
- // prevent `sys_tick` from preempting it while it modifies this resource
- // data. The critical section is required to prevent data races which can
- // lead to undefined behavior.
- r.COUNTER.claim_mut(t, |counter, _t| {
- // `claim_mut` creates a critical section
- *counter += 1;
- });
-
- // ..
-}
diff --git a/examples/ramfunc.rs b/examples/ramfunc.rs
new file mode 100644
index 0000000..b7fe252
--- /dev/null
+++ b/examples/ramfunc.rs
@@ -0,0 +1,53 @@
+//! examples/ramfunc.rs
+
+#![deny(unsafe_code)]
+#![deny(warnings)]
+#![no_main]
+#![no_std]
+
+extern crate panic_semihosting;
+
+use cortex_m_semihosting::debug;
+use rtfm::app;
+
+macro_rules! println {
+ ($($tt:tt)*) => {
+ if let Ok(mut stdout) = cortex_m_semihosting::hio::hstdout() {
+ use core::fmt::Write;
+
+ writeln!(stdout, $($tt)*).ok();
+ }
+ };
+}
+
+#[app(device = lm3s6965)]
+const APP: () = {
+ #[init(spawn = [bar])]
+ fn init() {
+ spawn.bar().unwrap();
+ }
+
+ #[inline(never)]
+ #[task]
+ fn foo() {
+ println!("foo");
+
+ debug::exit(debug::EXIT_SUCCESS);
+ }
+
+ // run this task from RAM
+ #[inline(never)]
+ #[link_section = ".data.bar"]
+ #[task(priority = 2, spawn = [foo])]
+ fn bar() {
+ spawn.foo().unwrap();
+ }
+
+ extern "C" {
+ fn UART0();
+
+ // run the task dispatcher from RAM
+ #[link_section = ".data.UART1"]
+ fn UART1();
+ }
+};
diff --git a/examples/resource.rs b/examples/resource.rs
new file mode 100644
index 0000000..2777da1
--- /dev/null
+++ b/examples/resource.rs
@@ -0,0 +1,60 @@
+//! examples/resource.rs
+
+#![deny(unsafe_code)]
+#![deny(warnings)]
+#![no_main]
+#![no_std]
+
+extern crate panic_semihosting;
+
+use cortex_m_semihosting::debug;
+use lm3s6965::Interrupt;
+use rtfm::app;
+
+macro_rules! println {
+ ($($tt:tt)*) => {
+ if let Ok(mut stdout) = cortex_m_semihosting::hio::hstdout() {
+ use core::fmt::Write;
+
+ writeln!(stdout, $($tt)*).ok();
+ }
+ };
+}
+
+#[app(device = lm3s6965)]
+const APP: () = {
+ // A resource
+ static mut SHARED: u32 = 0;
+
+ #[init]
+ fn init() {
+ rtfm::pend(Interrupt::UART0);
+ rtfm::pend(Interrupt::UART1);
+ }
+
+ #[idle]
+ fn idle() -> ! {
+ debug::exit(debug::EXIT_SUCCESS);
+
+ // error: `SHARED` can't be accessed from this context
+ // SHARED += 1;
+
+ loop {}
+ }
+
+ // `SHARED` can be access from this context
+ #[interrupt(resources = [SHARED])]
+ fn UART0() {
+ *resources.SHARED += 1;
+
+ println!("UART0: SHARED = {}", resources.SHARED);
+ }
+
+ // `SHARED` can be access from this context
+ #[interrupt(resources = [SHARED])]
+ fn UART1() {
+ *resources.SHARED += 1;
+
+ println!("UART1: SHARED = {}", resources.SHARED);
+ }
+};
diff --git a/examples/safe-static-mut-ref.rs b/examples/safe-static-mut-ref.rs
deleted file mode 100644
index 9579f52..0000000
--- a/examples/safe-static-mut-ref.rs
+++ /dev/null
@@ -1,31 +0,0 @@
-//! Safe creation of `&'static mut` references
-#![deny(unsafe_code)]
-#![deny(warnings)]
-#![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; 16] = r.BUFFER;
-}
-
-fn idle() -> ! {
- loop {
- rtfm::wfi();
- }
-}
diff --git a/examples/schedule.rs b/examples/schedule.rs
new file mode 100644
index 0000000..9fb2796
--- /dev/null
+++ b/examples/schedule.rs
@@ -0,0 +1,51 @@
+//! examples/schedule.rs
+
+#![deny(unsafe_code)]
+#![deny(warnings)]
+#![no_main]
+#![no_std]
+
+extern crate panic_semihosting;
+
+use rtfm::{app, Instant};
+
+macro_rules! println {
+ ($($tt:tt)*) => {
+ if let Ok(mut stdout) = cortex_m_semihosting::hio::hstdout() {
+ use core::fmt::Write;
+
+ writeln!(stdout, $($tt)*).ok();
+ }
+ };
+}
+
+// NOTE: does NOT work on QEMU!
+#[app(device = lm3s6965)]
+const APP: () = {
+ #[init(schedule = [foo, bar])]
+ fn init() {
+ let now = Instant::now();
+
+ println!("init @ {:?}", now);
+
+ // Schedule `foo` to run 8e6 cycles (clock cycles) in the future
+ schedule.foo(now + 8_000_000.cycles()).unwrap();
+
+ // Schedule `bar` to run 4e6 cycles in the future
+ schedule.bar(now + 4_000_000.cycles()).unwrap();
+ }
+
+ #[task]
+ fn foo() {
+ println!("foo @ {:?}", Instant::now());
+ }
+
+ #[task]
+ fn bar() {
+ println!("bar @ {:?}", Instant::now());
+ }
+
+ extern "C" {
+ fn UART0();
+ }
+};
diff --git a/examples/singleton.rs b/examples/singleton.rs
new file mode 100644
index 0000000..888a5a6
--- /dev/null
+++ b/examples/singleton.rs
@@ -0,0 +1,69 @@
+//! examples/singleton.rs
+
+#![deny(unsafe_code)]
+#![deny(warnings)]
+#![no_main]
+#![no_std]
+
+extern crate panic_semihosting;
+
+use alloc_singleton::stable::pool::{Box, Pool};
+use cortex_m_semihosting::debug;
+use lm3s6965::Interrupt;
+use rtfm::app;
+
+macro_rules! println {
+ ($($tt:tt)*) => {
+ if let Ok(mut stdout) = cortex_m_semihosting::hio::hstdout() {
+ use core::fmt::Write;
+
+ writeln!(stdout, $($tt)*).ok();
+ }
+ };
+}
+
+#[app(device = lm3s6965)]
+const APP: () = {
+ #[Singleton(Send)]
+ static mut M: [u32; 2] = [0; 2];
+
+ static mut P: Pool<M> = ();
+
+ #[init(resources = [M])]
+ fn init() {
+ rtfm::pend(Interrupt::I2C0);
+
+ P = Pool::new(resources.M);
+ }
+
+ #[interrupt(
+ priority = 2,
+ resources = [P],
+ spawn = [foo, bar],
+ )]
+ fn I2C0() {
+ spawn.foo(resources.P.alloc(1).unwrap()).unwrap();
+ spawn.bar(resources.P.alloc(2).unwrap()).unwrap();
+ }
+
+ #[task(resources = [P])]
+ fn foo(x: Box<M>) {
+ println!("foo({})", x);
+
+ resources.P.lock(|p| p.dealloc(x));
+
+ debug::exit(debug::EXIT_SUCCESS);
+ }
+
+ #[task(priority = 2, resources = [P])]
+ fn bar(x: Box<M>) {
+ println!("bar({})", x);
+
+ resources.P.dealloc(x);
+ }
+
+ extern "C" {
+ fn UART0();
+ fn UART1();
+ }
+};
diff --git a/examples/smallest.rs b/examples/smallest.rs
new file mode 100644
index 0000000..e4d86be
--- /dev/null
+++ b/examples/smallest.rs
@@ -0,0 +1,17 @@
+//! examples/smallest.rs
+
+#![deny(unsafe_code)]
+#![deny(warnings)]
+#![no_main]
+#![no_std]
+
+// panic-handler crate
+extern crate panic_semihosting;
+
+use rtfm::app;
+
+#[app(device = lm3s6965)]
+const APP: () = {
+ #[init]
+ fn init() {}
+};
diff --git a/examples/static.rs b/examples/static.rs
new file mode 100644
index 0000000..3dc0e89
--- /dev/null
+++ b/examples/static.rs
@@ -0,0 +1,47 @@
+//! examples/static.rs
+
+#![deny(unsafe_code)]
+#![deny(warnings)]
+#![no_main]
+#![no_std]
+
+extern crate panic_semihosting;
+
+use cortex_m_semihosting::debug;
+use lm3s6965::Interrupt;
+use rtfm::app;
+
+macro_rules! println {
+ ($($tt:tt)*) => {
+ if let Ok(mut stdout) = cortex_m_semihosting::hio::hstdout() {
+ use core::fmt::Write;
+
+ writeln!(stdout, $($tt)*).ok();
+ }
+ };
+}
+
+#[app(device = lm3s6965)]
+const APP: () = {
+ static KEY: u32 = ();
+
+ #[init]
+ fn init() {
+ rtfm::pend(Interrupt::UART0);
+ rtfm::pend(Interrupt::UART1);
+
+ KEY = 0xdeadbeef;
+ }
+
+ #[interrupt(resources = [KEY])]
+ fn UART0() {
+ println!("UART0(KEY = {:#x})", resources.KEY);
+
+ debug::exit(debug::EXIT_SUCCESS);
+ }
+
+ #[interrupt(priority = 2, resources = [KEY])]
+ fn UART1() {
+ println!("UART1(KEY = {:#x})", resources.KEY);
+ }
+};
diff --git a/examples/task.rs b/examples/task.rs
new file mode 100644
index 0000000..b1cd7ae
--- /dev/null
+++ b/examples/task.rs
@@ -0,0 +1,61 @@
+//! examples/task.rs
+
+#![deny(unsafe_code)]
+#![deny(warnings)]
+#![no_main]
+#![no_std]
+
+extern crate panic_semihosting;
+
+use cortex_m_semihosting::debug;
+use rtfm::app;
+
+macro_rules! println {
+ ($($tt:tt)*) => {
+ if let Ok(mut stdout) = cortex_m_semihosting::hio::hstdout() {
+ use core::fmt::Write;
+
+ writeln!(stdout, $($tt)*).ok();
+ }
+ };
+}
+
+#[app(device = lm3s6965)]
+const APP: () = {
+ #[init(spawn = [foo])]
+ fn init() {
+ spawn.foo().unwrap();
+ }
+
+ #[task(spawn = [bar, baz])]
+ fn foo() {
+ println!("foo");
+
+ // spawns `bar` onto the task scheduler
+ // `foo` and `bar` have the same priority so `bar` will not run until
+ // after `foo` terminates
+ spawn.bar().unwrap();
+
+ // spawns `baz` onto the task scheduler
+ // `baz` has higher priority than `foo` so it immediately preempts `foo`
+ spawn.baz().unwrap();
+ }
+
+ #[task]
+ fn bar() {
+ println!("bar");
+
+ debug::exit(debug::EXIT_SUCCESS);
+ }
+
+ #[task(priority = 2)]
+ fn baz() {
+ println!("baz");
+ }
+
+ // Interrupt handlers used to dispatch software tasks
+ extern "C" {
+ fn UART0();
+ fn UART1();
+ }
+};
diff --git a/examples/two-tasks.rs b/examples/two-tasks.rs
deleted file mode 100644
index 2348915..0000000
--- a/examples/two-tasks.rs
+++ /dev/null
@@ -1,58 +0,0 @@
-//! Two tasks running at the *same* priority with access to the same resource
-#![deny(unsafe_code)]
-#![deny(warnings)]
-#![no_std]
-
-extern crate cortex_m_rtfm as rtfm;
-extern crate stm32f103xx;
-
-use rtfm::{app, Threshold};
-
-app! {
- device: stm32f103xx,
-
- resources: {
- static COUNTER: u64 = 0;
- },
-
- // Both SYS_TICK and TIM2 have access to the `COUNTER` data
- tasks: {
- SYS_TICK: {
- path: sys_tick,
- resources: [COUNTER],
- },
-
- TIM2: {
- path: tim2,
- resources: [COUNTER],
- },
- },
-}
-
-fn init(_p: init::Peripherals, _r: init::Resources) {
- // ..
-}
-
-fn idle() -> ! {
- loop {
- rtfm::wfi();
- }
-}
-
-// As both tasks are running at the same priority one can't preempt the other.
-// Thus both tasks have direct access to the resource
-fn sys_tick(_t: &mut Threshold, mut r: SYS_TICK::Resources) {
- // ..
-
- *r.COUNTER += 1;
-
- // ..
-}
-
-fn tim2(_t: &mut Threshold, mut r: TIM2::Resources) {
- // ..
-
- *r.COUNTER += 1;
-
- // ..
-}
diff --git a/examples/types.rs b/examples/types.rs
new file mode 100644
index 0000000..6606208
--- /dev/null
+++ b/examples/types.rs
@@ -0,0 +1,54 @@
+//! examples/types.rs
+
+#![deny(unsafe_code)]
+#![deny(warnings)]
+#![no_main]
+#![no_std]
+
+extern crate panic_semihosting;
+
+use cortex_m_semihosting::debug;
+use rtfm::{app, Instant};
+
+#[app(device = lm3s6965)]
+const APP: () = {
+ static mut SHARED: u32 = 0;
+
+ #[init(schedule = [foo], spawn = [foo])]
+ fn init() {
+ let _: Instant = start;
+ let _: rtfm::Peripherals = core;
+ let _: lm3s6965::Peripherals = device;
+ let _: init::Schedule = schedule;
+ let _: init::Spawn = spawn;
+
+ debug::exit(debug::EXIT_SUCCESS);
+ }
+
+ #[exception(schedule = [foo], spawn = [foo])]
+ fn SVCall() {
+ let _: Instant = start;
+ let _: SVCall::Schedule = schedule;
+ let _: SVCall::Spawn = spawn;
+ }
+
+ #[interrupt(resources = [SHARED], schedule = [foo], spawn = [foo])]
+ fn UART0() {
+ let _: Instant = start;
+ let _: resources::SHARED = resources.SHARED;
+ let _: UART0::Schedule = schedule;
+ let _: UART0::Spawn = spawn;
+ }
+
+ #[task(priority = 2, resources = [SHARED], schedule = [foo], spawn = [foo])]
+ fn foo() {
+ let _: Instant = scheduled;
+ let _: foo::Resources = resources;
+ let _: foo::Schedule = schedule;
+ let _: foo::Spawn = spawn;
+ }
+
+ extern "C" {
+ fn UART1();
+ }
+};
diff --git a/examples/zero-tasks.rs b/examples/zero-tasks.rs
deleted file mode 100644
index abd1c4c..0000000
--- a/examples/zero-tasks.rs
+++ /dev/null
@@ -1,43 +0,0 @@
-//! Minimal example with zero tasks
-#![deny(unsafe_code)]
-#![deny(warnings)]
-#![no_std]
-
-extern crate cortex_m_rtfm as rtfm; // IMPORTANT always do this rename
-extern crate stm32f103xx; // the device crate
-
-// import the procedural macro
-use rtfm::app;
-
-// This macro call indicates that this is a RTFM application
-//
-// This macro will expand to a `main` function so you don't need to supply
-// `main` yourself.
-app! {
- // this is the path to the device crate
- device: stm32f103xx,
-}
-
-// The initialization phase.
-//
-// This runs first and within a *global* critical section. Nothing can preempt
-// this function.
-fn init(p: init::Peripherals) {
- // This function has access to all the peripherals of the device
- p.core.SYST;
- p.device.GPIOA;
- p.device.RCC;
- // ..
-}
-
-// The idle loop.
-//
-// This runs after `init` and has a priority of 0. All tasks can preempt this
-// function. This function can never return so it must contain some sort of
-// endless loop.
-fn idle() -> ! {
- loop {
- // This puts the processor to sleep until there's a task to service
- rtfm::wfi();
- }
-}