📄 os_cpu_a1.s
字号:
#------------------------------------------------------------------------------
#- File: os_cpu_a.s
#------------------------------------------------------------------------------
#- (c) Copyright ARM Limited 1999. All rights reserved.
#-
#- ARM Specific code
#------------------------------------------------------------------------------
#-
#-
#- Functions defined in this module:
#-
#- OS_CPU_SR GetProcST_DisableIntr(void) disable interrupts when in SVC
#- void SetProcST(OS_CPU_SR cpu_sr) enable interrupts when in SVC
#- void OS_TASK_SWAP(void) context switch
#- void OSStartHighRdy(void) start highest priority task
#################define some constants##############
.EQU NoIRQ, 0x80
.EQU INTPEND, 0x03FF4004
.EQU BIT_TIMER0, (0x1<<10)
.EQU SVC32Mode, 0x13
.EQU IRQ32Mode, 0x12
.EQU FIQ32Mode, 0x11
# AREA |subr|, CODE, READONLY
######## External symbols we need the addresses of##########
# .EXTERN OSTCBCur
#addr_OSTCBCur: .LONG OSTCBCur
# .EXTERN OSTCBHighRdy
#addr_OSTCBHighRdy: .LONG OSTCBHighRdy
# .EXTERN OSPrioCur
#addr_OSPrioCur: .LONG OSPrioCur
# .EXTERN OSPrioHighRdy
#addr_OSPrioHighRdy: .LONG OSPrioHighRdy
# .EXTERN OSRunning
#addr_OSRunning: .LONG OSRunning
# .EXTERN OSIntNesting
#addr_OSIntNesting: .LONG OSIntNesting
#########declare all external variables and functions#########
# .extern OSIntEnter
# .extern OSIntExit
# .extern OSTimeTick
#############all functions realized###############
.GLOBAL Timer0IRQHandler
Timer0IRQHandler: @ 中断向量
.extern TickHandler
# SUBS lr,lr,#4
# STMFD sp!,{lr}
# ADD lr,lr,#4
STMFD sp!, {r0-r12, lr} @ 中断栈保存
MRS r4, CPSR
STMFD sp!, {r4} @ save current PSR
MRS r4, SPSR @ YYY+
STMFD sp!, {r4} @ YYY+ save SPSR
#(Clear pending bit of INTPEND that don't accessed it.)
# rI_ISPC= BIT_TIMER0;
LDR r0, =INTPEND
LDR r1, =BIT_TIMER0
STR r1, [r0]
#;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
#Change Supervisor mode
#!!!r12 register don't preserved. (r12 that PC of task)
# MRS lr, SPSR
# AND lr, lr, #0xFFFFFFE0
# ORR lr, lr, #0x13
# MSR CPSR_cxsf, lr
# BL TickHandler @ 中断C处理函数
BL OSIntEnter
#OSIntNesting == 1?
LDR r4, addr_OSIntNesting
LDR r5,[r4]
CMP r5, #1
LDRNE pc, =INTRNESTING
# Get current task TCB address
#and store sp to preempted tasks's TCB
# LDR r4, addr_OSTCBCur
# LDR r5, [r4]
# STR sp, [r5] @ store sp in preempted tasks's TCB
#INTRNESTING:
# BL OSTimeTick
# BL OSIntExit
_NOCTXSW:
LDMFD sp!, {r4} @ YYY+
MSR SPSR_cxsf, r4 @ YYY+
LDMFD sp!, {r4} @ YYY+
MSR CPSR_cxsf, r4 @ YYY+
LDMFD sp!, {r0-r12, lr,pc} @ 恢复中断栈
# .GLOBAL OSIntCtxSw
#OSIntCtxSw:
#BL OSTaskSwHook
#;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
#Change Supervisor mode
#!!!r12 register don't preserved. (r12 that PC of task)
# MRS lr, SPSR
# AND lr, lr, #0xFFFFFFE0
# ORR lr, lr, #0x13
# MSR CPSR_cxsf, lr
##############################
#now lay in supervisor mode
##############################
# OSPrioCur = OSPrioHighRdy
# LDR r4, addr_OSPrioCur
# LDR r5, addr_OSPrioHighRdy
# LDRB r6, [r5]
# STRB r6, [r4]
# Get current task TCB address
# LDR r4, addr_OSTCBCur
# Get highest priority task TCB address
# LDR r6, addr_OSTCBHighRdy
# LDR r6, [r6]
# OSTCBCur = OSTCBHighRdy
# STR r6, [r4] @ set new current task TCB address
# LDR sp, [r6] @ give new task's stack pointer to sp
# LDMFD sp!, {r4} @ YYY+
# MSR SPSR_cxsf, r4 @ YYY+
# LDMFD sp!, {r4} @ YYY+
# MSR CPSR_cxsf, r4 @ YYY+
# LDMFD sp!, {r0-r12, lr, pc} @ YYY+
# OS_CPU_SR GetProcST_DisableIntr(void)
# void SetProcST(OS_CPU_SR cpu_sr)
#
# Disable and enable IRQ and FIQ preserving current CPU mode.
#
# .GLOBAL GetProcST_DisInt
#GetProcST_DisInt:
# STMDB sp!, {r8}
# MRS a1, CPSR
# ORR r8, a1, #NoIRQ
# MSR CPSR_cxsf, r8
# LDMIA sp!, {r8}
# MOV pc, lr
# .GLOBAL SetProcST
#SetProcST:
# MSR CPSR_cxsf, a1
# MOV pc, lr
# .GLOBAL ARMDisableInt
#ARMDisableInt:
# STMDB sp!, {r0}
# MRS r0, CPSR
# ORR r0, r0, #NoIRQ
# MSR CPSR_cxsf, r0
# LDMIA sp!, {r0}
# MOV pc, lr
# .GLOBAL ARMEnableInt
#ARMEnableInt:
# STMDB sp!, {r0}
# MRS r0, CPSR
# BIC r0, r0, #NoIRQ
# MSR CPSR_cxsf, r0
# LDMIA sp!, {r0}
# MOV pc, lr
# .GLOBAL ARMIsDisableInt
#ARMIsDisableInt: @return value [disable: 1 enable: 0]
# MRS a1, CPSR
# AND a1, a1, #NoIRQ
# MOV pc, lr
# void OSCtxSw(void)
#
# Perform a context switch.
#
# On entry, OSTCBCur and OSPrioCur hold the current TCB and priority
# and OSTCBHighRdy and OSPrioHighRdy contain the same for the task
# to be switched to.
#
# The following code assumes that the virtual memory is directly
# mapped into physical memory. If this is not true, the cache must
# be flushed at context switch to avoid address aliasing.
# .GLOBAL OSCtxSw
#OSCtxSw:
# STMFD sp!, {lr} @ save pc
# STMFD sp!, {lr} @ save lr
# STMFD sp!, {r0-r12} @ save register file and ret address
# MRS r4, CPSR
# STMFD sp!, {r4} @ save current PSR
# MRS r4, SPSR @ YYY+
# STMFD sp!, {r4} @ YYY+ save SPSR
#
# OSPrioCur = OSPrioHighRdy
# LDR r4, addr_OSPrioCur
# LDR r5, addr_OSPrioHighRdy
# LDRB r6, [r5]
# STRB r6, [r4]
@ Get current task TCB address and save current task stack pointer
# LDR r4, addr_OSTCBCur
# LDR r5, [r4]
# STR sp, [r5] @ store sp in preempted tasks's TCB
# Get highest priority task TCB address
# LDR r6, addr_OSTCBHighRdy
# LDR r6, [r6]
# LDR sp, [r6] @ get new task's stack pointer
# OSTCBCur = OSTCBHighRdy
# STR r6, [r4] @ set new current task TCB address
# LDMFD sp!, {r4} @ YYY+
# MSR SPSR_cxsf, r4 @ YYY+
# LDMFD sp!, {r4} @ YYY+
# MSR CPSR_cxsf, r4 @ YYY+
# LDMFD sp!, {r0-r12, lr, pc} @ YYY+
# void OSStartHighRdy(void)
#
# Start the task with the highest priority;
#
# .GLOBAL OSStartHighRdy
#OSStartHighRdy:
#.extern OSTaskSwHook
#BL OSTaskSwHook
# LDR r4, addr_OSTCBCur @ Get current task TCB address
# LDR r5, addr_OSTCBHighRdy @ Get highest priority task TCB address
# LDR r5, [r5] @ get stack pointer
# LDR sp, [r5] @ switch to the new stack
# STR r5, [r4] @ set new current task TCB address
# LDMFD sp!, {r4} @ YYY
# MSR SPSR_cxsf, r4
# LDMFD sp!, {r4} @ get new state from top of the stack
# MSR CPSR_cxsf, r4 @ CPSR should be SVC32Mode
# LDMFD sp!, {r0-r12, lr, pc } @ start the new task
.END
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -