Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Прерывания

Прерывания отличаются от исключений по многим признакам, но их работа и использование во многом похожи, и обрабатываются они одним и тем же контроллером прерываний. Исключения определяются архитектурой Cortex-M, а прерывания всегда реализуются производителем (и часто даже конкретным чипом) и различаются как по именам, так и по функциональности.

Прерывания дают большую гибкость, которую нужно учитывать при попытке использовать их продвинутым образом. В этой книге мы не будем рассматривать такие случаи, однако полезно помнить следующее:

  • У прерываний есть программируемые приоритеты, которые определяют порядок выполнения их обработчиков.
  • Прерывания могут вкладываться друг в друга и вытеснять друг друга: выполнение обработчика прерывания может быть прервано другим, более приоритетным прерыванием.
  • Обычно причину, вызвавшую прерывание, нужно сбросить, чтобы не допустить бесконечного повторного входа в обработчик прерывания.

Общие шаги инициализации во время выполнения всегда одинаковы:

  • Настроить периферию так, чтобы она генерировала запросы прерываний в нужные моменты;
  • Задать нужный приоритет обработчика прерывания в контроллере прерываний;
  • Разрешить обработчик прерывания в контроллере прерываний.

Подобно исключениям, крейт cortex-m-rt предоставляет атрибут interrupt для объявления обработчиков прерываний. Однако этот атрибут доступен только при включённом feature device. Кроме того, атрибут не предназначен для прямого использования: попытка сделать это приведёт к ошибке компиляции.

Вместо этого используйте повторно экспортированную версию атрибута interrupt, которую предоставляет крейт устройства (обычно сгенерированный с помощью svd2rust). Это гарантирует, что компилятор может проверить, существует ли прерывание на целевом устройстве. Список доступных прерываний и их позиций в таблице векторов прерываний обычно автоматически генерируется из файла SVD с помощью svd2rust.

use lm3s6965::interrupt; // Повторно экспортированный атрибут из крейта устройства

// Обработчик прерывания для прерывания Timer2
#[interrupt]
fn TIMER2A() {
    // ..
    // Сбросить причину, по которой сгенерирован запрос прерывания
}

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

Как и в случае с обработчиками исключений, внутри обработчиков прерываний можно объявлять static mut-переменные для безопасного хранения состояния.

#[interrupt]
fn TIMER2A() {
    static mut COUNT: u32 = 0;

    // `COUNT` имеет тип `&mut u32`, и её безопасно использовать
    *COUNT += 1;
}

Более подробное описание механизмов, показанных здесь, см. в разделе исключения.