📄 os_cpu_a.s
字号:
;---------------------------------------------------------------------------------------------------
;- uC/OS-II
;- The Real-Time Kernel
;-
;- (c) Copyright 1992-2004, Micrium, Weston, FL
;- All Rights Reserved
;-
;- Generic ARM Port
;-
;- File : OS_CPU_A.S
;- Version : V1.60
;- By : Jean J. Labrosse
;-
;- For : ARM7 or ARM9
;- Mode : ARM or Thumb
;- Toolchain : IAR-s EWARM V4.11a and higher
;---------------------------------------------------------------------------------------------------
ARM_MODE_USER EQU 0x10
ARM_MODE_FIQ EQU 0x11
ARM_MODE_IRQ EQU 0x12
ARM_MODE_SVC EQU 0x13
ARM_MODE_ABORT EQU 0x17
ARM_MODE_UNDEF EQU 0x1B
ARM_MODE_SYS EQU 0x1F
I_BIT EQU 0x80
F_BIT EQU 0x40
T_BIT EQU 0x20
IMPORT OSRunning ; External references
IMPORT OSPrioCur
IMPORT OSPrioHighRdy
IMPORT OSTCBCur
IMPORT OSTCBHighRdy
IMPORT OSIntNesting
IMPORT OSIntExit
EXPORT OS_CPU_SR_Save ; Functions declared in this file
EXPORT OS_CPU_SR_Restore
EXPORT OSStartHighRdy
EXPORT OSCtxSw
EXPORT OSIntCtxSw
AREA OSCtxOPs, CODE, READONLY
CODE32
;---------------------------------------------------------------------------------------------------
;- 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
msr CPSR_c, #I_BIT:OR:F_BIT:OR:ARM_MODE_SVC ;- 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
ldmfd sp!, {r4} ;- pop new task-s CPSR
msr SPSR_cxsf, r4
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 SYS 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
stmfd sp!, {lr}
stmfd sp!, {r0-r12, lr}
mrs r0, SPSR
stmfd sp!, {r0}
ldr r4, =OSPrioCur ;- OSPrioCur = OSPrioHighRdy
ldr r5, =OSPrioHighRdy
ldrb r6, [r5]
strb r6, [r4]
ldr r1, =OSTCBCur ;- OSTCBCur->OSTCBStkPtr = SP;
ldr r2, [r1]
str sp, [r2]
ldr r5, =OSTCBHighRdy ;- OSTCBCur = OSTCBHighRdy;
ldr r6, [r5]
str r6, [r1]
ldr sp, [r6] ;- SP = OSTCBHighRdy->OSTCBStkPtr;
ldmfd sp!, {r4} ;- pop new task-s CPSR
msr SPSR_cxsf, r4
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 SYS 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 r4, =OSPrioCur ;- OSPrioCur = OSPrioHighRdy
ldr r5, =OSPrioHighRdy
ldrb r6, [r5]
strb r6, [r4]
ldr r4, =OSTCBCur ;- OSTCBCur = OSTCBHighRdy;
ldr r5, =OSTCBHighRdy
ldr r6, [r5]
str r6, [r4]
ldr sp, [r6] ;- SP = OSTCBHighRdy->OSTCBStkPtr;
ldmfd sp!, {r4} ;- pop new task-s CPSR
msr SPSR_cxsf, r4
ldmfd sp!, {r0-r12, lr, pc}^ ;- pop new task-s context
;---------------------------------------------------------------------------------------------------
;- 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 cpu_sr);
;-
;-
;- Note(s) : 1) These functions are used in general like this:
;-
;- void Task (void *p_arg)
;- {
;- #if OS_CRITICAL_METHOD == 3 /* Allocate storage for CPU status register */
;- OS_CPU_SR cpu_sr;
;- #endif
;-
;- :
;- :
;- OS_ENTER_CRITICAL(); /* cpu_sr = OS_CPU_SaveSR(); */
;- :
;- :
;- OS_EXIT_CRITICAL(); /* OS_CPU_RestoreSR(cpu_sr); */
;- :
;- :
;- }
;-
;- 2) OS_CPU_SaveSR() is implemented as recommended by Atmel-s application note:
;-
;- "Disabling Interrupts at Processor Level"
;---------------------------------------------------------------------------------------------------
OS_CPU_SR_Save
mrs r0, CPSR ; Set IRQ and FIQ bits in CPSR to disable all interrupts
orr r1, r0, #I_BIT:OR:F_BIT
msr CPSR_c, r1
mrs r1, CPSR ; Confirm that CPSR contains the proper interrupt disable flags
and r1, r1, #I_BIT:OR:F_BIT
cmp r1, #I_BIT:OR:F_BIT
bne OS_CPU_SR_Save ; Not properly disabled (try again)
mov pc, lr ; Disabled, return the original CPSR contents in R0
OS_CPU_SR_Restore
msr CPSR_c, R0
mov pc, lr
END
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -