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

📄 os_cpu_a.s

📁 uC/OS 使用SDT 开发工具包,可以参考一下
💻 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 */

SwiV		EQU	0x08
IrqV		EQU	0x18
FiqV		EQU	0x1C
NoInt		EQU	0x80

SVC32Mode	EQU	0x13
IRQ32Mode	EQU	0x12
FIQ32Mode	EQU	0x11
SYS32Mode	EQU	0x1f

I_BIT		EQU 0x80

OSEnterSWI	EQU	0x00

	AREA	|subr|, CODE, READONLY

	; Improper use of locations within a READONLY area
SavedIRQ	DCD	0x0
SavedFIQ	DCD	0x0
SavedSWI	DCD	0x0

			IMPORT	SavedSPSR
addr_SavedSPSR		DCD	SavedSPSR
			IMPORT	SavedR14
addr_SavedR14		DCD	SavedR14

	; External symbols we need the addresses of
			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
addr_OSRunning		DCD	OSRunning
	
	EXPORT IRQContextSwap
IRQContextSwap

;- Restore scratch/used registers and LR from User Stack
            ldmia       sp!, { r0-r12, r14}

;- Disable Interrupt and switch back in IRQ mode
            mrs         r0, CPSR
            bic         r0, r0, #SVC32Mode
            orr         r0, r0, #I_BIT:OR:IRQ32Mode
            msr         CPSR_c, r0
            nop
            nop
            nop
            

;- Restore SPSR_irq and r0 from IRQ stack
            ldmia       sp!, {r0, r14}
            msr         SPSR_cxsf, r14


;- Restore ajusted LR_irq from IRQ stack directly in the PC
			nop
            ldmia       sp!, {r14}
            subs		pc,pc,#0
			nop
			nop
			nop			
			
			
	; we are now executing in the interrupted mode with IRQs enabled
;	BL	OS_TASK_SW		; perform the context switch
	STMFD	sp!, {r0-r12, lr}	; 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, r4		; YYY+
	LDMFD	sp!, {r4}		; YYY+
	MSR	CPSR, r4		; YYY+
	LDMFD	sp!, {r0-r12,lr}	; YYY+
	MOV	pc, lr

;	MOVS	pc,lr
	

;	void DisableInt(void)
;	void EnableInt(void)
;
;	Disable and enable IRQ and FIQ preserving current CPU mode.
;
	EXPORT	ARMDisableInt
ARMDisableInt
	MRS	r12, CPSR
	ORR	r12, r12, #NoInt
	MSR	CPSR, r12
	MOV	pc, lr

	EXPORT	ARMEnableInt
ARMEnableInt
	MRS	r12, CPSR
	BIC	r12, r12, #NoInt
	MSR	CPSR, r12
	MOV	pc, lr



;	void OS_TASK_SW(void)
;	
;	Perform a context switch.
;
;	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.
			IMPORT		swi_irq

	EXPORT	OS_TASK_SW
OS_TASK_SW
	STMFD	sp!, {r0-r12, lr}	; 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, r4		; YYY+
	LDMFD	sp!, {r4}		; YYY+
	MSR	CPSR, r4		; YYY+
	LDMFD	sp!, {r0-r12,lr}	; YYY+
	MOV	pc, lr

;	void OSStartHighRdy(void)
;	
;	Start the task with the highest priority;
;
	EXPORT	OSStartHighRdy
OSStartHighRdy
	;
	LDR	r4, addr_OSRunning
	MOV	r5,	#1
	STRB	r5,	[r4]
	; Get current task TCB address
	LDR	r4, addr_OSTCBCur
	; Get highest priority task TCB address
	LDR	r5, addr_OSTCBHighRdy
	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
	LDMFD	sp!, {r4}		; get new state from top of the stack
	MSR	CPSR, r4		; CPSR should be SVC32Mode
	LDMFD	sp!, {r0-r12, pc}	; start the new task


;-----------------------------------------;-----------------------------------------
;	from swi_irq.s
;-----------------------------------------;-----------------------------------------

;            AREA        WANGYFLED, CODE, READONLY

;            INCLUDE     Include/arm.inc
;I_BIT                   EQU     0x80


