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

📄 kern600.s

📁 各种硬件平台上的us OS移植实例(arm6)
💻 S
📖 第 1 页 / 共 2 页
字号:
    	;    	; out:  Thread context restored. This will either be the    	; processor state at the instance of the interrupt, or a    	; previously stored interrupted or de-scheduled thread    	; context.    	;       	; This implementation does not perform any interrupt source    	; masking before calling ISRs, resulting in IRQs being    	; disabled for the WHOLE of the IRQ and ISR handler    	; execution. If IRQs were to be enabled before the source has    	; been cleared then this system would get stuck in an infinite    	; loop.    	;    	SUB 	lr,lr,#4    	    	    ; modify to form true return address    	; The registers we *HAVE* to save as those that are not    	; preserved as part of the APCS-3 calling sequence:    	STMFD	sp!,{a1,a2,a3,a4,fp,ip,lr}  ; preserve work registers    	; If we change this code to allow re-entrant interrupts    	; (i.e. we mask the source before calling the ISR with IRQs    	; enabled), we would also *NEED* to save the SPSR register    	; before enabling IRQs. At the moment this code simply    	; executes ISRs with IRQs disabled.    	;    	MOV 	fp,#0x00000000	    	    ; empty call-frame pointer    	BL  	OSIntEnter  	    	    ; keep track of active interrupt handlers    	;    	getIRQsource	a1,a2	    	    ; architecture specific IRQ status load    	TEQ 	a1,#0x00000000	    	    ; check that we have at least one bit    	BEQ 	IgnoreIRQ   	    	    ; if zero we do not know the source    	;    	decodeIRQ   a1,a2,a3	    	    ; get a vector number for the sources    	; a1 = bit number of the highest priority pending    	; interrupt. NOTE: There is no check at the moment that the    	; bit number describes a slot in the IRQvectors table. It is    	; assumed that the NUMIRQS manifest within the architecture    	; description file is one greated than the maximum bit    	; position ever returned by the decodeIRQ macro. The check for    	; this SHOULD be in the target description header file.    	;    	LDR 	a2,=IRQvectors	    	    ; reference the IRQ handler table    	MOV 	lr,pc	    	    	    ; assumes next instruction is PC load    	LDR 	pc,[a2,a1,LSL #2]   	    ; vector through handler table    	; We return here after the ISR has completed.    	;    	BL  	OSIntExit   	    	    ; check if we need to re-schedule    	TEQ 	a1,#0    	    	    ; if !FALSE we need to perform a context switch    	LDMEQFD	sp!,{a1,a2,a3,a4,fp,ip,pc}^ ; else return to caller, restoring PSR state    	;    	; We have our own special version of the SAVECONTEXT code    	; here, since we need to de-stack the description of the    	; interrupted task, and ensure that the saved context    	; describes the interrupted stack and *NOT* this interrupt    	; handler thread.    	;     	; The SPSR register describes the processor mode of the    	; interrupted thread. NOTE: If the interrupted thread was in    	; the same mode as this interrupt handler is executing then we    	; will have lost some information (since the vector entry    	; overwrites the lr and SPSR values). Unless there has been    	; special code to cope with this, then it is more than likely    	; that such an occurrence will have corrupted the system.    	;    	; We have a1,a2,a3,a4,fp,ip and lr available as work registers.    	;    	MRS 	a1,SPSR	    	    ; get interrupted thread description    	ANDS	a2,a1,#SubModeMask  ; get the mode information    	BEQ 	interruptedUSR	    ; simpler code required for USR tasks    	;    	; We now know that we were executing in a priviledged mode:    	TEQ 	a2,#(FIQmode :AND: SubModeMask)	; check for FIQ mode    	BEQ 	interruptedFIQ	    ; special code to save more banked registers    	;    	; We now know that we are executing in a normal priviledged mode:    	SUB 	sp,sp,#(3 * 4)	    ; we will store 3 words of information    	MOV 	a3,sp	    	    ; take a copy of the IRQ stack pointer    	MRS 	a4,CPSR	    	    ; get our current PSR state    	ORR 	a2,a1,#IRQint	    ; set IRQ disable flag    	MSR 	CPSR,a2	    	    ; switch to interrupted mode (ensuring IRQs stay disabled)    	;    	MRS 	a2,SPSR	    	    ; get a copy of the SPSR for this mode    	STMIA	a3,{a2,sp,lr}	    ; stack the banked registers    	;    	MSR 	CPSR,a4	    	    ; and return to the interrupt handler state    	;    	; We now have on the IRQ stack the banked registers for the    	; mode of the interrupted task.    	;    	LDMFD	sp!,{a2,a3,a4}    	; a1 = CPSR of interrupted thread    	; a2 = SPSR of interrupted thread    	; a3 = stack-pointer of interrupted thread    	; a4 = link-register of interrupted thread    	;    	SUB 	lr,a3,#Ctx_sizeof   ; context save area for the task    	STR 	a4,[lr,#Ctx_lr]	    ; link-register    	ADD 	a4,lr,#Ctx_CPSR	    ; reference the PSR fields    	STMIA	a4,{a1,a2}  	    ; preserve the CPSR and SPSR for the task    	LDMFD	sp!,{a1,a2,a3,a4,fp,ip}    	STMIA	lr,{a1-ip}  	    ; preserve most of the register state    	MOV 	v1,lr	    	    ; keep a copy of the context pointer    	LDMFD	sp!,{lr}    	    ; recover the interrupted task program counter    	STR 	lr,[v1,#Ctx_pc]	    ; preserve the program counter    	ADD 	a4,v1,#Ctx_USR_sp   ; reference the banked USR fields    	STMIA	a4,{sp,lr}^ 	    ; store the banked USR registers    	B   	referenceCtx	    ; and ensure we reference the saved contextinterruptedFIQ    	; We reach this point if the interrupted task was executing in    	; FIQ mode. Such tasks have their own context save due to the    	; extra banked registers.    	;    	SUB 	sp,sp,#(8 * 4)	    ; we will store 8 words of information    	MOV 	a3,sp	    	    ; take a copy of the IRQ stack pointer    	MRS 	a4,CPSR	    	    ; get our current PSR state    	ORR 	a2,a1,#IRQint	    ; set IRQ disable flag    	MSR 	CPSR,a2	    	    ; switch to FIQ mode (ensuring IRQs stay disabled)    	;    	MRS 	a2,SPSR	    	    ; get a copy of the SPSR for this mode    	STMIA	a3,{a2,v5-lr}	    ; stack the banked registers    	;    	MSR 	CPSR,a4	    	    ; and return to the interrupt handler state    	;    	; We now have on the IRQ stack the FIQ banked registers.    	; The following is NASTY since we are peeking into the stack    	; to load the FIQ stack-pointer:    	LDR 	lr,[sp,#(6 * 4)]    ; load the FIQ stack-pointer    	SUB 	lr,lr,#Ctx_sizeof   ; context save area for the task    	LDMFD	sp!,{a2,a4,fp,ip}   ; load some FIQ registers    	ADD 	a3,lr,#Ctx_CPSR     ; reference the PSR fields    	STMIA	a3,{a1,a2}  	    ; store the CPSR and SPSR    	ADD 	a3,lr,#Ctx_v5	    ; reference fields in context    	STMIA	a3!,{a4,fp,ip}	    ; stack v5,v6 and sl    	LDMFD	sp!,{a1,a2,a4,fp}   ; load fp, ip, sp and lr    	STMIA	a3,{a1,a2,a4,fp}    ; and store into the context    	LDMFD	sp!,{a1,a2,a3,a4,fp,ip}    	STMIA	lr,{a1-v4}  	    ; store rest of FIQ registers    	MOV 	v1,lr	    	    ; keep a copy of the context pointer    	LDMFD	sp!,{lr}    	    ; recover the interrupted task program counter    	STR 	lr,[v1,#Ctx_pc]	    ; preserve the program counter    	ADD 	a4,v1,#Ctx_USR_v5   ; reference the banked USR fields    	STMIA	a4,{v5-lr}^ 	    ; store the banked USR registers    	B   	referenceCtx	    ; and ensure we reference the saved contextinterruptedUSR	    	    	    ; we reach here when de-scheduling a USR task    	SUB 	sp,sp,#4    	    ; create a temporary holder on our stack    	STMIA	sp,{sp}^    	    ; and force a USR transfer    	LDMFD	sp!,{lr}    	    ; we now have a pointer into the USR stack    	SUB 	lr,lr,#Ctx_sizeof   ; make space for the context state    [	{FALSE}	; this is not actually required, since the stack pointer is implicit in the context pointer    	STMFD	sp!,{lr}    	    ; push back onto our local stack    	LDMIA	sp,{sp}^    	    ; and ensure the USR stack pointer is updated    ]    	STR 	a1,[lr,#Ctx_CPSR]   ; store IRQ SPSR into CPSR for task    	ADD 	a1,lr,#Ctx_v1	    ; reference the variable registers    	STMIA	a1,{v1-sl}^ 	    ; force USR banked register save    	MOV 	v1,lr	    	    ; move the context state pointer    	LDMFD	sp!,{a1,a2,a3,a4,fp,ip,lr}  ; recover preserved interrupt state    	STMIA	v1,{a1,a2,a3,a4}    ; store argument registers    	ADD 	a1,v1,#Ctx_fp    	STMIA	a1,{fp,ip,sp,lr}^   ; store more USR banked registers    	STR 	lr,[v1,#Ctx_pc]	    ; return address when re-starting taskreferenceCtx    	; We reach this point when we have stored the complete    	; processor register state required.    	LDR 	a2,=OSTCBCur	    ; reference the current TCB holder    	LDR 	a2,[a2,#0x00]	    ; get pointer to context pointer save location    	STR 	v1,[a2,#0x00]	    ; save context pointer for task    	;    	; We have now saved the processor state at the instance of the    	; interrupt, and we know we are in a priviledged mode:    	STARTNEXTTASK	  	    	; startup the highest priority taskIgnoreIRQ    	; This point is reached if we did not find a source or a    	; handler routine for the interrupt. This is normally fatal    	; since it means that the source has probably not been    	; cleared, and we are about to re-enter the IRQ handler.    	LDMFD	sp!,{a1,a2,pc}^	    	; return to caller, restoring PSR state    	; ---------------------------------------------------------------------    	; These are simple (do nothing) routines that is attached by    	; default to the IRQvectors and FIQvectors. They conform to    	; the following prototype:    	;   	IRQHandlerFn DummyIRQ ;    	;   	FIQHandlerFn DummyFIQ ;DummyIRQDummyFIQ    	MOV 	pc,lr    	; ---------------------------------------------------------------------    	; -- Context manipulation ---------------------------------------------    	; ---------------------------------------------------------------------    	; void OSStartHighRdy(void) ;    	;	    	; Start the task with the highest priority:OSStartHighRdy    	; NOTE: The "ucos.c" OSStart routine expects this code to also    	; enable interrupts.    	STARTNEXTTASK	  	; startup the highest priority task    	; ---------------------------------------------------------------------    	; void OSCtxSw(void) ;    	;    	; Perform a context switch from the current task, to the    	; highest priority pending task.    	;    	; If a MMU is available and non-direct physical-to-logical    	; mapping is being used then we need to flush the cache (and    	; possibly the TLB) as part of the context switch to avoid    	; address aliasing. At the moment the ARM600 C-Demon does not    	; provide non-direct memory mapping.OSCtxSw    	; We first create a context on the stack of the current task,    	; and then switch to the pending task:    	SAVECONTEXT 	    	; save current context onto stack    	STARTNEXTTASK	 	; startup the highest priority task    	; ---------------------------------------------------------------------    	; void *InitTask(void *stack,void *data,PTV task) ;    	;    	; This routine constructs a starting thread context on the    	; given stack, returning the new stack pointer. The code    	; assumes that *ALL* threads start in USR mode. Even though    	; this is a new task being created, it is made to look like a    	; context switched task so that the standard routines can be used.InitTask    	SUB 	a1,a1,#Ctx_sizeof   	; allocate memory on the new stack for the context    	STR 	a2,[a1,#Ctx_a1]	    	; argument for the new task    	STR 	a3,[a1,#Ctx_pc]	    	; starting address for new task    	MOV 	a2,#USRmode 	    	; with IRQs and FIQs enabled    	STR 	a2,[a1,#Ctx_CPSR]   	; and this will be the starting PSR    	MOV 	a2,#0x00000000    	STR 	a2,[a1,#Ctx_fp]	    	; ensure an empty call-frame    	; We do not care what the majority of the new tasks registers    	; look like, as long as the starting state is a valid APCS-3    	; one. NOTE: This code does *NOT* initialise the stack    	; pointer, since that is implicitly derived from the address    	; of the stored context (i.e. plus Ctx_sizeof).    	MOV 	pc,lr	    	    	; return to caller    	; ---------------------------------------------------------------------	END 	; EOF kern600.s

⌨️ 快捷键说明

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