RL78G13移植BasicOS
2026/7/23 23:34:55 网站建设 项目流程

BasicOS

狗哥出品,基于“共享栈”的协作式调度内核;BasicOS
一切都是为了用“RTOS的任务”的形式写MCU任务;【可以,但是必要不大】
任务切换时需要处理任务栈,有别于ProtoThread的Superloop(唯一栈)本质;

有栈协程 and 无栈协程

无栈协程

对比

  • 有栈协程 (BasicOS)
    每个任务配备独立私有栈,切换时完整保存所有通用寄存器、栈指针 SP、程序断点 PC 与函数局部变量;
    可在任意嵌套函数内暂停 / 恢复,运行时动态记录断点位置,进出点不固定。

  • 无栈假协程 (ProtoThread,while(1)循环)
    ProtoThread基于编译期静态状态机实现(语法糖,),仅用 1 个状态变量(line 行号)记录执行分支;
    while(1)循环的内部函数可通过轮询状态机的形式实现假并发(软件定时器的并发);
    不保存寄存器、PC、局部变量(使用全局变量保存变量持续化的数据),所有暂停 / 恢复分支地址编译时固定;
    资源开销最小。
    轮流执行,round-robin执行方式,前后顺序就是优先级;
    内部可使用状态机实现进入点和退出点的有限控制;

  • 无栈真协程 (ctx)
    无独立任务栈,共用全局主栈;
    使用语法糖的形式保证了局部变量的持续化;
    不是通过轮询的形式来;
    仅在全局内存保存 PC 断点与少量核心寄存器,无法在嵌套子函数中 yield;?
    运行时动态记录断点地址,进出点不固定,RAM 占用极低。?

大佬总结
大佬的糖

协作式调度

大家文明排队,轮到你就一直跑,
只有当你自己说 “我好了,可以换人”,调度器才能换下一个;
没人能强制把你赶下来。

CPU 使用权只能由任务主动释放,内核不会强行剥夺

高优先级任务无法打断正在运行的任务;
只有当前运行任务主动让出 CPU,调度器才有机会切换其他就绪任务。

任务一旦拿到 CPU,会持续运行直到:

  • 主动调用 yield() / 任务切换接口; 【suspend】
  • 主动阻塞(延时、等待信号量、等待消息); 【blocked】
  • 任务执行完毕退出。

调度时机完全受控于任务代码,中断不会引发任务上下文切换

中断可以标记任务就绪,但中断返回后一定回到被打断的原任务,不会立刻切任务;
真正切换必须等到任务主动让出。
不需要复杂的临界区保护(相比抢占式)
不存在 “任务在任意指令中间被打断”,只要不在共享资源访问中间调用 yield,天然不会出现任务并发争抢破坏数据。

各线程是线性执行,不存在各线程间的资源共享;

中断都在任务栈中

不像freertos一进入中断就切换到中断栈;
因为freertos在中断中可能会调度任务;

共享栈的情况,中断都在任务栈中处理;没有独立中断栈

风险

共享资源要“一次性”处理

没有一次性处理完“共享资源”

不要苛求系统实时性

1.【考验程序设计】如果一个任务长时间运算、迟迟不 yield,外部事件对应的任务迟迟得不到调度。
例如按键检测任务需要 10ms 响应,但是后台运算任务连续运行几百毫秒不释放 CPU,按键响应严重滞后。
长时间循环内部必须周期性插入 yield,防止独占 CPU;
2.中断里“唤醒”高优先级任务【任务已经到了就绪时候】,但是当前正在运行的任务不肯 yield,新就绪任务只能==“礼貌”==排队等待。
实时需求强的场景很难满足。
3.TaskA(低优先级)正在运行
TaskB(高优先级)已经就绪
只要 TaskA 不主动 yield,高优先级 B 一直无法调度。
即使 B 事件紧急,也必须等 A 自愿放手。

只有yeild没有delay:导致任务一有空就运行,cpu没得歇

yield() 的定位:主动临时让出 CPU,不进入阻塞;任务保持「就绪态」
delay / 延时(sleep):让出 CPU + 进入「阻塞等待态」,到期才重新就绪

饥饿问题?

任务1 优先级高
任务2 3 优先级低一些且一致;
当任务2好了之后,任务1立马就绪,
有没有可能到值任务3是始终无法执行

高优先级任务空闲时必须进入阻塞态(block),而不是挂起态(suspend)

固定时间片-任务环 Round-Robin

运行固定时间后,强制切换上下文;

共享栈

栈大小动态调整:将有限的栈空间给正在运行的线程使用;其他栈保持最小尺寸;
缺点:增加栈空间调整的处理;
优点:省资源;用时间换空间;

export

把一个任务的“配置部分”和“实时数据”部分 分开

任务数据内容存储位置
配置部分任务入口、任务优先级、任务名称、参数地址;const rom段
实时数据任务栈指针、任务栈地址、栈大小、超时时间;ram

将"配置部分"部分使用magic_word包裹;
实现初始化动态判断任务个数;
并定义“内核任务”,作为整个任务的链表头,用于比遍历;

对比其他export 使用段的形式,定义该段数据统一处理方法
并使用段开始标记和段结束标记,集中判断;

移植

初始化栈

保存寄存器:PS PSW AX BC DE HL CS

BRK中断

上下文保存

入栈push寄存器
“栈空间的调整”
出栈pop寄存器

栈空间的调整


注意往前拷贝和往后拷贝有区别;

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

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

立即咨询