--name app
$ # следуйте остальным инструкциям
2. Добавьте крейт доступа к периферии (PAC), сгенерированный с помощьюsvd2rust v0.14.x, или крейт отладочной платы, у которой в зависимостях один из таких PAC'ов. Убедитесь, что опция rt крейта включена.
В этом примере я буду использовать крейт устройства lm3s6965. Эта библиотека не имеет Cargo-опции rt; эта опция всегда включена.
Этот крейт устройства предоставляет линковочный скрипт с макетом памяти целевого устройства, поэтому memory.x и build.rs нужно удалить.
$ cargo add lm3s6965 --vers 0.1.3
$ rm memory.x build.rs
3. Добавьте крейт cortex-m-rtic как зависимость.
$ cargo add cortex-m-rtic --allow-prerelease
4. Напишите свою RTIC программу.
Здесь я буду использовать пример init из крейта cortex-m-rtic.
Примеры находтся в папке examples, а содержание init.rs показано здесь:
//! examples/init.rs
#![deny(unsafe_code)]
#![deny(warnings)]
#![no_main]
#![no_std]
use panic_semihosting as _;
#[rtic::app(device = lm3s6965, peripherals = true)]
mod app {
use cortex_m_semihosting::{debug, hprintln};
#[shared]
struct Shared {}
#[local]
struct Local {}
#[init(local = [x: u32 = 0])]
fn init(cx: init::Context) -> (Shared, Local, init::Monotonics) {
// Cortex-M peripherals
let _core: cortex_m::Peripherals = cx.core;
// Device specific peripherals
let _device: lm3s6965::Peripherals = cx.device;
// Locals in `init` have 'static lifetime
let _x: &'static mut u32 = cx.local.x;
// Access to the critical section token,
// to indicate that this is a critical seciton
let _cs_token: bare_metaclass="underline" :CriticalSection = cx.cs;
hprintln!("init").unwrap();
debug::exit(debug::EXIT_SUCCESS);
(Shared {}, Local {}, init::Monotonics())
}
}
Пример init использует устройство lm3s6965. Не забудьте настроить аргумент device в атрибуте макроса app так, чтобы он соответствовал пути к PAC-крейту, если он отличается, а также добавить перифериб и другие аргументы если необходимо. Несмотря на то, что в программе могут использоваться псевдонимы типов, здесь необходимо указать полный путь (из корня крейта). Для многих устройств, есть общий подход в крейтах реализации HAL (с псевдонимом hal) и крейтах поддержки отладочных плат реекспортиорвать PAC как pac, что приводит нас к образцу, аналогичному приведенному ниже:
#![allow(unused)]
fn main() {
use abcd123_hal as hal;
//...
#[rtic::app(device = crate::haclass="underline" :pac, peripherals = true, monotonic = rtic::cyccnt::CYCCNT)]
mod app { /*...*/ }
}
Пример init также зависит от крейта panic-semihosting:
$ cargo add panic-semihosting
5. Соберите его, загрузите в микроконтроллер и запустите.
$ # ПРИМЕЧАНИЕ: Я раскомментировал опцию `runner` в `.cargo/config`
$ cargo run
init
Все объекты, предоставляющие ресурысы реализуют трейт rtic::Mutex. Если ресурс не реализует его, можно обернуть его в новый тип rtic::Exclusive, который реализует трейт Mutex. С помощью этого нового типа можно написать обобщенную функцию, которая работает с обобщенным ресурсом и вызывать его из различных задач, чтобы производить однотипные операции над похожим множеством ресурсов. Вот один такой пример:
#![allow(unused)]
fn main() {
//! examples/generics.rs
#![deny(unsafe_code)]
#![deny(warnings)]
#![no_main]
#![no_std]
use cortex_m_semihosting::hprintln;
use panic_semihosting as _;
use rtic::Mutex;
#[rtic::app(device = lm3s6965)]
mod app {
use cortex_m_semihosting::{debug, hprintln};
use lm3s6965::Interrupt;
#[shared]
struct Shared {
shared: u32,
}
#[local]
struct Local {}
#[init]
fn init(_: init::Context) -> (Shared, Local, init::Monotonics) {
rtic::pend(Interrupt::UART0);
rtic::pend(Interrupt::UART1);
(Shared { shared: 0 }, Local {}, init::Monotonics())
}
#[task(binds = UART0, shared = [shared], local = [state: u32 = 0])]
fn uart0(c: uart0::Context) {
hprintln!("UART0(STATE = {})", *c.local.state).unwrap();
// second argument has type `shared::shared`
super::advance(c.local.state, c.shared.shared);
rtic::pend(Interrupt::UART1);
debug::exit(debug::EXIT_SUCCESS);