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

📄 os_cpu_a.s

📁 S3C4510B是arm7内核的芯片
💻 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
    .include "asmdef.a"

	.EQU 	SwiV,		0x08
	.EQU 	IrqV,		0x18
	.EQU 	FiqV,		0x1C
	.EQU 	NoInt,		0x80

	.EQU	INTPEND,	0x03FF4004
	.EQU	BIT_TIMER0,	(0x1<<10)

	.EQU	SVC32Mode,	0x13
	.EQU	IRQ32Mode,	0x12
	.EQU	FIQ32Mode,	0x11

	.EQU	OSEnterSWI,	0x00

	.EQU	INTMSK,		0x1e0000c



#	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	OSIntNesting
addr_OSIntNesting:	.LONG	OSIntNesting

	.EXTERN	OSTimeTick
	.EXTERN ISR_IrqHandler
		
	.EXTERN OSIntEnter
	.EXTERN OSIntExit

	.EXTERN	OutDebug
	.EXTERN	BreakPoint


#	.GLOBAL	TickHandler
#TickHandler:
	.GLOBAL ArmIRQIsr
ArmIRQIsr:
	STMDB    sp!,{r0-r11,lr}

	#IMPORTANT CAUTION
	#Reseted!INTOFFSET'value is 0x000054.
    ldr	    r8,=INTOFFSET_ADDR
    ldr	    r8,[r8]

	cmp		r8, #0x00054			/* If all interrupt pending bits are "0", 	*/
									/* r8 may be 0x00054 sometimes.			*/
#	beq		HAVE_NOPENDING
	bne		HAVE_PENDING
	
HAVE_NOPENDING:
	LDMIA    sp!,{r0-r11,lr}
	subs	pc,lr,#4
	
HAVE_PENDING:
	mov		r8, r8, lsr #2
	str		r8, INTR_OFFSET		@STR OFFSET

	#clear pend bit
	mov		r9, #0x1
	mov r9, r9, lsl r8
#	mov r8, r8, lsl #2
	LDR	r10, =INTPEND
	STR	r9, [r10]

	#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, =INTPEND
#	LDR	r1, =BIT_TIMER0
#	STR	r1, [r0]

	#now context switching
	LDMIA    sp!,{r0-r11,lr}
	SUB		lr, lr, #4
	STR		lr, SAVED_LR		@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]	@ saved r12
	LDR		r12, SAVED_LR	@LDR r12, [pc, #SAVED_LR-.-8]
	STMFD	sp!, {r12}		@ r12 that PC of task
	SUB		sp, sp, #4		@ inclease stack point
	LDMIA	sp!, {r12}		@ restore r12
	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

	BL	OSIntEnter

	# OSIntNesting == 1?
	LDR	r4, addr_OSIntNesting
	LDR	r5, [r4]
	CMP r5, #1
	LDRNE	pc, =INTR_NESTING
	
	@ 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

INTR_NESTING:
	ldr		a1, INTR_OFFSET	@LDR a1, [pc, #INTR_OFFSET-.-8]

	bl	ISR_IrqHandler

	BL OSIntExit

#	CMP		a1, #0
#	LDRNE	pc, =_CON_SWAP

#_NOT_CON_SWAP:
	#not context switching
#	LDMIA    sp!,{r0-r11, lr}
#	SUBS	pc, lr, #4

#_CON_SWAP:
	# 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
_NO_CONSWAP:
	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:		.LONG		0
INTR_OFFSET:	.LONG		0

	.GLOBAL	OSIntCtxSw
OSIntCtxSw:
	# 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:		.LONG		0

#	void DisableInt(void)
#	void EnableInt(void)
#
#	Disable and enable IRQ and FIQ preserving current CPU mode.
#
	.GLOBAL	ARMDisableInt
ARMDisableInt:
	STMDB	sp!, {r0}
	MRS		r0, CPSR
	ORR		r0, r0, #NoInt
	MSR		CPSR_cxsf, r0
	LDMIA	sp!, {r0}
	MOV	pc, lr


	.GLOBAL	ARMEnableInt
ARMEnableInt:
	STMDB	sp!, {r0}
	MRS	r0, CPSR
	BIC	r0, r0, #NoInt
	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, #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.
	.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:
	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 + -