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

# Migrating from v0.5.x to v1.0.0

This section describes how to upgrade from v0.5.x to v1.0.0 of the RTIC framework.

## `Cargo.toml` - version bump

Change the version of `cortex-m-rtic` to `"1.0.0"`.

## `mod` instead of `const`

With the support of attributes on modules the `const APP` workaround is not needed.

Change

    #![allow(unused)]
    fn main() {
    #[rtic::app(/* .. */)]
    const APP: () = {
      [code here]
    };
    }

into

    #![allow(unused)]
    fn main() {
    #[rtic::app(/* .. */)]
    mod app {
      [code here]
    }
    }

Now that a regular Rust module is used it means it is possible to have custom user code within that module. Additionally, it means that `use`-statements for resources used in user code must be moved inside `mod app`, or be referred to with `super`. For example, change:

    #![allow(unused)]
    fn main() {
    use some_crate::some_func;

    #[rtic::app(/* .. */)]
    const APP: () = {
        fn func() {
            some_crate::some_func();
        }
    };
    }

into

    #![allow(unused)]
    fn main() {
    #[rtic::app(/* .. */)]
    mod app {
        use some_crate::some_func;

        fn func() {
            some_crate::some_func();
        }
    }
    }

or

    #![allow(unused)]
    fn main() {
    use some_crate::some_func;

    #[rtic::app(/* .. */)]
    mod app {
        fn func() {
            super::some_crate::some_func();
        }
    }
    }

## Move Dispatchers from `extern "C"` to app arguments

Change

    #![allow(unused)]
    fn main() {
    #[rtic::app(/* .. */)]
    const APP: () = {
        [code here]

        // RTIC requires that unused interrupts are declared in an extern block when
        // using software tasks; these free interrupts will be used to dispatch the
        // software tasks.
        extern "C" {
            fn SSI0();
            fn QEI0();
        }
    };
    }

into

    #![allow(unused)]
    fn main() {
    #[rtic::app(/* .. */, dispatchers = [SSI0, QEI0])]
    mod app {
      [code here]
    }
    }

This works also for ram functions, see examples/ramfunc.rs

## Resources structs - `#[shared]`, `#[local]`

Previously the RTIC resources had to be in in a struct named exactly "Resources":

    #![allow(unused)]
    fn main() {
    struct Resources {
        // Resources defined in here
    }
    }

With RTIC v1.0.0 the resources structs are annotated similarly like `#[task]`, `#[init]`, `#[idle]`: with the attributes `#[shared]` and `#[local]`

    #![allow(unused)]
    fn main() {
    #[shared]
    struct MySharedResources {
        // Resources shared between tasks are defined here
    }

    #[local]
    struct MyLocalResources {
        // Resources defined here cannot be shared between tasks; each one is local to a single task
    }
    }

These structs can be freely named by the developer.

## `shared` and `local` arguments in `#[task]`s

In v1.0.0 resources are split between `shared` resources and `local` resources. `#[task]`, `#[init]` and `#[idle]` no longer have a `resources` argument; they must now use the `shared` and `local` arguments.

In v0.5.x:

    #![allow(unused)]
    fn main() {
    struct Resources {
        local_to_b: i64,
        shared_by_a_and_b: i64,
    }

    #[task(resources = [shared_by_a_and_b])]
    fn a(_: a::Context) {}

    #[task(resources = [shared_by_a_and_b, local_to_b])]
    fn b(_: b::Context) {}
    }

In v1.0.0:

    #![allow(unused)]
    fn main() {
    #[shared]
    struct Shared {
        shared_by_a_and_b: i64,
    }

    #[local]
    struct Local {
        local_to_b: i64,
    }

    #[task(shared = [shared_by_a_and_b])]
    fn a(_: a::Context) {}

    #[task(shared = [shared_by_a_and_b], local = [local_to_b])]
    fn b(_: b::Context) {}
    }

## Symmetric locks

Now RTIC utilizes symmetric locks, this means that the `lock` method need to be used for all `shared` resource access. In old code one could do the following as the high priority task has exclusive access to the resource:

    #![allow(unused)]
    fn main() {
    #[task(priority = 2, resources = [r])]
    fn foo(cx: foo::Context) {
        cx.resources.r = /* ... */;
    }

    #[task(resources = [r])]
    fn bar(cx: bar::Context) {
        cx.resources.r.lock(|r| r = /* ... */);
    }
    }

