All RTIC applications use the app attribute (#[app(..)]). This attribute
only applies to a mod-item containing the RTIC application. The app
attribute has a mandatory device argument that takes a path as a value.
This must be a full path pointing to a
peripheral access crate (PAC) generated using svd2rustv0.14.x or
newer.
The app attribute will expand into a suitable entry point and thus replaces
the use of the cortex_m_rt::entry attribute.
To give a flavour of RTIC, the following example contains commonly used features.
In the following sections we will go through each feature in detail.
#![allow(unused)]fnmain() {
//! examples/common.rs#![deny(unsafe_code)]#![deny(warnings)]#![deny(missing_docs)]#![no_main]#![no_std]use panic_semihosting as _;
#[rtic::app(device = lm3s6965, dispatchers = [SSI0, QEI0])]
mod app {
use cortex_m_semihosting::{debug, hprintln};
use systick_monotonic::*; // Implements the `Monotonic` trait// A monotonic timer to enable scheduling in RTIC#[monotonic(binds = SysTick, default = true)]typeMyMono = Systick<100>; // 100 Hz / 10 ms granularity// Resources shared between tasks#[shared]structShared {
s1: u32,
s2: i32,
}
// Local resources to specific tasks (cannot be shared)#[local]structLocal {
l1: u8,
l2: i8,
}
#[init]fninit(cx: init::Context) -> (Shared, Local, init::Monotonics) {
let systick = cx.core.SYST;
// Initialize the monotonic (SysTick rate in QEMU is 12 MHz)let mono = Systick::new(systick, 12_000_000);
// Spawn the task `foo` directly after `init` finishes
foo::spawn().unwrap();
// Spawn the task `bar` 1 second after `init` finishes, this is enabled// by the `#[monotonic(..)]` above
bar::spawn_after(1.secs()).unwrap();
debug::exit(debug::EXIT_SUCCESS); // Exit QEMU simulator
(
// Initialization of shared resources
Shared { s1: 0, s2: 1 },
// Initialization of task local resources
Local { l1: 2, l2: 3 },
// Move the monotonic timer to the RTIC run-time, this enables// scheduling
init::Monotonics(mono),
)
}
// Background task, runs whenever no other tasks are running#[idle]fnidle(_: idle::Context) -> ! {
loop {
continue;
}
}
// Software task, not bound to a hardware interrupt.// This task takes the task local resource `l1`// The resources `s1` and `s2` are shared between all other tasks.#[task(shared = [s1, s2], local = [l1])]
fnfoo(_: foo::Context) {
// This task is only spawned once in `init`, hence this task will run// only once
hprintln!("foo");
}
// Software task, also not bound to a hardware interrupt// This task takes the task local resource `l2`// The resources `s1` and `s2` are shared between all other tasks.#[task(shared = [s1, s2], local = [l2])]
fnbar(_: bar::Context) {
hprintln!("bar");
// Run `bar` once per second
bar::spawn_after(1.secs()).unwrap();
}
// Hardware task, bound to a hardware interrupt// The resources `s1` and `s2` are shared between all other tasks.#[task(binds = UART0, priority = 3, shared = [s1, s2])]
fnuart0_interrupt(_: uart0_interrupt::Context) {
// This task is bound to the interrupt `UART0` and will run// whenever the interrupt fires// Note that RTIC does NOT clear the interrupt flag, this is up to the// user
hprintln!("UART0 interrupt!");
}
}
}