[i] Пороговый уровень прерываний в ARM Cortex-M

ID статьи: 61828
Дата последнего изменения: 16.12.2025 12:25:50
В статье рассмотрены аппаратные возможности процессорных ядер ARM Cortex-M0/M1/M3/M4 и их аналогов по повышению текущего уровня приоритета (задания порогового уровня приоритета) для временного запрещения прерываний на время выполнения критической секции кода.

Содержание

1. Процессорное ядро ARM Cortex-M0/M1 и аналоги (семейство МК К1986ВЕ1x, МК К1986ВК214 и К1986ВК234)
2. Процессорное ядро ARM Cortex-M3/M4 и аналоги (семейство МК К1986ВЕ9x, МК К1901ВЦ1QI, К1986ВК01GI, К1986ВЕ8Т)
    2.1 Регистр BASEPRI
    2.2 Регистр PRIMASK
    2.3 Регистр FAULTMASK

1. Процессорное ядро ARM Cortex-M0/M1 и аналоги (семейство МК К1986ВЕ1x, МК К1986ВК214 и К1986ВК234)

МК К1986ВК214 и К1986ВК234 построены на базе RISC-ядра, являющегося аналогом ARM Cortex-M0. Семейство МК К1986ВЕ1x построено на базе RISC-ядра, являющегося аналогом ARM Cortex-M1.

В данных ядрах для повышения текущего уровня приоритета (задания порогового уровня приоритета) доступен регистр PRIMASK, который запрещает все исключения, кроме HardFault и NMI (немаскируемое прерывание). В этом регистре используется только младший бит PRIMASK[0]. При установке данного бита в "1" приоритет текущего потока выполнения повышается до 0, таким образом, он может быть прерван только прерыванием с более высоким приоритетом - HardFault, NMI. Регистр PRIMASK используется для временного запрещения всех прерываний на время выполнения критической секции кода.

Использование CMSIS-функций для управления регистром PRIMASK приведено в фрагменте кода 1.

Фрагмент кода 1 - CMSIS-функции для управления регистром PRIMASK

__disable_irq();  // Записать 1 в регистр PRIMASK (отключение всех прерываний, кроме HardFault и NMI)
__enable_irq();   // Записать 0 в регистр PRIMASK (разрешение прерываний)
__set_PRIMASK(X); // Записать значение X в регистр PRIMASK
__get_PRIMASK();  // Прочитать значение из регистра PRIMASK

2. Процессорное ядро ARM Cortex-M3/M4 и аналоги (семейство МК К1986ВЕ9x, МК К1901ВЦ1QI, К1986ВК01GI, К1986ВЕ8Т)

Семейство МК К1986ВЕ9x и МК К1901ВЦ1Т построены на базе RISC-ядра, являющегося аналогом ARM Cortex-M3. МК К1986ВК01GI и К1986ВЕ8Т построены на базе RISC-ядра, являющегося аналогом ARM Cortex-M4.

В данных ядрах для повышения текущего уровня приоритета (задания порогового уровня приоритета) доступно несколько различных регистров:

Регистры BASEPRI и PRIMASK используются для временного запрещения прерываний или исключений на время выполнения критической секции кода. Регистр FAULTMASK в основном применяется для повышения текущего уровня приоритета исключения до уровня исключения HardFault.

2.1 Регистр BASEPRI

Регистр BASEPRI позволяет повысить приоритет текущего потока выполнения до заданного значения, тем самым запрещая другие прерывания, уровень которых равен или больше заданного значения. Таким образом регистр BASEPRI позволяет запретить не все прерывания, а только выбранную часть низкоприоритетных прерываний (чем больше уровень прерывания, тем ниже приоритет). Значение в регистре BASEPRI влияет на текущий приоритет выполнения лишь в том случае, если оно численно меньше, чем собственный приоритет текущего выполняющегося обработчика (то есть нельзя понизить приоритет кода ниже его собственного уровня). При этом значение 0 используется как индикатор того, что повышение приоритета с помощью BASEPRI отключено.

Использование CMSIS-функций для управления регистром BASEPRI приведено в фрагменте кода 2.

Фрагмент кода 2 - CMSIS-функции для управления регистром BASEPRI

__set_BASEPRI(X); // Записать значение X в регистр BASEPRI (прерывания с приоритетом X-0xFF запрещены)
__get_BASEPRI();  // Прочитать значение из регистра BASEPRI

2.2 Регистр PRIMASK

Регистр PRIMASK повышает текущий уровень приоритета до 0, тем самым запрещая все прерывания и исключения, кроме HardFault и NMI (немаскируемое прерывание). В этом регистре используется только младший бит PRIMASK[0]. При установке данного бита в "1" приоритет текущего потока выполнения повышается до 0, таким образом, он может быть прерван только прерыванием с более высоким приоритетом - HardFault и NMI.

Использование CMSIS-функций для управления регистром PRIMASK приведено в фрагменте кода 3.

Фрагмент кода 3 - CMSIS-функции для управления регистром PRIMASK

__disable_irq();  // Записать 1 в регистр PRIMASK (отключение всех прерываний, кроме HardFault и NMI)
__enable_irq();   // Записать 0 в регистр PRIMASK (разрешение прерываний)
__set_PRIMASK(X); // Записать значение X в регистр PRIMASK
__get_PRIMASK();  // Прочитать значение из регистра PRIMASK

2.3 Регистр FAULTMASK

Регистр FAULTMASK аналогичен регистру PRIMASK, за исключением того, что он повышает текущий уровень приоритета до -1 (уровень исключения HardFault). При установленном регистре FAULTMASK могут обрабатываться только прерывания исключения NMI. Возврат из любого исключения, кроме NMI, сбрасывает регистр FAULTMASK.

Как правило, регистр FAULTMASK используется обработчиками исключения (такими как BusFault, UsageFault и MemManageFault), которые хотят увеличить свой уровень приоритета до -1, что позволяет получить некоторые возможности обработчика исключения HardFault (маскирование отказов шины и обход модуля MPU).

Использование CMSIS-функций для управления регистром FAULTMASK приведено в фрагменте кода 4.

Фрагмент кода 4 - CMSIS-функции для управления регистром FAULTMASK

__set_FAULTMASK(X); // Записать значение X в регистр FAULTMASK (1 - отключение всех прерываний, кроме NMI)
__get_FAULTMASK();  // Прочитать значение из регистра FAULTMASK

Контактная информация

Сайт:https://support.milandr.ru
E-mail:support@milandr.ru
Телефон: +7 495 221-13-55