rtic/book/en/src/by-example/app.md
Henrik Tjäder 458db0b737 Markdown end of fenced code should be on a separate line
Done with sd -f c '}}' SUMMARY.md
by-example/app.md
by-example/new.md
by-example/resources.md
by-example/singletons.md
by-example/tasks.md
by-example/timer-queue.md
by-example/tips.md
by-example/types-send-sync.md
by-example.md
internals/ceilings.md
internals/tasks.md
internals/timer-queue.md
internals.md
preface.md
2020-10-12 08:06:37 +00:00

4 KiB

The app attribute

This is the smallest possible RTFM application:

{{#include ../../../../examples/smallest.rs}}

All RTFM applications use the app attribute (#[app(..)]). This attribute must be applied to a const item that contains items. The app attribute has a mandatory device argument that takes a path as a value. This path must point to a peripheral access crate (PAC) generated using svd2rust v0.14.x. The app attribute will expand into a suitable entry point so it's not required to use the cortex_m_rt::entry attribute.

ASIDE: Some of you may be wondering why we are using a const item as a module and not a proper mod item. The reason is that using attributes on modules requires a feature gate, which requires a nightly toolchain. To make RTFM work on stable we use the const item instead. When more parts of macros 1.2 are stabilized we'll move from a const item to a mod item and eventually to a crate level attribute (#![app]).

init

Within the pseudo-module the app attribute expects to find an initialization function marked with the init attribute. This function must have signature [unsafe] fn().

This initialization function will be the first part of the application to run. The init function will run with interrupts disabled and has exclusive access to Cortex-M and device specific peripherals through the core and device variables, which are injected in the scope of init by the app attribute. Not all Cortex-M peripherals are available in core because the RTFM runtime takes ownership of some of them -- for more details see the rtfm::Peripherals struct.

static mut variables declared at the beginning of init will be transformed into &'static mut references that are safe to access.

The example below shows the types of the core and device variables and showcases safe access to a static mut variable.

{{#include ../../../../examples/init.rs}}

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

$ cargo run --example init
{{#include ../../../../ci/expected/init.run}}

idle

A function marked with the idle attribute can optionally appear in the pseudo-module. This function is used as the special idle task and must have signature [unsafe] fn() - > !.

When present, the runtime will execute the idle task after init. Unlike init, idle will run with interrupts enabled and it's not allowed to return so it runs forever.

When no idle function is declared, the runtime sets the SLEEPONEXIT bit and then sends the microcontroller to sleep after running init.

Like in init, static mut variables will be transformed into &'static mut references that are safe to access.

The example below shows that idle runs after init.

{{#include ../../../../examples/idle.rs}}
$ cargo run --example idle
{{#include ../../../../ci/expected/idle.run}}

interrupt / exception

Just like you would do with the cortex-m-rt crate you can use the interrupt and exception attributes within the app pseudo-module to declare interrupt and exception handlers. In RTFM, we refer to interrupt and exception handlers as hardware tasks.

{{#include ../../../../examples/interrupt.rs}}
$ cargo run --example interrupt
{{#include ../../../../ci/expected/interrupt.run}}

So far all the RTFM applications we have seen look no different that the applications one can write using only the cortex-m-rt crate. In the next section we start introducing features unique to RTFM.