interrupt-management
2025-09-07 19:40:59
中断注意事项
在FreeRTOS中,任务程序由内核调度器统一调度和执行,程序的运行情况在一定程度上是稳定可预测的;中断相对而言是由外部环境决定是不可预测的,会对系统引入不确定性,如果使用不当的话会导致系统的失效和不稳定。
对中断的使用要根据实际需求和使用场景来决定,通过合理的配置和与FreeRTOS的中断管理(Interrupt Management)配合可以达到系统的高效能和高稳定性。
FreeRTOS中断管理
在FreeRTOS中中断的优先级和任务的优先级是有区别的,中断拥有更高的权限。
- 任务的优先级是由用户设置内核管理器管理的软件特性(software feature),与操作系统所在的硬件平台无关。
- 中断的优先级是由硬件平台相关的硬件特性(hardware feature),在中断代码运行的时候任务的代码将无法运行。即使是拥有最小优先级的中断也会打断拥有最高优先级的任务。
FreeRTOS对于一些系统API函数提供两种版本,一种是供任务调用的,一种是供中断调用的(Interrupt Safe API)。由中断调用的API函数后缀上会有“FromISR”。
当在普通任务中调用FreeRTOS的API函数(如xQueueSend()、xSemaphoreGive()等)时:如果configUSE_PREEMPTION设置为1(抢占式调度),并且调用API后有更高优先级的任务变为就绪状态,调度器会自动立即切换到那个更高优先级的任务。
当在中断处理时调用特殊的"FromISR"版本的API(如xQueueSendFromISR()、xSemaphoreGiveFromISR()等),如果有更高级别的任务进入就绪态,系统不会在中断处理函数结束后自动切换任务。而是需要手动根据"FromISR"版本函数的一个自带参数pxHigherPriorityTaskWoken参数的值,调用portTIELD_FROM_ISR(pxHigherPriorityTaskWoken)来手动决定是否切换任务。
- 如果API的调用导致更高级别任务进入就绪态,
pxHigherPriorityTaskWoken参数会被设为pdTRUE
1 | // 中断处理函数 |
延迟中断处理
延迟中断处理是一种设计模式:
- 最小化的中断服务程序(ISR):只做必要的紧急处理
- 专门的高优先级任务:处理剩余的中断相关工作
优点:
- 缩短中断响应时间:ISR应尽可能短,减少中断禁用时间
- 提高系统响应性:复杂处理放在任务中,不阻塞其他中断
- 简化代码:在任务中可以使用所有FreeRTOS API,而不仅限于FromISR版本
- 优先级控制:通过任务优先级控制中断处理的优先顺序
- 便于调试:任务比ISR更容易调试
1 | // 中断服务程序 - 硬件直接调用 |
工作流程:
- 硬件中断触发,进入InterruptHandling()函数
- ISR只做简单的记录和清除标志工作
- ISR调用portYIELD_FROM_ISR(pdTRUE)强制任务切换
- 调度器选择最高优先级的就绪任务
- 如果中断处理任务vInterruptHandling()是最高优先级,它会立即执行
- 中断处理任务分析并处理中断数据
一般还会搭配信号量,队列等机制来避免一直处于高优先级就绪态,阻塞其他任务执行。
1 | void vInterruptHandlingTask(void *pvParameters) |