Нереентерабельность

В RTIC задачи-обработчики не могут использоваться повторно. Переиспользование задачи-обработчика может сломать правила заимствования Rust и привести к неопределенному поведению. Задача-обработчик теоретически может быть переиспользована одним из двух способов: программно или аппаратно.

Программно

Чтобы переиспользовать задачу-обработчик программно, назначенный ей обработчик прерывания должен быть вызван с помощью FFI (смотрите пример ниже). FFI требует unsafe код, что уменьшает желание конечных пользователей вызывать обработчик прерывания.


#![allow(unused)]

fn main() {

#[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 должен сгенерировать код обработчика прерывания, который вызывает определенные пользователем задачи-обработчики. Мы аккуратны в том, чтобы обеспечить невозможность вызова этих обработчиков из пользовательского кода.

Пример выше раскрывается в:


#![allow(unused)]

fn main() {

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 нет.

Загрузка...