您的位置:首页 > 其它

移植uCOS-II到C51 - 3

2007-10-15 21:23 309 查看
昨天,修改SW的移植版本到自己平台的企图以失败告终。今天,看了一个稍微简单些的版本,来自John X.Liu。之所以说简单,是因为我至少看到了熟悉的reg52.h,还有,连SW也说他的移植是在Liu的基础上做的。搞了一天,对这个咚咚又了解了多一些。
吸取昨天匆忙上阵急于求成的教训,今天决定从简单的情况入手,看看调用OSStart()以后,第一个用户任务是如何开始执行的。可以看到这样的调用顺序:OSStart() -> OSStartHighRdy() -> LoadCtx()。我能想象到LoadCtx()的工作,就是从任务模拟栈恢复通用寄存器、PSW、SP等内容,最终还要让PC指向任务的入口。可是去看代码就看不明白了,满眼望去都是一些宏定义,还冒出来一个"hardware stack"。这是什么东西啊?又去翻C51的指令集参考和KeilC的宏汇编语法,终于感觉不那么迷茫了。"hardware stack"也在A51.pdf P104找到了答案:"The x51 architecture uses a hardware stack to store return addresses for CALL instructions and also for temporary storage using the PUSH and POP instructions."这个硬件栈当然是必要的,CALL的时候总是需要把CALL的下一条指令地址压栈,当从CALL返回时又把压栈的内容弹出到PC,不然程序不就跑飞了么?要搞清现场是怎样从模拟栈恢复的,先看模拟栈的结构。这个结构在OSTaskStkInit()函数中看得很清楚:
项 字节数 说明
offset 1 模拟栈的栈顶,其内容指向硬件栈的栈顶
EA 1 初值为0x80,即开中断
R7
| 4
R4
vd 3 R1-R3
R0 1
PSW 1
DPL 1
DPH 1
B 1
A 1
task 2
task 2
C51默认使用寄存器传递函数参数,当然如果参数太多导致寄存器不够用还是要用到其他内存。这里情况比较简单,因为每个任务都只有一个参数void* vd,这种情况下参数是通过R1-R3传递的。所以,在计算offset的时候,就把vd看作R1-R3了。
好,现在再回过头来看LoadCtx()的代码,得到硬件栈的结构,也就是上面蓝色的部分。LoadCtx()先把模拟栈中的内容搬到硬件栈,此时,SP指向硬件栈的栈顶。然后是一系列的POP指令,让硬件栈中的内容各归其位,执行RET时,SP正好指向task,于是,任务的入口被写入PC,任务开始执行了,真tm不容易啊!
弄清了这些,OSCtxSW()也容易理解了,明天继续。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: