⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 os_cpu_a.s

📁 基于ARM应用的源码
💻 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 + -