摘要:本文解析了FreeRTOS中ISR(中断服务函数)与Task(任务)的关键区别,指出ISR具有硬件触发、非调度管理、不可阻塞和执行时间短四大特征。重点阐述了信号量类型SemaphoreHandle_t的实现复用原理,特别强调互斥量因拥有者机制和优先级继承特性而禁止在ISR中使用。最后总结ISR的正确使用方式应是快速通知任务,并明确FromISR系列API仅适用于二值/计数信号量,不适用于互斥量。全文用简洁的技术语言揭示了RTOS中中断处理的三大核心原则。
目录
[一、 ISR 是啥?](#一、 ISR 是啥?)
[二、 Task 是啥?](#二、 Task 是啥?)
[三、为什么 FreeRTOS 里它们都叫 SemaphoreHandle_t?](#三、为什么 FreeRTOS 里它们都叫 SemaphoreHandle_t?)
[五、 那为啥你又看到 FromISR 版本原因只有一个:API 是"信号量家族通用接口"](#五、 那为啥你又看到 FromISR 版本原因只有一个:API 是“信号量家族通用接口”)
[六、那 ISR 里到底该干啥? ISR 正确三件套(记死)](#六、那 ISR 里到底该干啥? ISR 正确三件套(记死))
一、 ISR 是啥?
ISR = Interrupt Service Routine(中断服务函数)
》它不是任务(Task)
特征只有 4 条,你记住就够:
- 由硬件触发(定时器、串口、GPIO、中断)
- 不属于调度器管理
- 不能阻塞、不能延时
- 执行时间必须极短
ISR 的职责:"快进快出,通知任务干活"
二、 Task 是啥?
Task(任务) 是 RTOS 管理的执行单元:
- 有优先级
- 能阻塞 / 延时
- 能拿互斥量
- 能被调度
ISR ≠ Task
三、为什么 FreeRTOS 里它们都叫 SemaphoreHandle_t**?**
这是 实现层的复用,不是语义一样。
|-------------|----------|---------------|-------------|
| 类型 | 本质用途 | 是否有 owner | ISR 能用吗 |
| 二值信号量 | 通知 | 错 | 对 |
| 计数信号量 | 计数 / 资源 | 错 | 对 |
| 互斥量 (Mutex) | 资源保护 | 对 | 错 |
互斥量 ≠ 普通信号量
互斥量为什么"不能在 ISR 用"?
因为互斥量有 两样 ISR 根本不具备的东西:
1)拥有者(Owner)
- 互斥量必须记录:哪个 Task 拿着
- ISR 不是 Task
- ISR 不能成为 owner
2)优先级继承
- 低优先级任务拿着 mutex
- 高优先级任务等 mutex
- 内核会 临时提升低优先级任务
ISR 没优先级、没 TCB 继承机制没法玩
所以结论是硬性的:
互斥量禁止在 ISR 中使用
五、 那为啥你又看到 FromISR 版本原因只有一个:API 是"信号量家族通用接口"
xSemaphoreGiveFromISR()
这个函数是:
给"可以在 ISR 使用的信号量"准备的
包括:
- 二值信号量
- 计数信号量
不包括:
- 互斥量
关键点(一定记住)
"能编译 ≠ 能用"
SemaphoreHandle_t xMutex;
xSemaphoreGiveFromISR(xMutex, &xHPWoken); // 逻辑错误
类型没错
编译能过
语义是错的
debug 版可能直接 assert
六、那 ISR 里到底该干啥? ISR 正确三件套(记死)
ISR 里只干一件事:
通知任务
常用方式:
|--------|------------|
| 方式 | ISR 支持 |
| 二值信号量 | 对 |
| 计数信号量 | 对 |
| 队列 | 对 |
| 任务通知 | 对(最快) |
| 互斥量 | 错 |
七、三句话终极总结
ISR 不是任务,不能阻塞、不能拿互斥量
互斥量有 owner 和优先级继承,ISR 不具备
FromISR 函数只适用于二值/计数信号量,不适用于互斥量