fengyuganyu 发表于 2011-1-2 01:40:01

ucos 移植到2440上出问题,请帮忙分析下

我到目前为止的不良情况就一个:就是,当我所有任务按顺序执行完后,就进入空闲模式,但是当第二次任务就绪,在中断级任务切换时,就出现问题了。
                              当我的任务切换回主程序运行后再进入空闲任务,此时的空闲任务的断点就被指向了boot的复位向量,相当于程序跑飞了,                        请各位分析下,是什么情况

汇编调度的代码如下:
SRCPND           EQU0x4a000000    ; Source pending
INTPND           EQU0x4a000010    ; Interrupt request status

rEINTPEND   EQU0x560000a8
INTOFFSET   EQU0x4a000014


USERMODE    EQU         0x10
FIQMODE   EQU         0x11
IRQMODE   EQU         0x12
SVCMODE   EQU         0x13
ABORTMODE   EQU         0x17
UNDEFMODE   EQU         0x1b
MODEMASK    EQU         0x1f
NOINT       EQU         0xc0


;*********************************************************************************************************
;                                    EXPORT and EXTERNAL REFERENCES
;*********************************************************************************************************/
        IMPORTOSRunning
        IMPORTOSTCBCur
        IMPORTOSTCBHighRdy
        IMPORTOSPrioCur
        IMPORTOSPrioHighRdy
        IMPORTOSIntNesting
        IMPORTOS_IntCtxSwFlag
        IMPORTInt_ReturnAddr
                       
        IMPORTOSIntEnter
        IMPORTOSIntExit
        IMPORTOSTaskSwHook
        IMPORTC_IRQHandler
       

        EXPORTOSStartHighRdy
        EXPORTOSCtxSw       
        EXPORTOSIntCtxSw

        EXPORTOSCPUSaveSR
        EXPORTOSCPURestoreSR
        EXPORTOS_IRQHandler
       
        PRESERVE8
        AREA UCOS_ARM, CODE, READONLY
       
;====================================================================
; 函数名 : OS_StartHighRdy
; 功能 : 启动系统第一个任务
; 版本 : 1.0
;====================================================================
OSStartHighRdy
        ;----------------------------------------------------------------------------------       
        ; OSRunning = TRUE;
        ;----------------------------------------------------------------------------------       
       
        MSR   CPSR_cxsf,#SVCMODE|NOINT   ;Switch to SVC mode with IRQ&FIQ disable
       
        BL                OSTaskSwHook            ;Call user define Task switch hook
       
        LDR                R0, =OSRunning          ; OSRunning =TRUE
        MOV                R1, #1
        STRB         R1,

        ;----------------------------------------------------------------------------------               
        ;                 SP = OSTCBHighRdy->OSTCBStkPtr;
        ;----------------------------------------------------------------------------------       
        LDR         R0, =OSTCBHighRdy
        LDR         R0,          
        LDR         SP,
        B       POP_ALL      




;====================================================================
; 函数名 : OSCtxSw
; 功能 : 任务级任务的切换
; 版本 : 1.0
;====================================================================
OSCtxSw                                                                ; 任务级的任务切换                                                                                                               
                        stmfd sp!,{lr}            ; PC 入栈
                        stmfd sp!,{r0-r12,lr}                ; r0-r12,lr入栈
PUAH_CPSR                       
                        mrs r4,cpsr
                        stmfd sp!,{r4}                                ; cpsr入栈       

        ;----------------------------------------------------------------------------------               
        ; OSTaskSwHook();
        ;---------------------------------------------------------------------------------       
        BL                 OSTaskSwHook               
;====================================================================
; 函数名 : SaveCurTcb
; 功能 : 保存当前任务执行的断点
; 版本 : 1.0
;====================================================================
SaveCurTcb                                             
             
                        ldr r1,=OSPrioCur
                        ldr r2,=OSPrioHighRdy
                        ldrb r3,
                        strb r3,
                       
                       

                        ldr r4,=OSTCBCur                ; 取出当前任务的TCB地址
              ldr r5,                                        ;
              str sp,               ; 保存当前任务的堆顶指针到它的TCB(因为TaskCtrBlock地址亦即OSTCBStkPtr的地址)       

       
                        ldr r1,=OSTCBCur
                        ldr r2,=OSTCBHighRdy
                        ldr r2,
                        str r2,       

