FreeRTOS: ISR(中断服务例程)和 TCB(任务控制块)
在讨论 ISR(中断服务例程)和 TCB(任务控制块,Task Control Block)时,我们实际上是在探讨 FreeRTOS 中两个不同但又相互关联的概念:一个是用于处理硬件或软件触发的中断事件,另一个是操作系统用来管理任务的核心数据结构。下面我将详细解释这两个概念及其关系。
1. ISR (Interrupt Service Routine)
定义
- ISR 是一段专门编写的小型程序代码,用来处理特定类型的中断请求。当中断发生时,CPU 暂停当前执行的任务,转而执行相应的 ISR 来响应这个中断。ISR 必须快速完成其工作,以确保其他更高优先级的中断能够及时得到响应。
特点
- 高优先级:ISR 比普通任务具有更高的优先级。
- 非抢占性:在一个 ISR 执行期间,不会被另一个 ISR 或者普通任务所抢占,除非新来的中断源设置了更高的优先级。
- 简短高效:ISR 应尽可能快地完成,因为长时间运行的 ISR 可能会影响系统的实时性能和响应速度。
- 不能阻塞:ISR 内部不允许调用任何可能导致阻塞的操作(如
vTaskDelay()
),因为这会导致整个系统陷入死锁状态。
在 FreeRTOS 中使用 ISR
- 发送消息给队列:可以使用
xQueueSendFromISR()
函数将数据发送到队列,但要注意避免阻塞。 - 唤醒任务:可以通过
xSemaphoreGiveFromISR()
或xTaskResumeFromISR()
唤醒等待的任务,同样要避免阻塞。 - 检查是否需要上下文切换:某些 ISR 函数有一个参数指向一个布尔变量,如果该变量被设为
pdTRUE
,则表明有更高优先级的任务被唤醒,可能需要进行上下文切换。这时应该调用portYIELD_FROM_ISR()
来实现这一点。
2. TCB (Task Control Block)
定义
- TCB 是 FreeRTOS 内核用于管理每个任务的数据结构。它包含了任务的所有信息,包括但不限于:
- 任务状态:如就绪、运行、阻塞等。
- 任务堆栈指针:保存任务的寄存器状态和局部变量。
- 任务优先级:定义了任务相对于其他任务的执行顺序。
- 任务句柄:唯一标识符,用于从应用程序中引用任务。
- 任务延时计数器:用于定时阻塞任务。
- 消息队列:如果任务使用了队列,则包含相关队列的信息。
功能
- 任务调度:FreeRTOS 使用 TCB 中的状态信息来决定哪个任务应该获得 CPU 时间片。
- 内存管理:每个 TCB 都有自己的堆栈空间,用于存储任务执行期间的临时数据。
- 同步与通信:通过 TCB,任务可以访问和操作共享资源,如信号量、队列等,从而实现任务间的同步和通信。
ISR 和 TCB 的关系
尽管 ISR 和 TCB 分别代表了不同的概念,但在实际应用中它们之间存在一定的交互:
-
从中断上下文唤醒任务:当 ISR 处理完中断后,它可能会改变某个任务的状态(例如通过信号量或队列)。此时,ISR 可以通知 FreeRTOS 内核有关任务状态的变化,并可能触发一次上下文切换,让被唤醒的任务立即开始执行。这种情况下,ISR 会更新相关的 TCB,特别是那些涉及任务状态转换的部分。
-
任务创建与删除:虽然 ISR 不直接参与任务的创建或删除过程,但它可以在运行时影响哪些任务处于活动状态。例如,ISR 可能会向队列发送数据,导致原本处于阻塞状态的任务变得可运行,进而改变了这些任务对应的 TCB 状态。
-
上下文切换:当 ISR 结束时,如果检测到有更高优先级的任务被唤醒,则会触发一次上下文切换。这意味着当前正在执行的任务会被挂起,而新的最高优先级任务将接管 CPU。这一过程中,FreeRTOS 内核会根据各个任务的 TCB 来确定下一个要执行的任务,并相应地调整 CPU 上下文。