www.pudn.com > 44B0X_uCOS276.rar > OS_CPU_A.S


 
BIT_TIMER0	EQU		(0x1<<13) 
BIT_EINT0	EQU		(0x1<<25) 
I_ISPC		EQU		0x1e00024 
INTMSK		EQU		0x1e0000c 
 
	AREA	|subr|, CODE, READONLY 
	 
	IMPORT	OSTCBCur 
addr_OSTCBCur		DCD	OSTCBCur 
	IMPORT	OSTCBHighRdy 
addr_OSTCBHighRdy	DCD	OSTCBHighRdy 
	IMPORT	OSPrioCur 
addr_OSPrioCur		DCD	OSPrioCur 
	IMPORT	OSPrioHighRdy 
addr_OSPrioHighRdy	DCD	OSPrioHighRdy	 
	 
	IMPORT  OSRunning 
 
	IMPORT	OSIntEnter 
	IMPORT	OSIntExit 
	IMPORT	OSTimeTick 
	IMPORT	EInt4567Isr 
	 
	IMPORT	need_to_swap_context 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 
; Function: 	OSStartHighRdy																			; 
; Purpose:		To start the task with the highest priority during OS startup							; 
; Processing:	See uC/OS-II Task Level Context Switch flow chart										; 
; Parameters: 	void																					; 
; Outputs:  	None																					; 
; Returns:  	void																					; 
; Notes:		Called once during OSStart()															; 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 
	EXPORT	OSStartHighRdy 
OSStartHighRdy 
	LDR		r0, =OSRunning			; OSRunning = 1 
	MOV		r1, #1 
	STRB	r1, [r0] 
	 
	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 
 
	 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 
; Function: 	OS_TASK_SW 																				; 
; Purpose: 		To perform a context switch from the Task Level.										; 
; Processing:	See uC/OS-II Task Level Context Switch flow chart										; 
; Parameters:	void																					; 
; Outputs:  	None																					; 
; Returns:		void																					; 
; Notes:		The whole function is executed in CRITICAL state. See OSSched().						; 
;																										; 
; 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.												; 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 
	EXPORT	OSCtxSw 
OSCtxSw 
	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+ 
 
 
 
 
;	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 
	 
;	LDR		r4, addr_OSTCBCur 
;	LDR		r5, [r4] 
;	STR		sp, [r5]				; store sp in preempted tasks TCB 
 
;	; OSPrioCur = OSPrioHighRdy 
;	LDR		r4, addr_OSTCBHighRdy 
;	LDR		r4, [r4] 
;	LDR		r5, addr_OSTCBCur 
;	STR    r4, [r5] 
	 
;	 LDR    r6, =OSPrioHighRdy 
;    LDRB    r6, [r6] 
;    LDR    r5, =OSPrioCur 
;    STRB    r6, [r5]  
 
 
;	LDR		sp, [r4] 
;	LDMFD	sp!, {r4}				; YYY+ 
;	MSR		CPSR_cxsf, r4			; YYY+ 
;	LDMFD	sp!, {r0-r12, lr, pc}	; YYY+ 
 
 
 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 
; Function: 	OSIntCtxSW 																				; 
; Purpose: 		To perform a context switch from the Interrupt Level.									; 
; Processing:	See uC/OS-II Interrupt Level Context Switch flow chart									; 
; Parameters:	void																					; 
; Outputs:  	None																					; 
; Returns:		void																					; 
; Notes:		The whole function is executed in CRITICAL state. See OSIntExit().						; 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 
;	EXPORT 	OSIntCtxSw 
;OSIntCtxSw 
;	LDR    r4, =OSTCBHighRdy 
;    LDR    r4, [r4] 
;    LDR    r5, =OSTCBCur 
;    STR    r4, [r5]                  ;OSTCBCur = OSTCBHighRdy; 
; 
;    LDR    r6, =OSPrioHighRdy 
;    LDRB    r6, [r6] 
;    LDR    r5, =OSPrioCur 
;    STRB    r6, [r5]                  ;OSPrioCur = OSPrioHighRdy 
; 
;    LDR    sp, [r4] 
;    LDMFD     sp!, {r4}                  ;pop new task cpsr 
;    MSR     cpsr_cxsf, r4 
;    LDMFD     sp!, {r0-r12,lr,pc}          ;pop new task r0-r12,lr & pc 
 
 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 