;====================================================================
; 函数名 : GetHighTcb
; 功能 : 获取高优先级的任务的断点
; 版本 : 1.0
;====================================================================
GetHighTcb                                                       
             
               

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

;====================================================================
; 函数名 : POP_ALL
; 功能 : 出栈保存的断点,PC跳转到程序
; 版本 : 1.0
;====================================================================
POP_ALL                       
            ldmfd sp!,{r4}            ; cpsr出栈
            msr CPSR_cxsf,r4       
                        ldmfd sp!,{r0-r12,lr,pc}    ; r0-r12,lr,pc出栈

OS_IRQHandler                                                        ; 中断入口地址,在中断向量表初始化时被设置
                        sub lr,lr,#4                                ; 计算中断返回地址
                        stmfd sp!,{r0-r3,r12,lr}        ; 保护现场,此时处于中断模式下,sp指向中断模式下的堆栈.不能进行任务切换(各任务堆栈处在管理模式堆栈).
                                                                                ; R4-R11装的是局部变量,在进行函数跳转时,编译器它会自动保护它们,
                        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}^        ; 不进行任务切换,出栈返回被中断的任务。寄存器出栈同时将spsr_irq的值复制到CPSR,实现模式切换                                       

OSIntCtxSw
        ;----------------------------------------------------------------------------------               
        ; Call OSTaskSwHook();
        ;----------------------------------------------------------------------------------       
        BL                 OSTaskSwHook

OS_IntCtxSw                                                                ; 把中断的返回地址保存到Int_Return_Addr_Save变量中
                        ldr r0,=OS_IntCtxSwFlag
                        mov r1,#0
                        str r1,                                        ; OSIntCtxSwFlag = 0
                       
                        add sp,sp,#20                                ; 调整SP,使之指向之前入栈的lr(中断模式下的lr保存的是中断返回地址),
                        ldr r0,                                       
                        ldr r1,=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而不返回中断前运行的程序       
       
;====================================================================
; 函数名 : OS_TASK_SW_INT
; 功能 : 中断级任务的切换
; 版本 : 1.0
;====================================================================                       
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
                        stmfd sp,{r0}                                ; PC入栈
                        sub sp,sp,#56                                ; 调整SP回到栈顶
                        b        PUAH_CPSR
             
       
OSCPUSaveSR
            mrs r0,CPSR                                        ; 保存当前的CPSR值
                       LDR R2,=0xc0
                        orr r1,r0,R2                        ; 关闭所有中断
              msr CPSR_c,r1
              mov pc,lr

OSCPURestoreSR
        MSR   CPSR_c, R0
        MOV   PC, LR
                
        END

fengyuganyu 发表于 2011-1-2 01:43:18

OS_IntCtxSwFlag这是把源代码中的OSIntCtxSw 变换成用一个标志来判断。

堆栈如下:
    stk      = ptos;                /* Load stack pointer                                    */
   
    *(stk)   = (OS_STK)task;      /* Entry Point                                             */
    *(--stk) = (OS_STK)0;                 /* LR                                                      */
    *(--stk) = (OS_STK)0;                 /* R12                                                   */
    *(--stk) = (OS_STK)0;                 /* R11                                                   */
    *(--stk) = (OS_STK)0;                 /* R10                                                   */
    *(--stk) = (OS_STK)0;                 /* R9                                                      */
    *(--stk) = (OS_STK)0;                 /* R8                                                      */
    *(--stk) = (OS_STK)0;                 /* R7                                                      */
    *(--stk) = (OS_STK)0;                 /* R6                                                      */
    *(--stk) = (OS_STK)0;                 /* R5                                                      */
    *(--stk) = (OS_STK)0;                 /* R4                                                      */
    *(--stk) = (OS_STK)0;                 /* R3                                                      */
    *(--stk) = (OS_STK)0;                 /* R2                                                      */
    *(--stk) = (OS_STK)0;                 /* R1                                                      */
    *(--stk) = (OS_STK)p_arg;       /* R0 : argument                                           */
    *(--stk) = (OS_STK)0x00000013;/* SVC模式                                                 */
                                                                                
    return (stk);
页: [1]
查看完整版本: ucos 移植到2440上出问题,请帮忙分析下