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

Регистры ядра Cortex-M

В отладчике, на вкладке Registers, у любого Cortex-M3 или Cortex-M4 одинаковый список: R0–R12, SP, LR, PC, xPSR и несколько специальных регистров. Этот набор задаёт архитектура Armv7-M, а не производитель, поэтому он один и тот же у микроконтроллеров ST, NXP, TI и других.

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

Регистры ядра Cortex-M — набор регистров процессора, который задаёт архитектура Armv7-M и который одинаков у всех микроконтроллеров с ядрами Cortex-M3 и Cortex-M4. Это 13 регистров общего назначения R0–R12, три регистра со специальной ролью — SP, LR и PC — и специальные регистры: регистр состояния xPSR, регистры масок и регистр CONTROL (Armv7-M ARM, разд. A2.3.1 и B1.4). Все остальные регистры — периферия, NVIC, SysTick — отображены в память и доступны обычными командами загрузки и сохранения.

Основные регистры

РегистрНазначениеПосле сброса
R0–R12общего назначенияне определены
SP (R13)указатель активного стека: MSP или PSPMSP — первое слово таблицы векторов
LR (R14)адрес возврата из подпрограммы; при исключении — EXC_RETURN0xFFFFFFFF
PC (R15)счётчик командадрес обработчика сброса

Указателей стека два: основной MSP и процессный PSP. Какой из них сейчас SP, зависит от режима и бита SPSEL регистра CONTROL; после сброса выбран MSP. Младшие два бита SP всегда читаются как нули — стек выровнен хотя бы на 4 байта (разд. B1.4.1). Как эти регистры распределяются между вызывающей и вызываемой функцией, описывает соглашение AAPCS.

Регистр состояния xPSR

32-битный PSR состоит из трёх частей, которые не пересекаются по битам:

  • APSR — флаги результата: N, Z, C, V, флаг насыщения Q и, у ядер с DSP-расширением, флаги GE[3:0]. Их может читать и писать непривилегированная программа.
  • IPSR — номер исключения, которое сейчас обрабатывается; в режиме Thread — 0.
  • EPSR — бит T и поля ICI/IT для прерываемых команд и блоков IT. Программа читает EPSR как нули, запись игнорируется.

По разд. B1.4.2. Бит T должен всегда быть 1: Cortex-M исполняет только команды Thumb. Его значение берётся из младшего бита адреса перехода, поэтому адреса функций и векторов нечётные, а чётный адрес вызывает отказ INVSTATE и HardFault. Целиком регистр называют xPSR — так он сохраняется на стеке при входе в исключение вместе с R0–R3, R12, LR и адресом возврата (разд. B1.5.6; подробнее — «Кадр стека исключения»).

Специальные регистры

РегистрБитыНазначение
PRIMASK1 битзапрет всех исключений с настраиваемым приоритетом
FAULTMASK1 битповышение приоритета до уровня HardFault
BASEPRI8 битпорог приоритета прерываний
CONTROLnPRIV, SPSEL, FPCAпривилегии и стек режима Thread, активный контекст FPU

По разд. B1.4.3 и B1.4.4. После сброса все маски и CONTROL равны нулю: программа привилегированная и работает на MSP. Читают и пишут специальные регистры командами MRS и MSR, а PRIMASK и FAULTMASK переключают ещё и команды CPSID и CPSIE. Подробно о масках — в термине «PRIMASK, FAULTMASK и BASEPRI», о привилегиях и двух режимах — в термине «Режимы Thread и Handler».

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

Почему LR после сброса равен 0xFFFFFFFF?

Так задано архитектурой: при сбросе LR получает 0xFFFFFFFF, и если программа попытается вернуться из функции сброса через этот адрес, произойдёт отказ (Armv7-M ARM, разд. A2.3.1). Это ловушка для ошибочного выхода из Reset_Handler. При входе в исключение LR получает особое значение EXC_RETURN, по которому ядро потом выбирает режим и стек возврата.

Чем отличаются APSR, IPSR и EPSR?

Это три части одного 32-битного регистра PSR. APSR хранит флаги результата N, Z, C, V и Q, их может читать и менять обычная программа. IPSR содержит номер текущего исключения, в режиме Thread там 0. EPSR хранит бит T и состояние блоков IT; программа читает его как нули. Вместе их называют xPSR, и именно так регистр сохраняется на стеке при входе в прерывание.

Откуда берётся HardFault из-за бита T?

Cortex-M исполняет только команды Thumb, и бит T в EPSR всегда должен быть 1. Его значение берётся из младшего бита адреса перехода: если указатель на функцию или вектор в таблице записан чётным, бит T станет 0, и следующая команда вызовет отказ INVSTATE (Armv7-M ARM, разд. B1.4.2). Поэтому адреса функций в таблице векторов всегда нечётные.

Источники

  1. Arm. Armv7-M Architecture Reference Manual (ARM DDI 0403E.e, ID021621) — разд. A2.3.1: 13 регистров общего назначения R0–R12 по 32 бита и три специальных; SP (R13) — указатель активного стека, при сбросе — вершина основного стека; LR (R14) — адрес возврата из подпрограммы, вызванной с BL, при сбросе 0xFFFFFFFF, что вызывает отказ при попытке возврата, обновляется при входе в исключение; PC (R15) при сбросе загружается адресом обработчика сброса; разд. A2.3.2: флаги APSR N, Z, C, V, Q и GE[3:0] (только с DSP); разд. B1.4.1: два стека SP_main (MSP) и SP_process (PSP), текущий зависит от режима и CONTROL.SPSEL, сброс выбирает MSP; биты SP[1:0] читаются как 0; разд. B1.4.2: PSR из APSR (флаги, доступны непривилегированному коду), IPSR (номер исключения, 0 в режиме Thread), EPSR (бит T и поля ICI/IT); бит T должен быть 1, бит 0 вектора сброса задаёт T, при T = 0 — отказ INVSTATE; MRS и MSR читают и пишут сочетания IAPSR, EAPSR, IEPSR, XPSR; разд. B1.4.3: PRIMASK, BASEPRI, FAULTMASK, сброс обнуляет все маски; разд. B1.4.4: CONTROL — nPRIV (бит 0, непривилегированный Thread), SPSEL (бит 1, PSP в режиме Thread), FPCA (бит 2, активен контекст FPU); сброс обнуляет CONTROL; разд. B1.5.5 Reset behavior: R0–R12 и флаги APSR не определены, SP_main загружается из первого слова таблицы векторов, LR = 0xFFFFFFFF, бит T — из младшего бита вектора сброса, IPSR обнуляется; разд. B1.5.6: при входе в исключение на стек сохраняются xPSR, адрес возврата, LR, R12, R3–R0
  2. Arm. Cortex-M3 Devices Generic User Guide (ARM DUI 0552A) — разд. 2.1.3 Core registers: R0–R12, SP, LR, PC, PSR, PRIMASK, FAULTMASK, BASEPRI, CONTROL; бит 27 PSR — флаг насыщения Q

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