📄 os_cpu_a.asm
字号:
RSEG CODE:CODE:NOROOT(2)
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
;*********************************************************************************************************
RSEG CODE:CODE:NOROOT(2)
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
;*********************************************************************************************************
RSEG CODE:CODE:NOROOT(2)
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
;*********************************************************************************************************
DATA
??OS_TaskSwHook:
DC32 OSTaskSwHook
??OS_CPU_IRQ_ISR_Handler:
DC32 OS_CPU_IRQ_ISR_Handler
??OS_CPU_FIQ_ISR_Handler:
DC32 OS_CPU_FIQ_ISR_Handler
??OS_IntExit:
DC32 OSIntExit
??OS_IntNesting:
DC32 OSIntNesting
??OS_PrioCur:
DC32 OSPrioCur
??OS_PrioHighRdy:
DC32 OSPrioHighRdy
??OS_Running:
DC32 OSRunning
??OS_TCBCur:
DC32 OSTCBCur
??OS_TCBHighRdy:
DC32 OSTCBHighRdy
END
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -