实现原理可以拆成三步:
1. 硬件定时:芯片内部的 SysTick 定时器被设置成每 10 ms 产生一次中断。
2. 中断触发:一旦中断到来,CPU 暂停当前任务,进入中断服务程序。
3. 调度决策:中断服务程序递减系统节拍计数,检查是否有更高优先级任务就绪;若有则触发上下文切换,把 CPU 交给最高优先级任务;若无则继续运行当前任务。
这样,SysTick 每 10 ms “敲”一次,调度器就每 10 ms “看”一次要不要换任务,从而实现 10 ms 的调度周期。
在 FreeRTOS 里,节拍计数的递减由系统自动完成,无需用户手动写“减 1”代码。具体流程如下:
1. SysTick 定时器按配置好的周期(如 10 ms)产生中断。
2. 进入中断后,内核会调用 xTaskIncrementTick() ,该函数把全局变量 xTickCount 加 1,相当于“递增”系统节拍。
3. 加完后立即检查:是否有任务因等待的节拍数已到而解除阻塞;若存在更高优先级任务就绪,则触发 PendSV 异常进行上下文切换。
因此,节拍计数的“递减”实际上是逻辑上的:每个任务内部维护自己还需等待的节拍数,每次系统节拍中断到来时,该值减 1;当减到 0 时,任务被唤醒。用户只需配置好 SysTick 中断频率,其余工作由 FreeRTOS 内核完成。
FreeRTOS 用“阻塞列表 + 剩余计数”两步完成任务等待节拍的管理:
1. 阻塞时登记
当任务调用 vTaskDelay(n) 或等待队列/信号量超时,内核把该任务插入 阻塞列表(xDelayedTaskList),并把 n 保存在任务控制块的 xTicksToWait 字段。
2. 中断里递减
每次 SysTick 中断触发,内核遍历阻塞列表,把每个任务的 xTicksToWait 减 1。
减到 0 时,任务被移出阻塞列表,放入就绪列表,等待调度。
3. 唤醒与重置
一旦任务被唤醒(超时或事件提前发生), xTicksToWait 被清零;若再次调用延时 API,流程从第 1 步重新开始。
这样,每个任务只需在自己的控制块里保留一个“剩余节拍”计数,内核在每次节拍中断里统一递减即可。