rtic/book/ru/src/internals/interrupt-configuration.md
2021-04-08 12:22:43 +03:00

2.9 KiB
Raw Blame History

Настройка прерываний

Прерывания - это основа работы программ на RTIC. Правильно настроить приоритеты прерываний и убедиться, что они не изменяются во время выполнения обязательно для безопасной работы программы.

Фреймворк RTIC представляет приоритеты прерываний, как нечто, что должно быть определено на этапе компиляции. Однако, статическая настройка должна быть зашита в соответствующие регистры в процессе инициализации программы. Настройка прерываний происходит до запуска функции init.

Этот пример дает представление о коде, запускаемом фреймворком RTIC:

#[rtic::app(device = lm3s6965)]
mod app {
    #[init]
    fn init(c: init::Context) {
        // .. пользовательский код ..
    }

    #[idle]
    fn idle(c: idle::Context) -> ! {
        // .. пользовательский код ..
    }

    #[interrupt(binds = UART0, priority = 2)]
    fn foo(c: foo::Context) {
        // .. пользовательский код ..
    }
}

Фреймворк генерирует точку входа в программу, которая выглядит примерно так:

// настоящая точку входа в программу
#[no_mangle]
unsafe fn main() -> ! {
    // преобразует логические приоритеты в аппаратные / NVIC приоритеты
    fn logical2hw(priority: u8) -> u8 {
        use lm3s6965::NVIC_PRIO_BITS;

        // NVIC кодирует приоритеты верхними битами
        // большие значения обозначают меньший приоритет
        ((1 << NVIC_PRIORITY_BITS) - priority) << (8 - NVIC_PRIO_BITS)
    }

    cortex_m::interrupt::disable();

    let mut core = cortex_m::Peripheral::steal();

    core.NVIC.enable(Interrupt::UART0);

    // значение, определенное пользователем
    let uart0_prio = 2;

    // проверка на этапе компиляции, что определенный приоритет входит в поддерживаемый диапазон
    let _ = [(); (1 << NVIC_PRIORITY_BITS) - (uart0_prio as usize)];

    core.NVIC.set_priority(Interrupt::UART0, logical2hw(uart0_prio));

    // вызов пользовательского кода
    init(/* .. */);

    // ..

    cortex_m::interrupt::enable();

    // вызов пользовательского кода
    idle(/* .. */)
}