Давайте сначала глянем на код, генерируемый фреймворком для диспетчеризации задач. Рассмотрим пример:
#![allow(unused)]
fn main() {
#[rtic::app(device = ..)]
mod app {
#[interrupt(binds = UART0, priority = 2, spawn = [bar, baz])]
fn foo(c: foo::Context) {
foo.spawn.bar().ok();
foo.spawn.baz(42).ok();
}
#[task(capacity = 2, priority = 1)]
fn bar(c: bar::Context) {
}
#[task(capacity = 2, priority = 1, resources = [X])]
fn baz(c: baz::Context, input: i32) {
}
extern "C" {
fn UART1();
}
}
}
Фреймворк создает следующий диспетчер задач, состоящий из обработчика прерывания и очереди готовности:
#![allow(unused)]
fn main() {
fn bar(c: bar::Context) {
}
mod app {
use heapless::spsc::Queue;
use cortex_m::register::basepri;
struct Ready
task: T,
}
enum T1 {
bar,
baz,
}
static mut RQ1: Queue
#[no_mangle]
unsafe UART1() {
const PRIORITY: u8 = 1;
let snapshot = basepri::read();
while let Some(ready) = RQ1.split().1.dequeue() {
match ready.task {
T1::bar => {
let priority = Cell::new(PRIORITY);
bar(bar::Context::new(&priority));
}
T1::baz => {
}
}
}
basepri::write(snapshot);
}
}
}
Интерфейс spawn предоставлен пользователю как методы структурв Spawn. Для каждой задачи существует своя структура Spawn.
Код Spawn, генерируемый фреймворком для предыдущего примера выглядит так:
#![allow(unused)]
fn main() {
mod foo {
pub struct Context<'a> {
pub spawn: Spawn<'a>,
}
pub struct Spawn<'a> {
priority: &'a Cell
}
impl<'a> Spawn<'a> {
#[doc(hidden)]
pub unsafe fn priority(&self) -> &Cell
self.priority
}
}
}
mod app {
const RQ1_CEILING: u8 = 2;
static mut bar_FQ: Queue<(), U2> = Queue::new();
const bar_FQ_CEILING: u8 = 2;