HRTOS源码解析(一):从0实现51单片机协作式调度器,理解RTOS任务调度原理
2026/8/1 4:14:37 网站建设 项目流程

很多初学嵌入式的人第一次接触RTOS时,都会看到一些概念:

  • Task(任务)
  • Scheduler(调度器)
  • Ready List(就绪队列)
  • Tick(系统节拍)

但是这些概念到底是如何工作的?

如果直接阅读FreeRTOS等大型RTOS源码,会因为代码量太大而难以理解。

因此,本文通过一个简单的8051协作式调度器,分析RTOS最核心的运行机制。

本文代码来自HRTOS早期调度核心。

项目地址:

HRTOS官网:

HRTOS - Hard Real-Time Operating System | 硬实时操作系统


一、RTOS本质是什么?

很多人认为RTOS就是“同时运行多个程序”。

实际上,单片机通常只有一个CPU核心,同一时间只能执行一个任务。

RTOS做的事情其实是:

在不同任务之间快速切换,让多个任务看起来像同时运行。

例如:

任务1:LED闪烁 任务2:串口通信 任务3:按键检测

调度器负责决定:

下一次CPU应该运行哪个任务。


二、最简单的任务管理结构

HRTOS使用任务控制块(TCB)保存任务信息。

例如:

OS_TCB xdata os_task_table[OS_MAX_TASK];

任务表保存:

  • 任务ID
  • 任务入口地址
  • 等待时间
  • 任务状态

可以理解为:

任务表 +------------+ | Task 0 | +------------+ | Task 1 | +------------+ | Task 2 | +------------+

每个任务都有自己的管理信息。


三、就绪任务如何保存?

HRTOS使用位图管理任务状态:

unsigned int os_ready_bitmap;

例如:

bit: 0000 0111 表示: Task0 就绪 Task1 就绪 Task2 就绪 其他任务 未运行

相比遍历整个任务列表,位图方式更加适合资源有限的8051。


四、创建任务

任务创建函数:

char os_task_create( unsigned int addr, unsigned char id, unsigned char pr, unsigned char sd )

核心代码:

os_task_table[id].id=id; os_task_table[id].addr=addr; os_ready_bitmap|=(1 << (id));

这里完成三个动作:

  1. 保存任务入口地址
  2. 分配任务ID
  3. 加入就绪队列

例如:

创建LED任务:

os_task_create( LED_task, 1, 0, 0 );

系统之后就知道:

Task1在哪里,需要运行时跳转过去。


五、任务等待机制

RTOS中经常需要:

“等待一段时间后继续运行”。

例如:

LED每500ms翻转一次。

HRTOS:

os_wait(type,obj,tick);

核心:

os_task_table[os_current].wait_tick=tick; os_ready_bitmap &= (~(1 << os_current));

意思是:

当前任务进入等待状态。

同时:

从就绪列表中删除。

CPU可以运行其他任务。


六、系统节拍Tick如何唤醒任务?

8051定时器中断:

void wake_task() interrupt 1

每次中断:

检查所有任务:

if(os_task_table[i].wait_tick) { os_task_table[i].wait_tick--; if(os_task_table[i].wait_tick==0) { os_ready_bitmap|=(1<<i); } }

例如:

Task1等待5个tick:

tick5 ↓ tick4 ↓ tick3 ↓ tick2 ↓ tick1 ↓ 0 ↓ 重新加入就绪队列

这就是RTOS中的时间管理。


七、最核心的调度器

调度器:

void os_schedule()

它负责选择下一个任务。

核心逻辑:

for(i=os_current+1;i<OS_MAX_TASK;i++) { if(os_ready_bitmap&(1<<i)) { break; } }

简单来说:

从当前任务之后寻找下一个可运行任务。

例如:

当前:

Task0运行

就绪:

Task1 Task3

调度:

Task0 ↓ Task1 ↓ Task3 ↓ Task0

这就是最基本的轮询调度思想。


八、为什么这是协作式调度?

这个版本属于协作式调度。

特点:

任务主动让出CPU。

例如:

while(1) { LED(); os_wait(...); }

任务调用等待函数后:

CPU才会切换任务。

优点:

  • 实现简单
  • 代码量小
  • 非常适合学习RTOS原理

缺点:

如果某个任务:

while(1) { do_something(); }

一直占用CPU,不主动释放。

其他任务就无法运行。


九、从协作式到抢占式

现代RTOS通常采用抢占式调度。

区别:

协作式:

任务主动释放CPU Task A | wait() | Task B

抢占式:

定时器中断触发 Task A | 中断 | 调度器 | Task B

HRTOS后续版本在这个基础上增加了:

  • 优先级调度
  • 抢占式切换
  • 多级任务管理

十、总结

通过几十行核心代码,可以看到一个RTOS最基础的组成:

任务管理 | 任务状态 | 时间管理 | 调度器 | 任务切换

RTOS并不是神秘的软件。

它本质上就是:

管理多个任务,并决定CPU下一步执行谁。

对于8051这种资源有限的MCU,通过简单、高效的设计,同样可以实现实时任务管理。

更多HRTOS资料:

HRTOS - Hard Real-Time Operating System | 硬实时操作系统

https://hrtos.cn

欢迎交流8051、RTOS以及嵌入式系统开发。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询