The #[app] attribute and an RTIC application
Requirements on the app attribute
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 svd2rust v0.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.
Structure and zero-cost concurrency
An RTIC app is an executable system model for single-core applications, declaring a set of local and shared resources operated on by a set of init, idle, hardware and software tasks.
initruns before any other task, and returns thelocalandsharedresources.- Tasks (both hardware and software) run preemptively based on their associated static priority.
 - Hardware tasks are bound to underlying hardware interrupts.
 - Software tasks are schedulied by an set of asynchronous executors, one for each software task priority.
 idlehas the lowest priority, and can be used for background work, and/or to put the system to sleep until it is woken by some event.
At compile time the task/resource model is analyzed under the Stack Resource Policy (SRP) and executable code generated with the following outstanding properties:
- Guaranteed race-free resource access and deadlock-free execution on a single-shared stack.
 - Hardware task scheduling is performed directly by the hardware.
 - Software task scheduling is performed by auto generated async executors tailored to the application.
 
Overall, the generated code infers no additional overhead in comparison to a hand-written implementation, thus in Rust terms RTIC offers a zero-cost abstraction to concurrency.
Priority
Priorities in RTIC are specified using the priority = N (where N is a positive number) argument passed to the #[task] attribute. All #[task]s can have a priority. If the priority of a task is not specified, it is set to the default value of 0.
Priorities in RTIC follow a higher value = more important scheme. For examples, a task with priority 2 will preempt a task with priority 1.
An RTIC application example
To give a taste of RTIC, the following example contains commonly used features. In the following sections we will go through each feature in detail.
//! examples/common.rs
#![no_main]
#![no_std]
#![deny(warnings)]
#![deny(unsafe_code)]
#![deny(missing_docs)]
use panic_semihosting as _;
#[rtic::app(device = lm3s6965, dispatchers = [UART0, UART1])]
mod app {
    use cortex_m_semihosting::{debug, hprintln};
    #[shared]
    struct Shared {}
    #[local]
    struct Local {
        local_to_foo: i64,
        local_to_bar: i64,
        local_to_idle: i64,
    }
    // `#[init]` cannot access locals from the `#[local]` struct as they are initialized here.
    #[init]
    fn init(_: init::Context) -> (Shared, Local) {
        foo::spawn().unwrap();
        bar::spawn().unwrap();
        (
            Shared {},
            // initial values for the `#[local]` resources
            Local {
                local_to_foo: 0,
                local_to_bar: 0,
                local_to_idle: 0,
            },
        )
    }
    // `local_to_idle` can only be accessed from this context
    #[idle(local = [local_to_idle])]
    fn idle(cx: idle::Context) -> ! {
        let local_to_idle = cx.local.local_to_idle;
        *local_to_idle += 1;
        hprintln!("idle: local_to_idle = {}", local_to_idle);
        debug::exit(debug::EXIT_SUCCESS); // Exit QEMU simulator
        // error: no `local_to_foo` field in `idle::LocalResources`
        // _cx.local.local_to_foo += 1;
        // error: no `local_to_bar` field in `idle::LocalResources`
        // _cx.local.local_to_bar += 1;
        loop {
            cortex_m::asm::nop();
        }
    }
    // `local_to_foo` can only be accessed from this context
    #[task(local = [local_to_foo], priority = 1)]
    async fn foo(cx: foo::Context) {
        let local_to_foo = cx.local.local_to_foo;
        *local_to_foo += 1;
        // error: no `local_to_bar` field in `foo::LocalResources`
        // cx.local.local_to_bar += 1;
        hprintln!("foo: local_to_foo = {}", local_to_foo);
    }
    // `local_to_bar` can only be accessed from this context
    #[task(local = [local_to_bar], priority = 1)]
    async fn bar(cx: bar::Context) {
        let local_to_bar = cx.local.local_to_bar;
        *local_to_bar += 1;
        // error: no `local_to_foo` field in `bar::LocalResources`
        // cx.local.local_to_foo += 1;
        hprintln!("bar: local_to_bar = {}", local_to_bar);
    }
}