📄 os_cpu_a.s
字号:
; 的堆栈到寄存器就可以了 ................................/zf
;********************************************************************************************************/
OSIntCtxSw
LDR R0, =OSTaskSwHook ; OSTaskSwHook();
MOV LR, PC
BX R0
LDR R0, =OSPrioCur ; OSPrioCur = OSPrioHighRdy;
LDR R1, =OSPrioHighRdy
LDRB R2, [R1]
STRB R2, [R0]
LDR R0, =OSTCBCur ; OSTCBCur = OSTCBHighRdy;
LDR R1, =OSTCBHighRdy
LDR R2, [R1]
STR R2, [R0]
LDR SP, [R2] ; SP = OSTCBHighRdy->OSTCBStkPtr;
; RESTORE NEW TASK CONTEXT
LDMFD SP!, {R0} ; Pop new task CPSR
MSR CPSR_cxsf, R0
LDMFD SP!, {R0-R12, LR, PC} ; Pop new task context
;/********************************************************************************************************
; 以下代码对各种异常进行处理,流程如图所示 执行任务
; 发生异常(跳转)->||
; \/
; 寄存器保护函数
; 跳转 -> ||
; \/
; 异常处理函数(根据异常的类型,对任务堆栈保护,嵌套处理,判断是否进行任务切换)
; 跳转 -> ||
; \/
; 统一的异常处理函数入口地址(中断)
; 跳转 -> ||
; \/
; 返回到异常前的处理
;
; 根据上图可知,当发生异常(一般是中断)时,会进行四次跳转,其中第一次是自动跳转,后面三次是人为强制执行的 / zf
;********************************************************************************************************/
;********************************************************************************************************
; RESET EXCEPTION HANDLER
;********************************************************************************************************
OS_CPU_ARM_ExceptResetHndlr
; LR offset to return from this exception: 0
; (there is no way to return from a RESET exception)
STMFD SP!, {R0-R12, LR} ; Push working registers
MOV R3, LR ; Save link register
MOV R0, #OS_CPU_ARM_EXCEPT_RESET ; Set exception ID to OS_CPU_ARM_EXCEPT_RESET
B OS_CPU_ARM_ExceptHndlr ; Branch to global exception handler
;********************************************************************************************************
; UNDEFINED INSTRUCTION EXCEPTION HANDLER
;********************************************************************************************************
OS_CPU_ARM_ExceptUndefInstrHndlr
; LR offset to return from this exception: 0
STMFD SP!, {R0-R12, LR} ; Push working registers
MOV R3, LR ; Save link register
MOV R0, #OS_CPU_ARM_EXCEPT_UNDEF_INSTR ; Set exception ID to OS_CPU_ARM_EXCEPT_UNDEF_INSTR
B OS_CPU_ARM_ExceptHndlr ; Branch to global exception handler
;********************************************************************************************************
; SOFTWARE INTERRUPT EXCEPTION HANDLER
;********************************************************************************************************
OS_CPU_ARM_ExceptSwiHndlr
; LR offset to return from this exception: 0
STMFD SP!, {R0-R12, LR} ; Push working registers
MOV R3, LR ; Save link register
MOV R0, #OS_CPU_ARM_EXCEPT_SWI ; Set exception ID to OS_CPU_ARM_EXCEPT_SWI
B OS_CPU_ARM_ExceptHndlr ; Branch to global exception handler
;********************************************************************************************************
; PREFETCH ABORT EXCEPTION HANDLER
;********************************************************************************************************
OS_CPU_ARM_ExceptPrefetchAbortHndlr
SUB LR, LR, #4 ; LR offset to return from this exception: -4
STMFD SP!, {R0-R12, LR} ; Push working registers
MOV R3, LR ; Save link register
MOV R0, #OS_CPU_ARM_EXCEPT_PREFETCH_ABORT ; Set exception ID to OS_CPU_ARM_EXCEPT_PREFETCH_ABORT
B OS_CPU_ARM_ExceptHndlr ; Branch to global exception handler
;********************************************************************************************************
; DATA ABORT EXCEPTION HANDLER
;********************************************************************************************************
OS_CPU_ARM_ExceptDataAbortHndlr
SUB LR, LR, #8 ; LR offset to return from this exception: -8
STMFD SP!, {R0-R12, LR} ; Push working registers
MOV R3, LR ; Save link register
MOV R0, #OS_CPU_ARM_EXCEPT_DATA_ABORT ; Set exception ID to OS_CPU_ARM_EXCEPT_DATA_ABORT
B OS_CPU_ARM_ExceptHndlr ; Branch to global exception handler
;********************************************************************************************************
; ADDRESS ABORT EXCEPTION HANDLER
;********************************************************************************************************
OS_CPU_ARM_ExceptAddrAbortHndlr
SUB LR, LR, #8 ; LR offset to return from this exception: -8
STMFD SP!, {R0-R12, LR} ; Push working registers
MOV R3, LR ; Save link register
MOV R0, #OS_CPU_ARM_EXCEPT_ADDR_ABORT ; Set exception ID to OS_CPU_ARM_EXCEPT_ADDR_ABORT
B OS_CPU_ARM_ExceptHndlr ; Branch to global exception handler
;********************************************************************************************************
; INTERRUPT REQUEST EXCEPTION HANDLER
;********************************************************************************************************
OS_CPU_ARM_ExceptIrqHndlr
SUB LR, LR, #4 ; LR offset to return from this exception: -4
STMFD SP!, {R0-R12, LR} ; Push working registers
MOV R3, LR ; Save link register
MOV R0, #OS_CPU_ARM_EXCEPT_IRQ ; Set exception ID to OS_CPU_ARM_EXCEPT_IRQ
B OS_CPU_ARM_ExceptHndlr ; Branch to global exception handler
;********************************************************************************************************
; FAST INTERRUPT REQUEST EXCEPTION HANDLER
;********************************************************************************************************
OS_CPU_ARM_ExceptFiqHndlr
SUB LR, LR, #4 ; LR offset to return from this exception: -4
STMFD SP!, {R0-R12, LR} ; Push working registers
MOV R3, LR ; Save link register
MOV R0, #OS_CPU_ARM_EXCEPT_FIQ ; Set exception ID to OS_CPU_ARM_EXCEPT_FIQ
B OS_CPU_ARM_ExceptHndlr ; Branch to global exception handler
;********************************************************************************************************
; GLOBAL EXCEPTION HANDLER
;********************************************************************************************************
OS_CPU_ARM_ExceptHndlr
MRS R1, SPSR ; Save CPSR (i.e. exception SPSR)
; DETERMINE IF WE INTERRUPTED A TASK OR ANOTHER LOWER PRIORITY EXCEPTION
; SPSR.Mode = FIQ, IRQ, SVC, ABT, UND : Other exception
; SPSR.Mode = SYS : Task
; SPSR.Mode = USR : *unsupported state*
AND R2, R1, #OS_CPU_ARM_MODE_MASK
CMP R2, #OS_CPU_ARM_MODE_SYS ;
BNE OS_CPU_ARM_ExceptHndlr_BreakExcept ; 如果被中断的不是系统模式,说明先前就是处于其他异常模式,由于在前一次
; 进入异常之前就已经对任务进行了保护,并且堆栈指针也有过改变,所以在这里
; 应该根据发生异常前的状态进行不同的处理..........................zf
;********************************************************************************************************
; EXCEPTION HANDLER: TASK INTERRUPTED
;********************************************************************************************************
OS_CPU_ARM_ExceptHndlr_BreakTask
MRS R2, CPSR ; Save exception CPSR
MOV R4, SP ; Save exception stack pointer
; Change to SYS mode & disable interruptions
MSR CPSR_c, #(OS_CPU_ARM_CONTROL_INT_DIS | OS_CPU_ARM_MODE_SYS)
; SAVE TASK CONTEXT ONTO TASK STACK
STMFD SP!, {R3} ; Push task PC
STMFD SP!, {LR} ; Push task LR
STMFD SP!, {R5-R12} ; Push task R12-R5
LDMFD R4!, {R5-R9} ; Move task R4-R0 from exception stack to task stack
STMFD SP!, {R5-R9}
TST R3, #1 ; See if called from Thumb mode
ORRNE R1, R1, #OS_CPU_ARM_CONTROL_THUMB ; If yes, Set the T-bit
STMFD SP!, {R1} ; Push task CPSR (i.e. exception SPSR)
; if (OSRunning == 1)
LDR R1, =OSRunning
LDRB R1, [R1]
CMP R1, #1
BNE OS_CPU_ARM_ExceptHndlr_BreakTask_1
; HANDLE NESTING COUNTER
LDR R3, =OSIntNesting ; OSIntNesting++;
LDRB R4, [R3]
ADD R4, R4, #1
STRB R4, [R3]
LDR R3, =OSTCBCur ; OSTCBCur->OSTCBStkPtr = SP;
LDR R4, [R3]
STR SP, [R4]
OS_CPU_ARM_ExceptHndlr_BreakTask_1
MSR CPSR_cxsf, R2 ; RESTORE INTERRUPTED MODE
LDR R1, =OS_CPU_ExceptHndlr ; OS_CPU_ExceptHndlr();
MOV LR, PC
BX R1
; Adjust exception stack pointer. This is needed because
; exception stack is not used when restoring task context.
ADD SP, SP, #(14*4)
; Change to SYS mode & disable interruptions.
MSR CPSR_c, #(OS_CPU_ARM_CONTROL_INT_DIS | OS_CPU_ARM_MODE_SYS)
; Call OSIntExit(). This call MAY never return
; if a ready task with higher priority than
; the interrupted one is found.
LDR R0, =OSIntExit
MOV LR, PC
BX R0
; RESTORE NEW TASK CONTEXT
LDMFD SP!, {R0} ; Pop new task CPSR
MSR CPSR_cxsf, R0
LDMFD SP!, {R0-R12, LR, PC} ; Pop new task context
;********************************************************************************************************
; EXCEPTION HANDLER: EXCEPTION INTERRUPTED
;********************************************************************************************************
OS_CPU_ARM_ExceptHndlr_BreakExcept
MRS R2, CPSR ; Save exception CPSR
; Change to SYS mode & disable interruptions
MSR CPSR_c, #(OS_CPU_ARM_CONTROL_INT_DIS | OS_CPU_ARM_MODE_SYS)
; HANDLE NESTING COUNTER
LDR R3, =OSIntNesting ; OSIntNesting++;
LDRB R4, [R3]
ADD R4, R4, #1
STRB R4, [R3]
MSR CPSR_cxsf, R2 ; RESTORE INTERRUPTED MODE
LDR R3, =OS_CPU_ExceptHndlr ; OS_CPU_ExceptHndlr();
MOV LR, PC
BX R3
; Change to SYS mode & disable interruptions
MSR CPSR_c, #(OS_CPU_ARM_CONTROL_INT_DIS | OS_CPU_ARM_MODE_SYS)
; HANDLE NESTING COUNTER
LDR R3, =OSIntNesting ; OSIntNesting--;
LDRB R4, [R3]
SUB R4, R4, #1
STRB R4, [R3]
MSR CPSR_cxsf, R2 ; RESTORE INTERRUPTED MODE
LDMFD SP!, {R0-R12, PC}^ ; Pull working registers and return from exception.
END
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -