FreeRTOS中断优先级,临界区的配置(特别重要)

本文详细介绍了FreeRTOS在ARM-CM3内核上的中断优先级配置方案,包括内核优先级、系统调用优先级及任务优先级的具体设置与含义。并通过实例解释了这些配置如何影响中断处理及任务调度。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一 背景

网上有许多关于FreeRTOS中断优先级的配置资料,但是在v10.0中个别配置项发生了变化,在这篇文章中详细的介绍了整个优先级管理配置方案。
ARM芯片的优先级为0~255,不同的芯片厂商所用的优先级不同,并不是全部使用,这里以ARM Cortex-M3系列为例。CM3内核的优先级分组如下:


这里写图片描述

为了更方便管理中断优先级,ST官方建议并且默认使用第5分组:NVIC_PriorityGroup_4,其优先级寄存器为8位寄存器,CM3只使用了高4位,构成0~15共16个优先级,如下图:


这里写图片描述

在stm32f2xx.h文件中,通过__NVIC_PRIO_BITS定义了CM3内核优先级使用高四位,有如下代码:

/**
 * @brief Configuration of the Cortex-M3 Processor and Core Peripherals 
 */
#define __CM3_REV                 0x0200  /*!< Core Revision r2p0                            */
#define __MPU_PRESENT             1       /*!< STM32F2XX provides an MPU                     */
#define __NVIC_PRIO_BITS          4       /*!< STM32F2XX uses 4 Bits for the Priority Levels */
#define __Vendor_SysTickConfig    0       /*!< Set to 1 if different SysTick Config is used  */

二 FreeRTOS优先级配置(重要)

在FreeRTOSConfig.h中有三个配置项,负责优先级的管理:

  1. #define configKERNEL_INTERRUPT_PRIORITY 255 //配置内核使用的中断优先级,这里是8 bit,默认最低优先级
  2. #define configMAX_SYSCALL_INTERRUPT_PRIORITY 95 /**配置系统所能调用管理的最高优先级,95转为十六进制是0x5F,最高优先级是5,优先级0-4不归系统管理**/
  3. #define configLIBRARY_KERNEL_INTERRUPT_PRIORITY 15 /*配置系统内核优先级,这里使用的是4bit优先级,所以最低为15,跟1 中的配置相同*/

以上的配置在ARM-CM3内核中的具体释义为:FreeRTOS操作系统内核使用最低优先级,操作系统所能调用管理的最高优先级为5~15级。
我举了两个例子具体解释这个配置的含义,图1 是官方在手册中给出的例子,在这里,优先级1最低,优先级7为最高。如果分别配置 configMAX_SYSCALL_INTERRUPT_PRIORITY=3,且configKERNEL_INTERRUPT_PRIORITY=1,则优先级处于1~3的中断受到操作系统内核的影响和管理,在临界区可以被屏蔽等;优先级4~7的中断则不受操作系统影响,但是中断中绝不可以使用系统API函数(在不受系统管理的优先级中使用操作系统的函数可能会导致时序混乱,发生异常等)。
图 2 是以ARM-CM3内核,例如STM32F2xx和STM32F1系列单片机中,该内核使用4bit 优先级,优先级0最高,优先级15最低。如果设定 configMAX_SYSCALL_INTERRUPT_PRIORITY=111(0x6F),且configKERNEL_INTERRUPT_PRIORITY=255(0xFF),则0-5的优先级不受系统管理,同时也不可以调用系统的API函数;优先级6-15的中断受到系统的管理,可以使用API函数(结尾带有FromISR的函数),同时可能受到内核延时的影响,因为操作系统的临界区可以暂时屏蔽全局中断,导致中断发生时不能及时的相应,需等到退出临界区后方可执行。


FreeRTOS官方的例子
图1 FreeRTOS官方的例子


CM内核的ARM优先级
图2 CM内核的ARM优先级

三 FreeRTOS任务优先级

FreeRTOS的任务优先级配置为系统专有,与硬件无关,只负责操作系统中多个任务之间调度顺序。任务优先级的个数由FreeRTOSConfig.h中的#define configMAX_PRIORITIES ( 16 ),任务优先级0为最低,16为最高。这里简单的说一下,由于操作系统任务调度中使用的查找前导零的汇编(CLZ)指令,效率高,所以建议设定的最大任务优先级数量不超过32。

  1. 配置#define configUSE_PORT_OPTIMISED_TASK_SELECTION 1,开启前导零方式,前提是内核支持CLZ指令,百度一下。
  2. 配置#define configMAX_PRIORITIES ( 16 ),使用16个优先级数量。内核默认使用0级,最低优先级,空闲任务。
  3. 配置#define configIDLE_SHOULD_YIELD 0,仅影响空闲优先级任务,使处于空闲优先级(0级)的任务获的相同的CPU时间。

四 问题总结

临界区问题

任务名任务A任务B
优先级12
临界区有,耗时2s
阻塞时间10ms20ms
运行结果一直运行执行一次

原因分析:由于阻塞使用vTaskDelay(),在临界区时,该函数处于屏蔽状态,不计入阻塞周期,所以当任务A的阻塞时间为任务B的一半时,任务A执行两次的阻塞时间才可以使任务B进入就绪状态,进而在任务A退出临界区时切换到高优先级的任务B。

任务名任务A任务B
优先级12
临界区
阻塞时间10ms20ms
运行结果一直运行一直运行

当关闭临界区时,高优先级的任务可以正常抢占低优先级任务A。

### FreeRTOS 中的任务优先级中断优先级关系 在嵌入式系统开发中,FreeRTOS 提供了一种灵活的方式来管理任务和中断之间的交互。理解这两者的优先级设置对于构建高效可靠的实时操作系统至关重要。 #### 任务优先级配置 FreeRTOS允许开发者通过`vTaskPrioritySet()`函数来调整特定任务的执行顺序[^2]: ```c void vTaskPrioritySet(TaskHandle_t xTask, UBaseType_t uxNewPriority); ``` 此函数接收两个参数:一个是目标任务的手柄(可以是任何已创建的任务),另一个是要分配给该任务的新优先级别数值。较高数值表示更高的优先权,意味着这些高优先生命周期内的活动会先于低级别的被执行。 #### 中断优先级划分 针对ARM Cortex-M系列微控制器而言,NVIC (Nested Vectored Interrupt Controller) 支持多达16个可编程的不同敏感度等级(0至15),其中较低编号代表更紧急的情况。当运行FreeRTOS时,并不是所有的这16层都由内核直接掌控;通常情况下只有部分范围被保留下来专门服务于RTOS本身的操作需求——例如从5到15之间可能专属于RTOS内部机制所用,而低于这个阈值的部分则留给应用程序自由支配[^1]。 这意味着如果应用代码试图利用像`taskENTER_CRITICAL()`这样的API关闭全局中断,则实际上只会影响那些处于或高于预设界限以上的事件响应行为,而对于更低层次上的硬件异常依旧保持开放状态。 #### 实际操作指南 为了确保系统的稳定性和效率,在规划项目架构之初就应该仔细考虑如何合理安排各个组件的重要性次序以及它们相互作用的方式。下面是一些实践建议: - **定义清晰的任务结构**:根据功能模块化原则建立多个独立运作单元,并赋予各自适当的重要程度标签; - **谨慎选择临界区保护手段**:考虑到不同类型的锁定策略会对整体性能造成影响,务必评估各种选项的成本效益比后再做决定; - **遵循最佳实践指导方针**:查阅官方文档或其他权威资料获取更多关于优化调度算法、减少上下文切换开销等方面的知识点。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值