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

📄 os_cpu_a.s

📁 TCPIP协议栈
💻 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  I_ISPC,				0x1e00024
.EQU  INTMSK,				0x1e0000c

.EQU  OS_EnterOS,  0xff




#	AREA    subr, CODE, READONLY
	#; External symbols we need the addresses of
			.extern	OSTCBCur
			.extern	OSTCBHighRdy
			.extern	OSPrioCur
			.extern	OSPrioHighRdy
			.extern	OSTaskSwHook
			.extern	OSRunning
/*			
addr_OSTCBCur:		
            .WORD	OSTCBCur
addr_OSTCBHighRdy:	
			.WORD	OSTCBHighRdy
addr_OSPrioCur:		
			.WORD	OSPrioCur
addr_OSPrioHighRdy:
			.WORD	OSPrioHighRdy
*/

	.extern OSTaskSwHook
	.extern	need_to_swap_context
	.extern	OSTimeTick
	.extern OSIntEnter
	.extern OSIntExit
	.extern	IrqStart
	.extern	IrqFinish

	.extern	OutDebug
	.extern	BreakPoint

	.global	IRQContextSwap
	.global	TickHandler
	
	.global OSTickISR             
OSTickISR:	
	MOV       	ip, sp
	STMDB     	sp!, {fp, ip, lr, pc}
	SUB       	fp, ip, #4	

#	BL	OSIntEnter
	BL	OSTimeTick
#	BL	OSIntExit

	LDMDB     	fp, {fp, sp, pc}
#--------------------------------------------------------------------------------------

#;	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 OSStartHighRdy(void)
#;	
#;	Start the task with the highest priority#;
#;
#--------------------------------------------------------------------------------------
	 
    .global	OSStartHighRdy   
OSStartHighRdy:
	
	#; Need to be in a supervisor mode first, because of using spsr
	SWI	OS_EnterOS

	#; Call OSTaskSwHook()
	BL	OSTaskSwHook

	#; Set OSRunning to TRUE
	MOV	R0,#1
	LDR	R1,=OSRunning
	STRB	R0,[R1]
	

	#; Get stack ptr for task to resume (lives in OSTCBHighRdy->OSTCBStkPtr)
	LDR	R1,=OSTCBHighRdy
	LDR	R1,[R1]
	LDR	R0,[R1,#0]				/*; OSTCBStkPtr is at +0*/
	#;regdump	"Restoring context (OSStartHighRdy)", R0

	#; Restore saved context & return to task
	LDMFD	R0!,{R1,R14}				/*; SPSR & return addr*/
	MSR	SPSR_all,R1
	LDMFD	R0,{R0-R14}^				/*; Restore USR mode regs R0-R14*/
	NOP
	MOVS	PC,R14					/*; PC=ret addr & CPSR=SPSR*/

#--------------------------------------------------------------------------------------

	.global OS_TASK_SW
OS_TASK_SW:
# Call from OSSched()
# New Task Context switch  
	MOV	R2,R14
	MRS	R1,CPSR					/*; Take copy of current PSR*/
#	SWI	OS_EnterOS				/*; enter SVC mode*/
	BIC	R0,R1,#0x1f
	ORR	R0,R0,#0x92				/*; IRQ32 + interrupts off*/
	MSR	CPSR_all,R0
	NOP
	MSR	SPSR_all,R1				/*; SPSR=old PSR*/
#	ADD	R14,R2,#4				/*; R14_irq=return addr*/
	ADD	R14,R2,#0			/*; R14_irq=return addr*/
	#; Now in a state just like as if at 0x18
	B	OSCtxSw                            
#--------------------------------------------------------------------------------------

#;*********************************************************************************************************
#;                                PERFORM A CONTEXT SWITCH (From task level)
#;                                           void OSCtxSw(void)
#;
#;*********************************************************************************************************

OSCtxSw:
	STMFD	R13!,{R14}				/*; Stack return addr*/

	#; Save current task context
	STMDB	R13,{R13}^				/*; Determine R13_usr*/
	LDMDB	R13,{R14}
	STMFD	R14,{R0-R14}^				/*; Stack USR mode regs R0-R14*/
	MRS	R1, SPSR
	SUB	R0,R14,#15*4
	LDMFD	R13!,{R14}
	STMFD	R0!,{R1,R14}				/*; Stack SPSR & return addr*/

	#; Store stack ptr of task (lives in OSTCBCur->OSTCBStkPtr)
	LDR	R1,=OSTCBCur
	LDR	R1,[R1]
	STR	R0,[R1,#0]				/*; OSTCBStkPtr is at +0 */
	#; regdump	"Saving context (OSCtxSw)", R0
	
	#; Call user definable OSTaskSwHook()
	BL	OSTaskSwHook

	#; Set current task to new task
	LDR	R2,=OSTCBHighRdy
	LDR	R3,=OSTCBCur
	LDR	R4,=OSPrioHighRdy
	LDR	R5,=OSPrioCur
	LDR	R0,[R2]
	LDRB	R1,[R4]
	STR	R0,[R3]
	STRB	R1,[R5]

	#; Get stack ptr for task to resume (lives in OSTCBHighRdy->OSTCBStkPtr)
	LDR	R1,=OSTCBHighRdy
	LDR	R1,[R1]
	LDR	R0,[R1,#0]				/*; OSTCBStkPtr is at +0*/
	#; regdump	"Restoring context (OSCtxSw)", R0

	#; Restore saved context & return to task
	LDMFD	R0!,{R1,R14}				/*; SPSR & return addr*/
	MSR	SPSR_all,R1
	LDMFD	R0,{R0-R14}^			/*	; Restore USR mode regs R0-R14*/
	NOP
	MOVS    PC,R14					/*; PC=ret addr & CPSR=SPSR */
	
#;*********************************************************************************************************
#;                                PERFORM A CONTEXT SWITCH (From an ISR)
#;                                        void OSIntCtxSw(void)
#;
#;*********************************************************************************************************
	.global OSIntCtxSw
OSIntCtxSw:
	#; Remove all registers on IRQ stack so far
	#; This means the order in which things were called before calling this
	#; In our case, this means OSIntExit, the ISR routine and then anything which
	#; called the ISR (eg; a HAL like NedHAL)
	#; Regs stacked WILL BE DIFFERENT DEPENDING ON COMPILER VERSION

	#; Remove OSIntExit() stacked regs from ISR stack
	#; v2.5: {r14}
	#; v2.0: {r11,r12,r14,pc} 
	#;ADD	R13,R13,#4		; v2.5
	# SystemIrqHandler call ISR_IrqHandler, ISR_IrqHandler call OSTickISR, 
	# OSTickISR call OSIntExit(), OsIntExit then 
	# call OSIntCtxSw, so we need to remove this stack structure, otherwise after
	# a certain time, there will be no more IRQ stack left 
	LDMDB fp, {fp,sp,lr}    /* simulate quit OSIntExit stack  */
#	LDMDB fp, {fp,sp,lr}    /* simulate quit OSTickISR stack  */
    LDMDB fp,  {fp, sp, lr}	/* simulate quit ISR_IrqHandler orISR_FiqHandler stack */
    LDMFD	sp!, {r0-r12, lr}  /* simulate quit SystemIrqHandler stack */
    SUB lr,lr,#4               /* IRQ return address */
	#; Perform normal task swap
	B	OSCtxSw


#	END

⌨️ 快捷键说明

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