aboutsummaryrefslogtreecommitdiff
path: root/examples
diff options
context:
space:
mode:
Diffstat (limited to 'examples')
-rw-r--r--examples/baseline.rs23
-rw-r--r--examples/binds.rs5
-rw-r--r--examples/capacity.rs7
-rw-r--r--examples/cfg.rs37
-rw-r--r--examples/generics.rs35
-rw-r--r--examples/hardware.rs (renamed from examples/interrupt.rs)11
-rw-r--r--examples/idle.rs3
-rw-r--r--examples/init.rs11
-rw-r--r--examples/late.rs29
-rw-r--r--examples/lock.rs30
-rw-r--r--examples/message.rs3
-rw-r--r--examples/not-send.rs20
-rw-r--r--examples/not-sync.rs16
-rw-r--r--examples/only-shared-access.rs38
-rw-r--r--examples/periodic.rs17
-rw-r--r--examples/pool.rs7
-rw-r--r--examples/preempt.rs37
-rw-r--r--examples/ramfunc.rs3
-rw-r--r--examples/resource.rs38
-rw-r--r--examples/schedule.rs13
-rw-r--r--examples/shared-with-init.rs18
-rw-r--r--examples/smallest.rs11
-rw-r--r--examples/static.rs36
-rw-r--r--examples/t-binds.rs32
-rw-r--r--examples/t-cfg.rs50
-rw-r--r--examples/t-late-not-send.rs36
-rw-r--r--examples/t-resource.rs87
-rw-r--r--examples/t-schedule.rs59
-rw-r--r--examples/t-spawn.rs58
-rw-r--r--examples/task.rs9
-rw-r--r--examples/types.rs61
31 files changed, 607 insertions, 233 deletions
diff --git a/examples/baseline.rs b/examples/baseline.rs
index d743107d..b7144dd1 100644
--- a/examples/baseline.rs
+++ b/examples/baseline.rs
@@ -5,27 +5,26 @@
#![no_main]
#![no_std]
-extern crate panic_semihosting;
-
use cortex_m_semihosting::{debug, hprintln};
use lm3s6965::Interrupt;
+use panic_semihosting as _;
// NOTE: does NOT properly work on QEMU
-#[rtfm::app(device = lm3s6965)]
+#[rtfm::app(device = lm3s6965, monotonic = rtfm::cyccnt::CYCCNT)]
const APP: () = {
#[init(spawn = [foo])]
- fn init(c: init::Context) {
- hprintln!("init(baseline = {:?})", c.start).unwrap();
+ fn init(cx: init::Context) {
+ hprintln!("init(baseline = {:?})", cx.start).unwrap();
// `foo` inherits the baseline of `init`: `Instant(0)`
- c.spawn.foo().unwrap();
+ cx.spawn.foo().unwrap();
}
#[task(schedule = [foo])]
- fn foo(c: foo::Context) {
+ fn foo(cx: foo::Context) {
static mut ONCE: bool = true;
- hprintln!("foo(baseline = {:?})", c.scheduled).unwrap();
+ hprintln!("foo(baseline = {:?})", cx.scheduled).unwrap();
if *ONCE {
*ONCE = false;
@@ -36,12 +35,12 @@ const APP: () = {
}
}
- #[interrupt(spawn = [foo])]
- fn UART0(c: UART0::Context) {
- hprintln!("UART0(baseline = {:?})", c.start).unwrap();
+ #[task(binds = UART0, spawn = [foo])]
+ fn uart0(cx: uart0::Context) {
+ hprintln!("UART0(baseline = {:?})", cx.start).unwrap();
// `foo` inherits the baseline of `UART0`: its `start` time
- c.spawn.foo().unwrap();
+ cx.spawn.foo().unwrap();
}
extern "C" {
diff --git a/examples/binds.rs b/examples/binds.rs
index 3d2d9b54..b10cb434 100644
--- a/examples/binds.rs
+++ b/examples/binds.rs
@@ -5,10 +5,9 @@
#![no_main]
#![no_std]
-extern crate panic_semihosting;
-
use cortex_m_semihosting::{debug, hprintln};
use lm3s6965::Interrupt;
+use panic_semihosting as _;
// `examples/interrupt.rs` rewritten to use `binds`
#[rtfm::app(device = lm3s6965)]
@@ -31,7 +30,7 @@ const APP: () = {
loop {}
}
- #[interrupt(binds = UART0)]
+ #[task(binds = UART0)]
fn foo(_: foo::Context) {
static mut TIMES: u32 = 0;
diff --git a/examples/capacity.rs b/examples/capacity.rs
index 07edd9b8..ebc86b80 100644
--- a/examples/capacity.rs
+++ b/examples/capacity.rs
@@ -5,10 +5,9 @@
#![no_main]
#![no_std]
-extern crate panic_semihosting;
-
use cortex_m_semihosting::{debug, hprintln};
use lm3s6965::Interrupt;
+use panic_semihosting as _;
#[rtfm::app(device = lm3s6965)]
const APP: () = {
@@ -17,8 +16,8 @@ const APP: () = {
rtfm::pend(Interrupt::UART0);
}
- #[interrupt(spawn = [foo, bar])]
- fn UART0(c: UART0::Context) {
+ #[task(binds = UART0, spawn = [foo, bar])]
+ fn uart0(c: uart0::Context) {
c.spawn.foo(0).unwrap();
c.spawn.foo(1).unwrap();
c.spawn.foo(2).unwrap();
diff --git a/examples/cfg.rs b/examples/cfg.rs
index 03f9dbdc..2a43b5c9 100644
--- a/examples/cfg.rs
+++ b/examples/cfg.rs
@@ -5,38 +5,49 @@
#![no_main]
#![no_std]
-extern crate panic_semihosting;
-
+use cortex_m_semihosting::debug;
#[cfg(debug_assertions)]
use cortex_m_semihosting::hprintln;
+use panic_semihosting as _;
#[rtfm::app(device = lm3s6965)]
const APP: () = {
- #[cfg(debug_assertions)] // <- `true` when using the `dev` profile
- static mut COUNT: u32 = 0;
+ struct Resources {
+ #[cfg(debug_assertions)] // <- `true` when using the `dev` profile
+ #[init(0)]
+ count: u32,
+ }
- #[init]
- fn init(_: init::Context) {
- // ..
+ #[init(spawn = [foo])]
+ fn init(cx: init::Context) {
+ cx.spawn.foo().unwrap();
+ cx.spawn.foo().unwrap();
+ }
+
+ #[idle]
+ fn idle(_: idle::Context) -> ! {
+ debug::exit(debug::EXIT_SUCCESS);
+
+ loop {}
}
- #[task(priority = 3, resources = [COUNT], spawn = [log])]
- fn foo(c: foo::Context) {
+ #[task(capacity = 2, resources = [count], spawn = [log])]
+ fn foo(_cx: foo::Context) {
#[cfg(debug_assertions)]
{
- *c.resources.COUNT += 1;
+ *_cx.resources.count += 1;
- c.spawn.log(*c.resources.COUNT).ok();
+ _cx.spawn.log(*_cx.resources.count).unwrap();
}
// this wouldn't compile in `release` mode
- // *resources.COUNT += 1;
+ // *_cx.resources.count += 1;
// ..
}
#[cfg(debug_assertions)]
- #[task]
+ #[task(capacity = 2)]
fn log(_: log::Context, n: u32) {
hprintln!(
"foo has been called {} time{}",
diff --git a/examples/generics.rs b/examples/generics.rs
index e624da39..eafc6308 100644
--- a/examples/generics.rs
+++ b/examples/generics.rs
@@ -5,15 +5,17 @@
#![no_main]
#![no_std]
-extern crate panic_semihosting;
-
use cortex_m_semihosting::{debug, hprintln};
use lm3s6965::Interrupt;
-use rtfm::Mutex;
+use panic_semihosting as _;
+use rtfm::{Exclusive, Mutex};
#[rtfm::app(device = lm3s6965)]
const APP: () = {
- static mut SHARED: u32 = 0;
+ struct Resources {
+ #[init(0)]
+ shared: u32,
+ }
#[init]
fn init(_: init::Context) {
@@ -21,42 +23,43 @@ const APP: () = {
rtfm::pend(Interrupt::UART1);
}
- #[interrupt(resources = [SHARED])]
- fn UART0(c: UART0::Context) {
+ #[task(binds = UART0, resources = [shared])]
+ fn uart0(c: uart0::Context) {
static mut STATE: u32 = 0;
hprintln!("UART0(STATE = {})", *STATE).unwrap();
- advance(STATE, c.resources.SHARED);
+ // second argument has type `resources::shared`
+ advance(STATE, c.resources.shared);
rtfm::pend(Interrupt::UART1);
debug::exit(debug::EXIT_SUCCESS);
}
- #[interrupt(priority = 2, resources = [SHARED])]
- fn UART1(mut c: UART1::Context) {
+ #[task(binds = UART1, priority = 2, resources = [shared])]
+ fn uart1(c: uart1::Context) {
static mut STATE: u32 = 0;
hprintln!("UART1(STATE = {})", *STATE).unwrap();
- // just to show that `SHARED` can be accessed directly and ..
- *c.resources.SHARED += 0;
- // .. also through a (no-op) `lock`
- c.resources.SHARED.lock(|shared| *shared += 0);
+ // just to show that `shared` can be accessed directly
+ *c.resources.shared += 0;
- advance(STATE, c.resources.SHARED);
+ // second argument has type `Exclusive<u32>`
+ advance(STATE, Exclusive(c.resources.shared));
}
};
+// the second parameter is generic: it can be any type that implements the `Mutex` trait
fn advance(state: &mut u32, mut shared: impl Mutex<T = u32>) {
*state += 1;
- let (old, new) = shared.lock(|shared| {
+ let (old, new) = shared.lock(|shared: &mut u32| {
let old = *shared;
*shared += *state;
(old, *shared)
});
- hprintln!("SHARED: {} -> {}", old, new).unwrap();
+ hprintln!("shared: {} -> {}", old, new).unwrap();
}
diff --git a/examples/interrupt.rs b/examples/hardware.rs
index dd6efa0d..77f19d90 100644
--- a/examples/interrupt.rs
+++ b/examples/hardware.rs
@@ -1,14 +1,13 @@
-//! examples/interrupt.rs
+//! examples/hardware.rs
#![deny(unsafe_code)]
#![deny(warnings)]
#![no_main]
#![no_std]
-extern crate panic_semihosting;
-
use cortex_m_semihosting::{debug, hprintln};
use lm3s6965::Interrupt;
+use panic_semihosting as _;
#[rtfm::app(device = lm3s6965)]
const APP: () = {
@@ -16,7 +15,7 @@ const APP: () = {
fn init(_: init::Context) {
// Pends the UART0 interrupt but its handler won't run until *after*
// `init` returns because interrupts are disabled
- rtfm::pend(Interrupt::UART0);
+ rtfm::pend(Interrupt::UART0); // equivalent to NVIC::pend
hprintln!("init").unwrap();
}
@@ -34,8 +33,8 @@ const APP: () = {
loop {}
}
- #[interrupt]
- fn UART0(_: UART0::Context) {
+ #[task(binds = UART0)]
+ fn uart0(_: uart0::Context) {
static mut TIMES: u32 = 0;
// Safe access to local `static mut` variable
diff --git a/examples/idle.rs b/examples/idle.rs
index d10cc43e..c6f676b0 100644
--- a/examples/idle.rs
+++ b/examples/idle.rs
@@ -5,9 +5,8 @@
#![no_main]
#![no_std]
-extern crate panic_semihosting;
-
use cortex_m_semihosting::{debug, hprintln};
+use panic_semihosting as _;
#[rtfm::app(device = lm3s6965)]
const APP: () = {
diff --git a/examples/init.rs b/examples/init.rs
index df687794..194e3ec4 100644
--- a/examples/init.rs
+++ b/examples/init.rs
@@ -5,21 +5,20 @@
#![no_main]
#![no_std]
-extern crate panic_semihosting;
-
use cortex_m_semihosting::{debug, hprintln};
+use panic_semihosting as _;
-#[rtfm::app(device = lm3s6965)]
+#[rtfm::app(device = lm3s6965, peripherals = true)]
const APP: () = {
#[init]
- fn init(c: init::Context) {
+ fn init(cx: init::Context) {
static mut X: u32 = 0;
// Cortex-M peripherals
- let _core: rtfm::Peripherals = c.core;
+ let _core: cortex_m::Peripherals = cx.core;
// Device specific peripherals
- let _device: lm3s6965::Peripherals = c.device;
+ let _device: lm3s6965::Peripherals = cx.device;
// Safe access to local `static mut` variable
let _x: &'static mut u32 = X;
diff --git a/examples/late.rs b/examples/late.rs
index 0074fb32..2eb12d6a 100644
--- a/examples/late.rs
+++ b/examples/late.rs
@@ -5,38 +5,37 @@
#![no_main]
#![no_std]
-extern crate panic_semihosting;
-
use cortex_m_semihosting::{debug, hprintln};
use heapless::{
consts::*,
+ i,
spsc::{Consumer, Producer, Queue},
};
use lm3s6965::Interrupt;
+use panic_semihosting as _;
#[rtfm::app(device = lm3s6965)]
const APP: () = {
// Late resources
- static mut P: Producer<'static, u32, U4> = ();
- static mut C: Consumer<'static, u32, U4> = ();
+ struct Resources {
+ p: Producer<'static, u32, U4>,
+ c: Consumer<'static, u32, U4>,
+ }
#[init]
fn init(_: init::Context) -> init::LateResources {
- // NOTE: we use `Option` here to work around the lack of
- // a stable `const` constructor
- static mut Q: Option<Queue<u32, U4>> = None;
+ static mut Q: Queue<u32, U4> = Queue(i::Queue::new());
- *Q = Some(Queue::new());
- let (p, c) = Q.as_mut().unwrap().split();
+ let (p, c) = Q.split();
// Initialization of late resources
- init::LateResources { P: p, C: c }
+ init::LateResources { p, c }
}
- #[idle(resources = [C])]
+ #[idle(resources = [c])]
fn idle(c: idle::Context) -> ! {
loop {
- if let Some(byte) = c.resources.C.dequeue() {
+ if let Some(byte) = c.resources.c.dequeue() {
hprintln!("received message: {}", byte).unwrap();
debug::exit(debug::EXIT_SUCCESS);
@@ -46,8 +45,8 @@ const APP: () = {
}
}
- #[interrupt(resources = [P])]
- fn UART0(c: UART0::Context) {
- c.resources.P.enqueue(42).unwrap();
+ #[task(binds = UART0, resources = [p])]
+ fn uart0(c: uart0::Context) {
+ c.resources.p.enqueue(42).unwrap();
}
};
diff --git a/examples/lock.rs b/examples/lock.rs
index 814c7364..f33a60a4 100644
--- a/examples/lock.rs
+++ b/examples/lock.rs
@@ -5,14 +5,16 @@
#![no_main]
#![no_std]
-extern crate panic_semihosting;
-
use cortex_m_semihosting::{debug, hprintln};
use lm3s6965::Interrupt;
+use panic_semihosting as _;
#[rtfm::app(device = lm3s6965)]
const APP: () = {
- static mut SHARED: u32 = 0;
+ struct Resources {
+ #[init(0)]
+ shared: u32,
+ }
#[init]
fn init(_: init::Context) {
@@ -20,21 +22,21 @@ const APP: () = {
}
// when omitted priority is assumed to be `1`
- #[interrupt(resources = [SHARED])]
- fn GPIOA(mut c: GPIOA::Context) {
+ #[task(binds = GPIOA, resources = [shared])]
+ fn gpioa(mut c: gpioa::Context) {
hprintln!("A").unwrap();
// the lower priority task requires a critical section to access the data
- c.resources.SHARED.lock(|shared| {
+ c.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);
- hprintln!("B - SHARED = {}", *shared).unwrap();
+ hprintln!("B - shared = {}", *shared).unwrap();
- // GPIOC does not contend for `SHARED` so it's allowed to run now
+ // GPIOC does not contend for `shared` so it's allowed to run now
rtfm::pend(Interrupt::GPIOC);
});
@@ -45,16 +47,16 @@ const APP: () = {
debug::exit(debug::EXIT_SUCCESS);
}
- #[interrupt(priority = 2, resources = [SHARED])]
- fn GPIOB(mut c: GPIOB::Context) {
+ #[task(binds = GPIOB, priority = 2, resources = [shared])]
+ fn gpiob(c: gpiob::Context) {
// the higher priority task does *not* need a critical section
- *c.resources.SHARED += 1;
+ *c.resources.shared += 1;
- hprintln!("D - SHARED = {}", *c.resources.SHARED).unwrap();
+ hprintln!("D - shared = {}", *c.resources.shared).unwrap();
}
- #[interrupt(priority = 3)]
- fn GPIOC(_: GPIOC::Context) {
+ #[task(binds = GPIOC, priority = 3)]
+ fn gpioc(_: gpioc::Context) {
hprintln!("C").unwrap();
}
};
diff --git a/examples/message.rs b/examples/message.rs
index 1fd3b9d4..8bfed523 100644
--- a/examples/message.rs
+++ b/examples/message.rs
@@ -5,9 +5,8 @@
#![no_main]
#![no_std]
-extern crate panic_semihosting;
-
use cortex_m_semihosting::{debug, hprintln};
+use panic_semihosting as _;
#[rtfm::app(device = lm3s6965)]
const APP: () = {
diff --git a/examples/not-send.rs b/examples/not-send.rs
index c1b6bcdd..d27cc82f 100644
--- a/examples/not-send.rs
+++ b/examples/not-send.rs
@@ -5,11 +5,10 @@
#![no_main]
#![no_std]
-extern crate panic_halt;
-
use core::marker::PhantomData;
use cortex_m_semihosting::debug;
+use panic_halt as _;
use rtfm::app;
pub struct NotSend {
@@ -18,7 +17,10 @@ pub struct NotSend {
#[app(device = lm3s6965)]
const APP: () = {
- static mut SHARED: Option<NotSend> = None;
+ struct Resources {
+ #[init(None)]
+ shared: Option<NotSend>,
+ }
#[init(spawn = [baz, quux])]
fn init(c: init::Context) {
@@ -37,16 +39,16 @@ const APP: () = {
// scenario 1
}
- #[task(priority = 2, resources = [SHARED])]
- fn baz(mut c: baz::Context) {
+ #[task(priority = 2, resources = [shared])]
+ fn baz(c: baz::Context) {
// scenario 2: resource shared between tasks that run at the same priority
- *c.resources.SHARED = Some(NotSend { _0: PhantomData });
+ *c.resources.shared = Some(NotSend { _0: PhantomData });
}
- #[task(priority = 2, resources = [SHARED])]
- fn quux(mut c: quux::Context) {
+ #[task(priority = 2, resources = [shared])]
+ fn quux(c: quux::Context) {
// scenario 2
- let _not_send = c.resources.SHARED.take().unwrap();
+ let _not_send = c.resources.shared.take().unwrap();
debug::exit(debug::EXIT_SUCCESS);
}
diff --git a/examples/not-sync.rs b/examples/not-sync.rs
index bc714065..7ce2a82f 100644
--- a/examples/not-sync.rs
+++ b/examples/not-sync.rs
@@ -5,11 +5,10 @@
#![no_main]
#![no_std]
-extern crate panic_halt;
-
use core::marker::PhantomData;
use cortex_m_semihosting::debug;
+use panic_halt as _;
pub struct NotSync {
_0: PhantomData<*const ()>,
@@ -17,21 +16,24 @@ pub struct NotSync {
#[rtfm::app(device = lm3s6965)]
const APP: () = {
- static SHARED: NotSync = NotSync { _0: PhantomData };
+ struct Resources {
+ #[init(NotSync { _0: PhantomData })]
+ shared: NotSync,
+ }
#[init]
fn init(_: init::Context) {
debug::exit(debug::EXIT_SUCCESS);
}
- #[task(resources = [SHARED])]
+ #[task(resources = [&shared])]
fn foo(c: foo::Context) {
- let _: &NotSync = c.resources.SHARED;
+ let _: &NotSync = c.resources.shared;
}
- #[task(resources = [SHARED])]
+ #[task(resources = [&shared])]
fn bar(c: bar::Context) {
- let _: &NotSync = c.resources.SHARED;
+ let _: &NotSync = c.resources.shared;
}
extern "C" {
diff --git a/examples/only-shared-access.rs b/examples/only-shared-access.rs
new file mode 100644
index 00000000..c7060b14
--- /dev/null
+++ b/examples/only-shared-access.rs
@@ -0,0 +1,38 @@
+//! examples/static.rs
+
+#![deny(unsafe_code)]
+#![deny(warnings)]
+#![no_main]
+#![no_std]
+
+use cortex_m_semihosting::{debug, hprintln};
+use lm3s6965::Interrupt;
+use panic_semihosting as _;
+
+#[rtfm::app(device = lm3s6965)]
+const APP: () = {
+ struct Resources {
+ key: u32,
+ }
+
+ #[init]
+ fn init(_: init::Context) -> init::LateResources {
+ rtfm::pend(Interrupt::UART0);
+ rtfm::pend(Interrupt::UART1);
+
+ init::LateResources { key: 0xdeadbeef }
+ }
+
+ #[task(binds = UART0, resources = [&key])]
+ fn uart0(cx: uart0::Context) {
+ let key: &u32 = cx.resources.key;
+ hprintln!("UART0(key = {:#x})", key).unwrap();
+
+ debug::exit(debug::EXIT_SUCCESS);
+ }
+
+ #[task(binds = UART1, priority = 2, resources = [&key])]
+ fn uart1(cx: uart1::Context) {
+ hprintln!("UART1(key = {:#x})", cx.resources.key).unwrap();
+ }
+};
diff --git a/examples/periodic.rs b/examples/periodic.rs
index f7841183..ec110e11 100644
--- a/examples/periodic.rs
+++ b/examples/periodic.rs
@@ -5,27 +5,26 @@
#![no_main]
#![no_std]
-extern crate panic_semihosting;
-
use cortex_m_semihosting::hprintln;
-use rtfm::Instant;
+use panic_semihosting as _;
+use rtfm::cyccnt::{Instant, U32Ext};
const PERIOD: u32 = 8_000_000;
// NOTE: does NOT work on QEMU!
-#[rtfm::app(device = lm3s6965)]
+#[rtfm::app(device = lm3s6965, monotonic = rtfm::cyccnt::CYCCNT)]
const APP: () = {
#[init(schedule = [foo])]
- fn init(c: init::Context) {
- c.schedule.foo(Instant::now() + PERIOD.cycles()).unwrap();
+ fn init(cx: init::Context) {
+ cx.schedule.foo(Instant::now() + PERIOD.cycles()).unwrap();
}
#[task(schedule = [foo])]
- fn foo(c: foo::Context) {
+ fn foo(cx: foo::Context) {
let now = Instant::now();
- hprintln!("foo(scheduled = {:?}, now = {:?})", c.scheduled, now).unwrap();
+ hprintln!("foo(scheduled = {:?}, now = {:?})", cx.scheduled, now).unwrap();
- c.schedule.foo(c.scheduled + PERIOD.cycles()).unwrap();
+ cx.schedule.foo(cx.scheduled + PERIOD.cycles()).unwrap();
}
extern "C" {
diff --git a/examples/pool.rs b/examples/pool.rs
index 0b594b19..8c44cb17 100644
--- a/examples/pool.rs
+++ b/examples/pool.rs
@@ -5,14 +5,13 @@
#![no_main]
#![no_std]
-extern crate panic_semihosting;
-
use cortex_m_semihosting::{debug, hprintln};
use heapless::{
pool,
pool::singleton::{Box, Pool},
};
use lm3s6965::Interrupt;
+use panic_semihosting as _;
use rtfm::app;
// Declare a pool of 128-byte memory blocks
@@ -30,8 +29,8 @@ const APP: () = {
rtfm::pend(Interrupt::I2C0);
}
- #[interrupt(priority = 2, spawn = [foo, bar])]
- fn I2C0(c: I2C0::Context) {
+ #[task(binds = I2C0, priority = 2, spawn = [foo, bar])]
+ fn i2c0(c: i2c0::Context) {
// claim a memory block, leave it uninitialized and ..
let x = P::alloc().unwrap().freeze();
diff --git a/examples/preempt.rs b/examples/preempt.rs
new file mode 100644
index 00000000..d7a7e644
--- /dev/null
+++ b/examples/preempt.rs
@@ -0,0 +1,37 @@
+//! examples/preempt.rs
+
+#![no_main]
+#![no_std]
+
+use cortex_m_semihosting::{debug, hprintln};
+use lm3s6965::Interrupt;
+use panic_semihosting as _;
+use rtfm::app;
+
+#[app(device = lm3s6965)]
+const APP: () = {
+ #[init]
+ fn init(_: init::Context) {
+ rtfm::pend(Interrupt::GPIOA);
+ }
+
+ #[task(binds = GPIOA, priority = 1)]
+ fn gpioa(_: gpioa::Context) {
+ hprintln!("GPIOA - start").unwrap();
+ rtfm::pend(Interrupt::GPIOC);
+ hprintln!("GPIOA - end").unwrap();
+ debug::exit(debug::EXIT_SUCCESS);
+ }
+
+ #[task(binds = GPIOB, priority = 2)]
+ fn gpiob(_: gpiob::Context) {
+ hprintln!(" GPIOB").unwrap();
+ }
+
+ #[task(binds = GPIOC, priority = 2)]
+ fn gpioc(_: gpioc::Context) {
+ hprintln!(" GPIOC - start").unwrap();
+ rtfm::pend(Interrupt::GPIOB);
+ hprintln!(" GPIOC - end").unwrap();
+ }
+};
diff --git a/examples/ramfunc.rs b/examples/ramfunc.rs
index 4b0d69c7..c38635ff 100644
--- a/examples/ramfunc.rs
+++ b/examples/ramfunc.rs
@@ -5,9 +5,8 @@
#![no_main]
#![no_std]
-extern crate panic_semihosting;
-
use cortex_m_semihosting::{debug, hprintln};
+use panic_semihosting as _;
#[rtfm::app(device = lm3s6965)]
const APP: () = {
diff --git a/examples/resource.rs b/examples/resource.rs
index 06bdf395..8632525e 100644
--- a/examples/resource.rs
+++ b/examples/resource.rs
@@ -5,15 +5,17 @@
#![no_main]
#![no_std]
-extern crate panic_semihosting;
-
use cortex_m_semihosting::{debug, hprintln};
use lm3s6965::Interrupt;
+use panic_semihosting as _;
#[rtfm::app(device = lm3s6965)]
const APP: () = {
- // A resource
- static mut SHARED: u32 = 0;
+ struct Resources {
+ // A resource
+ #[init(0)]
+ shared: u32,
+ }
#[init]
fn init(_: init::Context) {
@@ -21,29 +23,31 @@ const APP: () = {
rtfm::pend(Interrupt::UART1);
}
+ // `shared` cannot be accessed from this context
#[idle]
- fn idle(_: idle::Context) -> ! {
+ fn idle(_cx: idle::Context) -> ! {
debug::exit(debug::EXIT_SUCCESS);
- // error: `SHARED` can't be accessed from this context
- // SHARED += 1;
+ // error: no `resources` field in `idle::Context`
+ // _cx.resources.shared += 1;
loop {}
}
- // `SHARED` can be access from this context
- #[interrupt(resources = [SHARED])]
- fn UART0(mut c: UART0::Context) {
- *c.resources.SHARED += 1;
+ // `shared` can be accessed from this context
+ #[task(binds = UART0, resources = [shared])]
+ fn uart0(cx: uart0::Context) {
+ let shared: &mut u32 = cx.resources.shared;
+ *shared += 1;
- hprintln!("UART0: SHARED = {}", c.resources.SHARED).unwrap();
+ hprintln!("UART0: shared = {}", shared).unwrap();
}
- // `SHARED` can be access from this context
- #[interrupt(resources = [SHARED])]
- fn UART1(mut c: UART1::Context) {
- *c.resources.SHARED += 1;
+ // `shared` can be accessed from this context
+ #[task(binds = UART1, resources = [shared])]
+ fn uart1(cx: uart1::Context) {
+ *cx.resources.shared += 1;
- hprintln!("UART1: SHARED = {}", c.resources.SHARED).unwrap();
+ hprintln!("UART1: shared = {}", cx.resources.shared).unwrap();
}
};
diff --git a/examples/schedule.rs b/examples/schedule.rs
index eaafb4c9..27d3bd1f 100644
--- a/examples/schedule.rs
+++ b/examples/schedule.rs
@@ -5,25 +5,24 @@
#![no_main]
#![no_std]
-extern crate panic_semihosting;
-
use cortex_m_semihosting::hprintln;
-use rtfm::Instant;
+use panic_halt as _;
+use rtfm::cyccnt::{Instant, U32Ext as _};
// NOTE: does NOT work on QEMU!
-#[rtfm::app(device = lm3s6965)]
+#[rtfm::app(device = lm3s6965, monotonic = rtfm::cyccnt::CYCCNT)]
const APP: () = {
#[init(schedule = [foo, bar])]
- fn init(c: init::Context) {
+ fn init(cx: init::Context) {
let now = Instant::now();
hprintln!("init @ {:?}", now).unwrap();
// Schedule `foo` to run 8e6 cycles (clock cycles) in the future
- c.schedule.foo(now + 8_000_000.cycles()).unwrap();
+ cx.schedule.foo(now + 8_000_000.cycles()).unwrap();
// Schedule `bar` to run 4e6 cycles in the future
- c.schedule.bar(now + 4_000_000.cycles()).unwrap();
+ cx.schedule.bar(now + 4_000_000.cycles()).unwrap();
}
#[task]
diff --git a/examples/shared-with-init.rs b/examples/shared-with-init.rs
index 0fb9191c..14fa54b7 100644
--- a/examples/shared-with-init.rs
+++ b/examples/shared-with-init.rs
@@ -5,30 +5,32 @@
#![no_main]
#![no_std]
-extern crate panic_halt;
-
use cortex_m_semihosting::debug;
use lm3s6965::Interrupt;
+use panic_halt as _;
use rtfm::app;
pub struct MustBeSend;
#[app(device = lm3s6965)]
const APP: () = {
- static mut SHARED: Option<MustBeSend> = None;
+ struct Resources {
+ #[init(None)]
+ shared: Option<MustBeSend>,
+ }
- #[init(resources = [SHARED])]
+ #[init(resources = [shared])]
fn init(c: init::Context) {
// this `message` will be sent to task `UART0`
let message = MustBeSend;
- *c.resources.SHARED = Some(message);
+ *c.resources.shared = Some(message);
rtfm::pend(Interrupt::UART0);
}
- #[interrupt(resources = [SHARED])]
- fn UART0(c: UART0::Context) {
- if let Some(message) = c.resources.SHARED.take() {
+ #[task(binds = UART0, resources = [shared])]
+ fn uart0(c: uart0::Context) {
+ if let Some(message) = c.resources.shared.take() {
// `message` has been received
drop(message);
diff --git a/examples/smallest.rs b/examples/smallest.rs
index c1537168..7b26a852 100644
--- a/examples/smallest.rs
+++ b/examples/smallest.rs
@@ -1,17 +1,10 @@
//! examples/smallest.rs
-#![deny(unsafe_code)]
-#![deny(warnings)]
#![no_main]
#![no_std]
-// panic-handler crate
-extern crate panic_semihosting;
-
+use panic_semihosting as _; // panic handler
use rtfm::app;
#[app(device = lm3s6965)]
-const APP: () = {
- #[init]
- fn init(_: init::Context) {}
-};
+const APP: () = {};
diff --git a/examples/static.rs b/examples/static.rs
deleted file mode 100644
index 2e3b5b41..00000000
--- a/examples/static.rs
+++ /dev/null
@@ -1,36 +0,0 @@
-//! examples/static.rs
-
-#![deny(unsafe_code)]
-#![deny(warnings)]
-#![no_main]
-#![no_std]
-
-extern crate panic_semihosting;
-
-use cortex_m_semihosting::{debug, hprintln};
-use lm3s6965::Interrupt;
-
-#[rtfm::app(device = lm3s6965)]
-const APP: () = {
- static KEY: u32 = ();
-
- #[init]
- fn init(_: init::Context) -> init::LateResources {
- rtfm::pend(Interrupt::UART0);
- rtfm::pend(Interrupt::UART1);
-
- init::LateResources { KEY: 0xdeadbeef }
- }
-
- #[interrupt(resources = [KEY])]
- fn UART0(c: UART0::Context) {
- hprintln!("UART0(KEY = {:#x})", c.resources.KEY).unwrap();
-
- debug::exit(debug::EXIT_SUCCESS);
- }
-
- #[interrupt(priority = 2, resources = [KEY])]
- fn UART1(c: UART1::Context) {
- hprintln!("UART1(KEY = {:#x})", c.resources.KEY).unwrap();
- }
-};
diff --git a/examples/t-binds.rs b/examples/t-binds.rs
new file mode 100644
index 00000000..dda8e201
--- /dev/null
+++ b/examples/t-binds.rs
@@ -0,0 +1,32 @@
+//! [compile-pass] Check that `binds` works as advertised
+
+#![deny(unsafe_code)]
+#![deny(warnings)]
+#![no_main]
+#![no_std]
+
+use panic_halt as _;
+
+#[rtfm::app(device = lm3s6965)]
+const APP: () = {
+ #[init]
+ fn init(_: init::Context) {}
+
+ // Cortex-M exception
+ #[task(binds = SVCall)]
+ fn foo(c: foo::Context) {
+ foo_trampoline(c)
+ }
+
+ // LM3S6965 interrupt
+ #[task(binds = UART0)]
+ fn bar(c: bar::Context) {
+ bar_trampoline(c)
+ }
+};
+
+#[allow(dead_code)]
+fn foo_trampoline(_: foo::Context) {}
+
+#[allow(dead_code)]
+fn bar_trampoline(_: bar::Context) {}
diff --git a/examples/t-cfg.rs b/examples/t-cfg.rs
new file mode 100644
index 00000000..e61ec795
--- /dev/null
+++ b/examples/t-cfg.rs
@@ -0,0 +1,50 @@
+//! [compile-pass] check that `#[cfg]` attributes are respected
+
+#![no_main]
+#![no_std]
+
+use panic_halt as _;
+
+#[rtfm::app(device = lm3s6965, monotonic = rtfm::cyccnt::CYCCNT)]
+const APP: () = {
+ struct Resources {
+ #[cfg(never)]
+ #[init(0)]
+ foo: u32,
+ }
+
+ #[init]
+ fn init(_: init::Context) {
+ #[cfg(never)]
+ static mut BAR: u32 = 0;
+ }
+
+ #[idle]
+ fn idle(_: idle::Context) -> ! {
+ #[cfg(never)]
+ static mut BAR: u32 = 0;
+
+ loop {}
+ }
+
+ #[task(resources = [foo], schedule = [quux], spawn = [quux])]
+ fn foo(_: foo::Context) {
+ #[cfg(never)]
+ static mut BAR: u32 = 0;
+ }
+
+ #[task(priority = 3, resources = [foo], schedule = [quux], spawn = [quux])]
+ fn bar(_: bar::Context) {
+ #[cfg(never)]
+ static mut BAR: u32 = 0;
+ }
+
+ #[cfg(never)]
+ #[task]
+ fn quux(_: quux::Context) {}
+
+ extern "C" {
+ fn UART0();
+ fn UART1();
+ }
+};
diff --git a/examples/t-late-not-send.rs b/examples/t-late-not-send.rs
new file mode 100644
index 00000000..4fd3504e
--- /dev/null
+++ b/examples/t-late-not-send.rs
@@ -0,0 +1,36 @@
+//! [compile-pass] late resources don't need to be `Send` if they are owned by `idle`
+
+#![no_main]
+#![no_std]
+
+use core::marker::PhantomData;
+
+use panic_halt as _;
+
+pub struct NotSend {
+ _0: PhantomData<*const ()>,
+}
+
+#[rtfm::app(device = lm3s6965)]
+const APP: () = {
+ struct Resources {
+ x: NotSend,
+ #[init(None)]
+ y: Option<NotSend>,
+ }
+
+ #[init(resources = [y])]
+ fn init(c: init::Context) -> init::LateResources {
+ // equivalent to late resource initialization
+ *c.resources.y = Some(NotSend { _0: PhantomData });
+
+ init::LateResources {
+ x: NotSend { _0: PhantomData },
+ }
+ }
+
+ #[idle(resources = [x, y])]
+ fn idle(_: idle::Context) -> ! {
+ loop {}
+ }
+};
diff --git a/examples/t-resource.rs b/examples/t-resource.rs
new file mode 100644
index 00000000..303340ed
--- /dev/null
+++ b/examples/t-resource.rs
@@ -0,0 +1,87 @@
+//! [compile-pass] Check code generation of resources
+
+#![deny(unsafe_code)]
+#![deny(warnings)]
+#![no_main]
+#![no_std]
+
+use panic_halt as _;
+
+#[rtfm::app(device = lm3s6965)]
+const APP: () = {
+ struct Resources {
+ #[init(0)]
+ o1: u32, // init
+ #[init(0)]
+ o2: u32, // idle
+ #[init(0)]
+ o3: u32, // EXTI0
+ #[init(0)]
+ o4: u32, // idle
+ #[init(0)]
+ o5: u32, // EXTI1
+ #[init(0)]
+ o6: u32, // init
+ #[init(0)]
+ s1: u32, // idle & uart0
+ #[init(0)]
+ s2: u32, // uart0 & uart1
+ #[init(0)]
+ s3: u32, // idle & uart0
+ }
+
+ #[init(resources = [o1, o4, o5, o6, s3])]
+ fn init(c: init::Context) {
+ // owned by `init` == `&'static mut`
+ let _: &'static mut u32 = c.resources.o1;
+
+ // owned by `init` == `&'static` if read-only
+ let _: &'static u32 = c.resources.o6;
+
+ // `init` has exclusive access to all resources
+ let _: &mut u32 = c.resources.o4;
+ let _: &mut u32 = c.resources.o5;
+ let _: &mut u32 = c.resources.s3;
+ }
+
+ #[idle(resources = [o2, &o4, s1, &s3])]
+ fn idle(mut c: idle::Context) -> ! {
+ // owned by `idle` == `&'static mut`
+ let _: &'static mut u32 = c.resources.o2;
+
+ // owned by `idle` == `&'static` if read-only
+ let _: &'static u32 = c.resources.o4;
+
+ // shared with `idle` == `Mutex`
+ c.resources.s1.lock(|_| {});
+
+ // `&` if read-only
+ let _: &u32 = c.resources.s3;
+
+ loop {}
+ }
+
+ #[task(binds = UART0, resources = [o3, s1, s2, &s3])]
+ fn uart0(c: uart0::Context) {
+ // owned by interrupt == `&mut`
+ let _: &mut u32 = c.resources.o3;
+
+ // no `Mutex` proxy when access from highest priority task
+ let _: &mut u32 = c.resources.s1;
+
+ // no `Mutex` proxy when co-owned by cooperative (same priority) tasks
+ let _: &mut u32 = c.resources.s2;
+
+ // `&` if read-only
+ let _: &u32 = c.resources.s3;
+ }
+
+ #[task(binds = UART1, resources = [s2, &o5])]
+ fn uart1(c: uart1::Context) {
+ // owned by interrupt == `&` if read-only
+ let _: &u32 = c.resources.o5;
+
+ // no `Mutex` proxy when co-owned by cooperative (same priority) tasks
+ let _: &mut u32 = c.resources.s2;
+ }
+};
diff --git a/examples/t-schedule.rs b/examples/t-schedule.rs
new file mode 100644
index 00000000..e6035b3f
--- /dev/null
+++ b/examples/t-schedule.rs
@@ -0,0 +1,59 @@
+//! [compile-pass] Check `schedule` code generation
+
+#![deny(unsafe_code)]
+#![deny(warnings)]
+#![no_main]
+#![no_std]
+
+use panic_halt as _;
+use rtfm::cyccnt::{Instant, U32Ext as _};
+
+#[rtfm::app(device = lm3s6965, monotonic = rtfm::cyccnt::CYCCNT)]
+const APP: () = {
+ #[init(schedule = [foo, bar, baz])]
+ fn init(c: init::Context) {
+ let _: Result<(), ()> = c.schedule.foo(c.start + 10.cycles());
+ let _: Result<(), u32> = c.schedule.bar(c.start + 20.cycles(), 0);
+ let _: Result<(), (u32, u32)> = c.schedule.baz(c.start + 30.cycles(), 0, 1);
+ }
+
+ #[idle(schedule = [foo, bar, baz])]
+ fn idle(c: idle::Context) -> ! {
+ let _: Result<(), ()> = c.schedule.foo(Instant::now() + 40.cycles());
+ let _: Result<(), u32> = c.schedule.bar(Instant::now() + 50.cycles(), 0);
+ let _: Result<(), (u32, u32)> = c.schedule.baz(Instant::now() + 60.cycles(), 0, 1);
+
+ loop {}
+ }
+
+ #[task(binds = SVCall, schedule = [foo, bar, baz])]
+ fn svcall(c: svcall::Context) {
+ let _: Result<(), ()> = c.schedule.foo(c.start + 70.cycles());
+ let _: Result<(), u32> = c.schedule.bar(c.start + 80.cycles(), 0);
+ let _: Result<(), (u32, u32)> = c.schedule.baz(c.start + 90.cycles(), 0, 1);
+ }
+
+ #[task(binds = UART0, schedule = [foo, bar, baz])]
+ fn uart0(c: uart0::Context) {
+ let _: Result<(), ()> = c.schedule.foo(c.start + 100.cycles());
+ let _: Result<(), u32> = c.schedule.bar(c.start + 110.cycles(), 0);
+ let _: Result<(), (u32, u32)> = c.schedule.baz(c.start + 120.cycles(), 0, 1);
+ }
+
+ #[task(schedule = [foo, bar, baz])]
+ fn foo(c: foo::Context) {
+ let _: Result<(), ()> = c.schedule.foo(c.scheduled + 130.cycles());
+ let _: Result<(), u32> = c.schedule.bar(c.scheduled + 140.cycles(), 0);
+ let _: Result<(), (u32, u32)> = c.schedule.baz(c.scheduled + 150.cycles(), 0, 1);
+ }
+
+ #[task]
+ fn bar(_: bar::Context, _x: u32) {}
+
+ #[task]
+ fn baz(_: baz::Context, _x: u32, _y: u32) {}
+
+ extern "C" {
+ fn UART1();
+ }
+};
diff --git a/examples/t-spawn.rs b/examples/t-spawn.rs
new file mode 100644
index 00000000..682b9b89
--- /dev/null
+++ b/examples/t-spawn.rs
@@ -0,0 +1,58 @@
+//! [compile-pass] Check code generation of `spawn`
+
+#![deny(unsafe_code)]
+#![deny(warnings)]
+#![no_main]
+#![no_std]
+
+use panic_halt as _;
+
+#[rtfm::app(device = lm3s6965)]
+const APP: () = {
+ #[init(spawn = [foo, bar, baz])]
+ fn init(c: init::Context) {
+ let _: Result<(), ()> = c.spawn.foo();
+ let _: Result<(), u32> = c.spawn.bar(0);
+ let _: Result<(), (u32, u32)> = c.spawn.baz(0, 1);
+ }
+
+ #[idle(spawn = [foo, bar, baz])]
+ fn idle(c: idle::Context) -> ! {
+ let _: Result<(), ()> = c.spawn.foo();
+ let _: Result<(), u32> = c.spawn.bar(0);
+ let _: Result<(), (u32, u32)> = c.spawn.baz(0, 1);
+
+ loop {}
+ }
+
+ #[task(binds = SVCall, spawn = [foo, bar, baz])]
+ fn svcall(c: svcall::Context) {
+ let _: Result<(), ()> = c.spawn.foo();
+ let _: Result<(), u32> = c.spawn.bar(0);
+ let _: Result<(), (u32, u32)> = c.spawn.baz(0, 1);
+ }
+
+ #[task(binds = UART0, spawn = [foo, bar, baz])]
+ fn uart0(c: uart0::Context) {
+ let _: Result<(), ()> = c.spawn.foo();
+ let _: Result<(), u32> = c.spawn.bar(0);
+ let _: Result<(), (u32, u32)> = c.spawn.baz(0, 1);
+ }
+
+ #[task(spawn = [foo, bar, baz])]
+ fn foo(c: foo::Context) {
+ let _: Result<(), ()> = c.spawn.foo();
+ let _: Result<(), u32> = c.spawn.bar(0);
+ let _: Result<(), (u32, u32)> = c.spawn.baz(0, 1);
+ }
+
+ #[task]
+ fn bar(_: bar::Context, _x: u32) {}
+
+ #[task]
+ fn baz(_: baz::Context, _x: u32, _y: u32) {}
+
+ extern "C" {
+ fn UART1();
+ }
+};
diff --git a/examples/task.rs b/examples/task.rs
index 5bb32acb..9e563d71 100644
--- a/examples/task.rs
+++ b/examples/task.rs
@@ -5,9 +5,8 @@
#![no_main]
#![no_std]
-extern crate panic_semihosting;
-
use cortex_m_semihosting::{debug, hprintln};
+use panic_semihosting as _;
#[rtfm::app(device = lm3s6965)]
const APP: () = {
@@ -18,16 +17,20 @@ const APP: () = {
#[task(spawn = [bar, baz])]
fn foo(c: foo::Context) {
- hprintln!("foo").unwrap();
+ hprintln!("foo - start").unwrap();
// spawns `bar` onto the task scheduler
// `foo` and `bar` have the same priority so `bar` will not run until
// after `foo` terminates
c.spawn.bar().unwrap();
+ hprintln!("foo - middle").unwrap();
+
// spawns `baz` onto the task scheduler
// `baz` has higher priority than `foo` so it immediately preempts `foo`
c.spawn.baz().unwrap();
+
+ hprintln!("foo - end").unwrap();
}
#[task]
diff --git a/examples/types.rs b/examples/types.rs
index c3dd89ca..fc391d07 100644
--- a/examples/types.rs
+++ b/examples/types.rs
@@ -5,48 +5,51 @@
#![no_main]
#![no_std]
-extern crate panic_semihosting;
-
use cortex_m_semihosting::debug;
-use rtfm::{Exclusive, Instant};
+use panic_semihosting as _;
+use rtfm::cyccnt;
-#[rtfm::app(device = lm3s6965)]
+#[rtfm::app(device = lm3s6965, peripherals = true, monotonic = rtfm::cyccnt::CYCCNT)]
const APP: () = {
- static mut SHARED: u32 = 0;
+ struct Resources {
+ #[init(0)]
+ shared: u32,
+ }
#[init(schedule = [foo], spawn = [foo])]
- fn init(c: init::Context) {
- let _: Instant = c.start;
- let _: rtfm::Peripherals = c.core;
- let _: lm3s6965::Peripherals = c.device;
- let _: init::Schedule = c.schedule;
- let _: init::Spawn = c.spawn;
+ fn init(cx: init::Context) {
+ let _: cyccnt::Instant = cx.start;
+ let _: rtfm::Peripherals = cx.core;
+ let _: lm3s6965::Peripherals = cx.device;
+ let _: init::Schedule = cx.schedule;
+ let _: init::Spawn = cx.spawn;
debug::exit(debug::EXIT_SUCCESS);
}
- #[exception(schedule = [foo], spawn = [foo])]
- fn SVCall(c: SVCall::Context) {
- let _: Instant = c.start;
- let _: SVCall::Schedule = c.schedule;
- let _: SVCall::Spawn = c.spawn;
+ #[idle(schedule = [foo], spawn = [foo])]
+ fn idle(cx: idle::Context) -> ! {
+ let _: idle::Schedule = cx.schedule;
+ let _: idle::Spawn = cx.spawn;
+
+ loop {}
}
- #[interrupt(resources = [SHARED], schedule = [foo], spawn = [foo])]
- fn UART0(c: UART0::Context) {
- let _: Instant = c.start;
- let _: resources::SHARED = c.resources.SHARED;
- let _: UART0::Schedule = c.schedule;
- let _: UART0::Spawn = c.spawn;
+ #[task(binds = UART0, resources = [shared], schedule = [foo], spawn = [foo])]
+ fn uart0(cx: uart0::Context) {
+ let _: cyccnt::Instant = cx.start;
+ let _: resources::shared = cx.resources.shared;
+ let _: uart0::Schedule = cx.schedule;
+ let _: uart0::Spawn = cx.spawn;
}
- #[task(priority = 2, resources = [SHARED], schedule = [foo], spawn = [foo])]
- fn foo(c: foo::Context) {
- let _: Instant = c.scheduled;
- let _: Exclusive<u32> = c.resources.SHARED;
- let _: foo::Resources = c.resources;
- let _: foo::Schedule = c.schedule;
- let _: foo::Spawn = c.spawn;
+ #[task(priority = 2, resources = [shared], schedule = [foo], spawn = [foo])]
+ fn foo(cx: foo::Context) {
+ let _: cyccnt::Instant = cx.scheduled;
+ let _: &mut u32 = cx.resources.shared;
+ let _: foo::Resources = cx.resources;
+ let _: foo::Schedule = cx.schedule;
+ let _: foo::Spawn = cx.spawn;
}
extern "C" {