📄 os_cpu_a.s
字号:
;*
;* File: os_cpu_a.s
;*
;* (c) Copyright ARM Limited 1999. All rights reserved.
;*
;* ARM Specific code
;*
;*
;
; Functions defined in this module:
;
; void ARMDisableInt(void) /* disable interrupts when in SVC */
; void ARMEnableInt(void) /* enable interrupts when in SVC */
; void OS_TASK_SWAP(void) /* context switch */
; void OSStartHighRdy(void) /* start highest priority task */
SwiV EQU 0x08
IrqV EQU 0x18
FiqV EQU 0x1C
NoInt EQU 0x80
SVC32Mode EQU 0x13
IRQ32Mode EQU 0x12
FIQ32Mode EQU 0x11
OSEnterSWI EQU 0x00
BIT_TIMER0 EQU (0x1<<13)
I_ISPC EQU 0x1e00024
INTMSK EQU 0x1e0000c
AREA |subr|, CODE, READONLY
;----------------------------------------------------------------------------------------------------------
; 本模块中所需的扩展符号地址
;----------------------------------------------------------------------------------------------------------
IMPORT OSTCBCur
IMPORT OSTCBHighRdy
IMPORT OSPrioCur
IMPORT OSPrioHighRdy
addr_OSTCBCur DCD OSTCBCur
addr_OSTCBHighRdy DCD OSTCBHighRdy
addr_OSPrioCur DCD OSPrioCur
addr_OSPrioHighRdy DCD OSPrioHighRdy
IMPORT need_to_swap_context
IMPORT IrqStart
IMPORT OSTimeTick
IMPORT IrqFinish
IMPORT BreakPoint
;----------------------------------------------------------------------------------------------------------
; void IRQContextSwap(void);
;----------------------------------------------------------------------------------------------------------
EXPORT IRQContextSwap
IRQContextSwap
LDMIA sp!,{a1-v1, lr}
SUBS pc, lr, #4
SUB lr, lr, #4
MOV r12, lr
MRS lr, SPSR
AND lr, lr, #0xFFFFFFE0
ORR lr, lr, #0xD3
MSR CPSR_cxsf, lr
;----------------------------------------------------------------------------------------------------------
; void __Tick(void); TIMER0 定时器中断处理,用于操作系统的时间片调度
;----------------------------------------------------------------------------------------------------------
EXPORT __Tick
__Tick
STMDB sp!,{r0-r11,lr}
; 禁止中断(不是必要的代码)
mrs r0, CPSR
orr r0, r0, #0x80 ; 设置 IRQ 禁止标记
msr CPSR_cxsf, r0
; 中断结束(清除INTPEND中的悬挂位以避免对基进行操作)
; rI_ISPC= BIT_TIMER0;
LDR r0, =I_ISPC
LDR r1, =BIT_TIMER0
STR r1, [r0]
BL IrqStart
BL OSTimeTick
BL IrqFinish
LDR r0, =need_to_swap_context
LDR r2, [r0]
CMP r2, #1
LDREQ pc, =_CON_SW
_NOT_CON_SW
;not context switching
LDMIA sp!,{r0-r11, lr}
SUBS pc, lr, #4
_CON_SW
; 设置 need_to_swap_context 标记为 '0'
MOV r1, #0
STR r1, [r0]
; 上下文切换
LDMIA sp!,{r0-r11,lr}
SUB lr, lr, #4
STR lr, [pc, #SAVED_LR-.-8]
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;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 Supervisor mode
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
STR r12, [sp, #-8] ; 保存 r12
LDR r12, [pc, #SAVED_LR-.-8]
STMFD sp!, {r12} ; r12 that PC of task
SUB sp, sp, #4 ; inclease stack point
LDMIA sp!, {r12} ; 恢复 r12
STMFD sp!, {lr} ; 保存 lr
STMFD sp!, {r0-r12} ; 保存寄存器文件并返回地址
MRS r4, CPSR
STMFD sp!, {r4} ; 保存当前 PSR
MRS r4, SPSR ; YYY+
STMFD sp!, {r4} ; YYY+ 保存 SPSR
; OSPrioCur = OSPrioHighRdy
LDR r4, addr_OSPrioCur
LDR r5, addr_OSPrioHighRdy
LDRB r6, [r5]
STRB r6, [r4]
; 获取当前任务的 TCB 地址
LDR r4, addr_OSTCBCur
LDR r5, [r4]
STR sp, [r5] ; 保存 sp in preempted tasks's TCB
; 获取最高优先级任务的 TCB 地址
LDR r6, addr_OSTCBHighRdy
LDR r6, [r6]
LDR sp, [r6] ; 获取新的任务栈指针
; OSTCBCur = OSTCBHighRdy
STR r6, [r4] ; 设置新的当前任务 TCB 地址
LDMFD sp!, {r4} ; YYY+
; AND r4, r4, #0xFFFFFF20
; ORR r4, r4, #0x13
MSR SPSR_cxsf, r4 ; YYY+
LDMFD sp!, {r4} ; YYY+
; AND r4, r4, #0xFFFFFF20
; ORR r4, r4, #0x13
MSR CPSR_cxsf, r4 ; YYY+
LDMFD sp!, {r0-r12, lr, pc} ; YYY+
SAVED_LR DCD 0
;----------------------------------------------------------------------------------------------------------
; void DisableInt(void); 在当前 CPU 模式下禁止 IRQ 及 FIQ
;----------------------------------------------------------------------------------------------------------
EXPORT ARMDisableInt
ARMDisableInt
STMDB sp!, {r0}
MRS r0, CPSR
ORR r0, r0, #NoInt
MSR CPSR_cxsf, r0
LDMIA sp!, {r0}
MOV pc, lr
;----------------------------------------------------------------------------------------------------------
; void AEMEnableInt(void); 在当前 CPU 模式下允许 IRQ 及 FIQ
;----------------------------------------------------------------------------------------------------------
EXPORT ARMEnableInt
ARMEnableInt
STMDB sp!, {r0}
MRS r0, CPSR
BIC r0, r0, #NoInt
MSR CPSR_cxsf, r0
LDMIA sp!, {r0}
MOV pc, lr
;----------------------------------------------------------------------------------------------------------
; void OS_TASK_SW(void); 执行一次上下文切换
;
; 在进入入口前,OSTCBCur 及 OSPrioCur 保存了当前 TCB 及优先级,
; 而 OSTCBHighRdy 和 OSPrioHighRdy 则包含了了将要被切换至的任务的 TCB 及优先级。
;
; 下面的代码以假设虚拟内存被直接映射到物理内存为前提。否则,缓存必须在上下文切换时刷新以避免地址失真。
;----------------------------------------------------------------------------------------------------------
EXPORT OS_TASK_SW
OS_TASK_SW
STMFD sp!, {lr} ; 保存 pc
STMFD sp!, {lr} ; 保存 lr
STMFD sp!, {r0-r12} ; 保存 register file and ret address
MRS r4, CPSR
STMFD sp!, {r4} ; 保存当前 PSR
MRS r4, SPSR ; YYY+
STMFD sp!, {r4} ; YYY+ 保存 SPSR
; OSPrioCur = OSPrioHighRdy
LDR r4, addr_OSPrioCur
LDR r5, addr_OSPrioHighRdy
LDRB r6, [r5]
STRB r6, [r4]
; 获取当前任务 TCB 地址
LDR r4, addr_OSTCBCur
LDR r5, [r4]
STR sp, [r5] ; store sp in preempted tasks's TCB
; 获取最高优先级任务的 TCB 地址
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); 启动拥有最高优先级的任务
;----------------------------------------------------------------------------------------------------------
EXPORT OSStartHighRdy
OSStartHighRdy
LDR r4, addr_OSTCBCur ; 获取当前任务的 TCB 地址
LDR r5, addr_OSTCBHighRdy ; 获取最高优先级任务的 TCB 地址
LDR r5, [r5] ; 获取栈指针
LDR sp, [r5] ; switch to the new stack
STR r5, [r4] ; 设置新的当前任务 TCB 地址
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 } ; 启动新任务
END
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -