Interrupt(中断触发)
SysTick 或外部中断进入内核调度入口,触发调度请求。 中断是调度流程的起点,决定了调度的时机和频率。
本页面描述 HRTOS 内核从中断触发到任务切换的完整调度链路, 覆盖中断、调度决策、上下文切换与任务恢复全过程。 调度流程决定 RTOS 实时性上限,是中断、任务与CPU切换的核心执行链路。
系统运行三个任务:task_a、task_b 与 task_c,每个任务独立控制一个 LED, 通过不同的延时参数展示调度器如何根据优先级和时间片进行任务切换。 验证 HRTOS 内核从中断触发到任务恢复的完整调度流程。
完整调度流程的核心组成
完整调度流程(Full Schedule Flow)是 HRTOS 内核实现多任务调度的核心机制, 描述从中断触发到任务恢复的完整执行链路。该流程确保任务在单一 CPU 上高效、可靠地并发执行。
SysTick 或外部中断进入内核调度入口,触发调度请求。 中断是调度流程的起点,决定了调度的时机和频率。
调度器评估就绪队列中的任务状态,根据优先级和时间片算法选择下一个执行任务。 调度决策是 RTOS 实时性的核心。
从就绪队列中选择最高优先级任务,确保高优先级任务优先获得 CPU 资源。 任务选择策略直接影响系统响应性。
保存当前任务上下文到任务栈,切换到目标任务栈。 上下文切换是任务并发执行的基础。
从目标任务栈恢复寄存器和程序计数器,任务继续执行。 恢复机制确保任务从中断点无缝继续。
五个环节环环相扣,形成完整的调度闭环。 每个环节的高效实现决定了 RTOS 的整体性能。
调度器如何做出任务切换决策
内核决策模型描述了 HRTOS 调度器在接收到调度请求后,如何评估系统状态并做出任务切换决策。 该模型综合考虑了中断上下文、就绪队列、任务优先级和切换条件等多个因素。
上下文来源:SysTick 定时器中断、外部中断
上下文保护:中断现场保存,确保调度安全
调度时机:中断服务程序中触发调度请求
实时性保障:中断响应时间决定系统实时性
队列管理:维护所有就绪任务的状态
优先级排序:按优先级组织任务队列
动态更新:任务状态变化时实时更新
查询效率:快速定位最高优先级任务
优先级范围:支持多级优先级配置
抢占策略:高优先级任务可抢占低优先级任务
时间片轮转:同优先级任务公平分配 CPU
优先级继承:防止优先级反转问题
时间片到期:当前任务时间片用完
任务让出:任务主动调用 os_delay 或 yield
高优先级就绪:更高优先级任务进入就绪态
中断事件:外部事件触发任务状态变化
从中断触发到任务恢复的完整路径
调度流程涉及的核心 API
功能:任务创建接口
作用:创建任务并加入就绪队列
参数:任务函数、任务ID、优先级、栈大小
返回:任务创建成功或失败状态
功能:触发调度请求
作用:通知调度器进行任务切换
调用时机:中断服务程序或任务让出时
执行方式:设置调度标志,延迟到安全时机执行
功能:进入临界区保护
作用:禁用中断,保护共享资源
使用场景:访问就绪队列等关键数据结构
配对调用:必须与 os_exit_critical 配对使用
功能:退出临界区
作用:恢复中断,结束临界区保护
使用场景:临界区操作完成后调用
调度检查:退出时检查是否需要触发调度
完整调度流程的示例实现
task_a、task_b 和 task_c 任务函数,分别控制不同的 LED, 通过不同的延时参数展示调度器行为
#include "hrtos.h"
sbit LED_A = P1^0;
sbit LED_B = P1^1;
sbit LED_C = P1^2;
static void task_a(void)
{
while(1)
{
LED_A = ~LED_A;
os_delay(5);
}
}
static void task_b(void)
{
while(1)
{
LED_B = ~LED_B;
os_delay(20);
}
}
static void task_c(void)
{
volatile u16 i;
while(1)
{
LED_C = ~LED_C;
for(i = 0; i < 3000; i++);
os_delay(50);
}
}
hrtos_main 函数,创建三个任务并启动调度系统
void hrtos_main(void)
{
LED_A = 0;
LED_B = 0;
LED_C = 0;
os_task_create((unsigned int)task_a, 1, 2, 5);
os_task_create((unsigned int)task_b, 2, 3, 5);
os_task_create((unsigned int)task_c, 3, 4, 5);
}
调度流程在 HRTOS 中的重要性
深入学习的相关资源