fengyuganyu 发表于 2011-1-3 22:28:11

ucosii移植新手发问:ucosii移植到ARM为什么要切换模式?

问一个很菜的问题,为什么在UCOS移植到ARM上时,在中断处理时为什么要切换模式?(在S32440上测试的)
   问题:1、在ARM上,当进入中断后不是只需保存{R0-R12,PC}吗?,为什么还要切换模式的保存过去有保存过来,不是R0_R12在除了FIQ模式下都是向通的
            吗?
         2、在ARM中断里面,在调用OSIntCtxSw时,我们不是可以直接把中断模式下把进入中断时的PC保存了,进而直接在调用OSIntCtxSw时,把调用   
            OSIntCtxSw当做退出中断的PC(退出中断时直接跳到OSIntCtxSw,把开始保存的那个中断的PC入栈,再保存到OSTCBCur中),这样可以吗?

请大家帮忙分析这个代码可以吗:
                        sub lr,lr,#4                ; 计算中断返回地址
                        stmfd sp!,{r0-r3,r12,lr}        ; 保护现场,此时处于中断模式下,sp指向中断模式下的堆栈       
                        BL OSIntEnter                                        
                        bl C_IRQHandler                ; 调用c语言的中断处理程序
                        bl OSIntExit                ; 判断中断后是否有更高优先级的任务进入就绪而需要进行任务切换
                        ldr r0,=OS_IntCtxSwFlag        ; if(OSIntCtxSwFlag == 1) OSIntCtxSw()
                        ldr r1,
                        cmp r1,#1                                       
                        beq OSIntCtxSw                ; 有更高优先级的任务进入了就绪状态,则跳转到OSIntCtxSw进行中断级的任务切换
                        ldmfd sp!,{r0-r3,r12,pc}^        ; 不进行任务切换,出栈返回被中断的任务。
OS_IntCtxSw                                        ; 把中断的返回地址保存到Int_ReturnAddr变量中
                        ldr r0,=OS_IntCtxSwFlag
                        mov r1,#0
                        str r1,                ; OSIntCtxSwFlag = 0
                       
                        add sp,sp,#20                ; 调整SP,使之指向之前入栈的lr(中断模式下的lr保存的是中断返回地址),
                        ldr r0,                                       
                        ldr r1,=Int_ReturnAddr          ; 将中断返回地址赋值给Int_ReturnAddr      
                        str r0,                ;保存中断退出的地址                               
                        ldr r0,=OS_TASK_SW_INT                       
                        str r0,                ; 保存中断任务执行的地址,即把进入中断的断点地址更新
                        sub sp,sp,#20                ; 调整SP回到栈顶
                        ldmfd sp!,{r0-r3,r12,pc}^        ; 退出中断后跳到OS_TASK_SW_INT而不返回中断前运行的程序
OS_TASK_SW_INT                                                                               
                              sub sp,sp,#4                ; 为PC保留位置
                        stmfd sp!,{r0-r12,lr}                ; r0-r12,lr入栈
                        ldr r0,=Int_ReturnAddr          ; 取出进入中断之前保存的PC
                        ldr r0,                                       
                        add sp,sp,#56                ; 调整SP 到堆栈格式的保存PC的位置
                        stmfd sp,{r0}                ; PC入栈 ,把进入中断时断点地址给保存起来,为下面的保存当前任务控制块做准备
                        sub sp,sp,#56                ; 调整SP回到栈顶
                        b        PUSH_CPSR       


PUSH_CPSR                       
                        mrs r4,cpsr
                        stmfd sp!,{r4}                                ; cpsr入栈       

                             BLOSTaskSwHook               
SaveCurTcb                                             
             
                        ldr r1,=OSPrioCur               ;更新当前的运行任务的优先级ID号
                        ldr r2,=OSPrioHighRdy
                        ldrb r3,
                        strb r3,
                       
                       

                        ldr r4,=OSTCBCur                  ; 取出当前任务的TCB地址
                                   ldr r5,                                        ;
                                   str sp,               ; 保存当前任务的堆顶指针到它的TCB的堆栈指针上       

       
                        ldr r1,=OSTCBCur               ;更新指向当前任务控制块指针的指向
                        ldr r2,=OSTCBHighRdy
                        ldr r2,
                        str r2,       

GetHighTcb                                                       
             
               

                        ldr r6,=OSTCBHighRdy        ; 取出更高优先级就绪任务的TCB的地址
                                   ldr r6,
                        ldr sp,               ; 取出更高优先级任务的堆顶指针到SP                
                        b   POP_ALL                                        ; 根据设定的栈结构顺序出栈       

POP_ALL                       
                               ldmfd sp!,{r4}            ; cpsr出栈
                               msr CPSR_cxsf,r4       
                        ldmfd sp!,{r0-r12,lr,pc}    ; r0-r12,lr,pc出栈

以上就是一个中断级任务切换的汇编代码,请问这个可行吗?我认为可行,但是为什么移植UCOS时老是出问题,这里我没有用到模式切换,我的程序运行在管理模式下,没有用系统模式。

请前辈解答下!这个代码是不是有错?...

luo496724812 发表于 2011-1-4 12:57:59

没研究过,中断中切换模式可能是为了支持中断嵌套
页: [1]
查看完整版本: ucosii移植新手发问:ucosii移植到ARM为什么要切换模式?