## Keyboard shortcuts

Press `←` or `→` to navigate between chapters

Press `S` or `/` to search in the book

Press `?` to show this help

Press `Esc` to hide this help

# The background task `#[idle]`

A function marked with the `idle` attribute can optionally appear in the module. This becomes the special idle task and must have signature `fn(idle::Context) -> !`.

When present, the runtime will execute the `idle` task after `init`. Unlike `init`, `idle` will run with interrupts enabled and must never return, as the `-> !` function signature indicates. The Rust type `!` means “never”.

Like in `init`, locally declared resources will have `'static` lifetimes that are safe to access.

The example below shows that `idle` runs after `init`.

    #![allow(unused)]
    fn main() {
    //! examples/idle.rs

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

    use panic_semihosting as _;

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

        #[shared]
        struct Shared {}

        #[local]
        struct Local {}

        #[init]
        fn init(_: init::Context) -> (Shared, Local, init::Monotonics) {
            hprintln!("init");

            (Shared {}, Local {}, init::Monotonics())
        }

        #[idle(local = [x: u32 = 0])]
        fn idle(cx: idle::Context) -> ! {
            // Locals in idle have lifetime 'static
            let _x: &'static mut u32 = cx.local.x;

            hprintln!("idle");

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

            loop {
                cortex_m::asm::nop();
            }
        }
    }
    }

    $ cargo run --target thumbv7m-none-eabi --example idle
    init
    idle

By default, the RTIC `idle` task does not try to optimize for any specific targets.

A common useful optimization is to enable the SLEEPONEXIT and allow the MCU to enter sleep when reaching `idle`.

> Caution some hardware unless configured disables the debug unit during sleep mode.

> Consult your hardware specific documentation as this is outside the scope of RTIC.

The following example shows how to enable sleep by setting the `SLEEPONEXIT` and providing a custom `idle` task replacing the default `nop()` with `wfi()`.

    #![allow(unused)]
    fn main() {
    //! examples/idle-wfi.rs

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

    use panic_semihosting as _;

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

        #[shared]
        struct Shared {}

        #[local]
        struct Local {}

        #[init]
        fn init(mut cx: init::Context) -> (Shared, Local, init::Monotonics) {
            hprintln!("init");

            // Set the ARM SLEEPONEXIT bit to go to sleep after handling interrupts
            // See https://developer.arm.com/docs/100737/0100/power-management/sleep-mode/sleep-on-exit-bit
            cx.core.SCB.set_sleepdeep();

            (Shared {}, Local {}, init::Monotonics())
        }

        #[idle(local = [x: u32 = 0])]
        fn idle(cx: idle::Context) -> ! {
            // Locals in idle have lifetime 'static
            let _x: &'static mut u32 = cx.local.x;

            hprintln!("idle");

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

            loop {
                // Now Wait For Interrupt is used instead of a busy-wait loop
                // to allow MCU to sleep between interrupts
                // https://developer.arm.com/documentation/ddi0406/c/Application-Level-Architecture/Instruction-Details/Alphabetical-list-of-instructions/WFI
                rtic::export::wfi()
            }
        }
    }
    }

    $ cargo run --target thumbv7m-none-eabi --example idle-wfi
    init
    idle