FreeRTOS中断管理
中断是MCU硬件特性,STM32由NVIC(嵌套向量中断控制器)管理硬件中断。以STM32F4为例,通过4位优先级分组配置中断的抢占优先级(数字越小优先级越高,决定中断嵌套)和子优先级(同抢占优先级时决定响应顺序)。每个中断对应一个中断服务例程(ISR),用于响应中断事件。
在启动freertos后,会自动对中断进行一些设置

在CubeMX配置FreeRTOS的“config”参数时需关注以下两个中断相关参数
configLIBRARY_LOWEST_INTERRUPT_PRIORITY:
表示系统中断的最低优先级数值。由于采用4位抢占优先级分组,该参数固定为 15(4位二进制最大值为15)
configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY:
表示FreeRTOS可管理的中断最高优先级,默认值为 5。其核心作用是:
- 仅当中断优先级 ≥ 5 时,中断服务程序(ISR)中才能调用FreeRTOS的中断安全API(即带
FromISR后缀的函数,如taskDISABLE_INTERRUPTS()); - 该参数绝不能设为0,且高优先级(>5)的中断ISR中禁止调用任何FreeRTOS API(包括中断安全函数)。
这里具体还是看书吧
中断安全API
中断安全API是FreeRTOS专门为中断服务程序(ISR)设计的特殊函数(通常带FromISR后缀,如taskDISABLE_INTERRUPTS_FromISR()、xQueueSendFromISR())。
普通API(如vTaskDelay()、xQueueSend()):只能在任务上下文(即任务函数内部)调用。若在中断里用,会直接操作调度器状态、访问共享资源(如任务队列),导致调度器崩溃或数据错乱。
中断安全API:内部做了中断上下文同步(比如先关闭中断再操作、用原子指令),确保在中断里调用也不会破坏FreeRTOS的内核状态。例如:
taskDISABLE_INTERRUPTS_FromISR():安全关闭中断(避免嵌套关闭导致中断永远无法开启);xQueueReceiveFromISR():安全从队列取数据(避免中断与任务争夺队列资源)。
FreeRTOS可屏蔽的中断
这里的“可屏蔽”不是指硬件上的NMI(不可屏蔽中断),而是FreeRTOS通过优先级管理,允许用户控制“哪些中断可以安全调用FreeRTOS API”。
PendSV是“可悬起中断”:若PendSV已挂起,SysTick中断到来时会先处理SysTick,之后再处理PendSV——这不会影响任务切换结果,因为两者都是最低优先级,不会干扰高优先级任务的执行。顺序不影响调度的正确性
中断服务例程ISR
只要有ISR在运行,就无法进行任务调度
不管任务的优先级有多高,最低的中断例程也能抢占
如果一个 ISR 执行的时间比较长,任务函数无法及时执行,FreeRTOS 也无法进行任务调度,就会导致软件响应变迟钝。
在实际的软件设计中,一般要尽量简化 ISR 的功能,使其尽量少占用 CPU 的时间。一般的硬件中断都是处理一些数据的接收或发送工作,例如,采用中断方式进行 ADC 数据采集时,只需在 ADC 的中断里将数据读取到缓冲区,而对数据进行滤波、频谱计算等耗时间的工作,就转移到任务函数里处理。
中断频闭和临界代码段
中断屏蔽
taskDISABLE_INTERRUPTS():屏蔽 MCU 的部分中断(不是全部!比如优先级为 0 的高优先级中断可能无法被屏蔽,具体看硬件)。大于等于5
taskENABLE_INTERRUPTS():解除中断屏蔽
临界代码段(内置嵌套计数器,一个加加一个减减)
taskENTER_CRITICAL():进入临界段
taskEXIT_CRITICAL():退出临界段
ISR(中断服务函数)专用的临界段宏(因为普通临界段宏不能在中断里直接调用,会引发重入或逻辑冲突):
taskENTER_CRITICAL_FROM_ISR():中断版本的“进入临界段”,内部调用
taskEXIT_CRITICAL_FROM_ISR(x):中断版本的“退出临界段”
ISR临界段的核心目的:保护ISR内部的原子性,即要么全执行,要么不执行,不会出现中间状态被干扰
当代码在ISR的临界代码段内执行的时候。此时出现更高级的中断时,需要对比BASEPRI的值,也就是所能屏蔽的最屌中断
两种版本的API函数
一种在任务中使用,一种在ISR中使用,可单向混用
设计原则
根据参数 configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY的设置,MCU(微控制单元)优先级为 0 到 15 的中断,会被划分为 FreeRTOS 不可屏蔽中断和 可屏蔽中断两类。需依据中断的“重要性”与“功能”,为其分配合适的中断优先级,以明确该中断属于“FreeRTOS 不可屏蔽中断”或“可屏蔽中断”。
ISR 的代码应尽量简洁精炼,需把耗时较长的处理逻辑转移到“任务函数”中实现(避免 ISR 执行过久阻塞系统调度)
中断调用规则:
- 若为可屏蔽中断的 ISR,仅能调用「中断级」的 FreeRTOS API 函数;绝对禁止调用「普通级」的 FreeRTOS API 函数。
- 若为不可屏蔽中断的 ISR,禁止调用任何 FreeRTOS API 函数。
代码示例
在临界代码段或者taskdisable_interrupts里,不能调用vtaskdelay等触发任务调度的函数,否则会直接打开中断(反正严禁调用就行)

