当前位置: 首页 > java >正文

freeRTOS中断中为什么不能进行任务切换2

FreeRTOS 不能在中断服务程序 (ISR) 中直接进行任务切换,主要基于以下核心原因:

  1. 破坏中断上下文与原子性‌:

    • 中断是异步事件,随时可能打断任何任务或低优先级中断的执行512。
    • 在 ISR 内部直接切换任务,会破坏当前被中断任务的完整上下文(寄存器、堆栈等)。当 ISR 返回时,系统无法正确恢复到被中断的任务状态,导致不可预测的错误(如数据损坏、崩溃)。(个人理解是进入ISR中断之前,要利用MSP保护上下文,那么如果ISR里面进行任务切换,任务切换时也要利用MSP对任务上下文进行切换,而freeRTOS的对MSP的保存机制,跟ISR对MSP的保存机制可能不同,很有可能会造成错乱)
    • 任务切换本身需要保存当前任务上下文并加载新任务上下文,这需要原子操作以保证状态的一致性。在中断嵌套环境下保证这种原子性极其复杂且容易出错。
  2. 堆栈管理冲突‌:

    • 任务有自己的独立堆栈空间,用于保存局部变量和函数调用上下文5。
    • ISR 执行时使用的堆栈取决于硬件架构和配置:
      • 在 ARM Cortex-M 等平台上,ISR 通常使用主堆栈指针 (MSP) 指向的独立中断堆栈(或共享堆栈)。
      • 任务则使用进程堆栈指针 (PSP) 指向其私有堆栈。
    • 直接在 ISR 中进行任务切换,涉及到从 MSP 环境切换到 PSP 环境以及操作任务的私有堆栈,这会破坏 FreeRTOS 的堆栈管理模型,极易导致堆栈溢出或数据错乱
  3. 抢占时机与实时性破坏‌:

    • 中断服务程序需要尽快执行完毕并返回,以保证系统的实时响应能力。
    • 任务切换是一个相对耗时的操作(保存/恢复大量寄存器、更新内核数据结构)12。在 ISR 内部进行切换会显著延长中断处理时间,阻塞更高优先级中断的响应,破坏系统的实时性保证。
  4. 临界区保护失效‌:

    • FreeRTOS 内核内部操作(如调度器、队列、信号量操作)需要在临界区(关中断或使用调度器锁)内进行,以保证数据结构的完整性。
    • 直接在 ISR 中进行任务切换,可能在内核状态不一致时强行切换,破坏临界区保护机制,导致内核数据结构损坏。
  5. FreeRTOS 的解决方案:延迟切换 (PendSV)‌:

    • FreeRTOS 采用一种安全的、延迟的任务切换机制来解决上述问题。
    • 当需要在中途进行任务切换时(例如在 SysTick 中断或调用 taskYIELD() 的 API 中):
      • 并不会立即切换任务。
      • 而是通过软件触发一个 ‌PendSV (可挂起系统调用) 异常‌,并将其优先级设置为‌最低‌。
    • 当前中断(即使是 SysTick 中断)服务程序完成后,在退出所有中断嵌套之后,系统才会执行 PendSV 异常服务程序。
    • 在 PendSV 异常服务程序(此时系统处于一个稳定的、无中断嵌套的状态)中才会执行‌真正的任务上下文切换‌(保存旧任务上下文、恢复新任务上下文)。
    • 这种方式确保了:
      • 所有中断都能得到及时响应。
      • 任务切换在安全的、非中断上下文中进行。
      • 被中断任务的上下文得到完整保存。
      • 内核数据结构操作的原子性得到保护。

总结‌:FreeRTOS 禁止在中断中直接进行任务切换,是为了保护被中断任务的上下文完整性、维护正确的堆栈管理、保证系统的实时响应能力以及确保内核操作的原子性。它通过将切换请求标记(触发 PendSV 异常)并在最低优先级的 PendSV 中断服务中执行实际切换操作来实现安全可靠的任务调度。用户应使用 FreeRTOS 提供的 xQueueSendFromISR()xSemaphoreGiveFromISR() 等带 FromISR 后缀的 API,这些 API 在需要时内部会安全地触发 PendSV 请求,而不是直接切换任务。

http://www.xdnf.cn/news/12280.html

相关文章:

  • 基于红黑树的插入功能,对Set和Map部分功能进行封装实现
  • 打造智慧医疗枢纽,香港维尔利引领东南亚健康科技升级
  • 八:操作系统设备管理之RAID
  • STM32 智能小车项目 两路红外循迹模块原理与实战应用详解
  • HTV 3.3 | 秒播无卡顿 直播源每天维护更新
  • Q: 数据库增删改查的逻辑如何实现?
  • 996引擎-自定义装备/道具:限时装备、限时道具
  • 如何通过requests和time模块限制爬虫请求速率?
  • 算法题(162):火烧赤壁
  • React状态管理Context API + useReducer
  • Flyway
  • vue3+js示例
  • delphi7 链表 使用方法
  • 基于STM32单片机的电子秤系统设计(原理图+PCB+程序+仿真+文章)
  • SpringCloud——OpenFeign
  • web第十次课后作业--Mybatis的增删改查
  • 微服务架构——配置管理与配置中心
  • 【Java】RxJava解析
  • 麒麟信安系统下修改系统默认记录日志大小
  • 上传、下载功能 巧实现
  • 如何修改项目在浏览器中的小图标
  • 【MATLAB去噪算法】基于CEEMDAN联合小波阈值去噪算法(第四期)
  • 轨道交通可视化,赋能智慧车站运维
  • C++034(一维数组)
  • 基于WSL搭建Ubnutu 20.04.6 LTS(二)-部署Docker环境
  • LoRA:大模型高效微调的低秩之道——原理解析与技术实现
  • 检测到 #include 错误。请更新 includePath。已为此翻译单元(D:\软件\vscode\test.c)禁用波形曲线
  • 力扣面试150题--被围绕的区域
  • std__map,std__unordered_map,protobuf__map之间的性能比较
  • 网页显示:嗯…无法访问此页面,的解决办法和原理