mirror of
https://github.com/rtic-rs/rtic.git
synced 2024-12-02 00:14:33 +01:00
79 lines
3.1 KiB
Markdown
79 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 нет.
|