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

Группировка приоритетов (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 его нужно сделать вручную.

Источники

  1. 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 младшие биты считаются нулевыми
  2. Arm. ARMv7-M Architecture Reference Manual, ARM DDI 0403C_errata_v3, 2010 — B1.5.4: приоритет исключения делится на группу и подприоритет; механизмы повышения приоритета (PRIMASK, FAULTMASK, BASEPRI) действуют только на группу, подприоритет лишь сортирует ожидающие исключения и не влияет на активные
  3. 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
  4. STMicroelectronics. RM0090 Reference manual STM32F405/415, STM32F407/417, STM32F427/437, STM32F429/439 (Rev 21) — разд. 12.1.1: 16 программируемых уровней приоритета — реализованы 4 бита приоритета
  5. Arm. Cortex-M0 Devices Generic User Guide, DUI 0497A, 2009 — разд. 1.1: NVIC Cortex-M0 — четыре уровня приоритета прерываний; разд. 4.3.4: в регистре AIRCR Cortex-M0 нет поля PRIGROUP

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