touch_avr 发表于 2010-2-13 22:47:11

ucos堆栈疑问

调用中断切换函数OSIntCtxSw()而不调用任务切换函数OS_TASK_SW(),有两个原因,
首先是,如程序清单中L3.5(1)和图F3.6(1)所示,一半的工作,即CPU 寄存器入栈的工作
已经做完了。第二个原因是,在中断服务子程序中调用OSIntExit()时,将返回地址推入了
堆栈。OSIntExit()中的进入临界段函数OS_ENTER_CRITICAL()或许将
CPU 的状态字也推入了堆栈L3.7(1)和F3.6(3)。这取决于中断是怎么被关掉的(见第8 章
移植μC/OS-Ⅱ)。最后,调用OSIntCtxSw()时的返回地址又被推入了堆栈[L3.17(4)和
F3.1(4)],除了栈中不相关的部分,当任务挂起时,栈结构应该与μC/OS-Ⅱ所规定的完全
一致。OSIntCtxSw()只需要对栈指针做简单的调整,如图F3.6(5)所示。换句话说,调整栈
结构要保证所有挂起任务的栈结构看起来是一样的

“在中断服务子程序中调用OSIntExit()时,将返回地址推入了堆栈”是什么意思?

aaa1982 发表于 2010-2-14 01:18:39

第一个原因比较容易明白,就是防止重复入栈(因为进入中断的时候已经入栈了)。邵贝贝教授的书也好像只提到了这一点。对于一些特殊的平台,比如cortex-m3,因为中断系统引入了很多新的特点,比如咬尾巴。所以导致OSCtxSw和OSIntCtxSw已经没有区别了,下面是zlg提供的基于cortex-m3移植范例,可以看出OSCtxSw和OSIntCtxSw的代码是完全一样的。

OSCtxSw
      PUSH    {R4, R5}
                LDR   R4, =NVIC_INT_CTRL                                    ;trigger the PendSV exception
                                                                        ;触发软件中断
      LDR   R5, =NVIC_PENDSVSET
      STR   R5,
                POP   {R4, R5}
      BX      LR


;*********************************************************************************************************
;** Function name:                        OSIntCtxSw
;** Descriptions:                  called by OSIntExit() when it determines a context switch is needed as the
;**                         result of an interrupt.
;**                         中断级任务切换               
;** Input parameters:          None 无
;** Output parameters:          None 无
;** Returned value:                        None 无
;** Created by:                                Steven Zhou 周绍刚
;** Created Date:                  2007.01.18
;**-------------------------------------------------------------------------------------------------------
;** Modified by:            Ni Likao 倪力考
;** Modified date:          2007.11.02
;**-------------------------------------------------------------------------------------------------------
;*********************************************************************************************************
OSIntCtxSw
      PUSH    {R4, R5}
                LDR   R4, =NVIC_INT_CTRL                                    ;trigger the PendSV exception
                                                                        ;触发软件中断
      LDR   R5, =NVIC_PENDSVSET
      STR   R5,
                POP   {R4, R5}
      BX      LR
      NOP

第二个原因感觉有点牵强,可能是我没理解透彻,呵呵


“在中断服务子程序中调用OSIntExit()时,将返回地址推入了堆栈”

是不是可以这么理解,因为OSIntExit()是被中断函数调用的,所以编译器根据C语言函数调用的实际情况生成了一个入栈操作,入栈的寄存器会在OSIntExit()函数返回的时候出栈。


引发了一个问题用C语言的写的程序,在函数调用的时候需不需要出入栈操作应该是编译器决定的吧?

感谢各位高手指点一下。

aaa1982

touch_avr 发表于 2010-2-14 09:58:31

引发了一个问题用C语言的写的程序,在函数调用的时候需不需要出入栈操作应该是编译器决定的吧?

我觉得是,原因如下,我以前调试过代码跟踪函数参数是如何传递的,发现编译器把R0当做参数传进来的位置,所以你嵌汇编就可以直接从R0拿参数,如果有冲突的话,你就得压栈了
页: [1]
查看完整版本: ucos堆栈疑问