2018-11-03 17:02:41 +01:00
|
|
|
# The `app` attribute
|
|
|
|
|
|
|
|
This is the smallest possible RTFM application:
|
|
|
|
|
|
|
|
``` rust
|
2019-02-11 21:40:53 +01:00
|
|
|
{{#include ../../../../examples/smallest.rs}}
|
2018-11-03 17:02:41 +01:00
|
|
|
```
|
|
|
|
|
|
|
|
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
|
2018-12-16 21:19:19 +01:00
|
|
|
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.
|
2018-11-03 17:02:41 +01:00
|
|
|
|
|
|
|
[`app`]: ../../api/cortex_m_rtfm_macros/attr.app.html
|
|
|
|
[`svd2rust`]: https://crates.io/crates/svd2rust
|
|
|
|
[`cortex_m_rt::entry`]: ../../api/cortex_m_rt_macros/attr.entry.html
|
|
|
|
|
|
|
|
> **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.
|
|
|
|
|
|
|
|
[`rtfm::Peripherals`]: ../../api/rtfm/struct.Peripherals.html
|
|
|
|
|
|
|
|
The example below shows the types of the `core` and `device` variables and
|
|
|
|
showcases safe access to a `static mut` variable.
|
|
|
|
|
|
|
|
``` rust
|
2019-02-11 21:40:53 +01:00
|
|
|
{{#include ../../../../examples/init.rs}}
|
2018-11-03 17:02:41 +01:00
|
|
|
```
|
|
|
|
|
|
|
|
Running the example will print `init` to the console and then exit the QEMU
|
|
|
|
process.
|
|
|
|
|
|
|
|
``` console
|
|
|
|
$ cargo run --example init
|
2019-02-11 21:40:53 +01:00
|
|
|
{{#include ../../../../ci/expected/init.run}}```
|
2018-11-03 17:02:41 +01:00
|
|
|
|
|
|
|
## `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`.
|
|
|
|
|
|
|
|
[SLEEPONEXIT]: https://developer.arm.com/products/architecture/cpu-architecture/m-profile/docs/100737/0100/power-management/sleep-mode/sleep-on-exit-bit
|
|
|
|
|
|
|
|
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`.
|
|
|
|
|
|
|
|
``` rust
|
2019-02-11 21:40:53 +01:00
|
|
|
{{#include ../../../../examples/idle.rs}}
|
2018-11-03 17:02:41 +01:00
|
|
|
```
|
|
|
|
|
|
|
|
``` console
|
|
|
|
$ cargo run --example idle
|
2019-02-11 21:40:53 +01:00
|
|
|
{{#include ../../../../ci/expected/idle.run}}```
|
2018-11-03 17:02:41 +01:00
|
|
|
|
|
|
|
## `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.
|
|
|
|
|
|
|
|
``` rust
|
2019-02-11 21:40:53 +01:00
|
|
|
{{#include ../../../../examples/interrupt.rs}}
|
2018-11-03 17:02:41 +01:00
|
|
|
```
|
|
|
|
|
|
|
|
``` console
|
|
|
|
$ cargo run --example interrupt
|
2019-02-11 21:40:53 +01:00
|
|
|
{{#include ../../../../ci/expected/interrupt.run}}```
|
2018-11-03 17:02:41 +01:00
|
|
|
|
|
|
|
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.
|