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 для объявления обработчиков прерываний. Однако этот атрибут доступен только при включении функции устройства. При этом данный атрибут не предназначен для прямого использования — это приведет к ошибке компиляции.

Вместо этого вы должны использовать переэкспортированную версию атрибута 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;
}

Для более подробного описания механизмов, продемонстрированных здесь, обратитесь к [разделу об исключениях].