;            INCLUDE     Include/pio.inc
;            INCLUDE     Include/aic.inc
AIC_BASE            EQU     0xFFFFF000
;-----------------------------------------
;- Advanced Interrupt Controller Structure
;-----------------------------------------
                    ^       0
AIC_SMR             #       32*4        ; Source Mode Register
AIC_SVR             #       32*4        ; Source Vector Register
AIC_IVR             #       4           ; Interrupt Vector Register
AIC_FVR             #       4           ; Fast Interrupt Vector Register
AIC_ISR             #       4           ; Interrupt Status Register
AIC_IPR             #       4           ; Interrupt Pending Register
AIC_IMR             #       4           ; Interrupt Mask Register
AIC_CISR            #       4           ; Core Interrupt Status Register
                    #       4
                    #       4
AIC_IECR            #       4           ; Interrupt Enable Command Register
AIC_IDCR            #       4           ; Interrupt Disable Command Register
AIC_ICCR            #       4           ; Interrupt Clear Command Register
AIC_ISCR            #       4           ; Interrupt Set Command Register
AIC_EOICR           #       4           ; End Of Interrupt Command Register


;            INCLUDE     Include/irq.mac

MY_TCB_BASE        EQU     0xFFFE0000

			IMPORT		need_to_swap_context
addr_n_t_s_c	DCD		need_to_swap_context

			IMPORT		timer_irq
;			IMPORT		IRQContextSwap
			IMPORT		IrqStart
			IMPORT		OSTimeTick
			IMPORT		IrqFinish
			
; ------------------------- List of Imported resources -------------------------
; Timer Counter Handler Table
            IMPORT      TCHandlerTable

; ------------------------- List of Internal resources -------------------------
MyPtTCBBase
            DCD         MY_TCB_BASE

;SVC32Mode	EQU		0x13
;IRQ32Mode	EQU		0x12

;------------------------------------------------------------------------------
;- Function             : interrupt_end
;- Treatments           : End of Timer Counter interrupt.
;- Input Parameters     : None
;- Output Parameters    : Come back in the interrupted mode,
;-                      : restore PC and SPSR.
;- Registers lost       : None
;- Called Functions     : None
;- Called Macros        : IRQ_EXIT
;------------------------------------------------------------------------------



			EXPORT		timer_2_isr
			
timer_2_isr

;- Adjust and save LR_irq mode in IRQ stack
            sub         r14, r14, #4
            stmfd       sp!, {r14}

;- Save SPSR and r0 in IRQ stack
            mrs         r14, SPSR
            stmfd       sp!, {r0, r14}

;- Enable Interrupt and Switch in SVC Mode
            mrs         r14, CPSR
            bic         r14, r14, #I_BIT
            orr         r14, r14, #SVC32Mode
            msr         CPSR_c, r14

;- Save scratch/used registers and LR in User Stack
            stmfd       sp!, { r0-r12, r14}

			bl			timer_irq
			bl			IrqStart
			bl			OSTimeTick
			bl			IrqFinish

;- Mark the End of Interrupt on the AIC
            ldr         r0, =AIC_BASE
            str         r0, [r0, #AIC_EOICR]
			
			ldr			r0, addr_n_t_s_c
			ldrb		r1, [r0]
			cmp			r1, #0
			beq			NoNeed
			mov			r1, #0
			strb		r1, [r0]
			bl			IRQContextSwap	
NoNeed			
			
;- Mark the End of Interrupt on the AIC
;            ldr         r0, =AIC_BASE
;            str         r0, [r0, #AIC_EOICR]

			
;- Restore scratch/used registers and LR from User Stack
            ldmia       sp!, { r0-r12, r14}

;- Disable Interrupt and switch back in IRQ mode
            mrs         r0, CPSR
            bic         r0, r0, #SVC32Mode
            orr         r0, r0, #I_BIT:OR:IRQ32Mode
            msr         CPSR_c, r0


;- Restore SPSR_irq and r0 from IRQ stack
            ldmia       sp!, {r0, r14}
            msr         SPSR_cxsf, r14

;- Restore ajusted LR_irq from IRQ stack directly in the PC
            ldmia       sp!, {pc}^

			
            END

⌨️ 快捷键说明

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