📄 os_cpu_a.asm
字号:
LDR R2, =OSIntNesting ; OSIntNesting--;
LDRB R4, [R2]
SUB R4, R4, #1
STRB R4, [R2]
; RESTORE IRQ'S CONTEXT:
LDMFD SP!, {R0} ; Pop IRQ's CPSR,
MSR SPSR_cxsf, R0
LDMFD SP!, {R0-R12, LR, PC}^ ; Pop IRQ's context.
;********************************************************************************************************
;********************************************************************************************************
; IRQ HANDLER
;********************************************************************************************************
;********************************************************************************************************
;********************************************************************************************************
; INTERRUPT REQUEST EXCEPTION HANDLER
;
; Register Usage: R0 Exception Type
; R1 Exception's SPSR
; R2 Return PC
; R3 Exception's SP
;
; Note(s) : 1) An IRQ can occur in three different circumstances; in each of these, the
; SVC stack pointer will point to a different entity :
;
; a) CONDITION: An exception occurs before the OS has been fully initialized.
; SVC STACK: Should point to a stack initialized by the application's startup code.
; STK USAGE: Interrupted context -- SVC stack.
; Exception -- SVC stack.
; Nested exceptions -- SVC stack.
;
; b) CONDITION: An IRQ interrupts a task.
; SVC STACK: Should point to task stack.
; STK USAGE: Interrupted context -- Task stack.
; Exception -- Exception stack 'OS_CPU_ExceptStk[]'.
; Nested exceptions -- Exception stack 'OS_CPU_ExceptStk[]'.
;
; c) CONDITION: An IRQ interrupts another IRQ.
; SVC STACK: Should point to location in exception stack, 'OS_CPU_ExceptStk[]'.
; STK USAGE: Interrupted context -- Exception stack 'OS_CPU_ExceptStk[]'.
; Exception -- Exception stack 'OS_CPU_ExceptStk[]'.
; Nested exceptions -- Exception stack 'OS_CPU_ExceptStk[]'.
;********************************************************************************************************
OS_CPU_ARM_ExceptIrqHndlr
SUB LR, LR, #4 ; LR offset to return from this exception: -4.
STMFD SP!, {R0-R3} ; Push working registers.
MOV R0, #OS_CPU_ARM_EXCEPT_IRQ ; Set exception ID to OS_CPU_ARM_EXCEPT_IRQ.
MRS R1, SPSR ; Save CPSR (i.e. exception's SPSR).
MOV R2, LR ; Save link register.
MOV R3, SP ; Save exception's stack pointer.
; Change to SVC mode & disable interruptions.
MSR CPSR_c, #(OS_CPU_ARM_CONTROL_INT_DIS | OS_CPU_ARM_MODE_SVC)
; SAVE CONTEXT ONTO SVC STACK:
STMFD SP!, {R2} ; Push task's PC,
STMFD SP!, {LR} ; Push task's LR,
STMFD SP!, {R4-R12} ; Push task's R12-R4,
LDMFD R3!, {R5-R8} ; Move task's R3-R0 from exception stack to task's stack.
STMFD SP!, {R5-R8}
STMFD SP!, {R1} ; Push task's CPSR (i.e. exception SPSR).
; if (OSRunning == 1)
LDR R3, =OSRunning
LDRB R4, [R3]
CMP R4, #1
BNE OS_CPU_ARM_IRQHndlr_BreakNothing
; HANDLE NESTING COUNTER:
LDR R3, =OSIntNesting ; OSIntNesting++;
LDRB R4, [R3]
ADD R4, R4, #1
STRB R4, [R3]
CMP R4, #1 ; if (OSIntNesting == 1)
BNE OS_CPU_ARM_IRQHndlr_BreakIRQ
;********************************************************************************************************
; IRQ HANDLER: TASK INTERRUPTED
;
; Register Usage: R0 Exception Type
; R1
; R2
; R3
;********************************************************************************************************
OS_CPU_ARM_IRQHndlr_BreakTask
LDR R3, =OSTCBCur ; OSTCBCur->OSTCBStkPtr = SP;
LDR R4, [R3]
STR SP, [R4]
LDR R3, =OS_CPU_ExceptStkBase ; Switch to exception stack.
LDR SP, [R3]
; EXECUTE EXCEPTION HANDLER:
LDR R1, =OS_CPU_ExceptHndlr ; OS_CPU_ExceptHndlr(except_type = R0)
MOV LR, PC
BX R1
; Change to IRQ mode & disable interruptions.
MSR CPSR_c, #(OS_CPU_ARM_CONTROL_INT_DIS | OS_CPU_ARM_MODE_IRQ)
; Adjust exception stack pointer. This is needed because
; exception stack is not used when restoring task context.
ADD SP, SP, #(4 * 4)
; Change to SVC mode & disable interruptions.
MSR CPSR_c, #(OS_CPU_ARM_CONTROL_INT_DIS | OS_CPU_ARM_MODE_SVC)
; 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
LDR R3, =OSTCBCur ; SP = OSTCBCur->OSTCBStkPtr;
LDR R4, [R3]
LDR SP, [R4]
; RESTORE NEW TASK'S CONTEXT:
LDMFD SP!, {R0} ; Pop new task's CPSR,
MSR SPSR_cxsf, R0
LDMFD SP!, {R0-R12, LR, PC}^ ; Pop new task's context.
;********************************************************************************************************
; IRQ HANDLER: IRQ INTERRUPTED
;
; Register Usage: R0 Exception Type
; R1
; R2
; R3
;********************************************************************************************************
OS_CPU_ARM_IRQHndlr_BreakIRQ
LDR R3, =OS_CPU_ExceptStkPtr ; OS_CPU_ExceptStkPtr = SP;
STR SP, [R3]
; EXECUTE EXCEPTION HANDLER:
LDR R3, =OS_CPU_ExceptHndlr ; OS_CPU_ExceptHndlr(except_type = R0)
MOV LR, PC
BX R3
; Change to IRQ mode & disable interruptions.
MSR CPSR_c, #(OS_CPU_ARM_CONTROL_INT_DIS | OS_CPU_ARM_MODE_IRQ)
; Adjust exception stack pointer. This is needed because
; exception stack is not used when restoring task context.
ADD SP, SP, #(4 * 4)
; Change to SVC mode & disable interruptions.
MSR CPSR_c, #(OS_CPU_ARM_CONTROL_INT_DIS | OS_CPU_ARM_MODE_SVC)
; HANDLE NESTING COUNTER:
LDR R3, =OSIntNesting ; OSIntNesting--;
LDRB R4, [R3]
SUB R4, R4, #1
STRB R4, [R3]
; RESTORE OLD CONTEXT:
LDMFD SP!, {R0} ; Pop old CPSR,
MSR SPSR_cxsf, R0
LDMFD SP!, {R0-R12, LR, PC}^ ; Pull working registers and return from exception.
;********************************************************************************************************
; IRQ HANDLER: 'NOTHING' INTERRUPTED
;
; Register Usage: R0 Exception Type
; R1
; R2
; R3
;********************************************************************************************************
OS_CPU_ARM_IRQHndlr_BreakNothing
; EXECUTE EXCEPTION HANDLER:
LDR R3, =OS_CPU_ExceptHndlr ; OS_CPU_ExceptHndlr(except_type = R0)
MOV LR, PC
BX R3
; Change to IRQ mode & disable interruptions.
MSR CPSR_c, #(OS_CPU_ARM_CONTROL_INT_DIS | OS_CPU_ARM_MODE_IRQ)
; Adjust exception stack pointer. This is needed because
; exception stack is not used when restoring task context.
ADD SP, SP, #(4 * 4)
; Change to SVC mode & disable interruptions.
MSR CPSR_c, #(OS_CPU_ARM_CONTROL_INT_DIS | OS_CPU_ARM_MODE_SVC)
; RESTORE OLD CONTEXT:
LDMFD SP!, {R0} ; Pop old CPSR,
MSR SPSR_cxsf, R0
LDMFD SP!, {R0-R12, LR, PC}^ ; Pull working registers and return from exception.
;********************************************************************************************************
;********************************************************************************************************
; ENABLE & DISABLE INTERRUPTS, IRQs, FIQs
;********************************************************************************************************
;********************************************************************************************************
;********************************************************************************************************
; ENABLE & DISABLE INTERRUPTS
;
; Note(s) : 1) OS_CPU_SR_INT_En() can be called by OS_CPU_ExceptHndlr() AFTER the external
; interrupt source has been cleared. This function will enable IRQs and FIQs so that
; nesting can occur.
;
; 2) OS_CPU_ARM_INT_Dis() can be called to disable IRQs and FIQs so that nesting will not occur.
;********************************************************************************************************
OS_CPU_SR_INT_En
MRS R0, CPSR
BIC R0, R0, #OS_CPU_ARM_CONTROL_INT_DIS ; Clear IRQ and FIQ bits in CPSR to enable all interrupts.
MSR CPSR_c, R0
BX LR
OS_CPU_SR_INT_Dis
MRS R0, CPSR
ORR R0, R0, #OS_CPU_ARM_CONTROL_INT_DIS ; Set IRQ and FIQ bits in CPSR to disable all interrupts.
MSR CPSR_c, R0
BX LR
;********************************************************************************************************
; ENABLE & DISABLE IRQs
;
; Note(s) : 1) OS_CPU_SR_IRQ_En() can be called by OS_CPU_ExceptHndlr() AFTER the external
; interrupt source has been cleared. This function will enable IRQs so that IRQ nesting
; can occur.
;
; 2) OS_CPU_ARM_IRQ_Dis() can be called to disable IRQs so that IRQ nesting will not occur.
;********************************************************************************************************
OS_CPU_SR_IRQ_En
MRS R0, CPSR
BIC R0, R0, #OS_CPU_ARM_CONTROL_IRQ_DIS ; Clear IRQ bit in CPSR to enable IRQs.
MSR CPSR_c, R0
BX LR
OS_CPU_SR_IRQ_Dis
MRS R0, CPSR
ORR R0, R0, #OS_CPU_ARM_CONTROL_IRQ_DIS ; Set IRQ bit in CPSR to disable IRQs.
MSR CPSR_c, R0
BX LR
;********************************************************************************************************
; ENABLE & DISABLE FIQs
;
; Note(s) : 1) OS_CPU_SR_FIQ_En() can be called by OS_CPU_ExceptHndlr() AFTER the external
; interrupt source has been cleared. This function will enable FIQs so that FIQ nesting
; can occur.
;
; 2) OS_CPU_ARM_FIQ_Dis() can be called to disable FIQs so that FIQ nesting will not occur.
;********************************************************************************************************
OS_CPU_SR_FIQ_En
MRS R0, CPSR
BIC R0, R0, #OS_CPU_ARM_CONTROL_FIQ_DIS ; Clear FIQ bit in CPSR to enable FIQs.
MSR CPSR_c, R0
BX LR
OS_CPU_SR_FIQ_Dis
MRS R0, CPSR
ORR R0, R0, #OS_CPU_ARM_CONTROL_FIQ_DIS ; Set FIQ bit in CPSR to disable FIQs.
MSR CPSR_c, R0
BX LR
END
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -