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.

fn main() {
//! examples/


use panic_semihosting as _;

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

    struct Shared {}

    struct Local {}

    fn init(_: init::Context) -> (Shared, Local, init::Monotonics) {

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

    fn foo(_: foo::Context) {

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

    // run this task from RAM
    #[link_section = ""]
    #[task(priority = 2)]
    fn bar(_: bar::Context) {

Running this program produces the expected output.

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

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