And with symmetric locks one needs to use locks in both tasks:

    #![allow(unused)]
    fn main() {
    #[task(priority = 2, shared = [r])]
    fn foo(cx: foo::Context) {
        cx.shared.r.lock(|r| r = /* ... */);
    }

    #[task(shared = [r])]
    fn bar(cx: bar::Context) {
        cx.shared.r.lock(|r| r = /* ... */);
    }
    }

Note that the performance does not change thanks to LLVM's optimizations which optimizes away unnecessary locks.

## Lock-free resource access

In RTIC 0.5 resources shared by tasks running at the same priority could be accessed without the `lock` API. This is still possible in 1.0: the `#[shared]` resource must be annotated with the field-level `#[lock_free]` attribute.

v0.5 code:

    #![allow(unused)]
    fn main() {
    struct Resources {
        counter: u64,
    }

    #[task(resources = [counter])]
    fn a(cx: a::Context) {
        *cx.resources.counter += 1;
    }

    #[task(resources = [counter])]
    fn b(cx: b::Context) {
        *cx.resources.counter += 1;
    }
    }

v1.0 code:

    #![allow(unused)]
    fn main() {
    #[shared]
    struct Shared {
        #[lock_free]
        counter: u64,
    }

    #[task(shared = [counter])]
    fn a(cx: a::Context) {
        *cx.shared.counter += 1;
    }

    #[task(shared = [counter])]
    fn b(cx: b::Context) {
        *cx.shared.counter += 1;
    }
    }

## no `static mut` transform

`static mut` variables are no longer transformed to safe `&'static mut` references. Instead of that syntax, use the `local` argument in `#[init]`.

v0.5.x code:

    #![allow(unused)]
    fn main() {
    #[init]
    fn init(_: init::Context) {
        static mut BUFFER: [u8; 1024] = [0; 1024];
        let buffer: &'static mut [u8; 1024] = BUFFER;
    }
    }

v1.0.0 code:

    #![allow(unused)]
    fn main() {
    #[init(local = [
        buffer: [u8; 1024] = [0; 1024]
    //   type ^^^^^^^^^^^^   ^^^^^^^^^ initial value
    ])]
    fn init(cx: init::Context) -> (Shared, Local, init::Monotonics) {
        let buffer: &'static mut [u8; 1024] = cx.local.buffer;

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

## Init always returns late resources

In order to make the API more symmetric the #[init]-task always returns a late resource.

From this:

    #![allow(unused)]
    fn main() {
    #[rtic::app(device = lm3s6965)]
    const APP: () = {
        #[init]
        fn init(_: init::Context) {
            rtic::pend(Interrupt::UART0);
        }

        // [more code]
    };
    }

to this:

    #![allow(unused)]
    fn main() {
    #[rtic::app(device = lm3s6965)]
    mod app {
        #[shared]
        struct MySharedResources {}

        #[local]
        struct MyLocalResources {}

        #[init]
        fn init(_: init::Context) -> (MySharedResources, MyLocalResources, init::Monotonics) {
            rtic::pend(Interrupt::UART0);

            (MySharedResources, MyLocalResources, init::Monotonics())
        }

        // [more code]
    }
    }

## Spawn from anywhere

With the new spawn/spawn_after/spawn_at interface, old code requiring the context `cx` for spawning such as:

    #![allow(unused)]
    fn main() {
    #[task(spawn = [bar])]
    fn foo(cx: foo::Context) {
        cx.spawn.bar().unwrap();
    }

    #[task(schedule = [bar])]
    fn bar(cx: bar::Context) {
        cx.schedule.foo(/* ... */).unwrap();
    }
    }

Will now be written as:

    #![allow(unused)]
    fn main() {
    #[task]
    fn foo(_c: foo::Context) {
        bar::spawn().unwrap();
    }

    #[task]
    fn bar(_c: bar::Context) {
        // Takes a Duration, relative to “now”
        let spawn_handle = foo::spawn_after(/* ... */);
    }

    #[task]
    fn bar(_c: bar::Context) {
        // Takes an Instant
        let spawn_handle = foo::spawn_at(/* ... */);
    }
    }

Thus the requirement of having access to the context is dropped.

Note that the attributes `spawn`/`schedule` in the task definition are no longer needed.

## Additions

### Extern tasks

Both software and hardware tasks can now be defined external to the `mod app`. Previously this was possible only by implementing a trampoline calling out the task implementation.

See examples `examples/extern_binds.rs` and `examples/extern_spawn.rs`.

This enables breaking apps into multiple files.