- 打卡等级:初来乍到
- 打卡总天数:1
- 最近打卡:2025-03-10 16:08:45
高级会员
- 积分
- 666
|
发表于 2024-7-19 16:14:36
|
显示全部楼层
本帖最后由 139182*** 于 2024-7-19 16:29 编辑
在写这个多任务的平台的过程中, 也加深对多任务在小资源CPU上的理解,
随笔记录, 版本针对8位平台,以后再拓展,至少目前8位平台成熟度性价比更好
Cx51不是标准C, 因为它尽可能少使用栈,从而节约硬件栈的使用(51 SP(IDATA <= 256 Bytes))
而多任务的现场决定每个任务运行栈都要是 存续 的, 任务切换出切换进, 任务本身不能有差异,因此,除了ALU和通用寄存器,最重要的是栈要存续。
51历史上20年前陈明计写了SmallRtos, 到最近版友Fanxsp写的TinyRtos, 以及CosyOS和UC/OSII的一些移植版本都让一个 idata空间只有256B的CPU能跑多任务
采用了主栈搬栈的做法,让活动任务占最大剩余空间,这是一个最合理的做法
但是搬栈也有不确定的工作量和时钟消耗,对于任务切换来说,这也是主要的开销之一,任务现场镜像ESI(STACK, Registers)如果不搬栈那么就会快很多
加上主动切换可以等同于函数调用(Cx51编译器保证LCALL之后的代码不会依赖之前的寄存器,所以可以看到SRC中只有interrupt中断代码有寄存器组缓存恢复的指令
后来我发现不止我在动这个脑子,其他版友也多有这个想法,只不过我用的不是单纯的8051, stc8h指令集中直接和间接访问data/idata几乎是一样快的
因此,只要管理好中断嵌入状态和中断代码对压栈的需求,任务栈并不会很大,只需要 2*(调用树+多极中断+NMI)就可以,
为了实现这个,我把中断ISR分成了ISV+ISH+IST三部分,ISV帮助ISH完成了通用的寄存器缓存恢复,IST则公用内核栈。具体过程以后慢慢写。
更重要的是,stc8h上xdata至少也有1k以上,任务内存需求大部分都可以搬到xdata中去
这样,除了0x2F之前的data, 后面除了用户节约下也必用的一点data, 其他都可以用作idata(stacks for tasks) 从 ?STACK开始到0xFF
因此,这就让各任务独立拥有栈成为可以,但是这又限制stc8h上任务数不可能太多,比如32bytes一个任务栈,系统栈64bytes, 一个stc8h最多也就3~5个任务
这也要求编写Q51任务代码的工程师要合并一些业务逻辑到3~5个任务中去
但是,这个限制如果放在edata>2k的32位251上,就不太成为制约。
总之,Q51这个多任务平台,采用不搬栈的方法,任务切换<1us成为了可能。
如果最后是nus, 那么n-1 us基本上是任务仲裁和执行统计的开销,如果采用简单的任务仲裁算法,1~2us的任务切换时间是有保障的
实现上,我发现由于不采用延迟中断切换的模式(ARM流行的PendSV异常状态切换)
任务主动切换的ESI是最小的,也是最快的
抢占切换的开销也没有想象的那么大,大致等同于一次中断处理,但不是在中断中切换。
相反,搞脑子最多的是把ISR分成 ISV+ISH+IST, 其中IST是中断中要处理的逻辑在任务态中执行的部分
虽然麻烦,但是因为缩短了中断时间,从而为硬件中断响应能力提供的保障。也算利大于弊
虽然,很慢很慢才接近于0.1完成,但是从中确实学到很多,原先不明白CPU演变的一些理由,也多了些理解,其实老外也是软硬件协同发展的
给自己加油。。。
参考了版友的不少代码,特别是TinyRTOS, 谢谢各位分享 |
|