首页 文章

使用STM32和FreeRTOS时,`HAL_NVIC_SetPriority()`的有效值是多少?

提问于
浏览
0

在学习了一些关于中断优先级的相当困难的过程之后,我仍然有点卡住试图理解我在 SysTick_IRQn (每隔1 ms调用FreeRTOS调度程序的ISR)上允许调用 HAL_NVIC_SetPriority() 的值 .

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) (相当高一点)之间的任何事情 . 这假设FreeRTOSConfig.h中的 configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY 设置为5.令人困惑的是,在FreeRTOS中,更高的数字是更高的优先级,但在STM32中,更高的数字是更低的优先级,并且文档很难理解 .


详情:

为了证明我目前的理解 . 我将以这样的方式写出我所知道的真实描述,即使我正在寻找上述问题的答案,以及 correctionconfirmationadditional insight 如你所愿 .

虽然这可能适用于许多STM32微控制器或系列,但我们将特别针对_1595208进行讨论 .

注意:STM32CubeF2 download is here .

我的理解:

如果您查看标准 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) )

自"STM32F2XX uses 4 Bits for the Priority Levels"以来, __NVIC_PRIO_BITS 在STM32Cube_FW_F2_V1.7.0 / Drivers / CMSIS / Device / ST / STM32F2xx / Include / stm32f217xx.h中定义为 4U .

首先,这很有趣,因为它意味着实际使用的8个优先级位中只有4个! STM32 HAL库调用 HAL_NVIC_SetPriority() 有一个如下所示的 Headers ,似乎表明你有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 .
enter image description here

FreeRTOS says in their documentation

如果将STM32与STM32驱动程序库一起使用,则通过调用NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4)确保将所有优先级位分配为抢占优先级位;在RTOS启动之前 .

所以,你应该在你的代码中做的第一件事(至少在通过 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 tick优先级 . 由于我们有4位可用,因此优先级为0到15,其中15为最低中断优先级,0为最高优先级 .

那么,为什么我们将SysTick设置为最低优先级?答:因为这是SysTick中断调用的FreeRTOS调度程序的一个好习惯 . 事实上,根据他们自己的文档,给予它太高的优先权将打破FreeRTOS . 让我们试着弄明白 .

我们知道 PreemptPriority 设置的中断选项现在为0到15,但它甚至比那更窄:我们只能将SysTick中断的PreemptPriority设置为 10 to 15 (我想 - 我需要一些帮助) . 为什么10到15?嗯,FreeRTOS documentation(虽然这是超级混乱)甚至明确指出:

以“FromISR”结尾的FreeRTOS函数是中断安全的,但即使这些函数也无法从具有以上逻辑优先级的中断调用[即:数字下降]由configMAX_SYSCALL_INTERRUPT_PRIORITY定义的优先级(在FreeRTOSConfig.h头文件中定义了configMAX_SYSCALL_INTERRUPT_PRIORITY ) . 因此,任何使用RTOS API函数的中断服务程序都必须将其优先级手动设置为数值等于或大于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文档提供了有关左移原因的一些有 Value 的见解(参见 Headers 为“Cortex-M内部优先级表示”的部分),但除此之外我无法辨别 .

所以现在进行一些有根据的猜测并知道我们的优先级选项为0到15,其中0为最高,15为最低,并且知道configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY为5,我们可能允许使用15 - 5 = 10作为最高优先级,15作为最低优先级,或者5到15可以,但0到4是禁区?我不知道......我很困惑......

1 回答

  • 1

    首先,不要将FreeRTOS任务优先级与NVIC优先级混淆 . 它们完全不同 .

    在上面的示例中,如果进行FreeRTOS API调用,则可以使用5到15的中断优先级作为中断 . 如果他们不进行FreeRTOS API调用,那么您可以使用0到15之间的任何优先级的中断 .

    不要担心移位,因为它全部由你处理,但原因是使用了优先级寄存器的前4位(注意一些处理器使用不同数量的优先级位) .

相关问题