}
#[interrupt(binds = UART1, resources = [X, Y])]
fn bar(c: bar::Context) {
// .. пользовательский код ..
}
// ..
}
}
Фреймворк создает код, подобный этому:
fn init(c: init::Context) {
// .. пользовательский код ..
}
fn foo(c: foo::Context) {
// .. пользовательский код ..
}
fn bar(c: bar::Context) {
// .. пользовательский код ..
}
// Публичное API
pub mod init {
pub struct Context<'a> {
pub resources: Resources<'a>,
// ..
}
pub struct Resources<'a> {
pub Y: &'a mut bool,
}
}
pub mod foo {
pub struct Context<'a> {
pub resources: Resources<'a>,
// ..
}
pub struct Resources<'a> {
pub X: &'a mut u64,
}
}
pub mod bar {
pub struct Context<'a> {
pub resources: Resources<'a>,
// ..
}
pub struct Resources<'a> {
pub X: &'a mut u64,
pub Y: &'a mut bool,
}
}
/// Детали реализации
mod app {
// все, что внутри этого модуля спрятано от пользовательского кода
static mut X: u64 = 0;
static mut Y: bool = 0;
// настоящая точка входа в программу
unsafe fn main() -> ! {
interrupt::disable();
// ..
// вызов пользовательского кода; передача ссылок на статические переменные
init(init::Context {
resources: init::Resources {
X: &mut X,
},
// ..
});
// ..
interrupt::enable();
// ..
}
// обработчик прерывания,с которым связан `foo`
#[no_mangle]
unsafe fn UART0() {
// вызов пользовательского кода; передача ссылок на статические переменные
foo(foo::Context {
resources: foo::Resources {
X: &mut X,
},
// ..
});
}
// обработчик прерывания,с которым связан `bar`
#[no_mangle]
unsafe fn UART1() {
// вызов пользовательского кода; передача ссылок на статические переменные
bar(bar::Context {
resources: bar::Resources {
X: &mut X,
Y: &mut Y,
},
// ..
});
}
}
Некоторые ресурсы инициализируются во время выполнения после завершения функции init. Важно то, что ресурсы (статические переменные) полностью инициализируются до того, как задачи смогут запуститься, вот почему они должны быть инициализированы пока прерывания отключены.
Ниже показан пример кода, генерируемого фреймворком для инициализации позних ресурсов.
#![allow(unused)]
fn main() {
#[rtic::app(device = ..)]
mod app {
struct Resources {
x: Thing,
}
#[init]
fn init() -> init::LateResources {
// ..
init::LateResources {
x: Thing::new(..),
}
}
#[task(binds = UART0, resources = [x])]
fn foo(c: foo::Context) {
let x: &mut Thing = c.resources.x;
x.frob();
// ..
}
// ..
}
}
Код, генерируемы фреймворком выглядит примерно так:
fn init(c: init::Context) -> init::LateResources {
// .. пользовательский код ..
}
fn foo(c: foo::Context) {
// .. пользовательский код ..
}
// Public API
pub mod init {
pub struct LateResources {
pub x: Thing,
}
// ..
}
pub mod foo {
pub struct Resources<'a> {
pub x: &'a mut Thing,
}
pub struct Context<'a> {
pub resources: Resources<'a>,
// ..
}