在了解了一些关于中断优先级的知识后,我仍然有点困惑,不知道可以在SysTick_IRQn
(每1毫秒调用FreeRTOS调度程序的ISR)上调用哪些值来使用HAL_NVIC_SetPriority()
。
简而言之;
我认为在configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY
在FreeRTOSConfig.h中设置为5的情况下,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)
(相当高)之间的任何值都是允许的。混淆的原因在于,在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位优先级级别"。
首先,这很有趣,因为这意味着只有8个可用的优先级位中的4个实际上被使用了!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。
如果您正在使用带有STM32驱动程序库的STM32,则在启动RTOS之前调用NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);以确保所有优先级位都被分配为抢占优先级位。
因此,在您的代码中应该首先执行以下操作(至少在通过osKernelStart()
或vTaskStartScheduler()
启动FreeRTOS调度程序之前):
/* 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。让我们尝试理解一下这个问题。
我们现在知道,PreemptPriority
设置的中断选项是0到15,但甚至比这还要窄:我们只能将SysTick中断的PreemptPriority设置为10到15(我想——我需要一些帮助)。为什么是10到15?嗯,FreeRTOS文档(尽管这非常令人困惑)甚至明确说明:
现在,请参考本页顶部的FreeRTOSConfig.h。我们知道__NVIC_PRIO_BITS为4,并且我们看到:
configMAX_SYSCALL_INTERRUPT_PRIORITY是(configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY << (8 - configPRIO_BITS)),这意味着它是5 << (8 - 4) = 十进制80 = 0b01010000。
FreeRTOS文档提供了一些有价值的见解,解释了左移的原因(请参阅标题为“Cortex-M Internal Priority Representation”的部分),但我无法理解更多内容。
现在做出一些合理的猜测,我们知道我们的优先级选项是0到15,其中0是最高的,15是最低的,而且我们知道configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY是5,那么我们或许可以使用15-5=10作为最高优先级,15作为最低优先级,或者5到15也可以,但0到4是禁止的?我不知道...我很困惑...