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

📄 os_cpu_a.s

📁 c的源码
💻 S
字号:
;********************************************************************************************************
;                                               uC/OS-II
;                                         The Real-Time Kernel
;
;                        (c) Copyright 1992-1998, Jean J. Labrosse, Plantation, FL
;                                          All Rights Reserved
;
;
;                                           ARM Specific code
;
; File : OS_CPU_A.s
; By   : N. Douglas (3rd April 2000)
;********************************************************************************************************

	AREA	OS_CPU_A, CODE, READONLY

	EXPORT	OSStartHighRdy
	EXPORT	OSCtxSw
	EXPORT	OSIntCtxSw
	EXPORT	OSTaskSw
	EXPORT	OSStackAndDisableInts
	EXPORT	OSRestoreStackedIntState

	IMPORT	OSTaskSwHook
	IMPORT	OSRunning
	IMPORT	OSTCBHighRdy
	IMPORT	OSTCBCur
	IMPORT	OSPrioHighRdy
	IMPORT	OSPrioCur

; Handy SWI definitions
OS_EnterOS	EQU	0x16

	[ 1=0
; Handy register dump macro (NEEDS NEDHAL)
	IMPORT	DbgIO_WriteF
	MACRO
	regdump		$txt, $src
	; R0=reg list (R14_usr, R13_usr, R12-R0, PC_usr, SPSR_irq), $txt=msg to print
	; corrupts R0-R5
	MOV	R4,$src
	B	%f03
1
	DCB	"$txt"
	DCB	" using task 0x%x",10,0
	ALIGN
2
	DCB	"R%d=0x%x",10,0
	ALIGN
3	ADR	R0,%b01
	LDR	R1,=OSTCBCur
	LDR	R1,[R1]
	BL	DbgIO_WriteF
	MVN	R5,#1
4	ADR	R0,%b02
	MOV	R1,R5
	LDMFD	R4!,{R2}
	BL	DbgIO_WriteF
	ADD	R5,R5,#1
	CMP	R5,#14
	BLE	%b04
	MEND
	]

;*********************************************************************************************************
;                                          START MULTITASKING
;                                       void OSStartHighRdy(void)
;
; Assumes context is saved as:
; First R14_usr, R13_usr, R12-R0
; Then PC_usr and SPSR_irq (ie; CPSR_usr)
;*********************************************************************************************************

OSStartHighRdy
	; Need to be in a privilaged mode first
	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


;*********************************************************************************************************
;                                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)
;
;*********************************************************************************************************

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
	; v2.5: {r14}
	; v2.0: {r11,r12,r14,pc} 
	;ADD	R13,R13,#4		; v2.5
	ADD	R13,R13,#4*4

	; Remove ISR() stacked regs (KEEP SIMILAR)
	; v2.5: {r4,r14}
	; v2.0: {r0,r4,r11,r12,r14,pc}
	;LDMFD	R13!,{R4,R14}		; v2.5
	ADD	R13,R13,#4*6

	; Remove HAL stacked regs (KEEP SIMILAR)
	; {spsr,r0-r12,r14}
	LDMFD	R13!,{R0}
	MSR	SPSR,R0
	LDMFD	R13!,{R0-R12,R14}

	; Perform normal task swap
	B	OSCtxSw


;*********************************************************************************************************
;                                        GENERATE SOFT INTERRUPT
;                                          void OSTaskSw(void)
;
;*********************************************************************************************************

OSTaskSw
	IMPORT	NedHAL_ISR

	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
	; Now in a state just like as if at 0x18
	B	OSCtxSw


;*********************************************************************************************************
;                                  STACK IRQ STATE AND DISABLE INTERRUPTS
;                                    void OSStackAndDisableInts(void)
;
; NOTE: Be careful calling from C code in SVC
;*********************************************************************************************************

OSStackAndDisableInts
	; Corrupts R0-R2 (okay during APCS use)
	MOV	R2,R14					; remember r14 (might be usr, irq, svc etc)
	SWI	OS_EnterOS				; enter SVC mode
	MRS	R0,SPSR					; disable interrupts in the SPSR
	ORR	R1,R0,#(1<<7)
	MSR	SPSR_all,R1
	STMFD	R13!,{R0}				; stack the old SPSR on SVC stack
	MOVS	PC,R2					; CPSR=SPSR & PC=ret addr


;*********************************************************************************************************
;                                  STACK IRQ STATE AND DISABLE INTERRUPTS
;                                    void OSRestoreStackedIntState(void)
;
; NOTE: Be careful calling from C code in SVC
;*********************************************************************************************************

OSRestoreStackedIntState
	; Corrupts R0,R1 (okay during APCS use)
	MOV	R1,R14					; remember r14
	SWI	OS_EnterOS				; enter SVC mode
	LDMFD	R13!,{R0}				; load the old SPSR off SVC stack
	MSR	SPSR_all,R0				; SPSR=what it did before
	MOVS	PC,R1					; CPSR=SPSR & PC=ret addr



	END

⌨️ 快捷键说明

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