追日填海 发表于 2012-4-4 11:02:07

学习small RTOS51遇到的问题

准备学习RTOS,发现有个可以在51运行的small RTOS51。于是就买了陈明计写的书,看了几遍,里面有些问题不懂,请大侠帮忙解答,谢谢了!

Q1:第37页:“如果允许smallRTOS管理(EN_OS_IN_ENTER>0),则OSSched()先判定本身是否由中断调用。若中断嵌套层数OSIntNesting大于0,则OSSched()由中断调用,将不进行任务调度,函数直接返回”,OSSched()不是在任务中实现任务切换的吗,它又怎么会被中断调用呢?
Q2: 第39页:“为了做任务切换OS_TASK_SW(),人为的模仿了一次中断。” 在代码中是如何实现的?
   ;/*********************************************************************************************************
;** 函数名称: OSIntCtxSw
;** 功能描述: 中断使任务放弃CPU环境保存函数
;** 输 入: OSTaskID
;** 输 出 : 无
;** 全局变量: OSFastSwap
;** 调用模块: 无
;**
;** 作 者: 陈明计
;** 日 期: 2002年2月22日
;**-------------------------------------------------------------------------------------------------------
;** 修 改: 陈明计
;** 日 期: 2002年12月2日
;**-------------------------------------------------------------------------------------------------------
;** 修 改:
;** 日 期:
;**-------------------------------------------------------------------------------------------------------
;********************************************************************************************************/
        RSEG?PR?OSIntCtxSw?OS_CPU_A
OSIntCtxSw:
        USING        0
                                        ;是否是优先级最低任务
    MOV   A,#OS_MAX_TASKS
    XRL   A,OSTaskID
    JNZ   OSIntCtxSw_0
                                        ;是则不需要保存所有寄存器
;SP=SP-13-4                           ;4:两层函数调用堆栈,13:寄存器数目
    MOV   A,#(-17)
    ADD   A,SP
    MOV   SP,A
                                        ;跳转到OSCtxSw,同时通知CPU中断处理完成
    MOV          A, #LOWOSCtxSw
    PUSH    ACC
    MOV          A, #HIGH OSCtxSw
    PUSH    ACC
    RETI
                                        ;需要保存所有寄存器
OSIntCtxSw_0:
;SP=SP-4                              ;4:两层函数调用堆栈
    MOV   A,#0FCH
    ADD   A,SP
    MOV   SP,A
                                        ;设置标志:任务再次恢复运行时需要恢复所有寄存器
    MOV   DPTR,#OSMapTbl
    MOV   A,OSTaskID
#if OS_MAX_TASKS < 9
    MOVC    A,@A+DPTR
    CPL   A
    ANL   A,OSFastSwap
    MOV   OSFastSwap,A   
#else
    CLR   C
    SUBB    A,#8
    JC      OSIntCtxSw_1   
    MOVC    A,@A+DPTR
    CPL   A   
    ANL   A,OSFastSwap
    MOV   OSFastSwap,A
    SJMP    OSIntCtxSw_2
OSIntCtxSw_1:
    MOV   A,OSTaskID
    MOVC    A,@A+DPTR
    CPL   A   
    ANL   A,OSFastSwap+1
    MOV   OSFastSwap+1,A
OSIntCtxSw_2:
#endif
                                        ;跳转到堆栈处理,同时通知CPU中断处理完成
    MOV          A, #LOWC_OSCtxSw
    PUSH    ACC
    MOV          A, #HIGH C_OSCtxSw
    PUSH    ACC
    RETI
这里面最后的子程序返回为什么要使用中断返回指令RETI?

Q4:第42页:“在中断服务程序中调用OSIntExit()时将返回地址压入栈,OSIntExit()调用OSIntCtxSw()时候又将返回地址压入栈,这两个地址完全无用”,这两个地址为什么无用?

electrlife 发表于 2012-4-4 11:34:13

对于SmallRTOS51不看过,不了解,不过我可以从UCOS-II上回答LZ的几个问题:
Q1:第37页:“如果允许smallRTOS管理(EN_OS_IN_ENTER>0),则OSSched()先判定本身是否由中断调用。若中断嵌套层数OSIntNesting大于0,则OSSched()由中断调用,将不进行任务调度,函数直接返回”,OSSched()不是在任务中实现任务切换的吗,它又怎么会被中断调用呢?
R1:任务调度为任务级和中断级的,任务级的调度,OSSched()按道理说是不会出现在ISR中,我想书中的意思是不是说用户误用RTOSg一些调用,则会判断是否在中断中调用,增代码的健壮性。

Q2: 第39页:“为了做任务切换OS_TASK_SW(),人为的模仿了一次中断。” 在代码中是如何实现的?
R2:LZ贴的代码中并没看到任务级切换的源码,不过人为模仿一次中断并不难理解,对于51的中断流程建议LZ可以在编译中写个中断程序
使用编译自带的ISR关键字,比如IAR __interrupt等,然后查看其生成的汇编代码,看看生成除了自己的代码,编译还加入了哪些代码。中断子程序和一般的程序调用不同,一般程序调用使用比如LCALL指令会自动的返回地址入栈。但是中断子程序是没有这样调用来运行的,因此返回时不同于一般的的了程序调用使用RET返回,而使用RETI。当然这是51的做法也是大部分MCU做法,也有通过返回地地址来判断是中断返回还是了程序返回,比如ARMv7的CORTEX-M3。由于对于51的中断流程我也并不是很熟悉,一般也在使用编译器的关键字来解决,并没有深究其具体的流程。

Q4:第42页:“在中断服务程序中调用OSIntExit()时将返回地址压入栈,OSIntExit()调用OSIntCtxSw()时候又将返回地址压入栈,这两个地址完全无用”,这两个地址为什么无用?
R4:我想会不会是因为51的中断结构造成的,因为可以使用RETI返回中断的函数,因此返回的地址无用。当然这里假设是返回被中断的函数而没有发生任务调度。

不知以上的回复能不能帮到楼主!如有不对还请大家指出,大家一起交流学习!

追日填海 发表于 2012-4-4 18:39:34

谢谢了,学习了

追日填海 发表于 2012-4-4 20:44:44

Q5:第78页;small RTOS51在初始化一个信号量的时候,如果是作为二值信号就初始化为1,如果是这样的话那么第一次等待信号量的时候不是就已经有信号量了吗?不明白这是为什么,合理的情况不是“被控制方总是处于等待同步信号的状态”(《基于嵌入式实时操作系统的程序设计》p64)吗?

electrlife 发表于 2012-4-4 21:41:10

追日填海 发表于 2012-4-4 20:44 static/image/common/back.gif
Q5:第78页;small RTOS51在初始化一个信号量的时候,如果是作为二值信号就初始化为1,如果是这样的话那么第 ...

二值信号量一般作为互斥资源的访问,初始化当然得为1,不然这个资源就无法访问了!

ShawnLinson 发表于 2012-4-5 03:11:25

学习了,先前都是知其然而不知其所以然……

追日填海 发表于 2012-4-13 08:37:59

嗯,我明白了,谢谢
页: [1]
查看完整版本: 学习small RTOS51遇到的问题