zlgucos移植的问题,关于swi软件中断返回的理解。【恢复】
问各位朋友一个zlgucos移植的问题在SoftwareInterrupt
LDR SP, StackSvc ; 重新设置堆栈指针
STMFD SP!, {R0-R3, R12, LR}
MOV R1, SP ; R1指向参数存储位置
MRS R3, SPSR
TST R3, #T_bit ; 中断前是否是Thumb状态
LDRNEH R0, ; 是: 取得Thumb状态SWI号
BICNE R0, R0, #0xff00
LDREQ R0, ; 否: 取得arm状态SWI号
BICEQ R0, R0, #0xFF000000
; r0 = SWI号,R1指向参数存储位置
CMP R0, #1
LDRLO PC, =OSIntCtxSw ;swi 0x00调用OSIntCtxSw
LDREQ PC, =__OSStartHighRdy ; SWI 0x01为第一次任务切换
BL SWI_Exception
LDMFD SP!, {R0-R3, R12, PC}^
中,程序有可能会跳到最后这个代码LDMFD SP!, {R0-R3, R12, PC}^ 处嘛?
LDRLO PC, =OSIntCtxSw ;swi 0x00调用OSIntCtxSw
LDREQ PC, =__OSStartHighRdy ; SWI 0x01为第一次任务切换
BL SWI_Exception
这三个语句都跳到相应的处理程序地方去了,没有看到它们跳回来的语句啊? 自问自答?太强大了!
ARM体系与结构书里绝对要提到这个上标的。 小三角的问题我找到答案了
答案:
'^'是一个后缀标志,不能在User模式和Sys系统模式下使用该标志.该标志有两个存在目的:
6.1.对于LDM操作,同时恢复的寄存器中含有pc(r15)寄存器,那么指令执行的同时cpu自动将spsr拷贝到cpsr中
如:在IRQ中断返回代码中[如下为ads环境下的代码gliethttp]
ldmfd {r4} //读取sp中保存的的spsr值到r4中
msr spsr_cxsf,r4 //对spsr的所有控制为进行写操作,将r4的值全部注入spsr
ldmfd {r0-r12,lr,pc}^//当指令执行完毕,pc跳转之前,将spsr的值自动拷贝到cpsr中
6.2.数据的送入、送出发生在User用户模式下的寄存器,而非当前模式寄存器
如:ldmdb sp,{r0 - lr}^;表示sp栈中的数据回复到User分组寄存器r0-lr中,而不是恢复到当前模式寄存器r0-lr 当然对于User,System,IRQ,SVC,Abort,Undefined这6种模式来说r0-r12是共用的,只是r13和r14
为分别独有,对于FIQ模式,仅仅r0-r7是和前6中模式的r0-r7共用,r8-r14都是FIQ模式下专有.
还有那个返回的问题没有 __OSStartHighRdy 程序如下
__OSStartHighRdy
MSR CPSR_c, #(NoInt | SYS32Mode)
;告诉uC/OS-II自身已经运行
LDR R4, =OSRunning
MOV R5, #1
STRB R5,
BL OSTaskSwHook ;调用钩子函数
LDR R6, =OSTCBHighRdy
LDR R6,
B OSIntCtxSw_1
AREA SWIStacks, DATA, NOINIT,ALIGN=2
SvcStackSpace SPACE SVC_STACK_LEGTH * 4 ;管理模式堆栈空间 还有个问题 这个汇编语言 LDMFD SP!, {R0-R12, LR, PC }^ 程序后面的这个小三角^ ,表示什么意思 在arm体系结构这书里面怎么没有看到介绍呢? 我就看不懂软件中断在这里是怎么返回了的 OSIntCtxSw
程序如下
OSIntCtxSw
;下面为保存任务环境
LDR R2, ;获取PC
LDR R12, ;获取R12
MRS R0, CPSR
MSR CPSR_c, #(NoInt | SYS32Mode)
MOV R1, LR
STMFD SP!, {R1-R2} ;保存LR,PC
STMFD SP!, {R4-R12} ;保存R4-R12
MSR CPSR_c, R0
LDMFD SP!, {R4-R7} ;获取R0-R3
ADD SP, SP, #8 ;出栈R12,PC
MSR CPSR_c, #(NoInt | SYS32Mode)
STMFD SP!, {R4-R7} ;保存R0-R3
LDR R1, =OsEnterSum ;获取OsEnterSum
LDR R2,
STMFD SP!, {R2, R3} ;保存CPSR,OsEnterSum
;保存当前任务堆栈指针到当前任务的TCB
LDR R1, =OSTCBCur
LDR R1,
STR SP,
BL OSTaskSwHook ;调用钩子函数
;OSPrioCur <= OSPrioHighRdy
LDR R4, =OSPrioCur
LDR R5, =OSPrioHighRdy
LDRB R6,
STRB R6,
;OSTCBCur <= OSTCBHighRdy
LDR R6, =OSTCBHighRdy
LDR R6,
LDR R4, =OSTCBCur
STR R6,
OSIntCtxSw_1
;获取新任务堆栈指针
LDR R4,
ADD SP, R4, #68 ;17寄存器CPSR,OsEnterSum,R0-R12,LR,SP
LDR LR,
MSR CPSR_c, #(NoInt | SVC32Mode) ;进入管理模式
MOV SP, R4 ;设置堆栈指针
LDMFD SP!, {R4, R5} ;CPSR,OsEnterSum
;恢复新任务的OsEnterSum
LDR R3, =OsEnterSum
STR R4,
MSR SPSR_cxsf, R5 ;恢复CPSR
LDMFD SP!, {R0-R12, LR, PC }^ ;运行新任务 LDRLO PC, =OSIntCtxSw ;swi 0x00调用OSIntCtxSw
LDREQ PC, =__OSStartHighRdy ; SWI 0x01为第一次任务切换
这两个跳转返回软件中断的问题还没有解决,希望哪位做过的朋友帮忙解答一下。 本来就不需要返回的吧,调用swi中断有三个功能,上面的两个和bl 那条语句。每次swi执行其中的一个 1 LDRLO PC, =OSIntCtxSw ;swi 0x00调用OSIntCtxSw
2 LDREQ PC, =__OSStartHighRdy ; SWI 0x01为第一次任务切换
3 BL SWI_Exception ,
4 LDMFD SP!, {R0-R3, R12, PC}^
1,2最后都会执行到OSIntCtxSw_1 ,就是进行任务的切换:
如果没有更高优先级的任务,则进入中断的任务出栈,此时执行4,执行楼主说没有执行的中断返回。
如果有更高优先级的任务,则把高优先级任务有关的寄存器出栈。
而OSIntCtxSw 到OSIntCtxSw_1工作是执行任务栈的保存
4 就更要返回了,因为是BL,就是跳转到C程序的,SWI_Exception执行完后就返回。
第一次回帖,不知道有没有讲清楚。 任务级切换采用软中断SWI方式实现,需要注意的是此时SWI中断处理程序并不返回,所以每次SWI中断一开始就重新初始化SVC管理模式的堆栈地址空间,否则会造成内存泄漏或溢出。 你要要仔细看看ARM汇编指令集 g RL-RTX, 也用到SWI. Mark
页:
[1]