; Function:		OSTickISR																				; 
; Purpose:		Timer0 Interrupt Sever																	; 
; Processing:	Call OSTimeTick																			; 
; Parameters: 	void																					; 
; Outputs:		None																					; 
; Returns:		void																					; 
; Notes:																								;					 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 
;LINK_SAVE	DCD		0 
;PSR_SAVE	DCD		0 
;	EXPORT 	OSTickISR 
;OSTickISR 
;	STMFD	sp!, {r4} 
;	LDR		r4, =LINK_SAVE 
;	STR		lr, [r4]				 ; LINK_SAVE = lr_irq 
;	MRS		lr,	spsr 
;	STR		lr, [r4, #4]			 ; PSR_SAVE = spsr_irq 
;	LDMFD	sp!, {r4} 
;	ORR		lr, lr,	#0x80			 ; Mask irq for context switching before  
;	MSR		cpsr_cxsf, lr 			 ; returning back from irq mode. 
; 
;	SUB		sp, sp, #4				 ; Space for PC 
;	STMFD	sp!, {r0-r12, lr} 
;	LDR		r4, =LINK_SAVE 
;	LDR		lr, [r4, #0] 
;	SUB		lr, lr, #4				 ; lr = LINK_SAVE - 4, 
;	STR		lr, [sp, #(14*4)]		 ; the return address for pc. 
;	LDR		r4, [r4, #4]			 ; r4 = PSR_SAVE, 
;	STMFD	sp!, {r4}		         ; CPSR of the task 
; 
;	LDR		r4, addr_OSTCBCur 
;	LDR		r4, [r4] 
;	STR		sp, [r4]				 ; OSTCBCur -> stkptr = sp 
; 
;	 
; 
;	BL	OSIntEnter 
;	BL 	OSTimeTick 
;	 
;	STMFD	sp!,{r0-r1} 
;	LDR		r0, =I_ISPC 
;	LDR		r1, =BIT_TIMER0 
;	STR		r1, [r0] 
;	LDMFD	sp!,{r0-r1} 
;	 
;	BL	OSIntExit 
; 
;	LDMFD 	sp!, {r4}                ; pop new task cpsr 
;	MSR 	cpsr_cxsf, r4 
;	LDMFD 	sp!, {r0-r12,lr,pc}      ; pop new task r0-r12,lr & pc 
 
 
SAVED_LR	DCD 0	 
	EXPORT OSTickISR	 
OSTickISR 
	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 
	 
	 
	 
	LDR	r0, =I_ISPC 
	LDR	r1, =BIT_TIMER0 
	STR	r1, [r0] 
 
	BL	OSIntEnter 
	 
	BL	OSTimeTick 
 
	BL	OSIntExit 
 
	 
	LDR		r0, =need_to_swap_context 
	LDR		r2, [r0] 
	CMP		r2, #1 
	LDREQ	pc, =_CON_SW 
 
 
_NOT_CON_SW 
	;not context switching 
	LDMIA    sp!,{r0-r11, lr} 
	SUBS	pc, lr, #4 
 
 
_CON_SW 
	;set need_to_swap_context is '0' 
	MOV		r1, #0 
	STR		r1, [r0] 
 
 
	;now context switching 
	LDMIA    sp!,{r0-r11,lr} 
	SUB		lr, lr, #4 
 
	STR				lr, SAVED_LR 
 
	 
 
    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 
	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] 
	 
	; 
	LDR	r4, addr_OSTCBCur 
	LDR	r5, [r4] 
	STR	sp, [r5]		;  
 
	; Get highest priority task TCB address 
	LDR	r6, addr_OSTCBHighRdy 
	LDR	r6, [r6] 
	LDR	sp, [r6]		; get new tasks 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+ 
 
	 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 
; Functions: 	ARMDisableInt	ARMEnableInt															; 
; Purpose:		Disable and enable IRQ and FIQ preserving current CPU mode.								; 
; Processing:	Push the cpsr onto the stack, Disable IRQ and FIQ interrupts, Return					; 
; Parameters: 	void																					; 
; Outputs:  	None																					; 
; Returns:  	void																					; 
; Notes:																								; 
;   (1) Can be called from SVC mode to protect Critical Sections. 										; 
;   (2) Do not use these calls at interrupt level.														; 
;   (3) Used in pairs within the same function level;													; 
;   (4) Will restore interrupt state when called; i.e., if interrupts									; 
;       are disabled when DisableInt is called, interrupts will still									; 
;       still be disabled when the matching EnableInt is called.										; 
;   (5) Uses the method described by Labrosse as "Method 2".											; 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 
	EXPORT 	ARMDisableInt 
ARMDisableInt 
	STMDB	sp!, {r0} 
	MRS		r0, CPSR 
	ORR		r0, r0, #0x80 
	MSR		CPSR_cxsf, r0 
	LDMIA	sp!, {r0} 
	MOV	pc, lr 
	 
	EXPORT 	ARMEnableInt 
ARMEnableInt 
	STMDB	sp!, {r0} 
	MRS	r0, CPSR 
	BIC	r0, r0, #0x80 
	MSR	CPSR_cxsf, r0 
	LDMIA	sp!, {r0} 
	MOV	pc, lr 
	 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 
;                                   CRITICAL SECTION METHOD 3 FUNCTIONS 
; 
; Description: Disable/Enable interrupts by preserving the state of interrupts.  Generally speaking you 
;              would store the state of the interrupt disable flag in the local variable 'cpu_sr' and then 
;              disable interrupts.  'cpu_sr' is allocated in all of uC/OS-II's functions that need to  
;              disable interrupts.  You would restore the interrupt disable state by copying back 'cpu_sr' 
;              into the CPU's status register. 
;              OS_CPU_SR OSCPUSaveSR() 
; Arguments  : none 
; Returns    : OS_CPU_SR 
;              OSCPURestoreSR(OS_CPU_SR cpu_sr) 
; Arguments  : OS_CPU_SR 
; Returns    : none 
; Note(s)    : These functions are used in general like this, 
; 
;            void Task (void *data) 
;            { 
;                    #if OS_CRITICAL_METHOD == 3 /* Allocate storage for CPU status register */ 
;                          OS_CPU_SR  cpu_sr; 
;                    #endif 
;                         : 
;                         : 
;                    OS_ENTER_CRITICAL(); /* cpu_sr = OSCPUSaveSR(); */ 
;                         : 
;                         : 
;                    OS_EXIT_CRITICAL();  /* OSCPURestoreSR(cpu_sr); */ 
;                         : 
;                         : 
;            } 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 
	EXPORT  OSCPUSaveSR 
OSCPUSaveSR 
	MRS 	r0,CPSR 
	ORR 	r1,r0,#0xC0 
	MSR		CPSR_c,r1 
	MOV		pc,lr 
 
	EXPORT  OSCPURestoreSR 
OSCPURestoreSR 
	MSR		cpsr_c,r0 
	MOV		pc,lr 
 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 
;																										; 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 
K_LINK_SAVE	DCD		0 
K_PSR_SAVE	DCD		0 
	EXPORT 	OSEINT4567ISR 
OSEINT4567ISR 
	STMFD	sp!, {r4} 
	LDR		r4, =K_LINK_SAVE 
	STR		lr, [r4]				 ; LINK_SAVE = lr_irq 
	MRS		lr,	spsr 
	STR		lr, [r4, #4]			 ; PSR_SAVE = spsr_irq 
	LDMFD	sp!, {r4} 
	ORR		lr, lr,	#0x80			 ; Mask irq for context switching before  
	MSR		cpsr_cxsf, lr 			 ; returning back from irq mode. 
 
	SUB		sp, sp, #4				 ; Space for PC 
	STMFD	sp!, {r0-r12, lr} 
	LDR		r4, =K_LINK_SAVE 
	LDR		lr, [r4, #0] 
	SUB		lr, lr, #4				 ; lr = LINK_SAVE - 4, 
	STR		lr, [sp, #(14*4)]		 ; the return address for pc. 
	LDR		r4, [r4, #4]			 ; r4 = PSR_SAVE, 
	STMFD	sp!, {r4}		         ; CPSR of the task 
 
	LDR		r4, addr_OSTCBCur 
	LDR		r4, [r4] 
	STR		sp, [r4]				 ; OSTCBCur -> stkptr = sp 
 
	BL	OSIntEnter 
	BL 	EInt4567Isr 
	BL	OSIntExit 
 
	LDMFD 	sp!, {r4}                ; pop new task cpsr 
	MSR 	cpsr_cxsf, r4 
	LDMFD 	sp!, {r0-r12,lr,pc}      ; pop new task r0-r12,lr & pc 
	 
 
 
 
 
	IMPORT	need_to_swap_context_EINT0 
	IMPORT  OSIntExitEINT0 
	IMPORT EINT0ISR 
SAVED_LR_EINT0	DCD 0	 
	EXPORT OSEINT0ISR	 
OSEINT0ISR 
	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 
	 
	 
	 
	LDR	r0, =I_ISPC 
	LDR	r1, =BIT_EINT0 
	STR	r1, [r0] 
 
	BL	OSIntEnter 
	 
	BL	EINT0ISR 
 
	BL	OSIntExitEINT0 
 
	 
	LDR		r0, =need_to_swap_context_EINT0 
	LDR		r2, [r0] 
	CMP		r2, #1 
	LDREQ	pc, =_CON_SW_EINT0 
 
 
_NOT_CON_SW_EINT0 
	;not context switching 
	LDMIA    sp!,{r0-r11, lr} 
	SUBS	pc, lr, #4 
 
 
_CON_SW_EINT0 
	;set need_to_swap_context is '0' 
	MOV		r1, #0 
	STR		r1, [r0] 
 
 
	;now context switching 
	LDMIA    sp!,{r0-r11,lr} 
	SUB		lr, lr, #4 
 
	STR				lr, SAVED_LR_EINT0 
 
	 
 
    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_EINT0 
	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] 
	 
	; 
	LDR	r4, addr_OSTCBCur 
	LDR	r5, [r4] 
	STR	sp, [r5]		;  
 
	; Get highest priority task TCB address 
	LDR	r6, addr_OSTCBHighRdy 
	LDR	r6, [r6] 
	LDR	sp, [r6]		; get new tasks 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+ 
	END