Группировка приоритетов (PRIGROUP)
У прерывания Cortex-M3 и M4 один байт приоритета, но работает он как два числа. Старшая часть решает, может ли прерывание вытеснить работающий обработчик, младшая — только порядок в очереди. Где проходит граница, задаёт поле PRIGROUP.
Обновлено Редакция GAW
Содержание
Группировка приоритетов — деление 8-битного поля приоритета исключения Cortex-M3 и M4 на две части. Старшие биты — группа приоритета (preempt priority): только она решает, может ли исключение вытеснить работающий обработчик. Младшие биты — подприоритет: он лишь упорядочивает ожидающие исключения одной группы, а при полном равенстве первым идёт меньший номер IRQ (DUI 0552A, разд. 2.3.6). Как всегда в Cortex-M, меньшее число означает более высокий приоритет.
Поле PRIGROUP
Границу между частями задаёт поле PRIGROUP (биты 10:8) регистра AIRCR по адресу 0xE000ED0C из блока управления системой. Запись в AIRCR принимается только с ключом 0x5FA в старшем полуслове (разд. 4.3.5). У STM32 реализованы 4 бита приоритета (RM0090, разд. 12.1.1), поэтому из восьми значений PRIGROUP различимы пять:
| PRIGROUP | Биты группы | Биты подприоритета | Уровней вытеснения × подприоритетов |
|---|---|---|---|
| 0–3 | [7:4] | — | 16 × 1 |
| 4 | [7:5] | [4] | 8 × 2 |
| 5 | [7:6] | [5:4] | 4 × 4 |
| 6 | [7] | [6:4] | 2 × 8 |
| 7 | — | [7:4] | 1 × 16 |
Пересчитано из табл. 4-18 DUI 0552A для четырёх реализованных бит. При PRIGROUP = 7 групп нет вовсе: все прерывания одного уровня и не вытесняют друг друга.
В коде
NVIC_SetPriorityGrouping(5); /* 4 groups x 4 subpriorities */
NVIC_SetPriority(USART1_IRQn, NVIC_EncodePriority(5, 1, 2));
NVIC_EncodePriority() из CMSIS собирает значение по группе и подприоритету с учётом числа реализованных бит, а NVIC_SetPriority() сдвигает его в старшие биты байта. Посчитать значения для регистров и кода по выбранной группе можно в калькуляторе приоритетов NVIC.
Подводные камни
- Группировку выбирают один раз, до настройки приоритетов: смена PRIGROUP меняет смысл уже записанных значений.
- Маски, в том числе порог BASEPRI, повышают приоритет выполнения только по группе; подприоритет лишь сортирует ожидающие исключения и на активные не влияет (ARMv7-M ARM, B1.5.4).
- У Cortex-M0 и M0+ поля PRIGROUP нет: там 4 уровня приоритета без подприоритетов.
Как приоритеты настраивают на STM32 и какую группу выбирает HAL — в статье «Прерывания STM32», общее устройство контроллера — в статье «NVIC».
Частые вопросы
Может ли прерывание с меньшим подприоритетом вытеснить обработчик?
Нет. Группа решает вытеснение: прерывание с меньшим номером группы прерывает работающий обработчик, с той же группой — ждёт его окончания. Подприоритет влияет только на очередь: если ждут несколько прерываний одной группы, первым обслужат то, у кого подприоритет меньше. Вытеснять друг друга по подприоритету прерывания не могут.
Какую группировку выбрать для STM32?
Чаще всего все 4 бита отдают группе: 16 уровней вытеснения без подприоритетов. Так делает HAL, и так проще рассуждать о том, кто кого прерывает. Подприоритеты нужны редко — когда много прерываний одного уровня и важен порядок их обслуживания. Главное — выбрать группировку один раз до настройки приоритетов и больше не менять.
Почему приоритет 1 на STM32 записывают как 0x10?
У STM32 реализованы только 4 старших бита байта приоритета, младшие 4 читаются как ноль. Уровень 1 в регистре NVIC_IPR — это 1 << 4 = 0x10. Функция CMSIS NVIC_SetPriority делает этот сдвиг сама, а при прямой записи в регистр или в BASEPRI его нужно сделать вручную.
Источники
- Arm. Cortex-M3 Devices Generic User Guide, DUI 0552A, 2010 — разд. 2.3.6: NVIC делит каждое поле приоритета на старшую часть — группу приоритета — и младшую — подприоритет внутри группы; вытеснение определяет только группа, прерывание той же группы не вытесняет работающий обработчик; среди ожидающих с одной группой порядок задаёт подприоритет, при равенстве — меньший номер IRQ; разд. 2.3.5: меньшее значение — более высокий приоритет, по умолчанию все настраиваемые приоритеты 0; разд. 4.3.5, табл. 4-17: AIRCR по адресу 0xE000ED0C, PRIGROUP — биты 10:8, запись только с ключом 0x5FA в VECTKEY; табл. 4-18: PRIGROUP 0b000 — группа [7:1], подприоритет [0] (128 × 2) … 0b111 — групп нет, подприоритет [7:0] (1 × 256); при числе бит меньше 8 младшие биты считаются нулевыми
- Arm. ARMv7-M Architecture Reference Manual, ARM DDI 0403C_errata_v3, 2010 — B1.5.4: приоритет исключения делится на группу и подприоритет; механизмы повышения приоритета (PRIMASK, FAULTMASK, BASEPRI) действуют только на группу, подприоритет лишь сортирует ожидающие исключения и не влияет на активные
- Arm. CMSIS 6, CMSIS-Core core_cm3.h (v6.4.0) — __NVIC_SetPriorityGrouping() пишет PRIGROUP в AIRCR с ключом; NVIC_EncodePriority(PriorityGroup, PreemptPriority, SubPriority): бит вытеснения min(__NVIC_PRIO_BITS, 7 − PriorityGroup), бит подприоритета — остаток от __NVIC_PRIO_BITS
- STMicroelectronics. RM0090 Reference manual STM32F405/415, STM32F407/417, STM32F427/437, STM32F429/439 (Rev 21) — разд. 12.1.1: 16 программируемых уровней приоритета — реализованы 4 бита приоритета
- Arm. Cortex-M0 Devices Generic User Guide, DUI 0497A, 2009 — разд. 1.1: NVIC Cortex-M0 — четыре уровня приоритета прерываний; разд. 4.3.4: в регистре AIRCR Cortex-M0 нет поля PRIGROUP
Нашли ошибку?
Смотрите также
- Приоритеты прерываний NVICPRIGROUP, вытеснение и подприоритет, NVIC_IPR, AIRCR, bit-band
- NVIC — контроллер прерыванийКонтроллер прерываний Cortex-M: приоритеты и вытеснение
- PRIMASK, FAULTMASK и BASEPRIРегистры масок исключений Cortex-M: полный запрет и порог приоритета
- SCB (блок управления системой)Регистры ядра Cortex-M для настройки исключений, сна и отказов
- Прерывания STM32Векторы и IRQn, приоритеты и HAL, EXTI и общие векторы, флаги, события, примеры