📄 os_cpu_a.s
字号:
NO_INT EQU 0xC0 ; Mask used to disable interrupts (Both FIR and IRQ)
SVC32_MODE EQU 0x13
FIQ32_MODE EQU 0x11
IRQ32_MODE EQU 0x12
CODE32
AREA |subr|, CODE, READONLY
EXTERN OSRunning ; External references
EXTERN OSPrioCur
EXTERN OSPrioHighRdy
EXTERN OSTCBCur
EXTERN OSTCBHighRdy
EXTERN OSIntNesting
EXTERN OSIntExit
EXTERN OSTaskSwHook
EXTERN OS_CPU_IRQ_ISR_Handler
EXTERN OS_CPU_FIQ_ISR_Handler
EXPORT OS_CPU_SR_Save
EXPORT OS_CPU_SR_Restore
EXPORT OSStartHighRdy
EXPORT OSCtxSw
EXPORT OSIntCtxSw
EXPORT OS_CPU_IRQ_ISR
EXPORT OS_CPU_FIQ_ISR
;/********************************************************************************************************
; 2) OS_CPU_SaveSR()
;*********************************************************************************************************/
OS_CPU_SR_Save
MRS R0,CPSR ; Set IRQ and FIQ bits in CPSR to disable all interrupts
ORR R1,R0,#NO_INT
MSR CPSR_c,R1
MRS R1,CPSR ; Confirm that CPSR contains the proper interrupt disable flags
AND R1,R1,#NO_INT
CMP R1,#NO_INT
BNE OS_CPU_SR_Save ; Not properly disabled (try again)
BX LR ; Disabled, return the original CPSR contents in R0
OS_CPU_SR_Restore
MSR CPSR_c,R0
BX LR
;/*********************************************************************************************************
; void OSStartHighRdy(void)
;*********************************************************************************************************/
OSStartHighRdy
LDR R0, =OSTaskSwHook ; OSTaskSwHook();
MOV LR, PC
BX R0
MSR CPSR_cxsf, #0xD3 ; Switch to SVC mode with IRQ and FIQ disabled
LDR R4, =OSRunning ; OSRunning = TRUE
MOV R5, #1
STRB R5, [R4]
; SWITCH TO HIGHEST PRIORITY TASK
LDR R4, =OSTCBHighRdy ; Get highest priority task TCB address
LDR R4, [R4] ; get stack pointer
LDR SP, [R4] ; switch to the new stack
LDR R4, [SP], #4 ; pop new CPSR of task
MSR SPSR_cxsf,R4
LDMFD SP!, {R0-R12,LR,PC}^ ; pop new context of task
;/*********************************************************************************************************
; PERFORM A CONTEXT SWITCH (From task level) - OSCtxSw()
;*********************************************************************************************************/
OSCtxSw
; SAVE CURRENT CONTEXT OF TASK
STMFD SP!, {LR} ; Push return address
STMFD SP!, {LR}
STMFD SP!, {R0-R12} ; Push registers
MRS R4, CPSR ; Push current CPSR
TST LR, #1 ; See if called from Thumb mode
ORRNE R4, R4, #0x20 ; If yes, Set the T-bit
STMFD SP!, {R4}
LDR R4, =OSTCBCur ; OSTCBCur->OSTCBStkPtr = SP;
LDR R5, [R4]
STR SP, [R5]
LDR R0, =OSTaskSwHook ; OSTaskSwHook();
MOV LR, PC
BX R0
LDR R4, =OSPrioCur ; OSPrioCur = OSPrioHighRdy
LDR R5, =OSPrioHighRdy
LDRB R6, [R5]
STRB R6, [R4]
LDR R4, =OSTCBCur ; OSTCBCur = OSTCBHighRdy;
LDR R6, =OSTCBHighRdy
LDR R6, [R6]
STR R6, [R4]
LDR SP, [R6] ; SP = OSTCBHighRdy->OSTCBStkPtr;
; RESTORE NEW CONTEXT of task
LDMFD SP!, {R4} ; Pop newly CPSR of task
MSR SPSR_cxsf, R4
LDMFD SP!, {R0-R12,LR,PC}^ ; Pop newly context of task
;/*********************************************************************************************************
;*********************************************************************************************************/
OSIntCtxSw
LDR R0, =OSTaskSwHook ; OSTaskSwHook();
MOV LR, PC
BX R0
LDR R4,=OSPrioCur ; OSPrioCur = OSPrioHighRdy
LDR R5,=OSPrioHighRdy
LDRB R6,[R5]
STRB R6,[R4]
LDR R4,=OSTCBCur ; OSTCBCur = OSTCBHighRdy;
LDR R6,=OSTCBHighRdy
LDR R6,[R6]
STR R6,[R4]
LDR SP,[R6] ; SP = OSTCBHighRdy->OSTCBStkPtr;
; RESTORE NEW CONTEXT of task
LDMFD SP!, {R4} ; Pop newly CPSR of task
MSR SPSR_cxsf, R4
LDMFD SP!, {R0-R12,LR,PC}^ ; Pop newly context of task
;/*********************************************************************************************************
; IRQ Interrupt Service Routine
;*********************************************************************************************************/
OS_CPU_IRQ_ISR
STMFD SP!, {R1-R3} ; PUSH WORKING REGISTERS ONTO IRQs STACK
MOV R1, SP ; Save IRQs stack pointer
ADD SP, SP,#12 ; Adjust IRQs stack pointer
SUB R2, LR,#4 ; Adjust PC fors returns address to task
MRS R3, SPSR ; Copy SPSRs (i.e. interrupted CPSR of task) to R3
MSR CPSR_c, #(NO_INT | SVC32_MODE) ; Change to SVC mode
; SAVE CONTEXT of task ONTO STACK of task
STMFD SP!, {R2} ; Push Return PC of task
STMFD SP!, {LR} ; Push LR of task
STMFD SP!, {R4-R12} ; Push R12-R4 of task
LDMFD R1!, {R4-R6} ; Move R1-R3 of task from IRQs stack to SVC stack
STMFD SP!, {R4-R6}
STMFD SP!, {R0} ; Push R0 of task onto stack of task
STMFD SP!, {R3} ; Push CPSR of task (i.e. SPSRs of IRQs)
; HANDLE NESTING COUNTER
LDR R0, =OSIntNesting ; OSIntNesting++;
LDRB R1, [R0]
ADD R1, R1,#1
STRB R1, [R0]
CMP R1, #1 ; ifs(OSIntNesting == 1) {
BNE OS_CPU_IRQ_ISR_1
LDR R4, =OSTCBCur ; OSTCBCur->OSTCBStkPtr = SP
LDR R5, [R4]
STR SP, [R5] ; }
OS_CPU_IRQ_ISR_1
MSR CPSR_c, #(NO_INT | IRQ32_MODE) ; Change to IRQs mode (to use the IRQs 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, =OSIntExit ; OSIntExit();
MOV LR, PC
BX R0
; RESTORE NEW CONTEXT of task
LDMFD SP!, {R4} ; Pop newly CPSR of task
MSR SPSR_cxsf, R4
LDMFD SP!, {R0-R12,LR,PC}^ ; Pop newly context of task
;/*********************************************************************************************************
; FIQ Interrupt Service Routine
;*********************************************************************************************************/
OS_CPU_FIQ_ISR
STMFD SP!, {R1-R3} ; PUSH WORKING REGISTERS ONTO FIQ STACK
MOV R1, SP ; Save FIQ stack pointer
ADD SP, SP,#12 ; Adjust FIQ stack pointer
SUB R2, LR,#4 ; Adjust PC fors returns address to task
MRS R3, SPSR ; Copy SPSRs (i.e. interrupted CPSR of task) to R3
MSR CPSR_c, #(NO_INT | SVC32_MODE) ; Change to SVC mode
; SAVE CONTEXT of task ONTO STACK of task
STMFD SP!, {R2} ; Push Return PC of task
STMFD SP!, {LR} ; Push LR of task
STMFD SP!, {R4-R12} ; Push tasks R12-R4
LDMFD R1!, {R4-R6} ; Move tasks R1-R3 from FIQ stack to SVC stack
STMFD SP!, {R4-R6}
STMFD SP!, {R0} ; Push tasks R0 onto tasks stack
STMFD SP!, {R3} ; Push tasks CPSR (i.e. FIQs SPSR)
; HANDLE NESTING COUNTER
LDR R0, =OSIntNesting ; OSIntNesting++;
LDRB R1, [R0]
ADD R1, R1,#1
STRB R1, [R0]
CMP R1, #1 ; ifs (OSIntNesting == 1) {
BNE OS_CPU_FIQ_ISR_1
LDR R4, =OSTCBCur ; 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 (to use the FIQ stack to handle interrupt)
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, =OSIntExit ; OSIntExit();
MOV LR, PC
BX R0
; RESTORE NEW TASKS CONTEXT
LDMFD SP!, {R4} ; Pop newly tasks CPSR
MSR SPSR_cxsf, R4
LDMFD SP!, {R0-R12,LR,PC}^ ; Pop newly tasks context
END
;/*********************************************************************************************************
; END OF FILES
;*********************************************************************************************************/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -