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

📄 os_cpu_a.s

📁 一个在KEIL公司的MDK3.20编译通过运行的基于S3C44B0X芯片的UCOSII源代码
💻 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

	  PRESERVE8

	AREA	|subr|, CODE, READONLY

	; External symbols we need the addresses of
			IMPORT	OSTCBCur
addr_OSTCBCur		DCD	OSTCBCur
			IMPORT	OSTCBHighRdy
addr_OSTCBHighRdy	DCD	OSTCBHighRdy
			IMPORT	OSPrioCur
addr_OSPrioCur		DCD	OSPrioCur
			IMPORT	OSPrioHighRdy
addr_OSPrioHighRdy	DCD	OSPrioHighRdy

	IMPORT	need_to_swap_context
	IMPORT	OSRunning
	IMPORT	IrqStart
	IMPORT	OSTimeTick
	IMPORT	IrqFinish
	IMPORT  OSIntNesting

;	IMPORT	OutDebug
	IMPORT	BreakPoint
	EXPORT	IRQContextSwap
	EXPORT	TickHandler

	IMPORT	OSIntEnter
	IMPORT	OSIntExit
	IMPORT  DoInt4567Isr
	
; 此段代码不会执行	
IRQContextSwap
	LDMIA	sp!,{a1-v1, lr}
	SUBS	pc, lr, #4
	
; 时钟中断服务程序
TickHandler
	STMDB    sp!,{r0-r11,lr}

	;interrupt disable(not nessary)
	mrs		r0, CPSR
	orr		r0, r0, #0x80		; and set IRQ disable flag
	msr		CPSR_cxsf, r0
	
	; End of interrupt
	; (Clear pending bit of INTPEND that don't accessed it.)
	; rI_ISPC= BIT_TIMER0;
	LDR	r0, =I_ISPC
	LDR	r1, =BIT_TIMER0
	STR	r1, [r0]

	BL	IrqStart
	
	BL	OSTimeTick

	BL	IrqFinish
	
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; 判断是否需要进行context switch																			;
; 若需要切换则跳转到_CON_SWAP																				;
; 若不需切换则跳转到_NOT_CN_SWAP																			;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

	LDR	r0, =need_to_swap_context
	LDR	r2, [r0]
	CMP	r2, #1
	LDREQ	pc, =_CON_SWAP

_NOT_CON_SWAP
	LDMIA	sp!,{r0-r11, lr}
	SUBS	pc, lr, #4

_CON_SWAP
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; context switch前的准备工作																				;
; 首先将need_to_swap_context清零																			;
; 由于进入中断的时候保存了被中断任务的r0-r11,所以在开始context switch前要先将堆栈复原							;
; 计算出被中断任务的返回指针,并暂存到SAVED_LR																;
; 由irq模式切换到svc模式																					;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

	MOV		r1, #0
	STR		r1, [r0]

	LDMIA	sp!,{r0-r11,lr}
	SUB		lr, lr, #4
	STR		lr, SAVED_LR

	MRS		lr, SPSR
	AND		lr, lr, #0xFFFFFFE0
	ORR		lr, lr, #0x13
	MSR		CPSR_cxsf, lr

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; 模式转换完成后,开始context switch																		;
; 堆栈内容的变化																							;
;					1			2			3			4			5			6						;
;H	sp	|---|	 sp	|---|		|---|		|---|	 	|---|		|---|		|---|					;
;		|   |	 	|   |	 sp	|_LR|	 	|_LR|	 sp	|_LR|		|_LR|		|_LR|					;
;		|   |	    |r12|		|r12|	 sp	|r12|		|   |>r12 sp|lr |		|lr |					;
;L		|   |	    |   |	    |   |	 	|   |		|   |		|   |		|r12|					;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
	STR		r12, [sp, #-8]			; 暂存r12								;1
	LDR		r12, SAVED_LR			; 载入任务返回指针
	STMFD	sp!, {r12}				; 将返回指针存储到栈顶						;2
	SUB		sp, sp, #4				; 调整堆栈指针指向r12的位置				;3
	LDMIA	sp!, {r12}				; 恢复r12								;4
	STMFD	sp!, {lr}				; 开始依次保存各寄存器						;5
	STMFD	sp!, {r0-r12}			; 										;6
	MRS		r4, CPSR				;
	STMFD	sp!, {r4}				; 
	MRS		r4, SPSR				; 
	STMFD	sp!, {r4}				; 

	; 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
	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+

SAVED_LR		DCD		0

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; ARMDisableInt		禁止中断																				;
; ARMEnableINt		允许中断																				;
; AEMIsDisableInt	查询中断状态																			;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

	EXPORT	ARMDisableInt
ARMDisableInt
	STMDB	sp!, {r0}
	MRS		r0, CPSR
	ORR		r0, r0, #NoInt
	MSR		CPSR_cxsf, r0
	LDMIA	sp!, {r0}
    MOV		pc, lr

	EXPORT	ARMEnableInt
ARMEnableInt
	STMDB	sp!, {r0}
	MRS		r0, CPSR
	BIC		r0, r0, #NoInt
	MSR		CPSR_cxsf, r0
	LDMIA	sp!, {r0}
	MOV		pc, lr

	EXPORT	ARMIsDisableInt
ARMIsDisableInt						;return value [disable: 1      enable: 0]
	MRS		a1, CPSR
	AND		a1, a1, #NoInt
    MOV		pc, lr	

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; void OS_TASK_SW(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.			;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

	EXPORT	OS_TASK_SW
OS_TASK_SW
	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
	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																;											
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

	EXPORT	OSStartHighRdy
OSStartHighRdy
	LDR		r0, =OSRunning			; OSRunning = 1
	MOV		r1, #1
    STRB	r1, [r0]
	
	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


K_LINK_SAVE	DCD		0
K_PSR_SAVE	DCD		0
	EXPORT 	OSEINT4567ISR
OSEINT4567ISR
	STMFD	sp!, {r4}
	LDR		r4, =K_LINK_SAVE
	STR		lr, [r4]				 ; LINK_SAVE = lr_irq
	MRS		lr,	spsr
	STR		lr, [r4, #4]			 ; PSR_SAVE = spsr_irq
	LDMFD	sp!, {r4}
	ORR		lr, lr,	#0x80			 ; Mask irq for context switching before 
	MSR		cpsr_cxsf, lr 			 ; returning back from irq mode.

	SUB		sp, sp, #4				 ; Space for PC
	STMFD	sp!, {r0-r12, lr}
	LDR		r4, =K_LINK_SAVE
	LDR		lr, [r4, #0]
	SUB		lr, lr, #4				 ; lr = LINK_SAVE - 4,
	STR		lr, [sp, #(14*4)]		 ; the return address for pc.
	LDR		r4, [r4, #4]			 ; r4 = PSR_SAVE,
	STMFD	sp!, {r4}		         ; CPSR of the task



	BL	    OSIntEnter
	LDR     r4, =OSIntNesting
	LDRB    r4, [r4]
	CMP     r4, #1
	LDRNE	pc, =_LDRSP

	LDR		r4, addr_OSTCBCur
	LDR		r4, [r4]
	STR		sp, [r4]				 ; OSTCBCur -> stkptr = sp

_LDRSP
	BL      DoInt4567Isr
	BL	    OSIntExit

	LDMFD 	sp!, {r4}                ; pop new task cpsr
	MSR 	cpsr_cxsf, r4
	LDMFD 	sp!, {r0-r12,lr,pc}      ; pop new task r0-r12,lr & pc
	

	END
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;end of Os_cpu_a.s;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -