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

📄 os_cpu_a.s

📁 uC/OS 使用gcc进行开发的例子,可以参考一下
💻 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		=	0x08
IrqV		=	0x18
FiqV		=	0x1C
NoInt		=	0x80

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

I_BIT		= 0x80

OSEnterSWI	=	0x00

/*	AREA	|subr|, CODE, READONLY */

/*	; Improper use of locations within a READONLY area */

SavedIRQ:	.word	0x0
SavedFIQ:	.word	0x0
SavedSWI:	.word	0x0

			.global	SavedSPSR
addr_SavedSPSR:		.word	SavedSPSR
			.global	SavedR14
addr_SavedR14:		.word	SavedR14

/*	; External symbols we need the addresses of */

			.global	OSTCBCur
addr_OSTCBCur:		.word	OSTCBCur
			.global	OSTCBHighRdy
addr_OSTCBHighRdy:	.word	OSTCBHighRdy
			.global	OSPrioCur
addr_OSPrioCur:		.word	OSPrioCur
			.global	OSPrioHighRdy
addr_OSPrioHighRdy:	.word	OSPrioHighRdy
			.global	OSRunning
addr_OSRunning:		.word	OSRunning
	
	.global 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 | IRQ32Mode
            msr         cpsr, r0
            nop
            nop
            nop
            

/* ;- Restore SPSR_irq and r0 from IRQ stack */
            ldmia       sp!, {r0, r14}
            msr         spsr, 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.
;
*/
	.global	ARMDisableInt
ARMDisableInt:
	MRS	r12, cpsr
	ORR	r12, r12, #NoInt
	MSR	cpsr, r12
	MOV	pc, lr

	.global	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.
*/
			.global		swi_irq

	.global	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;
;
*/
	.global _debug_led
	.global	_DispHex32
	.global	OSStartHighRdy
TempSave:
			.word	0x4321cdef

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  */

/*	ldmfd	sp!, {r0}		 ;pc 

	mov		pc, r0
*/		

/*
;-----------------------------------------;-----------------------------------------
;	from swi_irq.s
;-----------------------------------------;-----------------------------------------

;            AREA        WANGYFLED, CODE, READONLY

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


;            INCLUDE     Include/pio.inc
;            INCLUDE     Include/aic.inc
*/

AIC_BASE            =     0xFFFFF000
/*
@ -----------------------------------------
@ - Advanced Interrupt Controller Structure
@ -----------------------------------------
*/

AIC_SMR		= 0         @  Source Mode Register
AIC_SVR 	= AIC_SMR + 32*4        @  Source Vector Register
AIC_IVR 	= AIC_SVR + 32*4           @  Interrupt Vector Register
AIC_FVR 	= AIC_IVR + 4           @  Fast Interrupt Vector Register
AIC_ISR 	= AIC_FVR + 4           @  Interrupt Status Register
AIC_IPR 	= AIC_ISR + 4           @  Interrupt Pending Register
AIC_IMR 	= AIC_IPR + 4           @  Interrupt Mask Register
AIC_CISR	= AIC_IMR + 4          @  Core Interrupt Status Register
AIC_IECR	= AIC_CISR + 3*4           @  Interrupt Enable Command Register
AIC_IDCR	= AIC_IECR + 4           @  Interrupt Disable Command Register
AIC_ICCR	= AIC_IDCR + 4           @  Interrupt Clear Command Register
AIC_ISCR	= AIC_ICCR + 4           @  Interrupt Set Command Register
AIC_EOICR	= AIC_ISCR + 4           @  End Of Interrupt Command Register


/* ;            INCLUDE     Include/irq.mac */

MY_TCB_BASE        =     0xFFFE0000

			.global		need_to_swap_context
addr_n_t_s_c:
			.word		need_to_swap_context

			.global		timer_irq
/* ;			.global		IRQContextSwap */
			.global		IrqStart
			.global		OSTimeTick
			.global		IrqFinish

/*			
; ------------------------- List of Imported resources -------------------------
; Timer Counter Handler Table
*/
            .global      TCHandlerTable

/* ; ------------------------- List of Internal resources ------------------------- */
MyPtTCBBase:
            .word         MY_TCB_BASE

/*
;------------------------------------------------------------------------------
;- 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
;------------------------------------------------------------------------------
*/
			.global		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, 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 | IRQ32Mode
            msr         cpsr, r0


/* ;- Restore SPSR_irq and r0 from IRQ stack */
            ldmia       sp!, {r0, r14}
            msr         spsr, 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 + -