FreeRTOS 任务上下文 vs 中断上下文
简介
中断上下文用于快速响应硬件事件且不可阻塞,任务上下文由调度器管理可执行复杂逻辑并允许阻塞等待资源。
中断上下文 Interrupt Context
定义
- CPU 正在响应硬件中断(IRQ / FIQ / Exception)
- 执行的是 中断服务程序(ISR, Interrupt Service Routine)
- 当前不属于任何任务/线程
特点
- 非任务执行环境
- 不隶属于调度器管理的任务
- 没有 task control block(TCB)概念
- 独立栈
- 使用中断栈(或 MSP,具体与架构/RTOS 实现相关)
- 通常为共享栈,空间有限
- 不可阻塞
- 不能 sleep
- 不能等待锁、信号量、队列等会导致阻塞的操作
- 执行时间要求严格
- 中断必须尽快返回
- 长时间 ISR 会导致:
- 丢中断
- 系统实时性下降
- 任务调度延迟
- 可抢占任务上下文
- 硬件中断可以随时打断正在运行的任务
- ISR 执行完成后,可能触发一次调度
可/不可调用的函数
❌ 一般禁止在中断上下文中调用
- 会阻塞或可能阻塞的函数
- 会触发调度的函数
- 非 ISR-safe 的库函数
典型包括:
sleep()malloc() / free()(除非有专用 ISR 版本)printf()(慢 + 可能用锁)mutex_lock()xQueueReceive()(阻塞版)
RTOS 提供的 ISR 专用接口
RTOS 通常提供 FromISR 版本 API,例如(以 FreeRTOS 为例):
xQueueSendFromISRxSemaphoreGiveFromISRxEventGroupSetBitsFromISR
这些 API 的特点:
- 不阻塞
- 不直接触发上下文切换
- 通过标志在 ISR 结束后请求调度
典型用途
- 读取/清除硬件中断源
- 保存少量状态
- 向任务发信号(事件、信号量、消息)
- 触发 deferred work(延后处理)
常见问题与风险
- ISR 里做复杂逻辑 → 实时性下降
- ISR 里使用大局部变量 → 中断栈溢出
- ISR 里调用非 ISR-safe API → 系统不稳定或死锁
任务上下文 Task Context
定义
- CPU 正在执行调度器管理的任务/线程
- 属于某个具体任务(Task / Thread / Process)
特点
- 完整运行环境
- 拥有独立的任务栈
- 有任务控制块(TCB)
- 受调度器管理
- 可被中断抢占
- 可被高优先级任务抢占
- 允许阻塞
- 可以等待时间
- 可以等待资源
- 执行时间相对自由
- 允许执行较复杂逻辑
- 不要求“立即返回”
可调用的操作
- 阻塞式 API
- 动态内存管理(取决于系统策略)
- 同步原语
- 大部分标准库函数(依平台而定)
例如:
sleep()malloc() / free()mutex_lock()xQueueReceive()printf()
典型用途
- 协议栈处理
- 算法计算
- 业务逻辑
- 状态机
- 与其他任务协作
中断上下文 vs 任务上下文 对比
| 对比项 | 中断上下文 | 任务上下文 | | ---------------- | ------------------------ | ---------- | | 触发方式 | 硬件中断 | 调度器调度 | | 当前是否属于任务 | 否 | 是 | | 栈 | 中断栈(共享/受限) | 任务私有栈 | | 是否可被中断 | 可能被更高优先级中断打断 | 可被中断 | | 是否允许阻塞 | ❌ 不允许 | ✅ 允许 | | 是否允许触发调度 | ❌(直接) | ✅ | | API 使用限制 | 只能使用 ISR-safe API | 基本无限制 | | 适合执行的工作 | 快速、最小化 | 复杂、耗时 |