mirror of
https://github.com/rtic-rs/rtic.git
synced 2025-12-17 21:35:20 +01:00
Rename RTFM to RTIC
This commit is contained in:
parent
4a0393f756
commit
602a5b4374
129 changed files with 454 additions and 454 deletions
|
|
@ -2,4 +2,4 @@
|
|||
authors = ["Jorge Aparicio"]
|
||||
multilingual = false
|
||||
src = "src"
|
||||
title = "Real Time For the Masses"
|
||||
title = "Real-Time Interrupt-driven Concurrency"
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
# Summary
|
||||
|
||||
[Preface](./preface.md)
|
||||
- [RTFM by example](./by-example.md)
|
||||
- [RTIC by example](./by-example.md)
|
||||
- [The `app` attribute](./by-example/app.md)
|
||||
- [Resources](./by-example/resources.md)
|
||||
- [Software tasks](./by-example/tasks.md)
|
||||
|
|
|
|||
|
|
@ -1,13 +1,13 @@
|
|||
# RTFM by example
|
||||
# RTIC by example
|
||||
|
||||
This part of the book introduces the Real Time For the Masses (RTFM) framework
|
||||
This part of the book introduces the Real-Time Interrupt-driven Concurrency (RTIC) framework
|
||||
to new users by walking them through examples of increasing complexity.
|
||||
|
||||
All examples in this part of the book can be found in the GitHub [repository] of
|
||||
the project, and most of the examples can be run on QEMU so no special hardware
|
||||
is required to follow along.
|
||||
|
||||
[repository]: https://github.com/rtfm-rs/cortex-m-rtfm
|
||||
[repository]: https://github.com/rtic-rs/cortex-m-rtic
|
||||
|
||||
To run the examples on your laptop / PC you'll need the `qemu-system-arm`
|
||||
program. Check [the embedded Rust book] for instructions on how to set up an
|
||||
|
|
|
|||
|
|
@ -1,26 +1,26 @@
|
|||
# The `app` attribute
|
||||
|
||||
This is the smallest possible RTFM application:
|
||||
This is the smallest possible RTIC application:
|
||||
|
||||
``` rust
|
||||
{{#include ../../../../examples/smallest.rs}}
|
||||
```
|
||||
|
||||
All RTFM applications use the [`app`] attribute (`#[app(..)]`). This attribute
|
||||
All RTIC 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** or newer. The `app` attribute will expand into a suitable entry
|
||||
point so it's not required to use the [`cortex_m_rt::entry`] attribute.
|
||||
|
||||
[`app`]: ../../../api/cortex_m_rtfm_macros/attr.app.html
|
||||
[`app`]: ../../../api/cortex_m_rtic_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
|
||||
> RTIC 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]`).
|
||||
|
||||
|
|
@ -39,7 +39,7 @@ to Cortex-M and, optionally, device specific peripherals through the `core` and
|
|||
`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
|
||||
[`rtic::Peripherals`]: ../../api/rtic/struct.Peripherals.html
|
||||
|
||||
The example below shows the types of the `core` and `device` fields and
|
||||
showcases safe access to a `static mut` variable. The `device` field is only
|
||||
|
|
@ -106,9 +106,9 @@ mut` variables are safe to use within a hardware task.
|
|||
$ cargo run --example hardware
|
||||
{{#include ../../../../ci/expected/hardware.run}}```
|
||||
|
||||
So far all the RTFM applications we have seen look no different than the
|
||||
So far all the RTIC applications we have seen look no different than the
|
||||
applications one can write using only the `cortex-m-rt` crate. From this point
|
||||
we start introducing features unique to RTFM.
|
||||
we start introducing features unique to RTIC.
|
||||
|
||||
## Priorities
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
# Starting a new project
|
||||
|
||||
Now that you have learned about the main features of the RTFM framework you can
|
||||
Now that you have learned about the main features of the RTIC framework you can
|
||||
try it out on your hardware by following these instructions.
|
||||
|
||||
1. Instantiate the [`cortex-m-quickstart`] template.
|
||||
|
|
@ -36,19 +36,19 @@ $ cargo add lm3s6965 --vers 0.1.3
|
|||
$ rm memory.x build.rs
|
||||
```
|
||||
|
||||
3. Add the `cortex-m-rtfm` crate as a dependency.
|
||||
3. Add the `cortex-m-rtic` crate as a dependency.
|
||||
|
||||
``` console
|
||||
$ cargo add cortex-m-rtfm --allow-prerelease
|
||||
$ cargo add cortex-m-rtic --allow-prerelease
|
||||
```
|
||||
|
||||
4. Write your RTFM application.
|
||||
4. Write your RTIC application.
|
||||
|
||||
Here I'll use the `init` example from the `cortex-m-rtfm` crate.
|
||||
Here I'll use the `init` example from the `cortex-m-rtic` crate.
|
||||
|
||||
``` console
|
||||
$ curl \
|
||||
-L https://github.com/rtfm-rs/cortex-m-rtfm/raw/v0.5.0/examples/init.rs \
|
||||
-L https://github.com/rtic-rs/cortex-m-rtic/raw/v0.5.0/examples/init.rs \
|
||||
> src/main.rs
|
||||
```
|
||||
|
||||
|
|
|
|||
|
|
@ -46,8 +46,8 @@ instead of a reference. This resource proxy is a structure that implements the
|
|||
[`Mutex`] trait. The only method on this trait, [`lock`], runs its closure
|
||||
argument in a critical section.
|
||||
|
||||
[`Mutex`]: ../../../api/rtfm/trait.Mutex.html
|
||||
[`lock`]: ../../../api/rtfm/trait.Mutex.html#method.lock
|
||||
[`Mutex`]: ../../../api/rtic/trait.Mutex.html
|
||||
[`lock`]: ../../../api/rtic/trait.Mutex.html#method.lock
|
||||
|
||||
The critical section created by the `lock` API is based on dynamic priorities:
|
||||
it temporarily raises the dynamic priority of the context to a *ceiling*
|
||||
|
|
@ -113,7 +113,7 @@ shared reference (`&-`) to the resource, limiting the operations it can perform
|
|||
on it, but where a shared reference is enough this approach reduces the number
|
||||
of required locks.
|
||||
|
||||
Note that in this release of RTFM it is not possible to request both exclusive
|
||||
Note that in this release of RTIC it is not possible to request both exclusive
|
||||
access (`&mut-`) and shared access (`&-`) to the *same* resource from different
|
||||
tasks. Attempting to do so will result in a compile error.
|
||||
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
# Software tasks
|
||||
|
||||
In addition to hardware tasks, which are invoked by the hardware in response to
|
||||
hardware events, RTFM also supports *software* tasks which can be spawned by the
|
||||
hardware events, RTIC also supports *software* tasks which can be spawned by the
|
||||
application from any execution context.
|
||||
|
||||
Software tasks can also be assigned priorities and, under the hood, are
|
||||
dispatched from interrupt handlers. RTFM requires that free interrupts are
|
||||
dispatched from interrupt handlers. RTIC requires that free interrupts are
|
||||
declared in an `extern` block when using software tasks; some of these free
|
||||
interrupts will be used to dispatch the software tasks. An advantage of software
|
||||
tasks over hardware tasks is that many tasks can be mapped to a single interrupt
|
||||
|
|
@ -45,7 +45,7 @@ $ cargo run --example message
|
|||
|
||||
## Capacity
|
||||
|
||||
RTFM does *not* perform any form of heap-based memory allocation. The memory
|
||||
RTIC does *not* perform any form of heap-based memory allocation. The memory
|
||||
required to store messages is statically reserved. By default the framework
|
||||
minimizes the memory footprint of the application so each task has a message
|
||||
"capacity" of 1: meaning that at most one message can be posted to the task
|
||||
|
|
@ -91,7 +91,7 @@ its message buffer will never be emptied. This situation is depicted in the
|
|||
following snippet:
|
||||
|
||||
``` rust
|
||||
#[rtfm::app(..)]
|
||||
#[rtic::app(..)]
|
||||
const APP: () = {
|
||||
#[init(spawn = [foo, bar])]
|
||||
fn init(cx: init::Context) {
|
||||
|
|
|
|||
|
|
@ -20,11 +20,11 @@ type (see [`core::time::Duration`]) and this `Duration` type must implement the
|
|||
integer. If the result of the conversion doesn't fit in a 32-bit number then the
|
||||
operation must return an error, any error type.
|
||||
|
||||
[`Monotonic`]: ../../../api/rtfm/trait.Monotonic.html
|
||||
[`Monotonic`]: ../../../api/rtic/trait.Monotonic.html
|
||||
[std-instant]: https://doc.rust-lang.org/std/time/struct.Instant.html
|
||||
[`core::time::Duration`]: https://doc.rust-lang.org/core/time/struct.Duration.html
|
||||
|
||||
For ARMv7+ targets the `rtfm` crate provides a `Monotonic` implementation based
|
||||
For ARMv7+ targets the `rtic` crate provides a `Monotonic` implementation based
|
||||
on the built-in CYCle CouNTer (CYCCNT). Note that this is a 32-bit timer clocked
|
||||
at the frequency of the CPU and as such it is not suitable for tracking time
|
||||
spans in the order of seconds.
|
||||
|
|
@ -36,7 +36,7 @@ executed must be passed as the first argument of the `schedule` invocation.
|
|||
|
||||
Additionally, the chosen `monotonic` timer must be configured and initialized
|
||||
during the `#[init]` phase. Note that this is *also* the case if you choose to
|
||||
use the `CYCCNT` provided by the `cortex-m-rtfm` crate.
|
||||
use the `CYCCNT` provided by the `cortex-m-rtic` crate.
|
||||
|
||||
The example below schedules two tasks from `init`: `foo` and `bar`. `foo` is
|
||||
scheduled to run 8 million clock cycles in the future. Next, `bar` is scheduled
|
||||
|
|
@ -61,7 +61,7 @@ console:
|
|||
When the `schedule` API is being used the runtime internally uses the `SysTick`
|
||||
interrupt handler and the system timer peripheral (`SYST`) so neither can be
|
||||
used by the application. This is accomplished by changing the type of
|
||||
`init::Context.core` from `cortex_m::Peripherals` to `rtfm::Peripherals`. The
|
||||
`init::Context.core` from `cortex_m::Peripherals` to `rtic::Peripherals`. The
|
||||
latter structure contains all the fields of the former minus the `SYST` one.
|
||||
|
||||
## Periodic tasks
|
||||
|
|
|
|||
|
|
@ -8,15 +8,15 @@ appear as *different* types in different contexts one cannot refactor a common
|
|||
operation that uses resources into a plain function; however, such refactor is
|
||||
possible using *generics*.
|
||||
|
||||
All resource proxies implement the `rtfm::Mutex` trait. On the other hand,
|
||||
All resource proxies implement the `rtic::Mutex` trait. On the other hand,
|
||||
unique references (`&mut-`) do *not* implement this trait (due to limitations in
|
||||
the trait system) but one can wrap these references in the [`rtfm::Exclusive`]
|
||||
the trait system) but one can wrap these references in the [`rtic::Exclusive`]
|
||||
newtype which does implement the `Mutex` trait. With the help of this newtype
|
||||
one can write a generic function that operates on generic resources and call it
|
||||
from different tasks to perform some operation on the same set of resources.
|
||||
Here's one such example:
|
||||
|
||||
[`rtfm::Exclusive`]: ../../../api/rtfm/struct.Exclusive.html
|
||||
[`rtic::Exclusive`]: ../../../api/rtic/struct.Exclusive.html
|
||||
|
||||
``` rust
|
||||
{{#include ../../../../examples/generics.rs}}
|
||||
|
|
@ -51,8 +51,8 @@ $ cargo run --example cfg
|
|||
|
||||
## Running tasks from RAM
|
||||
|
||||
The main goal of moving the specification of RTFM applications to attributes in
|
||||
RTFM v0.4.0 was to allow inter-operation with other attributes. For example, the
|
||||
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.
|
||||
|
||||
|
|
@ -119,22 +119,22 @@ $ cargo run --example pool
|
|||
|
||||
## Inspecting the expanded code
|
||||
|
||||
`#[rtfm::app]` is a procedural macro that produces support code. If for some
|
||||
`#[rtic::app]` is a procedural macro that produces support code. If for some
|
||||
reason you need to inspect the code generated by this macro you have two
|
||||
options:
|
||||
|
||||
You can inspect the file `rtfm-expansion.rs` inside the `target` directory. This
|
||||
file contains the expansion of the `#[rtfm::app]` item (not your whole program!)
|
||||
of the *last built* (via `cargo build` or `cargo check`) RTFM application. The
|
||||
You can inspect the file `rtic-expansion.rs` inside the `target` directory. This
|
||||
file contains the expansion of the `#[rtic::app]` item (not your whole program!)
|
||||
of the *last built* (via `cargo build` or `cargo check`) RTIC application. The
|
||||
expanded code is not pretty printed by default so you'll want to run `rustfmt`
|
||||
over it before you read it.
|
||||
|
||||
``` console
|
||||
$ cargo build --example foo
|
||||
|
||||
$ rustfmt target/rtfm-expansion.rs
|
||||
$ rustfmt target/rtic-expansion.rs
|
||||
|
||||
$ tail target/rtfm-expansion.rs
|
||||
$ tail target/rtic-expansion.rs
|
||||
```
|
||||
|
||||
``` rust
|
||||
|
|
@ -144,19 +144,19 @@ const APP: () = {
|
|||
use lm3s6965 as _;
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn main() -> ! {
|
||||
rtfm::export::interrupt::disable();
|
||||
let mut core: rtfm::export::Peripherals = core::mem::transmute(());
|
||||
rtic::export::interrupt::disable();
|
||||
let mut core: rtic::export::Peripherals = core::mem::transmute(());
|
||||
core.SCB.scr.modify(|r| r | 1 << 1);
|
||||
rtfm::export::interrupt::enable();
|
||||
rtic::export::interrupt::enable();
|
||||
loop {
|
||||
rtfm::export::wfi()
|
||||
rtic::export::wfi()
|
||||
}
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
Or, you can use the [`cargo-expand`] subcommand. This subcommand will expand
|
||||
*all* the macros, including the `#[rtfm::app]` attribute, and modules in your
|
||||
*all* the macros, including the `#[rtic::app]` attribute, and modules in your
|
||||
crate and print the output to the console.
|
||||
|
||||
[`cargo-expand`]: https://crates.io/crates/cargo-expand
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ The example below shows the different types generates by the `app` attribute.
|
|||
## `Send`
|
||||
|
||||
[`Send`] is a marker trait for "types that can be transferred across thread
|
||||
boundaries", according to its definition in `core`. In the context of RTFM the
|
||||
boundaries", according to its definition in `core`. In the context of RTIC the
|
||||
`Send` trait is only required where it's possible to transfer a value between
|
||||
tasks that run at *different* priorities. This occurs in a few places: in
|
||||
message passing, in shared resources and in the initialization of late
|
||||
|
|
@ -57,7 +57,7 @@ the `Send` trait.
|
|||
|
||||
Similarly, [`Sync`] is a marker trait for "types for which it is safe to share
|
||||
references between threads", according to its definition in `core`. In the
|
||||
context of RTFM the `Sync` trait is only required where it's possible for two,
|
||||
context of RTIC the `Sync` trait is only required where it's possible for two,
|
||||
or more, tasks that run at different priorities and may get a shared reference
|
||||
(`&-`) to a resource. This only occurs with shared access (`&-`) resources.
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
# Heterogeneous multi-core support
|
||||
|
||||
This section covers the *experimental* heterogeneous multi-core support provided
|
||||
by RTFM behind the `heterogeneous` Cargo feature.
|
||||
by RTIC behind the `heterogeneous` Cargo feature.
|
||||
|
||||
**Content coming soon**
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
# Homogeneous multi-core support
|
||||
|
||||
This section covers the *experimental* homogeneous multi-core support provided
|
||||
by RTFM behind the `homogeneous` Cargo feature.
|
||||
by RTIC behind the `homogeneous` Cargo feature.
|
||||
|
||||
**Content coming soon**
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
# Under the hood
|
||||
|
||||
This section describes the internals of the RTFM framework at a *high level*.
|
||||
This section describes the internals of the RTIC framework at a *high level*.
|
||||
Low level details like the parsing and code generation done by the procedural
|
||||
macro (`#[app]`) will not be explained here. The focus will be the analysis of
|
||||
the user specification and the data structures used by the runtime.
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
# Access control
|
||||
|
||||
One of the core foundations of RTFM is access control. Controlling which parts
|
||||
One of the core foundations of RTIC is access control. Controlling which parts
|
||||
of the program can access which static variables is instrumental to enforcing
|
||||
memory safety.
|
||||
|
||||
|
|
@ -12,8 +12,8 @@ resides in the same scope in which they are declared. Modules give some control
|
|||
over how a static variable can be accessed by they are not flexible enough.
|
||||
|
||||
To achieve the fine-grained access control where tasks can only access the
|
||||
static variables (resources) that they have specified in their RTFM attribute
|
||||
the RTFM framework performs a source code level transformation. This
|
||||
static variables (resources) that they have specified in their RTIC attribute
|
||||
the RTIC framework performs a source code level transformation. This
|
||||
transformation consists of placing the resources (static variables) specified by
|
||||
the user *inside* a `const` item and the user code *outside* the `const` item.
|
||||
This makes it impossible for the user code to refer to these static variables.
|
||||
|
|
@ -28,7 +28,7 @@ The code below is an example of the kind of source level transformation that
|
|||
happens behind the scenes:
|
||||
|
||||
``` rust
|
||||
#[rtfm::app(device = ..)]
|
||||
#[rtic::app(device = ..)]
|
||||
const APP: () = {
|
||||
static mut X: u64: 0;
|
||||
static mut Y: bool: 0;
|
||||
|
|
|
|||
|
|
@ -2,10 +2,10 @@
|
|||
|
||||
A resource *priority ceiling*, or just *ceiling*, is the dynamic priority that
|
||||
any task must have to safely access the resource memory. Ceiling analysis is
|
||||
relatively simple but critical to the memory safety of RTFM applications.
|
||||
relatively simple but critical to the memory safety of RTIC applications.
|
||||
|
||||
To compute the ceiling of a resource we must first collect a list of tasks that
|
||||
have access to the resource -- as the RTFM framework enforces access control to
|
||||
have access to the resource -- as the RTIC framework enforces access control to
|
||||
resources at compile time it also has access to this information at compile
|
||||
time. The ceiling of the resource is simply the highest logical priority among
|
||||
those tasks.
|
||||
|
|
@ -27,7 +27,7 @@ gets a unique reference (`&mut-`) to resources.
|
|||
An example to illustrate the ceiling analysis:
|
||||
|
||||
``` rust
|
||||
#[rtfm::app(device = ..)]
|
||||
#[rtic::app(device = ..)]
|
||||
const APP: () = {
|
||||
struct Resources {
|
||||
// accessed by `foo` (prio = 1) and `bar` (prio = 2)
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
When a resource (static variable) is shared between two, or more, tasks that run
|
||||
at different priorities some form of mutual exclusion is required to mutate the
|
||||
memory in a data race free manner. In RTFM we use priority-based critical
|
||||
memory in a data race free manner. In RTIC we use priority-based critical
|
||||
sections to guarantee mutual exclusion (see the [Immediate Ceiling Priority
|
||||
Protocol][icpp]).
|
||||
|
||||
|
|
@ -31,7 +31,7 @@ task we give it a *resource proxy*, whereas we give a unique reference
|
|||
The example below shows the different types handed out to each task:
|
||||
|
||||
``` rust
|
||||
#[rtfm::app(device = ..)]
|
||||
#[rtic::app(device = ..)]
|
||||
const APP: () = {
|
||||
struct Resources {
|
||||
#[init(0)]
|
||||
|
|
@ -102,7 +102,7 @@ pub mod bar {
|
|||
const APP: () = {
|
||||
static mut x: u64 = 0;
|
||||
|
||||
impl rtfm::Mutex for resources::x {
|
||||
impl rtic::Mutex for resources::x {
|
||||
type T = u64;
|
||||
|
||||
fn lock<R>(&mut self, f: impl FnOnce(&mut u64) -> R) -> R {
|
||||
|
|
@ -161,7 +161,7 @@ In this particular example we could implement the critical section as follows:
|
|||
> **NOTE:** this is a simplified implementation
|
||||
|
||||
``` rust
|
||||
impl rtfm::Mutex for resources::x {
|
||||
impl rtic::Mutex for resources::x {
|
||||
type T = u64;
|
||||
|
||||
fn lock<R, F>(&mut self, f: F) -> R
|
||||
|
|
@ -224,7 +224,7 @@ provides extra information to the compiler.
|
|||
Consider this program:
|
||||
|
||||
``` rust
|
||||
#[rtfm::app(device = ..)]
|
||||
#[rtic::app(device = ..)]
|
||||
const APP: () = {
|
||||
struct Resources {
|
||||
#[init(0)]
|
||||
|
|
@ -235,7 +235,7 @@ const APP: () = {
|
|||
|
||||
#[init]
|
||||
fn init() {
|
||||
rtfm::pend(Interrupt::UART0);
|
||||
rtic::pend(Interrupt::UART0);
|
||||
}
|
||||
|
||||
#[interrupt(binds = UART0, priority = 1, resources = [x, y])]
|
||||
|
|
@ -338,7 +338,7 @@ const APP: () = {
|
|||
|
||||
// similarly for `UART0` / `foo` and `UART2` / `baz`
|
||||
|
||||
impl<'a> rtfm::Mutex for resources::x<'a> {
|
||||
impl<'a> rtic::Mutex for resources::x<'a> {
|
||||
type T = u64;
|
||||
|
||||
fn lock<R>(&mut self, f: impl FnOnce(&mut u64) -> R) -> R {
|
||||
|
|
@ -419,7 +419,7 @@ fn foo(c: foo::Context) {
|
|||
|
||||
## The BASEPRI invariant
|
||||
|
||||
An invariant that the RTFM framework has to preserve is that the value of the
|
||||
An invariant that the RTIC framework has to preserve is that the value of the
|
||||
BASEPRI at the start of an *interrupt* handler must be the same value it has
|
||||
when the interrupt handler returns. BASEPRI may change during the execution of
|
||||
the interrupt handler but running an interrupt handler from start to finish
|
||||
|
|
@ -429,7 +429,7 @@ This invariant needs to be preserved to avoid raising the dynamic priority of a
|
|||
handler through preemption. This is best observed in the following example:
|
||||
|
||||
``` rust
|
||||
#[rtfm::app(device = ..)]
|
||||
#[rtic::app(device = ..)]
|
||||
const APP: () = {
|
||||
struct Resources {
|
||||
#[init(0)]
|
||||
|
|
@ -439,7 +439,7 @@ const APP: () = {
|
|||
#[init]
|
||||
fn init() {
|
||||
// `foo` will run right after `init` returns
|
||||
rtfm::pend(Interrupt::UART0);
|
||||
rtic::pend(Interrupt::UART0);
|
||||
}
|
||||
|
||||
#[task(binds = UART0, priority = 1)]
|
||||
|
|
@ -447,7 +447,7 @@ const APP: () = {
|
|||
// BASEPRI is `0` at this point; the dynamic priority is currently `1`
|
||||
|
||||
// `bar` will preempt `foo` at this point
|
||||
rtfm::pend(Interrupt::UART1);
|
||||
rtic::pend(Interrupt::UART1);
|
||||
|
||||
// BASEPRI is `192` at this point (due to a bug); the dynamic priority is now `2`
|
||||
// this function returns to `idle`
|
||||
|
|
@ -472,7 +472,7 @@ const APP: () = {
|
|||
|
||||
// this has no effect due to the BASEPRI value
|
||||
// the task `foo` will never be executed again
|
||||
rtfm::pend(Interrupt::UART0);
|
||||
rtic::pend(Interrupt::UART0);
|
||||
|
||||
loop {
|
||||
// ..
|
||||
|
|
@ -488,10 +488,10 @@ const APP: () = {
|
|||
```
|
||||
|
||||
IMPORTANT: let's say we *forget* to roll back `BASEPRI` in `UART1` -- this would
|
||||
be a bug in the RTFM code generator.
|
||||
be a bug in the RTIC code generator.
|
||||
|
||||
``` rust
|
||||
// code generated by RTFM
|
||||
// code generated by RTIC
|
||||
|
||||
const APP: () = {
|
||||
// ..
|
||||
|
|
|
|||
|
|
@ -1,18 +1,18 @@
|
|||
# Interrupt configuration
|
||||
|
||||
Interrupts are core to the operation of RTFM applications. Correctly setting
|
||||
Interrupts are core to the operation of RTIC applications. Correctly setting
|
||||
interrupt priorities and ensuring they remain fixed at runtime is a requisite
|
||||
for the memory safety of the application.
|
||||
|
||||
The RTFM framework exposes interrupt priorities as something that is declared at
|
||||
The RTIC framework exposes interrupt priorities as something that is declared at
|
||||
compile time. However, this static configuration must be programmed into the
|
||||
relevant registers during the initialization of the application. The interrupt
|
||||
configuration is done before the `init` function runs.
|
||||
|
||||
This example gives you an idea of the code that the RTFM framework runs:
|
||||
This example gives you an idea of the code that the RTIC framework runs:
|
||||
|
||||
``` rust
|
||||
#[rtfm::app(device = lm3s6965)]
|
||||
#[rtic::app(device = lm3s6965)]
|
||||
const APP: () = {
|
||||
#[init]
|
||||
fn init(c: init::Context) {
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ The example below shows the kind of code that the framework generates to
|
|||
initialize late resources.
|
||||
|
||||
``` rust
|
||||
#[rtfm::app(device = ..)]
|
||||
#[rtic::app(device = ..)]
|
||||
const APP: () = {
|
||||
struct Resources {
|
||||
x: Thing,
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
# Non-reentrancy
|
||||
|
||||
In RTFM, tasks handlers are *not* reentrant. Reentering a task handler can break
|
||||
In RTIC, tasks handlers are *not* reentrant. Reentering a task handler can break
|
||||
Rust aliasing rules and lead to *undefined behavior*. A task handler can be
|
||||
reentered in one of two ways: in software or by hardware.
|
||||
|
||||
|
|
@ -11,7 +11,7 @@ invoked using FFI (see example below). FFI requires `unsafe` code so end users
|
|||
are discouraged from directly invoking an interrupt handler.
|
||||
|
||||
``` rust
|
||||
#[rtfm::app(device = ..)]
|
||||
#[rtic::app(device = ..)]
|
||||
const APP: () = {
|
||||
#[init]
|
||||
fn init(c: init::Context) { .. }
|
||||
|
|
@ -42,7 +42,7 @@ const APP: () = {
|
|||
};
|
||||
```
|
||||
|
||||
The RTFM framework must generate the interrupt handler code that calls the user
|
||||
The RTIC framework must generate the interrupt handler code that calls the user
|
||||
defined task handlers. We are careful in making these handlers impossible to
|
||||
call from user code.
|
||||
|
||||
|
|
@ -76,5 +76,5 @@ const APP: () = {
|
|||
|
||||
A task handler can also be reentered without software intervention. This can
|
||||
occur if the same handler is assigned to two or more interrupts in the vector
|
||||
table but there's no syntax for this kind of configuration in the RTFM
|
||||
table but there's no syntax for this kind of configuration in the RTIC
|
||||
framework.
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
# Software tasks
|
||||
|
||||
RTFM supports software tasks and hardware tasks. Each hardware task is bound to
|
||||
RTIC supports software tasks and hardware tasks. Each hardware task is bound to
|
||||
a different interrupt handler. On the other hand, several software tasks may be
|
||||
dispatched by the same interrupt handler -- this is done to minimize the number
|
||||
of interrupts handlers used by the framework.
|
||||
|
|
@ -27,7 +27,7 @@ Let's first take a look the code generated by the framework to dispatch tasks.
|
|||
Consider this example:
|
||||
|
||||
``` rust
|
||||
#[rtfm::app(device = ..)]
|
||||
#[rtic::app(device = ..)]
|
||||
const APP: () = {
|
||||
// ..
|
||||
|
||||
|
|
@ -183,7 +183,7 @@ const APP: () = {
|
|||
});
|
||||
|
||||
// pend the interrupt that runs the task dispatcher
|
||||
rtfm::pend(Interrupt::UART0);
|
||||
rtic::pend(Interrupt::UART0);
|
||||
}
|
||||
|
||||
None => {
|
||||
|
|
@ -252,7 +252,7 @@ const APP: () = {
|
|||
});
|
||||
|
||||
// pend the interrupt that runs the task dispatcher
|
||||
rtfm::pend(Interrupt::UART0);
|
||||
rtic::pend(Interrupt::UART0);
|
||||
}
|
||||
|
||||
None => {
|
||||
|
|
@ -315,7 +315,7 @@ lock-free.
|
|||
|
||||
## Queue capacity
|
||||
|
||||
The RTFM framework uses several queues like ready queues and free queues. When
|
||||
The RTIC framework uses several queues like ready queues and free queues. When
|
||||
the free queue is empty trying to `spawn` a task results in an error; this
|
||||
condition is checked at runtime. Not all the operations performed by the
|
||||
framework on these queues check if the queue is empty / full. For example,
|
||||
|
|
@ -356,7 +356,7 @@ endpoint is owned by a task dispatcher.
|
|||
Consider the following example:
|
||||
|
||||
``` rust
|
||||
#[rtfm::app(device = ..)]
|
||||
#[rtic::app(device = ..)]
|
||||
const APP: () = {
|
||||
#[idle(spawn = [foo, bar])]
|
||||
fn idle(c: idle::Context) -> ! {
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ appropriate ready queue.
|
|||
Let's see how this in implemented in code. Consider the following program:
|
||||
|
||||
``` rust
|
||||
#[rtfm::app(device = ..)]
|
||||
#[rtic::app(device = ..)]
|
||||
const APP: () = {
|
||||
// ..
|
||||
|
||||
|
|
@ -47,7 +47,7 @@ mod foo {
|
|||
}
|
||||
|
||||
const APP: () = {
|
||||
type Instant = <path::to::user::monotonic::timer as rtfm::Monotonic>::Instant;
|
||||
type Instant = <path::to::user::monotonic::timer as rtic::Monotonic>::Instant;
|
||||
|
||||
// all tasks that can be `schedule`-d
|
||||
enum T {
|
||||
|
|
@ -141,7 +141,7 @@ const APP: () = {
|
|||
});
|
||||
|
||||
// pend the task dispatcher
|
||||
rtfm::pend(Interrupt::UART0);
|
||||
rtic::pend(Interrupt::UART0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -160,7 +160,7 @@ timeout interrupt to the `SysTick` handler.
|
|||
|
||||
## Resolution and range of `cyccnt::Instant` and `cyccnt::Duration`
|
||||
|
||||
RTFM provides a `Monotonic` implementation based on the `DWT`'s (Data Watchpoint
|
||||
RTIC provides a `Monotonic` implementation based on the `DWT`'s (Data Watchpoint
|
||||
and Trace) cycle counter. `Instant::now` returns a snapshot of this timer; these
|
||||
DWT snapshots (`Instant`s) are used to sort entries in the timer queue. The
|
||||
cycle counter is a 32-bit counter clocked at the core clock frequency. This
|
||||
|
|
@ -221,7 +221,7 @@ analysis.
|
|||
To illustrate, consider the following example:
|
||||
|
||||
``` rust
|
||||
#[rtfm::app(device = ..)]
|
||||
#[rtic::app(device = ..)]
|
||||
const APP: () = {
|
||||
#[task(priority = 3, spawn = [baz])]
|
||||
fn foo(c: foo::Context) {
|
||||
|
|
@ -353,7 +353,7 @@ const APP: () = {
|
|||
});
|
||||
});
|
||||
|
||||
rtfm::pend(Interrupt::UART0);
|
||||
rtic::pend(Interrupt::UART0);
|
||||
}
|
||||
|
||||
None => {
|
||||
|
|
|
|||
|
|
@ -1,16 +1,16 @@
|
|||
# Migrating from v0.4.x to v0.5.0
|
||||
|
||||
This section covers how to upgrade an application written against RTFM v0.4.x to
|
||||
This section covers how to upgrade an application written against RTIC v0.4.x to
|
||||
the version v0.5.0 of the framework.
|
||||
|
||||
## `Cargo.toml`
|
||||
|
||||
First, the version of the `cortex-m-rtfm` dependency needs to be updated to
|
||||
First, the version of the `cortex-m-rtic` dependency needs to be updated to
|
||||
`"0.5.0"`. The `timer-queue` feature needs to be removed.
|
||||
|
||||
|
||||
``` toml
|
||||
[dependencies.cortex-m-rtfm]
|
||||
[dependencies.cortex-m-rtic]
|
||||
# change this
|
||||
version = "0.4.3"
|
||||
|
||||
|
|
@ -24,15 +24,15 @@ features = ["timer-queue"]
|
|||
|
||||
## `Context` argument
|
||||
|
||||
All functions inside the `#[rtfm::app]` item need to take as first argument a
|
||||
All functions inside the `#[rtic::app]` item need to take as first argument a
|
||||
`Context` structure. This `Context` type will contain the variables that were
|
||||
magically injected into the scope of the function by version v0.4.x of the
|
||||
framework: `resources`, `spawn`, `schedule` -- these variables will become
|
||||
fields of the `Context` structure. Each function within the `#[rtfm::app]` item
|
||||
fields of the `Context` structure. Each function within the `#[rtic::app]` item
|
||||
gets a different `Context` type.
|
||||
|
||||
``` rust
|
||||
#[rtfm::app(/* .. */)]
|
||||
#[rtic::app(/* .. */)]
|
||||
const APP: () = {
|
||||
// change this
|
||||
#[task(resources = [x], spawn = [a], schedule = [b])]
|
||||
|
|
@ -80,7 +80,7 @@ The syntax used to declare resources has been changed from `static mut`
|
|||
variables to a `struct Resources`.
|
||||
|
||||
``` rust
|
||||
#[rtfm::app(/* .. */)]
|
||||
#[rtic::app(/* .. */)]
|
||||
const APP: () = {
|
||||
// change this
|
||||
static mut X: u32 = 0;
|
||||
|
|
@ -102,13 +102,13 @@ const APP: () = {
|
|||
|
||||
If your application was accessing the device peripherals in `#[init]` through
|
||||
the `device` variable then you'll need to add `peripherals = true` to the
|
||||
`#[rtfm::app]` attribute to continue to access the device peripherals through
|
||||
`#[rtic::app]` attribute to continue to access the device peripherals through
|
||||
the `device` field of the `init::Context` structure.
|
||||
|
||||
Change this:
|
||||
|
||||
``` rust
|
||||
#[rtfm::app(/* .. */)]
|
||||
#[rtic::app(/* .. */)]
|
||||
const APP: () = {
|
||||
#[init]
|
||||
fn init() {
|
||||
|
|
@ -122,7 +122,7 @@ const APP: () = {
|
|||
Into this:
|
||||
|
||||
``` rust
|
||||
#[rtfm::app(/* .. */, peripherals = true)]
|
||||
#[rtic::app(/* .. */, peripherals = true)]
|
||||
// ^^^^^^^^^^^^^^^^^^
|
||||
const APP: () = {
|
||||
#[init]
|
||||
|
|
@ -144,7 +144,7 @@ hardware tasks in v0.5.x use the `#[task]` attribute with the `binds` argument.
|
|||
Change this:
|
||||
|
||||
``` rust
|
||||
#[rtfm::app(/* .. */)]
|
||||
#[rtic::app(/* .. */)]
|
||||
const APP: () = {
|
||||
// hardware tasks
|
||||
#[exception]
|
||||
|
|
@ -164,7 +164,7 @@ const APP: () = {
|
|||
Into this:
|
||||
|
||||
``` rust
|
||||
#[rtfm::app(/* .. */)]
|
||||
#[rtic::app(/* .. */)]
|
||||
const APP: () = {
|
||||
#[task(binds = SVCall)]
|
||||
// ^^^^^^^^^^^^^^
|
||||
|
|
@ -186,12 +186,12 @@ const APP: () = {
|
|||
|
||||
The `timer-queue` feature has been removed. To use the `schedule` API one must
|
||||
first define the monotonic timer the runtime will use using the `monotonic`
|
||||
argument of the `#[rtfm::app]` attribute. To continue using the cycle counter
|
||||
argument of the `#[rtic::app]` attribute. To continue using the cycle counter
|
||||
(CYCCNT) as the monotonic timer, and match the behavior of version v0.4.x, add
|
||||
the `monotonic = rtfm::cyccnt::CYCCNT` argument to the `#[rtfm::app]` attribute.
|
||||
the `monotonic = rtic::cyccnt::CYCCNT` argument to the `#[rtic::app]` attribute.
|
||||
|
||||
Also, the `Duration` and `Instant` types and the `U32Ext` trait have been moved
|
||||
into the `rtfm::cyccnt` module. This module is only available on ARMv7-M+
|
||||
into the `rtic::cyccnt` module. This module is only available on ARMv7-M+
|
||||
devices. The removal of the `timer-queue` also brings back the `DWT` peripheral
|
||||
inside the core peripherals struct, this will need to be enabled by the application
|
||||
inside `init`.
|
||||
|
|
@ -199,9 +199,9 @@ inside `init`.
|
|||
Change this:
|
||||
|
||||
``` rust
|
||||
use rtfm::{Duration, Instant, U32Ext};
|
||||
use rtic::{Duration, Instant, U32Ext};
|
||||
|
||||
#[rtfm::app(/* .. */)]
|
||||
#[rtic::app(/* .. */)]
|
||||
const APP: () = {
|
||||
#[task(schedule = [b])]
|
||||
fn a() {
|
||||
|
|
@ -213,10 +213,10 @@ const APP: () = {
|
|||
Into this:
|
||||
|
||||
``` rust
|
||||
use rtfm::cyccnt::{Duration, Instant, U32Ext};
|
||||
use rtic::cyccnt::{Duration, Instant, U32Ext};
|
||||
// ^^^^^^^^
|
||||
|
||||
#[rtfm::app(/* .. */, monotonic = rtfm::cyccnt::CYCCNT)]
|
||||
#[rtic::app(/* .. */, monotonic = rtic::cyccnt::CYCCNT)]
|
||||
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
const APP: () = {
|
||||
#[init]
|
||||
|
|
|
|||
|
|
@ -1,17 +1,17 @@
|
|||
<h1 align="center">Real Time For the Masses</h1>
|
||||
<h1 align="center">Real-Time Interrupt-driven Concurrency</h1>
|
||||
|
||||
<p align="center">A concurrency framework for building real time systems</p>
|
||||
|
||||
# Preface
|
||||
|
||||
This book contains user level documentation for the Real Time For the Masses
|
||||
(RTFM) framework. The API reference can be found [here](../../api/).
|
||||
This book contains user level documentation for the Real-Time Interrupt-driven Concurrency
|
||||
(RTIC) framework. The API reference can be found [here](../../api/).
|
||||
|
||||
There is a translation of this book in [Russian].
|
||||
|
||||
[Russian]: ../ru/index.html
|
||||
|
||||
This is the documentation of v0.5.x of RTFM; for the documentation of version
|
||||
This is the documentation of v0.5.x of RTIC; for the documentation of version
|
||||
v0.4.x go [here](/0.4).
|
||||
|
||||
{{#include ../../../README.md:5:44}}
|
||||
|
|
|
|||
|
|
@ -2,4 +2,4 @@
|
|||
authors = ["Jorge Aparicio"]
|
||||
multilingual = false
|
||||
src = "src"
|
||||
title = "Real Time For the Masses"
|
||||
title = "Real-Time Interrupt-driven Concurrency"
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
# Real Time For the Masses
|
||||
# Real-Time Interrupt-driven Concurrency
|
||||
|
||||
Конкурентный фреймворк для создания систем реального времени.
|
||||
|
||||
|
|
@ -43,17 +43,17 @@
|
|||
|
||||
- Программы нужно писать используя 2018 edition.
|
||||
|
||||
## [User documentation](https://japaric.github.io/cortex-m-rtfm/book)
|
||||
## [User documentation](https://japaric.github.io/cortex-m-rtic/book)
|
||||
|
||||
## [API reference](https://japaric.github.io/cortex-m-rtfm/api/rtfm/index.html)
|
||||
## [API reference](https://japaric.github.io/cortex-m-rtic/api/rtic/index.html)
|
||||
|
||||
## Благодарности
|
||||
|
||||
Эта библиотека основана на [языке RTFM][rtfm-lang], созданном Embedded
|
||||
Эта библиотека основана на [языке RTIC][rtic-lang], созданном Embedded
|
||||
Systems group в [Техническом Университете Luleå][ltu], под рук.
|
||||
[Prof. Per Lindgren][per].
|
||||
|
||||
[rtfm-lang]: http://www.rtfm-lang.org/
|
||||
[rtic-lang]: http://www.rtic-lang.org/
|
||||
[ltu]: https://www.ltu.se/?l=en
|
||||
[per]: https://www.ltu.se/staff/p/pln-1.11258?l=en
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
# Summary
|
||||
|
||||
[Введение](./preface.md)
|
||||
- [RTFM в примерах](./by-example.md)
|
||||
- [RTIC в примерах](./by-example.md)
|
||||
- [Атрибут `app`](./by-example/app.md)
|
||||
- [Ресурсы](./by-example/resources.md)
|
||||
- [Задачи](./by-example/tasks.md)
|
||||
|
|
|
|||
|
|
@ -1,13 +1,13 @@
|
|||
# RTFM в примерах
|
||||
# RTIC в примерах
|
||||
|
||||
Эта часть книги представляет фреймворк Real Time For the Masses (RTFM)
|
||||
Эта часть книги представляет фреймворк Real-Time Interrupt-driven Concurrency (RTIC)
|
||||
новым пользователям через примеры с растущей сложностью.
|
||||
|
||||
Все примеры в этой книге можно найти в [репозитории] проекта на GitHub,
|
||||
и большинство примеров можно запустить на эмуляторе QEMU, поэтому никакого
|
||||
специального оборудования не требуется их выполнять.
|
||||
|
||||
[репозитории]: https://github.com/japaric/cortex-m-rtfm
|
||||
[репозитории]: https://github.com/japaric/cortex-m-rtic
|
||||
|
||||
Чтобы запустить примеры на Вашем ноутбуке / ПК, Вам нужна программа
|
||||
`qemu-system-arm`. Инструкции по настройке окружения для разработки
|
||||
|
|
|
|||
|
|
@ -1,26 +1,26 @@
|
|||
# The `app` attribute
|
||||
|
||||
Это наименьшая возможная программа на RTFM:
|
||||
Это наименьшая возможная программа на RTIC:
|
||||
|
||||
``` rust
|
||||
{{#include ../../../../examples/smallest.rs}}
|
||||
```
|
||||
|
||||
Все программы на RTFM используют атрибут [`app`] (`#[app(..)]`). Этот атрибут
|
||||
Все программы на RTIC используют атрибут [`app`] (`#[app(..)]`). Этот атрибут
|
||||
нужно применять к `const`-элементам, содержащим элементы. Атрибут `app` имеет
|
||||
обязательный аргумент `device`, в качестве значения которому передается *путь*.
|
||||
Этот путь должен указывать на библиотеку *устройства*, сгенерированную с помощью
|
||||
[`svd2rust`] **v0.14.x**. Атрибут `app` развернется в удобную точку входа,
|
||||
поэтому нет необходимости использовать атрибут [`cortex_m_rt::entry`].
|
||||
|
||||
[`app`]: ../../../api/cortex_m_rtfm_macros/attr.app.html
|
||||
[`app`]: ../../../api/cortex_m_rtic_macros/attr.app.html
|
||||
[`svd2rust`]: https://crates.io/crates/svd2rust
|
||||
[`cortex_m_rt::entry`]: ../../../api/cortex_m_rt_macros/attr.entry.html
|
||||
|
||||
> **ОТСТУПЛЕНИЕ**: Некоторые из вас удивятся, почему мы используем ключевое слово `const` как
|
||||
> модуль, а не правильное `mod`. Причина в том, что использование атрибутов на
|
||||
> модулях требует feature gate, который требует ночную сборку. Чтобы заставить
|
||||
> RTFM работать на стабильной сборке, мы используем вместо него слово `const`.
|
||||
> RTIC работать на стабильной сборке, мы используем вместо него слово `const`.
|
||||
> Когда большая часть макросов 1.2 стабилизируются, мы прейдем от `const` к `mod` и в конце концов в атрибуту уровне приложения (`#![app]`).
|
||||
|
||||
## `init`
|
||||
|
|
@ -32,13 +32,13 @@
|
|||
Функция `init` запустится *с отключенными прерываниями* и будет иметь эксклюзивный
|
||||
доступ к периферии Cortex-M и специфичной для устройства периферии через переменные
|
||||
`core` and `device`, которые внедряются в область видимости `init` атрибутом `app`.
|
||||
Не вся периферия Cortex-M доступна в `core`, потому что рантайм RTFM принимает владение
|
||||
частью из неё -- более подробно см. структуру [`rtfm::Peripherals`].
|
||||
Не вся периферия Cortex-M доступна в `core`, потому что рантайм RTIC принимает владение
|
||||
частью из неё -- более подробно см. структуру [`rtic::Peripherals`].
|
||||
|
||||
Переменные `static mut`, определённые в начале `init` будут преобразованы
|
||||
в ссылки `&'static mut` с безопасным доступом.
|
||||
|
||||
[`rtfm::Peripherals`]: ../../api/rtfm/struct.Peripherals.html
|
||||
[`rtic::Peripherals`]: ../../api/rtic/struct.Peripherals.html
|
||||
|
||||
Пример ниже показывает типы переменных `core` и `device` и
|
||||
демонстрирует безопасный доступ к переменной `static mut`.
|
||||
|
|
@ -85,7 +85,7 @@ $ cargo run --example idle
|
|||
|
||||
Как Вы бы сделали с помощью библиотеки `cortex-m-rt`, Вы можете использовать атрибуты
|
||||
`interrupt` и `exception` внутри псевдо-модуля `app`, чтобы определить обработчики
|
||||
прерываний и исключений. В RTFM, мы называем обработчики прерываний и исключений
|
||||
прерываний и исключений. В RTIC, мы называем обработчики прерываний и исключений
|
||||
*аппаратными* задачами.
|
||||
|
||||
``` rust
|
||||
|
|
@ -96,6 +96,6 @@ $ cargo run --example idle
|
|||
$ cargo run --example interrupt
|
||||
{{#include ../../../../ci/expected/interrupt.run}}```
|
||||
|
||||
До сих пор программы RTFM, которые мы видели не отличались от программ, которые
|
||||
До сих пор программы RTIC, которые мы видели не отличались от программ, которые
|
||||
можно написать, используя только библиотеку `cortex-m-rt`. В следующем разделе
|
||||
мы начнем знакомиться с функционалом, присущим только RTFM.
|
||||
мы начнем знакомиться с функционалом, присущим только RTIC.
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
# Создание нового проекта
|
||||
|
||||
Теперь, когда Вы изучили основные возможности фреймворка RTFM, Вы можете
|
||||
Теперь, когда Вы изучили основные возможности фреймворка RTIC, Вы можете
|
||||
попробовать его использовать на Вашем оборудовании следуя этим инструкциям.
|
||||
|
||||
1. Создайте экземпляр из шаблона [`cortex-m-quickstart`].
|
||||
|
|
@ -36,20 +36,20 @@ $ cargo add lm3s6965 --vers 0.1.3
|
|||
$ rm memory.x build.rs
|
||||
```
|
||||
|
||||
3. Добавьте библиотеку `cortex-m-rtfm` как зависимость, и если необходимо,
|
||||
3. Добавьте библиотеку `cortex-m-rtic` как зависимость, и если необходимо,
|
||||
включите опцию `timer-queue`.
|
||||
|
||||
``` console
|
||||
$ cargo add cortex-m-rtfm --allow-prerelease --upgrade=none
|
||||
$ cargo add cortex-m-rtic --allow-prerelease --upgrade=none
|
||||
```
|
||||
|
||||
4. Напишите программу RTFM.
|
||||
4. Напишите программу RTIC.
|
||||
|
||||
Здесь я буду использовать пример `init` из библиотеки `cortex-m-rtfm`.
|
||||
Здесь я буду использовать пример `init` из библиотеки `cortex-m-rtic`.
|
||||
|
||||
``` console
|
||||
$ curl \
|
||||
-L https://github.com/japaric/cortex-m-rtfm/raw/v0.4.0-beta.1/examples/init.rs \
|
||||
-L https://github.com/japaric/cortex-m-rtic/raw/v0.4.0-beta.1/examples/init.rs \
|
||||
> src/main.rs
|
||||
```
|
||||
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@
|
|||
достаточно информации, чтобы оптимизировать доступ к разделяемым данным.
|
||||
|
||||
Атрибут `app` имеет полную картину приложения, поэтому может оптимизировать доступ к
|
||||
`static`-переменным. В RTFM мы обращаемся к `static`-переменным, объявленным внутри
|
||||
`static`-переменным. В RTIC мы обращаемся к `static`-переменным, объявленным внутри
|
||||
псевдо-модуля `app` как к *ресурсам*. Чтобы получить доступ к ресурсу, контекст
|
||||
(`init`, `idle`, `interrupt` или `exception`) должен сначала определить
|
||||
аргумент `resources` в соответствующем атрибуте.
|
||||
|
|
@ -45,13 +45,13 @@ $ cargo run --example resource
|
|||
критические секции не нужны для обработчика с наивысшим приоритетом, имеющим
|
||||
доступ к ресурсу.
|
||||
|
||||
API критической секции, предоставляемое фреймворком RTFM (см. [`Mutex`]),
|
||||
API критической секции, предоставляемое фреймворком RTIC (см. [`Mutex`]),
|
||||
основано на динамических приоритетах вместо отключения прерываний. Из этого следует,
|
||||
что критические секции не будут допускать *запуск некоторых* обработчиков,
|
||||
включая все соперничающие за ресурс, но будут позволять запуск обработчиков с
|
||||
большим приоритетом не соперничащих за ресурс.
|
||||
|
||||
[`Mutex`]: ../../../api/rtfm/trait.Mutex.html
|
||||
[`Mutex`]: ../../../api/rtic/trait.Mutex.html
|
||||
|
||||
В примере ниже у нас есть 3 обработчика прерываний с приоритетами от одного
|
||||
до трех. Два обработчика с низким приоритетом соперничают за ресурс `SHARED`.
|
||||
|
|
@ -61,7 +61,7 @@ API критической секции, предоставляемое фрей
|
|||
с наивысшим приоритетом может свободно вытеснять критическую секцию,
|
||||
созданную обработчиком с низшим приоритетом.
|
||||
|
||||
[`lock`]: ../../../api/rtfm/trait.Mutex.html#method.lock
|
||||
[`lock`]: ../../../api/rtic/trait.Mutex.html#method.lock
|
||||
|
||||
``` rust
|
||||
{{#include ../../../../examples/lock.rs}}
|
||||
|
|
|
|||
|
|
@ -1,12 +1,12 @@
|
|||
# Программные задачи
|
||||
|
||||
RTFM обрабатывает прерывания и исключения как *аппаратные* задачи. Аппаратные
|
||||
RTIC обрабатывает прерывания и исключения как *аппаратные* задачи. Аппаратные
|
||||
задачи могут вызываться устройством в ответ на события, такие как нажатие кнопки.
|
||||
RTFM также поддерживает *программные* задачи, порождаемые программой из любого
|
||||
RTIC также поддерживает *программные* задачи, порождаемые программой из любого
|
||||
контекста выполнения.
|
||||
|
||||
Программным задачам также можно назначать приоритет и диспетчеризовать из
|
||||
обработчиков прерываний. RTFM требует определения свободных прерываний в блоке
|
||||
обработчиков прерываний. RTIC требует определения свободных прерываний в блоке
|
||||
`extern`, когда используются программные задачи; эти свободные прерывания будут использованы, чтобы диспетчеризовать программные задачи. Преимущество программных
|
||||
задач перед аппаратными в том, что на один обработчик прерывания можно назначить
|
||||
множество задач.
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
# Очередь таймера
|
||||
|
||||
Когда включена опция `timer-queue`, фреймворк RTFM включает
|
||||
Когда включена опция `timer-queue`, фреймворк RTIC включает
|
||||
*глобальную очередь таймера*, которую приложения могут использовать, чтобы
|
||||
*планировать* программные задачи на запуск через некоторое время в будущем.
|
||||
|
||||
|
|
@ -9,16 +9,16 @@
|
|||
планируется, момент ([`Instant`]), в который задачу нужно запустить, нужно передать
|
||||
как первый аргумент вызова `schedule`.
|
||||
|
||||
[`Instant`]: ../../../api/rtfm/struct.Instant.html
|
||||
[`Instant`]: ../../../api/rtic/struct.Instant.html
|
||||
|
||||
Рантайм RTFM включает монотонный, растущий только вверх, 32-битный таймер,
|
||||
Рантайм RTIC включает монотонный, растущий только вверх, 32-битный таймер,
|
||||
значение которого можно запросить конструктором `Instant::now`. Время ([`Duration`])
|
||||
можно передать в `Instant::now()`, чтобы получить `Instant` в будущем. Монотонный
|
||||
таймер отключен пока запущен `init`, поэтому `Instant::now()` всегда возвращает
|
||||
значение `Instant(0 /* циклов тактовой частоты */)`; таймер включается сразу перед
|
||||
включением прерываний и запуском `idle`.
|
||||
|
||||
[`Duration`]: ../../../api/rtfm/struct.Duration.html
|
||||
[`Duration`]: ../../../api/rtic/struct.Duration.html
|
||||
|
||||
В примере ниже две задачи планируются из `init`: `foo` и `bar`. `foo` -
|
||||
запланирована на запуск через 8 миллионов тактов в будущем. Кроме того, `bar`
|
||||
|
|
|
|||
|
|
@ -22,8 +22,8 @@ $ cargo run --example generics
|
|||
|
||||
## Запуск задач из ОЗУ
|
||||
|
||||
Главной целью переноса описания программы на RTFM в атрибуты в
|
||||
RTFM v0.4.x была возможность взаимодействия с другими атрибутами.
|
||||
Главной целью переноса описания программы на RTIC в атрибуты в
|
||||
RTIC v0.4.x была возможность взаимодействия с другими атрибутами.
|
||||
Напримерe, атрибут `link_section` можно применять к задачам, чтобы разместить
|
||||
их в ОЗУ; это может улучшить производительность в некоторых случаях.
|
||||
|
||||
|
|
@ -64,7 +64,7 @@ $ cargo nm --example ramfunc --release | grep ' bar::'
|
|||
|
||||
## `binds`
|
||||
|
||||
**ПРИМЕЧАНИЕ**: Требуется RTFM не ниже 0.4.2
|
||||
**ПРИМЕЧАНИЕ**: Требуется RTIC не ниже 0.4.2
|
||||
|
||||
Вы можете давать аппаратным задачам имена похожие на имена обычных задач.
|
||||
Для этого нужно использовать аргумент `binds`: Вы называете функцию
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@
|
|||
## `Send`
|
||||
|
||||
[`Send`] - маркерный типаж (trait) для "типов, которые можно передавать через границы
|
||||
потоков", как это определено в `core`. В контексте RTFM типаж `Send` необходим
|
||||
потоков", как это определено в `core`. В контексте RTIC типаж `Send` необходим
|
||||
только там, где возможна передача значения между задачами, запускаемыми на
|
||||
*разных* приоритетах. Это возникает в нескольких случаях: при передаче сообщений,
|
||||
в совместно используемых `static mut` ресурсах и инициализации поздних ресурсов.
|
||||
|
|
@ -41,7 +41,7 @@
|
|||
## `Sync`
|
||||
|
||||
Похожая ситуация, [`Sync`] - маркерный типаж для "типов, на которых можно
|
||||
ссылаться в разных потоках", как это определено в `core`. В контексте RTFM
|
||||
ссылаться в разных потоках", как это определено в `core`. В контексте RTIC
|
||||
типаж `Sync` необходим только там, где возможны две или более задачи,
|
||||
запускаемые на разных приоритетах, чтобы захватить разделяемую ссылку на
|
||||
ресурс. Это возникает только совместно используемых `static`-ресурсах.
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
<h1 align="center">Real Time For the Masses</h1>
|
||||
<h1 align="center">Real-Time Interrupt-driven Concurrency</h1>
|
||||
|
||||
<p align="center">Конкурентный фреймворк для создания систем реального времени</p>
|
||||
|
||||
# Введение
|
||||
|
||||
Эта книга содержит документацию уровня пользователя фреймворком Real Time For the Masses
|
||||
(RTFM). Описание API можно найти [здесь](../../api/rtfm/index.html).
|
||||
Эта книга содержит документацию уровня пользователя фреймворком Real-Time Interrupt-driven Concurrency
|
||||
(RTIC). Описание API можно найти [здесь](../../api/rtic/index.html).
|
||||
|
||||
{{#include README_RU.md:5:44}}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue