在使用STM32和FreeRTOS时,`HAL_NVIC_SetPriority()`的有效值是什么? [英] What are valid values of `HAL_NVIC_SetPriority()` when using STM32 and FreeRTOS?

查看:15
本文介绍了在使用STM32和FreeRTOS时,`HAL_NVIC_SetPriority()`的有效值是什么?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在经历了一个相当困难的学习中断优先级的过程之后,我仍然试图理解允许我在SysTick_IRQn(ISR每1ms调用一次FreeRTOS调度程序)上调用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中,数字越大优先级越低,文档很难理解。


详细信息:

为了证明我做出了英勇的努力,并帮助你们帮助我填补空白,以下是我目前的理解。我将以一种看起来像正在教导的方式来描述我知道是正确的内容,即使我正在寻求上述问题的答案,以及您认为合适的更正确认其他见解

虽然这可能适用于许多STM32微控制器或系列,但让我们特别从STM32F207ZG的角度来讨论它。

注意: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) )
__NVIC_PRIO_BITSSTM32Cube_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。

FreeRTOS says in their documentation

如果您将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设置为最低优先级?答:因为这对于SysTick中断调用的FreeRTOS调度程序来说是一个很好的实践。事实上,根据他们自己的文档,给它太高的优先级会破坏自由实时操作系统。让我们试着弄清楚这一点。

我们知道PreemptPriority设置的中断选项现在是0到15,但它甚至更窄:我们只能将SysTick中断的PreemptPriority设置为10到15(我认为--我这里需要一些帮助)。为什么是10到15个?嗯,FreeRTOS documentation(尽管这非常令人困惑)甚至明确表示:

以"FromISR"结尾的FreeRTOS函数是中断安全的,但即使是这些函数也不能从逻辑优先级高于配置MAX_SYSCALL_INTERRUPT_PRIORITY定义的优先级[例如:数字上低于]的中断中调用(配置MAX_SYSCALL_INTERRUPT_PRIORITY在FreeRTOSConfig.h头文件中定义)。因此,使用RTOS API函数的任何中断服务例程必须手动将其优先级设置为等于或大于配置MAX_SYSCALL_INTERRUPT_PRIORITY设置的数值。这可确保中断的逻辑优先级等于或小于配置MAX_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是禁止的?我不知道...我很困惑...

推荐答案

首先,不要将免费实时操作系统任务优先级与NVIC优先级混淆。它们是完全不同的。

在上面的示例中,如果您的中断进行了FreeRTOS API调用,您可以对中断使用5到15的中断优先级。如果它们不进行FreeRTOS API调用,则您可以使用从0到15的任何优先级的中断。

不要担心移位,因为这都是为您处理的,但原因是使用了优先级寄存器的前4位(请注意,某些处理器使用不同数量的优先级位)。

这篇关于在使用STM32和FreeRTOS时,`HAL_NVIC_SetPriority()`的有效值是什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