## 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

# Running tasks from RAM

The main goal of moving the specification of RTIC applications to attributes in RTIC v0.4.0 was to allow inter-operation with other attributes. For example, the `link_section` attribute can be applied to tasks to place them in RAM; this can improve performance in some cases.

> IMPORTANT: In general, the `link_section`, `export_name` and `no_mangle` attributes are powerful but also easy to misuse. Incorrectly using any of these attributes can cause undefined behavior; you should always prefer to use safe, higher level attributes around them like `cortex-m-rt`'s `interrupt` and `exception` attributes.

> In the particular case of RAM functions there's no safe abstraction for it in `cortex-m-rt` v0.6.5 but there's an RFC for adding a `ramfunc` attribute in a future release.

The example below shows how to place the higher priority task, `bar`, in RAM.

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

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

    use panic_semihosting as _;

    #[rtic::app(
        device = lm3s6965,
        dispatchers = [
            UART0,
            #[link_section = ".data.UART1"]
            UART1
        ])
    ]
    mod app {
        use cortex_m_semihosting::{debug, hprintln};

        #[shared]
        struct Shared {}

        #[local]
        struct Local {}

        #[init]
        fn init(_: init::Context) -> (Shared, Local, init::Monotonics) {
            foo::spawn().unwrap();

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

        #[inline(never)]
        #[task]
        fn foo(_: foo::Context) {
            hprintln!("foo");

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

        // run this task from RAM
        #[inline(never)]
        #[link_section = ".data.bar"]
        #[task(priority = 2)]
        fn bar(_: bar::Context) {
            foo::spawn().unwrap();
        }
    }
    }

Running this program produces the expected output.

    $ cargo run --target thumbv7m-none-eabi --example ramfunc
    foo

One can look at the output of `cargo-nm` to confirm that `bar` ended in RAM (`0x2000_0000`), whereas `foo` ended in Flash (`0x0000_0000`).

    $ cargo nm --example ramfunc --release | grep ' foo::'
    00000162 t ramfunc::foo::h30e7789b08c08e19

    $ cargo nm --example ramfunc --release | grep ' bar::'
    20000000 t ramfunc::bar::h9d6714fe5a3b0c89