resources: foo::Resources {
x: &mut *x.as_mut_ptr(),
},
})
}
}
Важная деталь здесь то, что interrupt::enable ведет себя как like a
Архитектурам с более сложным конвейером инструкций нужен барьер памяти (atomic::fence) вместо compiler fence для полной очистки операции записи перед включением прерываний. Архитектура ARM Cortex-M не нуждается в барьере памяти в одноядерном контексте.
Когда ресурсы (статические переменные) разделяются между двумя или более задачами, которые выполняются с разными приоритетами, некая форма запрета изменений необходима, чтобы изменять память без гонки данных. В RTIC мы используем основанные на приоритетах критические секции, чтобы гарантировать запрет изменений (см. Протокол немедленного максимального приоритета).
Критическия секция состоит во временном увеличении
Насколько большим должен быть динамический приориткт, чтобы гарантировать запрет изменений определенного ресурса? Анализ приоритетов отвечает на этот вопрос и будет обсужден в следующем разделе. В этом разделе мы сфокусируемся на реализации критической секции.
Для упрощения, давайте взглянем на ресурс, разделяемый двумя задачами, запускаемыми с разными приоритетами. Очевидно, что одна задача может вытеснить другую; чтобы предотвратить гонку данных задача с
Пример ниже показывает разные типы, передаваемые каждой задаче:
#![allow(unused)]
fn main() {
#[rtic::app(device = ..)]
mut app {
struct Resources {
#[init(0)]
x: u64,
}
#[interrupt(binds = UART0, priority = 1, resources = [x])]
fn foo(c: foo::Context) {
let mut x: resources::x = c.resources.x;
x.lock(|x: &mut u64| {
*x += 1
});
}
#[interrupt(binds = UART1, priority = 2, resources = [x])]
fn bar(c: bar::Context) {
let mut x: &mut u64 = c.resources.x;
*x += 1;
}
}
}
Теперь давайте посмотрим. как эти типы создаются фреймворком.
#![allow(unused)]
fn main() {
fn foo(c: foo::Context) {
}
fn bar(c: bar::Context) {
}
pub mod resources {
pub struct x {
}
}
pub mod foo {
pub struct Resources {
pub x: resources::x,
}
pub struct Context {
pub resources: Resources,
}
}
pub mod bar {
pub struct Resources<'a> {
pub x: &'a mut u64,
}
pub struct Context {
pub resources: Resources,
}
}
mod app {
static mut x: u64 = 0;
impl rtic::Mutex for resources::x {
type T = u64;
fn lock
}
}
#[no_mangle]
unsafe fn UART0() {
foo(foo::Context {
resources: foo::Resources {
x: resources::x::new(
},
})
}
#[no_mangle]
unsafe fn UART1() {
bar(bar::Context {
resources: bar::Resources {
x: &mut x,
},
})
}
}
}