Перейти к содержанию

Прерывание

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

Обновлено Редакция GAW

Прерывание (interrupt, IRQ) — сигнал от периферии или ядра, по которому процессор приостанавливает выполнение основной программы, сохраняет её состояние и переходит к специальной функции — обработчику прерывания (ISR, interrupt service routine). После завершения обработчика программа продолжается с того места, где была прервана. Без прерываний программе пришлось бы постоянно опрашивать флаги периферии в цикле.

Как устроено

У каждого источника — таймера, UART, АЦП, вывода — свой номер и своя ячейка в таблице векторов, где лежит адрес обработчика. Когда периферия выставляет флаг события и прерывание разрешено, контроллер прерываний передаёт запрос ядру, ядро сохраняет адрес возврата (и у Cortex-M часть регистров) в стек и переходит по вектору.

  • STM32. Прерываниями управляет контроллер NVIC ядра Cortex-M. У STM32F103 приоритет задаётся 4 битами — 16 уровней, меньшее число важнее, по умолчанию у всех 0. Прерывание с более высоким приоритетом может вытеснить выполняющийся обработчик. Номера каналов, общие векторы и внешние прерывания EXTI — в статье о прерываниях STM32, раскладку приоритетов по группам считает калькулятор приоритетов NVIC.
  • AVR. Приоритет задаёт положение в таблице векторов, вложенных прерываний по умолчанию нет: при входе флаг I в SREG сбрасывается. Реакция — не меньше четырёх тактов, подробнее — в статье об архитектуре AVR.

Правила для обработчиков

  • Коротко. Обработчик выставляет флаг или кладёт байт в буфер, а обработку делает основная программа.
  • Сбросить флаг источника, иначе обработчик вызовется снова сразу после выхода.
  • Общие переменные объявлять volatile и читать атомарно, если их размер больше разрядности процессора.
  • Кнопки на входе прерывания выдают дребезг — серию прерываний вместо одного.

Частые вопросы

Что такое вектор прерывания?

Адрес обработчика в таблице векторов — массиве адресов в начале памяти программ, по одному на каждый источник. По номеру прерывания ядро находит в таблице, куда перейти. У STM32 таблицу после сброса читают из начала Flash, а загрузчик может перенести её регистром SCB_VTOR. В C обработчик объявляют функцией с именем вектора: USART1_IRQHandler у STM32, ISR(USART_RX_vect) у AVR.

Почему обработчик прерывания вызывается снова и снова?

Чаще всего не сброшен флаг источника. Пока флаг установлен, запрос остаётся активным, и после выхода из обработчика ядро сразу входит в него снова. Флаг сбрасывают в начале обработчика: в STM32 — записью в регистр флагов периферии, например единицы в EXTI_PR, у многих флагов AVR — аппаратно при входе в обработчик.

Сколько тактов проходит до входа в обработчик?

У AVR — не меньше четырёх тактов на сохранение счётчика команд плюс переход из таблицы векторов; текущая многотактная команда сначала завершается. Возврат командой RETI — ещё четыре такта. Регистр SREG AVR сохраняет не аппаратно: это делает компилятор в функции ISR().

Источники

  1. STMicroelectronics. RM0008 Rev 21. Reference manual: STM32F101xx–STM32F107xx — 10.1 — NVIC: 16 уровней приоритета, таблицы векторов; 10.2 — EXTI
  2. STMicroelectronics. PM0056 Rev 7. STM32F10xxx/20xxx/21xxx/L1xxxx Cortex-M3 programming manual — 2.3.5 — приоритеты по умолчанию равны 0; 4.3.9 — повторный вход при несброшенном запросе; 4.4.4 — VTOR
  3. Microchip. ATmega48A/PA/88A/PA/168A/PA/328/P Data Sheet, DS40002061B — гл. 7 — время реакции на прерывание: не меньше 4 тактов, RETI — 4 такта; флаг I в SREG

Нашли ошибку?