App initialization and the #[init] task

An RTIC application requires an init task setting up the system. The corresponding init function must have the signature fn(init::Context) -> (Shared, Local), where Shared and Local are resource structures defined by the user.

The init task executes after system reset, [after an optionally defined pre-init code section]1 and an always occurring internal RTIC initialization.

The init and optional pre-init tasks runs with interrupts disabled and have exclusive access to Cortex-M (the bare_metal::CriticalSection token is available as cs).

Device specific peripherals are available through the core and device fields of init::Context.

Example

The example below shows the types of the core, device and cs fields, and showcases the use of a local variable with 'static lifetime. Such variables can be delegated from the init task to other tasks of the RTIC application.

The device field is only available when the peripherals argument is set to the default value true. In the rare case you want to implement an ultra-slim application you can explicitly set peripherals to false.

//! examples/init.rs

#![no_main]
#![no_std]
#![deny(warnings)]
#![deny(unsafe_code)]
#![deny(missing_docs)]

use panic_semihosting as _;

#[rtic::app(device = lm3s6965, peripherals = true)]
mod app {
    use cortex_m_semihosting::{debug, hprintln};

    #[shared]
    struct Shared {}

    #[local]
    struct Local {}

    #[init(local = [x: u32 = 0])]
    fn init(cx: init::Context) -> (Shared, Local) {
        // Cortex-M peripherals
        let _core: cortex_m::Peripherals = cx.core;

        // Device specific peripherals
        let _device: lm3s6965::Peripherals = cx.device;

        // Locals in `init` have 'static lifetime
        let _x: &'static mut u32 = cx.local.x;

        // Access to the critical section token,
        // to indicate that this is a critical section
        let _cs_token: bare_metal::CriticalSection = cx.cs;

        hprintln!("init");

        debug::exit(debug::EXIT_SUCCESS); // Exit QEMU simulator

        (Shared {}, Local {})
    }
}

Running the example will print init to the console and then exit the QEMU process.

$ cargo xtask qemu --verbose --example init
init