Приоритеты прерываний в Cortex-M и их настройка в STM32Cube

STM32Cube — это набор библиотек фирмы STM для своих микроконтроллеров (STM32). Эти библиотеки пришли на смену библиотекам SPL.

Микроконтроллеры STM32 сделаны на базе ядра ARM Cortex-M. Это ядро служит основой микроконтроллеров и у других производителей.

Ядро поддерживает прерывания, которые могут прерывать не только основную программу, но и друг друга, либо не прерывать, что определяется их приоритетом.

Приоритет прерывания зависит от 3 факторов:

 

  • группа, в которую входит прерывание,
  • подгруппа, к которой принадлежит прерывание,
  • номер прерывания в таблице прерываний.

Группу и подгруппу прерываний можно настраивать, а таблица задается производителем.

Некоторые системные прерывания имеют фиксированный приоритет, но обычные прерывания, которых большинство, настраиваются.

В первую очередь, приоритет определяется группой, затем — подгруппой и в последнюю— номером в таблице. Прерывания могут принадлежать к одной группе и подгруппе, но все равно имеют разные номера, поэтому каждое прерывание имеет свой уникальный приоритет.

Группа определяет какие прерывания могут перебивать друг друга. То есть, если прерывания имеют разные группы, то одни прерывания могут прервать другие, если случились позже по времени. Прервать — значит приостановить обработку одного прерывания и запустить обработку другого.

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

Номер тоже не влияет на перебиваемость. Он играет роль, если прерывания принадлежат одной группе и одной подгруппе, и также определяет последовательность обработки прерываний при их одновременном возникновении.

Группа, подгруппа и номер задаются числами, и чем меньше числа, тем выше приоритет прерывания. То есть, имеет место обратная пропорциональность.

Примеры:

  • Прерывание группы 0 произошло во время обработки прерывания 1, тогда прерывание группы 0 перебивает прерывание группы 1.
  • Прерывание группы 1 произошло во время обработки прерывания группы 0, обработка прерывания группы 1 не запустится, пока не обработано прерывание группы 0.
  • Если 2 прерывания (подгруппа 1 и 2) принадлежат одной группе, и возникли одновременно, то сначала обработается прерывание подгруппы 1, а затем подгруппы 2.
  • Если 2 прерывания (подгруппа 1 и 2) принадлежат одной группе, и одно из прерываний возникло позже другого, то одно будет ждать пока не обработается другое, независимо от подгруппы.
  • Если прерывания с номерами 10 и 15 принадлежат одной группе и одной подгруппе и возникли одновременно, то сначала обработается прерывание с номером 10, затем с номером 15.

Количество групп и подгрупп настраивается. При этом, чем больше групп нам нужно, тем меньше у нас будет подгрупп и наоборот. Можно сравнить с перетягиванием каната.

Параметр, от которого зависит количество групп и подгрупп, будем называть разбиением.

В STM32Cube есть две функции, которые позволяют управлять приоритетом прерываний:

  • HAL_NVIC_SetPriorityGrouping()
  • HAL_NVIC_SetPriority()

Первая задает разбиение, а вторая — группу и подгруппы для конкретного прерывания.

В функцию HAL_NVIC_SetPriorityGrouping() передается только один аргумент, который может принимать одно из следующих значений:

  • NVIC_PRIORITYGROUP_0
  • NVIC_PRIORITYGROUP_1
  • NVIC_PRIORITYGROUP_2
  • NVIC_PRIORITYGROUP_3
  • NVIC_PRIORITYGROUP_4

То есть в STM32 возможно только 5 разбиений. Ядро Cortex-M позволяет больше, и возможно в других микроконтроллерах их больше, но в STM32 всего 5.

В таблице ниже представлена зависимость групп и подгрупп от разбиения:

Разбиение Количество групп Количество подгрупп Значения групп Значения подгрупп
0 0 16 нет 0…15
1 2 8 0…1 0…7
2 4 4 0…3 0…3
3 8 2 0…7 0…1
4 16 0 0…15 нет

Функция HAL_NVIC_SetPriority() принимает 3 аргумента и имеет следующий прототип:

1
2
3
4
5
void HAL_NVIC_SetPriority(
    IRQn_Type IRQn,
    uint32_t PreemptPriority,
    uint32_t SubPriority
)

Где аргументы функции:

  • IRQn — прерывание. Принимает значения из перечисленияIRQn_Type, которое определено в файле stm32xxxx.h для конкретного микроконтроллера.
  • PreemptPriority — группа прерывания.
  • SubPriority — подгруппа прерывания.

Аргументы группы и подгруппы могут принимать значения из таблицы выше в соответствии с разбиением. Если у группы или подгруппы не может быть значений, то можно указать любое число.

Перечисление IRQn_Type содержит достаточно много прерываний, поэтому приведу его в очень сокращенном виде, чтобы стала понятна его организация:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
-->
X
Обратный звонок