移植uCOS-II到C51 - 3

来源:互联网 发布:物流配送软件 编辑:程序博客网 时间:2024/05/16 03:42

昨天,修改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()也容易理解了,明天继续。 

原创粉丝点击