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

📄 subr.s

📁 UCSO在三星S3C44B0X CPU上的移植。ejoy it
💻 S
字号:
;*;* File: subr.s;*;* uC/OS Real-time multitasking kernel for the ARM processor.;* Low-level routines.;*;* Created by Marco Graziano (marcog@crl.com).;*;	Functions defined in this module:;;	void NewIRQ(PFI)		/* used in PIDInit() [pid.c] */;	void NewFIQ(PFV)		/* used in PIDInit() */;	void NewSWI(PFV)		/* used in PIDInit() */;	void SWITrap(void) 		/* SWI trap wrapper */;	void IRQTrap(void)		/* IRQ trap wrapper */;	void FIQTrap(void)		/* FIQ trap wrapper */;	void rplev(void)		/* re-enable interrupts after a trap */;	void OSDisableInt(void)		/* disable interrupts when in SVC */;	void OSEnableInt(void)		/* enable interrupts when in SVC */;	void OSCtxSw(void)		/* context switch */;	void OSStartHighRdy(void)	/* start highest priority task */SwiV		EQU	0x08IrqV		EQU	0x18FiqV		EQU	0x1CNoInt		EQU	0xC0SVC32Mode	EQU	0x13IRQ32Mode	EQU	0x12FIQ32Mode	EQU	0x11OSEnterSWI	EQU	0x00	AREA	|subr|, CODE, READONLY	; Improper use of locations within a READONLY areaSavedIRQ	DCD	0x0SavedFIQ	DCD	0x0SavedSWI	DCD	0x0	; External symbols we need the addresses of			IMPORT	OSTCBCuraddr_OSTCBCur		DCD	OSTCBCur			IMPORT	OSTCBHighRdyaddr_OSTCBHighRdy	DCD	OSTCBHighRdy;	void NewIRQ(PFI NewHandler);	PFI NewHandler - Address of a new high level handler.;;       Install a new IRQ trap wrapper in the ARM execptions vector.;	*** Call with interrupts disabled.;	EXPORT	NewIRQNewIRQ	STMFD	sp!, {v1-v2}			; save working registers	STR	a1, SavedIRQ			; save new high-level handler        ADR     v1, IRQTrap - 8 - IrqV          ; offset from branch location        MOV     v1, v1, LSR #2                  ; turn into a word offset        ORR     v1, v1, #0xEA000000             ; assemble a branch to the        MOV     v2, #IrqV			; wrapper instruction        STR     v1, [v2]                        ; store branch in vector	LDMFD	sp!, {v1-v2}			; restore registers	MOV	pc, lr				; return	;	void NewFIQ(PFV NewHandler);	PFV NewHandler - Address of a new high level handler.;;       Install a new FIQ trap wrapper in the ARM execptions vector.;	*** Call with interrupts disabled.;	EXPORT	NewFIQNewFIQ	STMFD	sp!, {v1-v2}			; save working registers	STR	a1, SavedFIQ			; save new high-level handler        ADR     v1, FIQTrap - 8 - FiqV          ; offset from branch location        MOV     v1, v1, LSR #2                  ; turn into a word offset        ORR     v1, v1, #0xEA000000             ; assemble a branch to the        MOV     v2, #FiqV			; wrapper instruction        STR     v1, [v2]                        ; store branch in vector	LDMFD	sp!, {v1-v2}			; restore registers	MOV	pc, lr				; return;	void NewSWI(PFV NewHandler);	PFV NewHandler - Address of a new high level handler.;;       Install a new SWI trap wrapper in the ARM execptions vector.;	*** Call with interrupts disabled.;	EXPORT	NewSWINewSWI	STMFD	sp!, {v1-v2}			; save working registers	STR	a1, SavedSWI			; save high-level handler	ADR	v1, SWITrap - 8 - SwiV		; offset from branch	MOV	v1, v1, LSR #2			; turn into words	ORR	v1, v1, #0xEA000000		; build a branch to it	MOV	v2, #SwiV			; replace vector	STR	v1, [v2]			; store it	LDMFD	sp!, {v1-v2}			; restore registers	MOV	pc, lr				; return;	SWITrap - SWI trap handler;;	Wrapper to service the trap and call a high-level handler.;	We assume that the demon allocated a stack for SVC mode.;	The trap is started with interrupts disabled.;SWITrap        STMFD   sp!, {r0-r12, lr}       ; save registers	LDR	a1, [lr, #-4]		; get swi instruction	BIC	a1, a1, #0xFF000000	; extract swi number from instruction	; A special SWI is used to enter uC/OS and switch to SVC mode	TST	a1, #OSEnterSWI		; check if enter OS swi	BNE	%F01				; The data-sheet states that no attempt will be made to write	; an 8bit constants into the whole PSR.	MRS	r0,CPSR	BIC	r0,r0,#0xDF	ORR	r0,r0,#(SVC32Mode | NoInt)	MSR	CPSR,r0	LDMFD	sp!, {r0-r12, pc}	; return staying in SVC mode01					; re-enable interrupts if needed	MRS	v1, SPSR		; get saved psr	MRS	v2, CPSR		; get current psr	AND	v1, v1, #NoInt		; extract interrupt level from old psr	BIC	v2, v2, #NoInt		; clear I bit in current psr	ORR	v2, v2, v1		; set current interrupt from saved psr	MSR	CPSR, v2		; change current psr	ADR	v1, SavedSWI	MOV	lr, pc			; arrange for a safe return here		LDR	pc, [v1]		; call high-level handler passing swi#        LDMFD   sp!, {r0-r12, pc}^      ; restore registers and return;	IRQTrap - IRQ trap handler;;	Wrapper to service the trap and call a high-level handler.;IRQTrap	; We take the cycle hit of modifying the return address here,	; to simplify the code needed to return to the interrupted	; thread, possibly performing a context switch on the way.	SUB	lr,lr,#4	; At this points IRQs are disabled, so we know that the SPSR	; register will not be trashed by another interrupt.        STMFD   sp!, {r0-r12, lr}       ; save registers        MRS     v1, SPSR		; push SPSR to allow nested interrupts        STMFD   sp!, {v1}	ADR	v1, SavedIRQ        MOV     lr, pc                  ; arrange for a safe return here        LDR     pc, [v1]         	; call high-level handler					; it will re-enable interrupts	; The high-level handler dispatches the IRQ to the proper	; user defined ISR and returns 1 if pre-emption is needed	CMP	a1, #0			; a1 is TRUE if preemption	; NOTE: The following code assumes that all threads use r13 as	; the stack-pointer, and that it is a APCS conformant stack.	; i.e. there is never any data stored beneath the current	; stack-pointer.	; The above needs to be true to enable the context switches	; started as a return from an interrupt to use the current	; threads stack as the state save area.	;	LDMFD	sp!,{r12}		; recover SPSR value from stack	; if NE then we need to check if we were a nested interrupt	AND	r11,r12,#0x1F		; mask out all but the mode bits	TEQNE	r11,#IRQ32Mode		; check for interrupted IRQ thread	; if EQ then we can return immediately	MSREQ	SPSR,r12		; restore the SPSR	LDMEQFD	sp!,{r0-r12,pc}^	; and return to the interrupted thread	; We now need to perform a context switch.	; r12 = SPSR describing the interrupted thread.	; r11 = interrupted thread processor mode	; We need to protect the SPSR before we actually perform the	; return to the interrupted thread, since we don't want to	; lose the value by another interrupt occuring between the	; SPSR load and the PC+CPSR load. Similarly we need to protect	; the IRQ stack and threading code while we setup the state	; required to enter the context switch code from an interrupt	; routine. We rely on the interrupted thread having IRQs	; enabled (since we would never have reached this point	; otherwise).	; We have recovered the SPSR value, so only r0-r12,lr are on the stack.	LDR	r4,[sp,#(13 * 4)]	; load return address: nasty use of					; a constant	; r11 contains the mode bits describing the interrupted thread	MRS	r0,CPSR			; get current mode info.	ORR	r0,r0,#0x80		; and set IRQ disable flag	BIC	r1,r0,#0x1F		; clear mode bits	ORR	r1,r1,r11		; insert interrupted thread mode bits	MSR	CPSR,r1			; and change to that mode	; We are now in the interrupted thread mode with IRQs	; disabled.	MOV	r3,lr			; copy the current lr	MRS	r1,SPSR			; copy current SPSR	MRS	r2,CPSR			; copy current CPSR	STMFD	sp!,{r1,r2,r3,r4}	; and construct return stack	MSR	CPSR,r0			; return to IRQ mode	; IRQ mode; IRQs disabled	; r12 = SPSR describing interrupted thread	MSR	SPSR,r12		; restore SPSR_irq ready for return	LDMFD	sp!,{r0-r12,lr}		; restore all the registers	SUBS	pc,pc,#0		; and return to the interrupted mode	NOP				; flush the pipeline	NOP	NOP	; we are now executing in the interrupted mode with IRQs enabled	BL	OSCtxSw			; perform the context switch	LDMFD	sp!,{lr}	MSR	SPSR,lr			; recover the SPSR when the thread 					; was interrupted	LDMFD	sp!,{lr}	MSR	CPSR,lr			; recover the CPSR when the thread 					; was interrupted	LDMFD	sp!,{lr,pc}		; return to the interrupted thread;	FIQTrap - FIQ trap handler;;	Wrapper to service the trap and call a high-level handler.;	WARNING: NEEDS CHANGES TO ALLOW CONTEXT SWITCH AFTER THE INTERRUPT;		 LOOK AT IRQTrap() to figure out what to do. (MEG);FIQTrap        STMFD   sp!, {r0-r7, lr}        ; save registers        MRS     v1, SPSR		; push SPSR to allow nested interrupts        STMFD   sp!, {v1}	ADR	v1, SavedFIQ        MOV     lr, pc                  ; arrange for a safe return here        LDR     pc, [v1]         	; call high-level handler        LDMFD   sp!, {v1}		; pop SPSR        MSR     SPSR, v1        LDMFD   sp!, {r0-r7, lr}        ; restore registers        SUBS    pc, lr, #4              ; return from trap ;	void rplev(void);	;	Restore processor level to the level before the trap.;;	*** To be invoked in priviled mode.	EXPORT	rplevrplev	STMFD	sp!, {v1, v2}	MRS	v1, SPSR		; get saved psr	MRS	v2, CPSR		; get current psr	AND	v1, v1, #NoInt		; extract interrupt level from old psr	BIC	v2, v2, #NoInt		; clear I and F bits in current psr	ORR	v2, v2, v1		; set current interrupt from saved psr	MSR	CPSR, v2		; change current psr	LDMFD	sp!, {v1, v2}	MOV	pc, lr;	void OSDisableInt(void);	void OSEnableInt(void);;	Disable and enable IRQ and FIQ preserving current CPU mode.;	EXPORT	OSDisableIntOSDisableInt	MRS	r12, CPSR	ORR	r12, r12, #NoInt	MSR	CPSR, r12	MOV	pc, lr	EXPORT	OSEnableIntOSEnableInt	MRS	r12, CPSR	BIC	r12, r12, #NoInt	MSR	CPSR, r12	MOV	pc, lr;	void OSCtxSw(void);	;	Perform a context switch.;	; 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	OSCtxSwOSCtxSw	STMFD	sp!, {r0-r12, lr}	; save register file and ret address	MRS	v1, CPSR	STMFD	sp!, {v1}		; save current PSR	MRS	v1, SPSR		; YYY+	STMFD	sp!, {v1}		; YYY+ save SPSR	; Get current task TCB address	LDR	v1, addr_OSTCBCur	LDR	v2, [v1]	STR	sp, [v2]		; store sp in preempted tasks's TCB	; Get highest priority task TCB address	LDR	v3, addr_OSTCBHighRdy	LDR	v3, [v3]	LDR	sp, [v3]		; get new task's stack pointer	STR	v3, [v1]		; set new current task TCB address	LDMFD	sp!, {v1}		; YYY+	MSR	SPSR, v1		; YYY+	LDMFD	sp!, {v1}		; YYY+	MSR	CPSR, v1		; YYY+	LDMFD	sp!, {r0-r12, pc}	; YYY+;	void OSStartHighRdy(void);	;	Start the task with the highest priority;;	EXPORT	OSStartHighRdyOSStartHighRdy	; Get current task TCB address	LDR	v1, addr_OSTCBCur	; Get highest priority task TCB address	LDR	v2, addr_OSTCBHighRdy	LDR	v2, [v2]		; get stack pointer	LDR	sp, [v2]		; switch to the new stack	STR	v2, [v1]		; set new current task TCB address	LDMFD	sp!, {v1}		; YYY	LDMFD	sp!, {v1}		; get new state from top of the stack	MSR	CPSR, v1		; CPSR should be SVC32Mode	LDMFD	sp!, {r0-r12, pc}	; start the new task	END

⌨️ 快捷键说明

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