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 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]