Выбрать главу

Пример ниже демонстрирует разные смыслы базового времени.

#![allow(unused)]

fn main() {

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

}

Запуск программы на реальном оборудовании приведет к следующему выводу в консоли:

init(baseline = Instant(0))

foo(baseline = Instant(0))

UART0(baseline = Instant(904))

foo(baseline = Instant(904))

Каждая функция в модуле app принимает структуру Context в качесте первого параметра. Все поля этих структур имеют предсказуемые, неанонимные типы, поэтому вы можете написать обычные функции, принимающие их как аргументы.

Справочник по API определяет как эти типы генерируются на основе входных данных. Вы можете также сгенерировать документацию к вашему крейту программы (cargo doc --bin <name>); в документации вы найдете структуры Context (например init::Context и idle::Context).

Пример ниже показывает различные типы, сгенерированные атрибутом app.

#![allow(unused)]

fn main() {

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

}

Send - это маркерный трейт для "типов, которые можно передавать через границы потоков", как это определено в core. В контексте RTIC трейт Send необходим только там, где возможна передача значения между задачами, запускаемыми на разных приоритетах. Это возникает в нескольких случаях: при передаче сообщений, в разделяемых static mut ресурсах и при инициализации поздних ресурсов.

Атрибут app проверит, что Send реализован, где необходимо, поэтому вам не стоит волноваться об этом. В настоящий момент все передаваемые типы в RTIC должны быть Send, но это ограничение возможно будет ослаблено в будущем.

Аналогично, Sync - маркерный трейт для "типов, на которые можно безопасно разделять между потоками", как это определено в core. В контексте RTIC типаж Sync необходим только там, где возможно для двух или более задач, запускаемых на разных приоритетах получить разделяемую ссылку (&-) на ресурс. Это возникает только (&-) ресурсах с разделяемым доступом.

Атрибут app проверит, что Sync реализован, где необходимо, но важно знать, где ограничение Sync не требуется: в (&-) ресурсах с разделяемым доступом, за которые соперничают задачи с одинаковым приоритетом.

В примере ниже показано, где можно использовать типы, не реализующие Sync.

#![allow(unused)]

fn main() {

//! `examples/not-sync.rs`

// #![deny(unsafe_code)]

#![deny(warnings)]

#![no_main]

#![no_std]

use core::marker::PhantomData;

use panic_semihosting as _;

pub struct NotSync {

_0: PhantomData<*const ()>,

}

unsafe impl Send for NotSync {}

#[rtic::app(device = lm3s6965, dispatchers = [SSI0])]

mod app {

use super::NotSync;

use core::marker::PhantomData;

use cortex_m_semihosting::debug;

#[shared]

struct Shared {

shared: NotSync,

}

#[local]

struct Local {}

#[init]

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

debug::exit(debug::EXIT_SUCCESS);

(

Shared {

shared: NotSync { _0: PhantomData },

},

Local {},

init::Monotonics(),

)

}

#[task(shared = [&shared])]

fn foo(c: foo::Context) {

let _: &NotSync = c.shared.shared;

}

#[task(shared = [&shared])]

fn bar(c: bar::Context) {

let _: &NotSync = c.shared.shared;

}

}

}

Теперь, когда Вы изучили основные возможности фреймворка RTIC, Вы можете попробовать его использовать на Вашем оборудовании следуя этим инструкциям.

   1. Создайте экземпляр из шаблона cortex-m-quickstart.

$ # например используя `cargo-generate`

$ cargo generate \

--git https://github.com/rust-embedded/cortex-m-quickstart \