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 为例):

  • xQueueSendFromISR
  • xSemaphoreGiveFromISR
  • xEventGroupSetBitsFromISR

这些 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 | 基本无限制 | | 适合执行的工作 | 快速、最小化 | 复杂、耗时 |

卡片 ID: process-context-vs-interrupt-context