任务优先级和中断优先级之间经常会出现混淆。中断优先级,即中断服务程序(ISR)相对于彼此执行的优先级。分配给任务的优先级与分配给中断的优先级没有任何关系。硬件决定ISR何时执行,而软件决定任务何时执行。响应硬件中断而执行的ISR将中断任务,但是任务无法抢占ISR。
支持中断嵌套的端口需要在FreeRTOSConfig.h中定义下表中详细说明的一个或两个常量,configMAX_SYSCALL_INTERRUPT_PRIORITY和configMAX_API_CALL_INTERRUPT_PRIORITY都定义相同的属性。较旧的FreeRTOS端口使用configMAX_SYSCALL_INTERRUPT_PRIORITY,较新的FreeRTOS端口使用configMAX_API_CALL_INTERRUPT_PRIORITY。
常量 | 描述 |
configMAX_SYSCALL_INTERRUPT_PRIORITY或configMAX_API_CALL_INTERRUPT_PRIORITY | 设置最高的中断优先级,从中可以调用中断安全的FreeRTOS API函数。 |
configKERNEL_INTERRUPT_PRIORITY | 设置滴答中断使用的中断优先级,并且必须始终将其设置为最低的中断优先级。
如果正在使用的FreeRTOS端口也未使用configMAX_SYSCALL_INTERRUPT_PRIORITY 常量,那么使用中断安全的FreeRTOS API函数的任何中断也必须以由定义的优先级执行 configKERNEL_INTERRUPT_PRIORITY。 |
每个中断源都有一个数字优先级和一个逻辑优先级:
1. 数值优先级
数字优先级只是分配给中断优先级的数字。例如,如果将中断的优先级分配为7,则其数字优先级为7。同样,如果将中断的优先级分配为200,则其数字优先级为200。
2. 逻辑优先级
中断的逻辑优先级描述了该中断相对于其他中断的优先级。
如果两个优先级不同的中断同时发生,则处理器将为两个中断中优先级较高的中断执行ISR,然后再为两个中断中较低优先级的中断执行ISR。
中断可以中断(嵌套)具有较低逻辑优先级的任何中断,但是中断不能中断(嵌套)具有相同或更高逻辑优先级的任何中断。
中断的数字优先级和逻辑优先级之间的关系取决于处理器体系结构。在某些处理器上,分配给中断的数字优先级越高,则中断的逻辑优先级越高;而在其他处理器体系结构上,分配给中断的数字优先级越高,则中断的逻辑优先级就越低。
通过将configMAX_SYSCALL_INTERRUPT_PRIORITY设置为比configKERNEL_INTERRUPT_PRIORITY更高的逻辑中断优先级,可以创建完整的中断嵌套模型,下图显示该模型。
- 处理器具有七个独特的中断优先级
- 数值越大,其逻辑优先级越高
- configKERNEL_INTERRUPT_PRIORITY设置为1
- configMAX_SYSCALL_INTERRUPT_PRIORITY设置为3
1. 当内核或应用程序位于关键部分内时,将阻止执行使用优先级1至3(包括1和3)的中断。以这些优先级运行的ISR可以使用中断安全的FreeRTOS API函数。。
2.使用优先级4或更高优先级的中断不受关键部分的影响,因此调度程序所做的任何事情都不会阻止这些中断立即执行-在硬件本身的限制内。以这些优先级执行的ISR不能使用任何FreeRTOS API函数。
3.通常,要求非常严格的定时精度的功能(例如,电动机控制)将使用高于configMAX_SYSCALL_INTERRUPT_PRIORITY的优先级,以确保调度程序不会在中断响应时间中引入抖动。
对于ARM Cortex-M 和ARM GIC
Cortex-M处理器上的中断配置令人困惑,并且容易出错。在开发过程中,可以通过FreeRTOS Cortex-M端口会自动检查中断配置,但前提是已定义configASSERT()。
ARM Cortex内核和ARM通用中断控制器(GIC)使用低优先级数字表示逻辑上高优先级的中断。这似乎违反直觉,并且很容易忘记。如果希望将中断分配为逻辑低优先级,则必须为其分配较高的数值。如果希望将中断分配为逻辑高优先级,则必须为其分配较低的数值。
Cortex-M中断控制器最多允许使用八位来指定每个中断优先级,使255为最低可能的优先级。零是最高优先级。但是,Cortex-M微控制器通常仅实现八个可能位的子集。实际实现的位数取决于微控制器系列。
#define __NVIC_PRIO_BITS 2 /*!< Number of Bits used for Priority Levels
当仅实现了八个可能位的子集时,仅可以使用字节的最高有效位,而使最低有效位未实现。未实现的位可以取任何值,但是将它们设置为1是正常的。下图显示了二进制文件101的优先级如何存储在实现四个优先级位的Cortex-M微控制器中。
在上图中,因为未实现最低有效的四位,所以二进制值101已移入最高有效的四位。未实现的位已设置为1。
1.有的库函数是在将优先级值上移至已实现(最高有效)位后指定优先级值。当使用这种功能时,可以将上图所示的优先级指定为十进制95。十进制95是二进制101向上移四以形成二进制101nnnn(其中“ n”是未实现的位),并且未实现的位设置为1制作二进制1011111。
2.有些库函数是在将优先级值上移到已实现(最高有效)位之前指定优先级值。当使用这种功能时,必须将上图所示的优先级指定为十进制5。十进制5是二进制101,无任何移位。
configMAX_SYSCALL_INTERRUPT_PRIORITY和configKERNEL_INTERRUPT_PRIORITY必须以允许将它们直接写入Cortex-M寄存器的方式指定,以便在将优先级值上移至实现的位之后。configKERNEL_INTERRUPT_PRIORITY必须始终设置为最低的中断优先级。可以将未实现的优先级位设置为1,因此无论实际实现了多少个优先级位,常量都可以始终设置为255。
NOTE:Cortex-M中断的默认优先级为零,即最高优先级。Cortex-M硬件的实现不允许将configMAX_SYSCALL_INTERRUPT_PRIORITY设置为0,因此使用FreeRTOS API的中断的优先级绝不能保持其默认值。