|
问一个很菜的问题,为什么在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,[r0]
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,[r0] ; OSIntCtxSwFlag = 0
add sp,sp,#20 ; 调整SP,使之指向之前入栈的lr(中断模式下的lr保存的是中断返回地址),
ldr r0,[sp]
ldr r1,=Int_ReturnAddr ; 将中断返回地址赋值给Int_ReturnAddr
str r0,[r1] ;保存中断退出的地址
ldr r0,=OS_TASK_SW_INT
str r0,[sp] ; 保存中断任务执行的地址,即把进入中断的断点地址更新
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,[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入栈
BL OSTaskSwHook
SaveCurTcb
ldr r1,=OSPrioCur ;更新当前的运行任务的优先级ID号
ldr r2,=OSPrioHighRdy
ldrb r3,[r2]
strb r3,[r1]
ldr r4,=OSTCBCur ; 取出当前任务的TCB地址
ldr r5,[r4] ;
str sp,[r5] ; 保存当前任务的堆顶指针到它的TCB的堆栈指针上
ldr r1,=OSTCBCur ;更新指向当前任务控制块指针的指向
ldr r2,=OSTCBHighRdy
ldr r2,[r2]
str r2,[r1]
GetHighTcb
ldr r6,=OSTCBHighRdy ; 取出更高优先级就绪任务的TCB的地址
ldr r6,[r6]
ldr sp,[r6] ; 取出更高优先级任务的堆顶指针到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时老是出问题,这里我没有用到模式切换,我的程序运行在管理模式下,没有用系统模式。
请前辈解答下! 这个代码是不是有错?... |
阿莫论坛20周年了!感谢大家的支持与爱护!!
曾经有一段真挚的爱情摆在我的面前,我没有珍惜,现在想起来,还好我没有珍惜……
|