📄 os_cpu_a.s
字号:
@
@********************************************************************************************************
@ uC/OS-II
@ The Real-Time Kernel
@
@
@ (c) Copyright 1992-2007, Micrium, Weston, FL
@ All Rights Reserved
@
@ Generic ARM Port
@
@ File : OS_CPU_A.ASM
@ Version : V1.82
@ By : Jean J. Labrosse
@ Jean-Denis Hatier
@
@ For : ARM7 or ARM9
@ Mode : ARM or Thumb
@ Toolchain : GNU GCC
@********************************************************************************************************
@
@********************************************************************************************************
@ PUBLIC FUNCTIONS
@********************************************************************************************************
@ External references.
.extern OSRunning
.extern OSPrioCur
.extern OSPrioHighRdy
.extern OSTCBCur
.extern OSTCBHighRdy
.extern OSIntNesting
.extern OSIntExit
.extern OSTaskSwHook
@ Functions declared in this file.
.global OS_CPU_SR_Save
.global OS_CPU_SR_Restore
.global OSStartHighRdy
.global OSCtxSw
.global OSIntCtxSw
@ Functions related to exception handling.
.global OS_CPU_ARM_ExceptResetHndlr
.global OS_CPU_ARM_ExceptUndefInstrHndlr
.global OS_CPU_ARM_ExceptSwiHndlr
.global OS_CPU_ARM_ExceptPrefetchAbortHndlr
.global OS_CPU_ARM_ExceptDataAbortHndlr
.global OS_CPU_ARM_ExceptAddrAbortHndlr
.global OS_CPU_ARM_ExceptIrqHndlr
.global OS_CPU_ARM_ExceptFiqHndlr
.extern OS_CPU_ExceptHndlr
@********************************************************************************************************
@ EQUATES
@********************************************************************************************************
.equ OS_CPU_ARM_CONTROL_INT_DIS, 0xC0 @ Disable both FIQ and IRQ.
.equ OS_CPU_ARM_CONTROL_FIQ_DIS, 0x40 @ Disable FIQ.
.equ OS_CPU_ARM_CONTROL_IRQ_DIS, 0x80 @ Disable IRQ.
.equ OS_CPU_ARM_CONTROL_THUMB, 0x20 @ Set THUMB mode.
.equ OS_CPU_ARM_CONTROL_ARM, 0x00 @ Set ARM mode.
.equ OS_CPU_ARM_MODE_MASK, 0x1F
.equ OS_CPU_ARM_MODE_USR, 0x10
.equ OS_CPU_ARM_MODE_FIQ, 0x11
.equ OS_CPU_ARM_MODE_IRQ, 0x12
.equ OS_CPU_ARM_MODE_SVC, 0x13
.equ OS_CPU_ARM_MODE_ABT, 0x17
.equ OS_CPU_ARM_MODE_UND, 0x1B
.equ OS_CPU_ARM_MODE_SYS, 0x1F
.equ OS_CPU_ARM_EXCEPT_RESET, 0x00
.equ OS_CPU_ARM_EXCEPT_UNDEF_INSTR, 0x01
.equ OS_CPU_ARM_EXCEPT_SWI, 0x02
.equ OS_CPU_ARM_EXCEPT_PREFETCH_ABORT, 0x03
.equ OS_CPU_ARM_EXCEPT_DATA_ABORT, 0x04
.equ OS_CPU_ARM_EXCEPT_ADDR_ABORT, 0x05
.equ OS_CPU_ARM_EXCEPT_IRQ, 0x06
.equ OS_CPU_ARM_EXCEPT_FIQ, 0x07
@********************************************************************************************************
@ CODE GENERATION DIRECTIVES
@********************************************************************************************************
.code 32
@*********************************************************************************************************
@ CRITICAL SECTION METHOD 3 FUNCTIONS
@
@ Description: Disable/Enable interrupts by preserving the state of interrupts. Generally speaking you
@ would store the state of the interrupt disable flag in the local variable 'cpu_sr' and then
@ disable interrupts. 'cpu_sr' is allocated in all of uC/OS-II's functions that need to
@ disable interrupts. You would restore the interrupt disable state by copying back 'cpu_sr'
@ into the CPU's status register.
@
@ Prototypes : OS_CPU_SR OS_CPU_SR_Save (void);
@ void OS_CPU_SR_Restore (OS_CPU_SR os_cpu_sr);
@
@
@ Note(s) : (1) These functions are used in general like this:
@
@ void Task (void *p_arg)
@ {
@ /* Allocate storage for CPU status register. */
@ #if (OS_CRITICAL_METHOD == 3)
@ OS_CPU_SR os_cpu_sr;
@ #endif
@
@ :
@ :
@ OS_ENTER_CRITICAL(); /* os_cpu_sr = OS_CPU_SR_Save(); */
@ :
@ :
@ OS_EXIT_CRITICAL(); /* OS_CPU_SR_Restore(cpu_sr); */
@ :
@ :
@ }
@*********************************************************************************************************
OS_CPU_SR_Save:
MRS R0, CPSR
ORR R1, R0, #OS_CPU_ARM_CONTROL_INT_DIS @ Set IRQ and FIQ bits in CPSR to disable all interrupts.
MSR CPSR_c, R1
BX LR @ Disabled, return the original CPSR contents in R0.
OS_CPU_SR_Restore:
MSR CPSR_c, R0
BX LR
@*********************************************************************************************************
@ START MULTITASKING
@ void OSStartHighRdy(void)
@
@ Note(s) : 1) OSStartHighRdy() MUST:
@ a) Call OSTaskSwHook() then,
@ b) Set OSRunning to TRUE,
@ c) Switch to the highest priority task.
@*********************************************************************************************************
OSStartHighRdy:
@ Change to SVC mode.
MSR CPSR_c, #(OS_CPU_ARM_CONTROL_INT_DIS | OS_CPU_ARM_MODE_SVC)
LDR R0, =OSTaskSwHook @ OSTaskSwHook();
MOV LR, PC
BX R0
LDR R0, =OSRunning @ OSRunning = TRUE;
MOV R1, #1
STRB R1, [R0]
@ SWITCH TO HIGHEST PRIORITY TASK:
LDR R0, =OSTCBHighRdy @ Get highest priority task TCB address,
LDR R0, [R0] @ Get stack pointer,
LDR SP, [R0] @ Switch to the new stack,
LDR R0, [SP], #4 @ Pop new task's CPSR,
MSR SPSR_cxsf, R0
LDMFD SP!, {R0-R12, LR, PC}^ @ Pop new task's context.
@*********************************************************************************************************
@ PERFORM A CONTEXT SWITCH (From task level) - OSCtxSw()
@
@ Note(s) : 1) OSCtxSw() is called in SVC mode with BOTH FIQ and IRQ interrupts DISABLED.
@
@ 2) The pseudo-code for OSCtxSw() is:
@ a) Save the current task's context onto the current task's stack,
@ b) OSTCBCur->OSTCBStkPtr = SP;
@ c) OSTaskSwHook();
@ d) OSPrioCur = OSPrioHighRdy;
@ e) OSTCBCur = OSTCBHighRdy;
@ f) SP = OSTCBHighRdy->OSTCBStkPtr;
@ g) Restore the new task's context from the new task's stack,
@ h) Return to new task's code.
@
@ 3) Upon entry:
@ OSTCBCur points to the OS_TCB of the task to suspend,
@ OSTCBHighRdy points to the OS_TCB of the task to resume.
@*********************************************************************************************************
OSCtxSw:
@ SAVE CURRENT TASK'S CONTEXT:
STMFD SP!, {LR} @ Push return address,
STMFD SP!, {LR}
STMFD SP!, {R0-R12} @ Push registers,
MRS R0, CPSR @ Push current CPSR,
TST LR, #1 @ See if called from Thumb mode,
ORRNE R0, R0, #OS_CPU_ARM_CONTROL_THUMB @ If yes, set the T-bit.
STMFD SP!, {R0}
LDR R0, =OSTCBCur @ OSTCBCur->OSTCBStkPtr = SP;
LDR R1, [R0]
STR SP, [R1]
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'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.
@*********************************************************************************************************
@ PERFORM A CONTEXT SWITCH (From interrupt level) - OSIntCtxSw()
@
@ Note(s) : 1) OSIntCtxSw() is called in SVC mode with BOTH FIQ and IRQ interrupts DISABLED.
@
@ 2) The pseudo-code for OSCtxSw() is:
@ a) OSTaskSwHook();
@ b) OSPrioCur = OSPrioHighRdy;
@ c) OSTCBCur = OSTCBHighRdy;
@ d) SP = OSTCBHighRdy->OSTCBStkPtr;
@ e) Restore the new task's context from the new task's stack,
@ f) Return to new task's code.
@
@ 3) Upon entry:
@ OSTCBCur points to the OS_TCB of the task to suspend,
@ OSTCBHighRdy points to the OS_TCB of the task to resume.
@*********************************************************************************************************
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'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.
@********************************************************************************************************
@ RESET EXCEPTION HANDLER
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -