fn lock(priority: &Cell
}
impl<'a> foo::Spawn<'a> {
pub fn bar(&self) -> Result<(), ()> {
unsafe {
match lock(self.priority(), bar_FQ_CEILING, || {
bar_FQ.split().1.dequeue()
}) {
Some(()) => {
lock(self.priority(), RQ1_CEILING, || {
RQ1.split().1.enqueue_unchecked(Ready {
task: T1::bar,
})
});
rtic::pend(Interrupt::UART0);
}
None => {
Err(())
}
}
}
}
}
}
}
Использование bar_FQ для ограничения числа задач bar, которые могут бы вызваны, может показаться искусственным, но это будет иметь больше смысла, когда мы поговорим о вместительности задач.
Мы пропустили, как на самом деле работает передача сообщений, поэтому давайте вернемся к реализации spawn, но в этот раз для задачи baz, которая принимает сообщение типа u64.
#![allow(unused)]
fn main() {
fn baz(c: baz::Context, input: u64) {
}
mod app {
struct Ready {
task: Task,
index: u8,
}
static mut baz_INPUTS: [MaybeUninit
[MaybeUninit::uninit(), MaybeUninit::uninit()];
static mut baz_FQ: Queue
const baz_FQ_CEILING: u8 = 2;
impl<'a> foo::Spawn<'a> {
pub fn baz(&self, message: u64) -> Result<(), u64> {
unsafe {
match lock(self.priority(), baz_FQ_CEILING, || {
baz_FQ.split().1.dequeue()
}) {
Some(index) => {
baz_INPUTS[index as usize].write(message);
lock(self.priority(), RQ1_CEILING, || {
RQ1.split().1.enqueue_unchecked(Ready {
task: T1::baz,
index,
});
});
rtic::pend(Interrupt::UART0);
}
None => {
Err(message)
}
}
}
}
}
}
}
А теперь давайте взглянем на настоящую реализацию диспетчера задач:
#![allow(unused)]
fn main() {
mod app {
#[no_mangle]
unsafe UART1() {
const PRIORITY: u8 = 1;
let snapshot = basepri::read();
while let Some(ready) = RQ1.split().1.dequeue() {
match ready.task {
Task::baz => {