📄 os_cpu_a_gnu.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.ASM
# Version : V1.60
# By : Jean J. Labrosse
#
# For : ARM7 or ARM9
# Mode : ARM or Thumb
# Toolchain : ARM Developer Suite Version 1.2 and higher
#********************************************************************************************************
.extern OSRunning /* External references */
.extern OSPrioCur
.extern OSPrioHighRdy
.extern OSTCBCur
.extern OSTCBHighRdy
.extern OSIntNesting
.extern OSIntExit
.extern OSTaskSwHook
.extern OSTimeTickISRHandler
.extern OSTimeTick
.global OS_CPU_SR_Save /* Functions declared in this file */
.global OS_CPU_SR_Restore
.global OSStartHighRdy
.global OSCtxSw
.global OSIntCtxSw
.global OSTimeTickISR
.equ NO_INT, 0xC0 /* Mask used to disable interrupts (Both FIR and IRQ) */
.equ SVC32_MODE, 0x13
.equ FIQ32_MODE, 0x11
.equ IRQ32_MODE, 0x12
.text
#*********************************************************************************************************
# 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,#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
#*********************************************************************************************************
# 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, #0xD3 /* Switch to SVC mode with IRQ and FIQ disabled */
LDR R0, =OSTaskSwHook /* OSTaskSwHook(); */
MOV LR, PC
BX R0
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 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:
/* SAVE CURRENT TASK'S CONTEXT */
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 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 */
#*********************************************************************************************************
# 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 R6,=OSTCBHighRdy
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 */
#*********************************************************************************************************
# Time Tick IRQ Interrupt Service Routine
#*********************************************************************************************************
OSTimeTickISR:
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, =OSIntNesting /* 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, =OSTCBCur /* OSTCBCur->OSTCBStkPtr = SP; */
LDR R5, [R4]
STR SP, [R5] /* } */
OS_CPU_IRQ_ISR_1:
MSR CPSR_c, #(NO_INT | IRQ32_MODE) /* Change to IRQ mode (to use the IRQ stack to handle interrupt) */
LDR R0, =OSTimeTickISRHandler /* OSTimeTickISRHandler(); */
MOV LR, PC
BX R0
LDR R0, =OSTimeTick /* OSTimeTick(); */
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 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 */
.ltorg
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -