После довольно сложного процесса изучения некоторых вещей о приоритете прерывания я все еще немного застрял, пытаясь понять, какие значения мне разрешено вызывать для HAL_NVIC_SetPriority()
на SysTick_IRQn
(то есть ISR, вызывающий планировщик FreeRTOS каждые 1 мс).
TLDR;
Часть меня думает, что разрешено что-либо между HAL_NVIC_SetPriority(SysTick_IRQn, 15 ,0U)
(возможно, с самым низким приоритетом) и HAL_NVIC_SetPriority(SysTick_IRQn, 10 ,0U)
(немного выше), а часть меня думает, что что-то между HAL_NVIC_SetPriority(SysTick_IRQn, 15 ,0U)
(возможно, с самым низким приоритетом) и HAL_NVIC_SetPriority(SysTick_IRQn, 5 ,0U)
(немного выше) разрешено. Предполагается, что configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY
в FreeRTOSConfig.h установлен на 5. Путаница заключается в том, что в FreeRTOS более высокие числа имеют более высокий приоритет, но в STM32 более высокие числа имеют более низкий приоритет, и Документация довольно сложна для понимания.
подробности:
Чтобы доказать, что я сделал доблестное усилие, и чтобы помочь вам помочь мне заполнить пробелы, вот мое текущее понимание. Я собираюсь написать описание того, что я знаю, чтобы быть правдой так, чтобы это выглядело как Я учу Вы , хотя я ищу ответ на мой Приведенный выше вопрос, а также исправление , подтверждение или дополнительное понимание по вашему усмотрению.
Хотя это, вероятно, относится ко многим микроконтроллерам или семействам STM32, давайте обсудим это, в частности, в отношении STM32F207ZG .
Примечание: STM32CubeF2 скачать здесь .
Мое понимание:
Если вы посмотрите на стандартный FreeRTOSConfig.h файл (например, STM32Cube_FW_F2_V1.7.0 / Projects / STM322xG_EVAL / Applications / FreeRTOS / FreeRTOS_ThreadCreation / Inc / FreeRTOSConfig.h), вы увидите следующее:
/* Cortex-M specific definitions. */
#ifdef __NVIC_PRIO_BITS
/* __BVIC_PRIO_BITS will be specified when CMSIS is being used. */
#define configPRIO_BITS __NVIC_PRIO_BITS
#else
#define configPRIO_BITS 4 /* 15 priority levels */
#endif
/* The lowest interrupt priority that can be used in a call to a "set priority"
function. */
#define configLIBRARY_LOWEST_INTERRUPT_PRIORITY 0xf
/* The highest interrupt priority that can be used by any interrupt service
routine that makes calls to interrupt safe FreeRTOS API functions. DO NOT CALL
INTERRUPT SAFE FREERTOS API FUNCTIONS FROM ANY INTERRUPT THAT HAS A HIGHER
PRIORITY THAN THIS! (higher priorities are lower numeric values. */
#define configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY 5
/* Interrupt priorities used by the kernel port layer itself. These are generic
to all Cortex-M ports, and do not rely on any particular library functions. */
#define configKERNEL_INTERRUPT_PRIORITY ( configLIBRARY_LOWEST_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) )
/* !!!! configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to zero !!!!
See http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html. */
#define configMAX_SYSCALL_INTERRUPT_PRIORITY ( configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) )
__NVIC_PRIO_BITS
определено в STM32Cube_FW_F2_V1.7.0 / Drivers / CMSIS / Device / ST / STM32F2xx / Include / stm32f217xx.h как 4U
, поскольку «STM32F2XX использует 4 бита для уровней приоритета».
Во-первых, это интересно, поскольку это означает, что фактически используются только 4 из 8 доступных битов приоритета! Вызов библиотеки STM32 HAL HAL_NVIC_SetPriority()
имеет заголовок, который выглядит следующим образом и, кажется, указывает на то, что вам нужно установить 8 бит (PreemptPriority
от 0 до 15 и SubPriority
от 0 до 15), но на самом деле это не так - у вас есть только 4 бита для установки.
/**
* @brief Sets the priority of an interrupt.
* @param IRQn: External interrupt number.
* This parameter can be an enumerator of IRQn_Type enumeration
* (For the complete STM32 Devices IRQ Channels list, please refer to the appropriate CMSIS device file (stm32f2xxxx.h))
* @param PreemptPriority: The preemption priority for the IRQn channel.
* This parameter can be a value between 0 and 15
* A lower priority value indicates a higher priority
* @param SubPriority: the subpriority level for the IRQ channel.
* This parameter can be a value between 0 and 15
* A lower priority value indicates a higher priority.
* @retval None
*/
void HAL_NVIC_SetPriority(IRQn_Type IRQn, uint32_t PreemptPriority, uint32_t SubPriority)
{
Итак, у вас есть только 4 бита для установки, но оказывается, что вы можете решить, сколько будет PreemptPriority
битов, а сколько SubPriority
битов, следующим образом:
HAL_NVIC_SetPriorityGrouping()
из UM1940 , 9.2.4, p124 / 1371.
FreeRTOS говорит в своей документации :
Если вы используете STM32 с библиотекой драйвера STM32, убедитесь, что все приоритетные биты назначены для приоритетных битов с приоритетом, вызвав NVIC_PriorityGroupConfig (NVIC_PriorityGroup_4); до запуска ОСРВ.
Итак, одна из самых первых вещей, которые вы должны сделать в своем коде (по крайней мере, перед запуском планировщика FreeRTOS через osKernelStart()
или vTaskStartScheduler()
, это:
/* Set Interrupt Group Priority */
HAL_NVIC_SetPriorityGrouping(NVIC_PRIORITYGROUP_4);
Конфигурирует все 4 ваших приоритетных бита как PreemptPriority
битов, а ни один - SubPriority
битов. Это означает, что любые вызовы функции HAL_NVIC_SetPriority(IRQn_Type IRQn, uint32_t PreemptPriority, uint32_t SubPriority)
теперь будут всегда использовать 0 в качестве крайнего правого параметра.
Затем вы должны по существу позвонить (примечание: это вызывается через HAL_InitTick()
:
/*Configure the SysTick IRQ priority */
HAL_NVIC_SetPriority(SysTick_IRQn, 15 ,0U);
где 15
- приоритет тика SysTick. Поскольку у нас есть все 4 доступных бита, это дает нам диапазон приоритетов от 0 до 15, где 15 - это приоритет прерывания наименьший , а 0 - приоритет наивысший .
Ну, почему мы устанавливаем SysTick на низший приоритет? Ответ: потому что это хорошая практика для планировщика FreeRTOS, который вызывает прерывание SysTick. На самом деле, присвоение ему слишком высокого приоритета нарушит FreeRTOS, согласно их собственной документации. Попробуем это выяснить.
Мы знаем, что наши параметры прерывания теперь от 0 до 15 для параметра PreemptPriority
, но это даже уже: мы можем установить только нашу PreemptPriority для прерывания SysTick, равное 10 до 15 ( Я думаю - мне нужна помощь здесь). Почему с 10 до 15? Ну, документация FreeRTOS (хотя это очень запутанно) даже прямо заявляет:
Функции FreeRTOS, оканчивающиеся на «FromISR», безопасны от прерываний, но даже эти функции нельзя вызывать из прерываний, которые имеют логический приоритет выше [то есть: численно ниже] приоритет, определенный configMAX_SYSCALL_INTERRUPT_PRIORITY (configMAX_SYSCALL_INTERRUPT_PRIORITY определяется в FreeRR). заголовочный файл). Поэтому любая подпрограмма обработки прерываний, использующая функцию API-интерфейса RTOS, должна иметь свой приоритет, вручную установленный на значение, которое численно равно или больше, чем параметр configMAX_SYSCALL_INTERRUPT_PRIORITY. Это гарантирует, что логический приоритет прерывания равен или меньше значения параметра configMAX_SYSCALL_INTERRUPT_PRIORITY.
Теперь вернитесь к FreeRTOSConfig.h вверху этой страницы. Мы знаем, что __NVIC_PRIO_BITS
равно 4, и мы видим, что:
configMAX_SYSCALL_INTERRUPT_PRIORITY
- это (configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY << (8 - configPRIO_BITS))
, что означает 5 << (8 - 4) = decimal 80 = 0b01010000
.
Документация FreeRTOS дает некоторое ценное представление о причинах левого смещения (см. Раздел «Внутреннее представление приоритетов Cortex-M»), но я не могу разглядеть дальше.
Так что теперь, делая некоторые образованные предположения и зная, что у нас есть варианты приоритетов от 0 до 15, где 0 - наивысший, а 15 - наименьший, и зная, что configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY - 5, нам, возможно, разрешат использовать 15 - 5 = 10 в качестве наивысшего приоритета и 15 как низкое, или, может быть, от 5 до 15 - это нормально, но от 0 до 4 - запрещено? Я не знаю ... я в замешательстве ...