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

Таблица векторов прерываний

Когда приходит прерывание, процессор должен знать, куда перейти. Адреса всех обработчиков хранятся в таблице векторов — обычно в самом начале флеш-памяти. Её содержимое формирует код запуска и скрипт компоновщика.

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

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

Cortex-M

По руководству Arm (разд. 2.3.4) таблица Cortex-M содержит не команды, а адреса: в слове 0 — начальное значение указателя стека, в слове 1 — адрес обработчика сброса, дальше системные исключения и прерывания периферии.

СмещениеСодержимое
0x00начальный SP
0x04Reset
0x08NMI
0x0CHardFault
0x40 + 4·nпрерывание периферии IRQn

При сбросе процессор загружает указатель стека из слова 0 и переходит по адресу из слова 1. Младший бит каждого адреса равен 1 — признак кода Thumb. В шаблоне ST для STM32F103 таблица — массив g_pfnVectors в секции .isr_vector, которую скрипт компоновщика с KEEP ставит в начало флеш-памяти. После сброса таблица находится по адресу 0, но регистр VTOR позволяет перенести её — это нужно загрузчикам.

AVR

У AVR в таблице не адреса, а команды перехода — у ATmega328P 26 векторов по 4 байта. avr-libc собирает их в секции .vectors; вектор без обработчика ведёт на __bad_interrupt и затем на сброс. Номер вектора определяет и приоритет: чем меньше адрес, тем выше приоритет.

Не путать таблицу векторов с NVIC: таблица хранит адреса, а NVIC решает, какое прерывание и когда обслужить. Как таблица попадает в начало флеш-памяти, разобрано в статье «Скрипт компоновщика GNU ld», что выполняется по вектору сброса — в термине «Код запуска», правила обработчиков — в статье «Прерывания и общие данные». Код инициализации периферии с обработчиками прерываний сгенерирует генератор кода STM32.

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

Что лежит в первых словах таблицы векторов Cortex-M?

Слово 0 — начальное значение указателя стека, слово 1 — адрес Reset_Handler, дальше NMI, HardFault и другие системные исключения, а с адреса 0x40 — прерывания периферии по 4 байта на каждое. После сброса процессор сам берёт SP из слова 0 и переходит по слову 1.

Можно ли перенести таблицу векторов в ОЗУ?

У Cortex-M3 и старше — да: регистр VTOR задаёт её адрес, по руководству Arm в диапазоне 0x00000080–0x3FFFFF80. Так делают загрузчики: после передачи управления прошивке таблицу переносят на начало её образа.

Что будет, если для прерывания нет обработчика на AVR?

По умолчанию avr-libc ставит в такой вектор переход на __bad_interrupt, который ведёт к вектору сброса — микроконтроллер фактически перезапускается. Поэтому включённое прерывание без функции ISR выглядит как самопроизвольная перезагрузка.

Источники

  1. Arm. Cortex-M3 Devices Generic User Guide, DUI 0552A, 2010 — разд. 2.3.4: таблица векторов содержит начальное значение указателя стека и адреса всех обработчиков; младший бит каждого вектора — 1 (код Thumb); после сброса таблица по адресу 0x00000000, регистр VTOR позволяет перенести её в диапазон 0x00000080–0x3FFFFF80; разд. 4.3.4: смещение выравнивается на число элементов таблицы, округлённое вверх до степени двойки, минимум 32 слова; табл. 2-16: смещения векторов — Reset 0x04, NMI 0x08, HardFault 0x0C, первое прерывание 0x40, шаг 4
  2. Arm. ARMv7-M Architecture Reference Manual, DDI 0403E.e, 2021 — B1.5.5: при сбросе SP_main загружается из слова 0 таблицы векторов (младшие 2 бита обнуляются)
  3. STMicroelectronics. cmsis-device-f1, коммит c8e9a4a: Source/Templates/gcc/linker/STM32F103XB_FLASH.ld и Source/Templates/gcc/startup_stm32f103xb.s — g_pfnVectors в секции .isr_vector, слово 0 — _estack, слово 1 — Reset_Handler; секция .isr_vector с KEEP в начале FLASH
  4. AVR-LibC 2.3.2: Memory Sections (doc/api/sections.dox), avr/iom328p.h — секция .vectors — переходы на __vector_N, без обработчика — __bad_interrupt и сброс; ATmega328P — 26 векторов по 4 байта, TIMER1_COMPA_vect — вектор 11

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