📄 softwareinterrupt.s
字号:
; SWI中断处理函数,由此进入SVC处理模式,调用系统函数进行任务切换
; nuaa tedden 导航研究中心 2008-12-8
;
;
;
;
;
;
;
NoInt EQU 0x80
SVC32Mode EQU 0x13
SYS32Mode EQU 0x1f
CODE32
AREA SWI_INT, CODE, READONLY
;引入外部变量
IMPORT pxCurrentTCB ;当前任务TCB的指针
IMPORT ulCriticalNesting ;中断嵌套层数全局变量
IMPORT StackUsr
IMPORT vTaskSwitchContext ;OS系统函数
EXPORT SoftWareInterrupt ;软件中断入口
SoftWareInterrupt
;////////////////////////////加上偏移//////////////////////////////////////////////////
ADD LR, LR, #4
;///////////////////////////保护中断现场///////////////////////////////////////////////
; Push R0 as we are going to use the register.
STMDB SP!, {R0} ;先将R0压入栈底,后面要用到R0
; Set R0 to point to the task stack pointer.
STMDB SP,{SP}^ ;将SYS模式的SP指针入栈,^
NOP
SUB SP, SP, #4 ;
LDMIA SP!,{R0} ;
; Push the return address onto the stack.
STMDB R0!, {LR} ;将返回地址压栈,从堆栈的结构来看应该压在栈底
; Now we have saved LR we can use it instead of R0.
MOV LR, R0
; Pop R0 so we can save it onto the system mode stack.
LDMIA SP!, {R0}
; Push all the system mode registers onto the task stack.
STMDB LR,{R0-LR}^
NOP
SUB LR, LR, #60
; Push the SPSR onto the task stack.
MRS R0, SPSR
STMDB LR!, {R0}
LDR R0, =ulCriticalNesting
LDR R0, [R0]
STMDB LR!, {R0}
; Store the new top of stack for the task.
LDR R0, =pxCurrentTCB
LDR R0, [R0]
STR LR, [R0]
;//////////////////////////保护中断现场结束////////////////////////////////////////////////////////
;//////////////////////////切换处理器模式,重定位SP指针///////////////////////////////////////////
MSR CPSR_c, #(NoInt | SYS32Mode) ; 切换到系统模式
LDR SP, =StackUsr ;堆栈定义到Usr段
;//////////////////////////模式切换结束///////////////////////////////////////////////////////////
;//////////////////////////调用SWI系统函数////////////////////////////////////////////////////////
BL vTaskSwitchContext
;/////////////////////////调用结束////////////////////////////////////////////////////////////////
;///////////////////////////切换到SVC模式/////////////////////////////////////////////////////////
MSR CPSR_c, #(NoInt | SVC32Mode)
;//////////////////////////恢复断点内容///////////////////////////////////////////////////////////
;Set the LR to the task stack.
;将LR指向当前任务堆栈顶
LDR R0, =pxCurrentTCB ;获取当前任务TCB结构体指针
LDR R0, [R0] ;获取指向存储栈顶数据的指针
LDR LR, [R0] ;取出栈顶指针数据到LR中
; The critical nesting depth is the first item on the stack.
; Load it into the ulCriticalNesting variable.
;弹出栈顶的中断层数到全局变量中
LDR R0, =ulCriticalNesting
LDMFD LR!, {R1}
STR R1, [R0]
; Get the SPSR from the stack.
;弹出保存的SPSR
LDMFD LR!, {R0} ;栈顶的首个数据是保存的SPSR
MSR SPSR_cxsf, R0 ;将SPSR恢复
; Restore all system mode registers for the task.
; 恢复R0~R14
LDMFD LR, {R0-R14}^ ;依次恢复R0-R14,LR不会被改写。^表示更改的是用户模式的寄存器,因此将恢复用户模式的
;LR.要进行任务切换有两种情况.一是在中断的时候处于中断模式;或是处于SWI中断中,在特权模式
NOP
; Restore the return address.
; 获取返回地址
LDR LR, [LR, #+60] ;获取存放在栈底的返回地址
; And return - correcting the offset in the LR to obtain the
; correct address.
;设置PC,执行跳转
SUBS PC, LR, #4 ;返回地址-4,返回任务断点
;MOVS PC, LR ;执行SWI异常返回
END
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -