mirror of
https://github.com/rtic-rs/rtic.git
synced 2024-12-02 00:14:33 +01:00
80 lines
3.1 KiB
Markdown
80 lines
3.1 KiB
Markdown
|
# Нереентерабельность
|
|||
|
|
|||
|
В RTIC задачи-обработчики *не* могут использоваться повторно. Переиспользование задачи-обработчика
|
|||
|
может сломать правила заимствования Rust и привести к *неопределенному поведению*.
|
|||
|
Задача-обработчик теоретически может быть переиспользована одним из двух способов: программно или аппаратно.
|
|||
|
|
|||
|
## Программно
|
|||
|
|
|||
|
Чтобы переиспользовать задачу-обработчик программно, назначенный ей обработчик прерывания
|
|||
|
должен быть вызван с помощью FFI (смотрите пример ниже). FFI требует `unsafe` код,
|
|||
|
что уменьшает желание конечных пользователей вызывать обработчик прерывания.
|
|||
|
|
|||
|
``` rust
|
|||
|
#[rtic::app(device = ..)]
|
|||
|
mod app {
|
|||
|
#[init]
|
|||
|
fn init(c: init::Context) { .. }
|
|||
|
|
|||
|
#[interrupt(binds = UART0)]
|
|||
|
fn foo(c: foo::Context) {
|
|||
|
static mut X: u64 = 0;
|
|||
|
|
|||
|
let x: &mut u64 = X;
|
|||
|
|
|||
|
// ..
|
|||
|
|
|||
|
//~ `bar` может вытеснить `foo` в этом месте
|
|||
|
|
|||
|
// ..
|
|||
|
}
|
|||
|
|
|||
|
#[interrupt(binds = UART1, priority = 2)]
|
|||
|
fn bar(c: foo::Context) {
|
|||
|
extern "C" {
|
|||
|
fn UART0();
|
|||
|
}
|
|||
|
|
|||
|
// этот обработчик прерывания вызовет задачу-обработчик `foo`, что сломает
|
|||
|
// ссылку на статическую переменную `X`
|
|||
|
unsafe { UART0() }
|
|||
|
}
|
|||
|
}
|
|||
|
```
|
|||
|
|
|||
|
Фреймворк RTIC должен сгенерировать код обработчика прерывания, который вызывает
|
|||
|
определенные пользователем задачи-обработчики. Мы аккуратны в том, чтобы обеспечить
|
|||
|
невозможность вызова этих обработчиков из пользовательского кода.
|
|||
|
|
|||
|
Пример выше раскрывается в:
|
|||
|
|
|||
|
``` rust
|
|||
|
fn foo(c: foo::Context) {
|
|||
|
// .. пользовательский код ..
|
|||
|
}
|
|||
|
|
|||
|
fn bar(c: bar::Context) {
|
|||
|
// .. пользовательский код ..
|
|||
|
}
|
|||
|
|
|||
|
mod app {
|
|||
|
// все в этом блоке невидимо для пользовательского кода
|
|||
|
|
|||
|
#[no_mangle]
|
|||
|
unsafe fn USART0() {
|
|||
|
foo(..);
|
|||
|
}
|
|||
|
|
|||
|
#[no_mangle]
|
|||
|
unsafe fn USART1() {
|
|||
|
bar(..);
|
|||
|
}
|
|||
|
}
|
|||
|
```
|
|||
|
|
|||
|
## Аппаратно
|
|||
|
|
|||
|
Обработчик прерывания также может быть вызван без программного вмешательства.
|
|||
|
Это может произойти, если один обработчик будет назначен двум или более прерываниям
|
|||
|
в векторе прерываний, но синтаксиса для такого рода функциональности в RTIC нет.
|