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

📄 os_cpu_a.s

📁 ucos源码
💻 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

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

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

	.EQU	OSEnterSWI,	0x00

	.EQU	BIT_TIMER0,	(0x1<<13)
	.EQU    BIT_EINT1,  (0x1<<24)
	.EQU	I_ISPC,		0x1e00024
	.EQU	INTMSK,		0x1e0000c
	.EQU    EXTINTPND,  0x1d20054



#	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	need_to_swap_context
	.EXTERN	IrqStart
	.EXTERN	OSTimeTick
	.EXTERN	IrqFinish
	
	.EXTERN IrqStartKey
	
	.EXTERN OSIntEnter
	.EXTERN OSIntExit
	
	.EXTERN	OutDebug
	.EXTERN	BreakPoint

	.GLOBAL	IRQContextSwap
	.GLOBAL	TickHandler
	.GLOBAL	keyscan
	
IRQContextSwap:
	MOV	a1, #1
	MOV	lr, pc	
	
keyscan:
	STMDB    sp!,{r0-r11,lr}
	#interrupt disable
	
	mrs     r0, CPSR
	orr     r0, r0, #0x80      @disable irq interrupt flag write cpsr
	msr     CPSR_cxsf, r0
	
	#End of interrupt
	#(Clear pending bit of INTPEND that don't accessed it.)
	#	rI_ISPC= BIT_EINT1;
	LDR    r0,=I_ISPC
	LDR    r1,=BIT_EINT1
	STR    r1,[r0]

#	BL   OSIntEnter
	
	
#	BL   OSIntExit
	BL    IrqStart
	
#	BL	OSTimeTick

	BL	IrqFinish		@a1= return value	0:not context switch, otherwise:context switch

	CMP		a1, #0
	LDRNE	pc, =_CONQHY_SWAP
	

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


_CONQHY_SWAP:
	#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


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








	
		

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]

#	LDR r0, =EXTINTPND
#	LDR 

	BL	IrqStart
	
	BL	OSTimeTick

	BL	IrqFinish		@a1= return value	0:not context switch, otherwise:context switch

	CMP		a1, #0
	LDRNE	pc, =_CON_SWAP


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


_CON_SWAP:
	#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


	# 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+
#	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:		.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	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;
#
	.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 + -