📄 os_cpu_a.s
字号:
;*********************************************************************************************************
AREA CODE, CODE, READONLY
CODE32
OSIntCtxSw
LDR R0, __OS_TaskSwHook ; OSTaskSwHook();
MOV LR, PC
BX R0
LDR R4,__OS_PrioCur ; OSPrioCur = OSPrioHighRdy
LDR R5,__OS_PrioHighRdy
LDRB R6,[R5]
STRB R6,[R4]
LDR R4,__OS_TCBCur ; OSTCBCur = OSTCBHighRdy;
LDR R6,__OS_TCBHighRdy
LDR R6,[R6]
STR R6,[R4]
LDR SP,[R6] ; SP = OSTCBHighRdy->OSTCBStkPtr;
; RESTORE NEW TASK'S CONTEXT
LDMFD SP!, {R4} ; Pop new task's CPSR
MSR SPSR_cxsf, R4
LDMFD SP!, {R0-R12,LR,PC}^ ; Pop new task's context
;*********************************************************************************************************
; IRQ Interrupt Service Routine
;*********************************************************************************************************
AREA CODE, CODE, READONLY
CODE32
OS_CPU_IRQ_ISR
; Disable FIQ for a moment
MSR CPSR_c, #(NO_INT | IRQ32_MODE) ; Change to IRQ mode (to use the IRQ stack to handle interrupt)
STMFD SP!, {R1-R3} ; PUSH WORKING REGISTERS ONTO IRQ STACK
MOV R1, SP ; Save IRQ stack pointer
ADD SP, SP,#12 ; Adjust IRQ stack pointer
SUB R2, LR,#4 ; Adjust PC for return address to task
MRS R3, SPSR ; Copy SPSR (i.e. interrupted task's CPSR) to R3
MSR CPSR_c, #(NO_INT | SVC32_MODE) ; Change to SVC mode
; SAVE TASK'S CONTEXT ONTO TASK'S STACK
STMFD SP!, {R2} ; Push task's Return PC
STMFD SP!, {LR} ; Push task's LR
STMFD SP!, {R4-R12} ; Push task's R12-R4
LDMFD R1!, {R4-R6} ; Move task's R1-R3 from IRQ stack to SVC stack
STMFD SP!, {R4-R6}
STMFD SP!, {R0} ; Push task's R0 onto task's stack
STMFD SP!, {R3} ; Push task's CPSR (i.e. IRQ's SPSR)
; HANDLE NESTING COUNTER
LDR R0, __OS_IntNesting ; OSIntNesting++;
LDRB R1, [R0]
ADD R1, R1,#1
STRB R1, [R0]
CMP R1, #1 ; if (OSIntNesting == 1) {
BNE OS_CPU_IRQ_ISR_1
LDR R4, __OS_TCBCur ; OSTCBCur->OSTCBStkPtr = SP
LDR R5, [R4]
STR SP, [R5] ; }
OS_CPU_IRQ_ISR_1
MSR CPSR_c, #(NO_IRQ | IRQ32_MODE) ; Re-enable FIQ, Change to IRQ mode (to use the IRQ stack to handle interrupt)
LDR R0, __OS_CPU_IRQ_ISR_Handler ; OS_CPU_IRQ_ISR_Handler();
MOV LR, PC
BX R0
MSR CPSR_c, #(NO_INT | SVC32_MODE) ; Change to SVC mode
LDR R0, __OS_IntExit ; OSIntExit();
MOV LR, PC
BX R0
; RESTORE NEW TASK'S CONTEXT
LDMFD SP!, {R4} ; Pop new task's CPSR
MSR SPSR_cxsf, R4
LDMFD SP!, {R0-R12,LR,PC}^ ; Pop new task's context
;*********************************************************************************************************
; FIQ Interrupt Service Routine
;*********************************************************************************************************
AREA CODE, CODE, READONLY
CODE32
OS_CPU_FIQ_ISR
STMFD SP!, {R1-R4} ; PUSH WORKING REGISTERS ONTO FIQ STACK
MOV R1, SP ; Save FIQ stack pointer
SUB R2, LR,#4 ; Adjust PC for return address to task
MRS R3, SPSR ; Copy SPSR (i.e. interrupted task's CPSR) to R3 and R4
MOV R4, R3
AND R4, R4, #0x1F ; Isolate Mode bits
CMP R4, #IRQ32_MODE ; See if we interrupted an IRQ
BEQ OS_CPU_FIQ_ISR_2 ; Branch if yes.
; =============== FIQ interrupted Task ===============
MSR CPSR_c, #(NO_INT | SVC32_MODE) ; Change to SVC mode
; SAVE TASK'S CONTEXT ONTO TASK'S STACK
STMFD SP!, {R2} ; Push task's Return PC
STMFD SP!, {LR} ; Push task's LR
STMFD SP!, {R5-R12} ; Push task's R12-R5
LDMFD R1!, {R5-R8} ; Move task's R1-R4 from FIQ stack to SVC stack
STMFD SP!, {R5-R8}
STMFD SP!, {R0} ; Push task's R0 onto task's stack
STMFD SP!, {R3} ; Push task's CPSR (i.e. FIQ's SPSR)
; HANDLE NESTING COUNTER
LDR R0, __OS_IntNesting ; OSIntNesting++;
LDRB R1, [R0]
ADD R1, R1,#1
STRB R1, [R0]
CMP R1, #1 ; if (OSIntNesting == 1){
BNE OS_CPU_FIQ_ISR_1
LDR R4, __OS_TCBCur ; OSTCBCur->OSTCBStkPtr = SP
LDR R5, [R4]
STR SP, [R5] ; }
OS_CPU_FIQ_ISR_1
MSR CPSR_c, #(NO_INT | FIQ32_MODE) ; Change to FIQ mode (touse the FIQ stack to handle interrupt)
ADD SP, SP, #16 ; Adjust FIQ stack pointer (Working register were saved)
LDR R0, __OS_CPU_FIQ_ISR_Handler ; OS_CPU_FIQ_ISR_Handler();
MOV LR, PC
BX R0
MSR CPSR_c, #(NO_INT | SVC32_MODE) ; Change to SVC mode
LDR R0, __OS_IntExit ; OSIntExit();
MOV LR, PC
BX R0
; RESTORE NEW TASK'S CONTEXT
LDMFD SP!, {R4} ; Pop new task's CPSR
MSR SPSR_cxsf, R4
LDMFD SP!, {R0-R12,LR,PC}^ ; Pop new task's context
; =============== FIQ interrupted IRQ ===============
OS_CPU_FIQ_ISR_2
; SAVE IRQ'S CONTEXT ONTO FIQ'S STACK
STMFD SP!, {R0-R7,LR} ; Push shared registers
; HANDLE NESTING COUNTER
LDR R0, __OS_IntNesting ; OSIntNesting++; (Notify uC/OS-II)
LDRB R1, [R0]
ADD R1, R1,#1
STRB R1, [R0]
LDR R0, __OS_CPU_FIQ_ISR_Handler ; OS_CPU_FIQ_ISR_Handler();
MOV LR, PC
BX R0
; HANDLE NESTING COUNTER
LDR R0, __OS_IntNesting ; OSIntNesting--;
LDRB R1, [R0] ; NO need to call OSIntExit() we are returning to IRQ handler
SUB R1, R1, #1
STRB R1, [R0]
LDMFD SP!, {R0-R7,LR} ; Pop IRQ's context
LDMFD SP!, {R1-R4} ; PULL WORKING REGISTERS ONTO FIQ STACK
SUBS PC, LR, #4 ; Return to IRQ
;*********************************************************************************************************
; POINTERS TO VARIABLES
;*********************************************************************************************************
AREA CODE, CODE, READONLY
CODE32
__OS_TaskSwHook
DCD OSTaskSwHook
__OS_CPU_IRQ_ISR_Handler
DCD OS_CPU_IRQ_ISR_Handler
__OS_CPU_FIQ_ISR_Handler
DCD OS_CPU_FIQ_ISR_Handler
__OS_IntExit
DCD OSIntExit
__OS_IntNesting
DCD OSIntNesting
__OS_PrioCur
DCD OSPrioCur
__OS_PrioHighRdy
DCD OSPrioHighRdy
__OS_Running
DCD OSRunning
__OS_TCBCur
DCD OSTCBCur
__OS_TCBHighRdy
DCD OSTCBHighRdy
END
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -