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

📄 os_cpu_a.s

📁 ucos 在GAMEBOY上的移植
💻 S
字号:
;/****************************************************
; $Workfile:   os_cpu_a.S   for SkyEye simulator    $
; $Revision: 1.1.1.1 $
; $Author: skyeye $
; $Email:   lmcs00;mails.tsinghua.edu.cn            $
; $Date: 2003/02/19 02:42:22 $
;****************************************************/
;/****************************************************
; $Workfile:   os_cpu_a.S   for SkyEye simulator    $
; $Revision: 1.1.1.1 $
; $Author: skyeye $
; $Email:   chenyu;hpclab.cs.tsinghua.edu.cn        $
; $Email:   lmcs00;mails.tsinghua.edu.cn            $
; $Date: 2003/02/19 02:42:22 $
;****************************************************/
;/***************************************************
; $Workfile:   os_cpu_a.S   for SkyEye simulator    $
; $Revision: 1.1.1.1 $
; $Author: skyeye $
; $Email:   chenyu;hpclab.cs.tsinghua.edu.cn        $
; $Email:   lmcs00;mails.tsinghua.edu.cn            $
; $Date: 2003/02/19 02:42:22 $
;****************************************************/
;/***************************************************
; $Workfile:   Os_cpu_a.s  $
; $Revision: 1.1.1.1 $
; $Author: skyeye $
; $Date: 2003/02/19 02:42:22 $
; **************************************************/

;/***************************************************
; 代码基本上基于uCOS-II 在skyeye ARM 系统上的移植 
; 并依照<<uC/OS-II 嵌入式实时操作系统>>规整代码并注释
; 
;	李强(mail2li in C51BBS)
;		mail2li@21cn.com or mail2li@163.com
;				03.11.28
; **************************************************/

;/********************************************************************/
        AREA	OSCPUASM, CODE, READONLY

;/***********************************************************************
;
; 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
	IMPORT	OSTaskSwHook
	IMPORT  OSTCBHighRdy
	IMPORT  OSRunning
OSStartHighRdy
;1. 调用OSTaskSwHook();
        BL 	OSTaskSwHook             ; Call user-defined hook function

;2.	Get the stack pointer of the task to resume: sp = OSTCBHighRdy->OSTCBStkPtr;
        LDR 	r4, =OSTCBHighRdy        ; Get highest priority task TCB address
        LDR 	r4, [r4]                 ; get stack pointer
        LDR 	sp, [r4]                 ; switch to the new stack

;3.	OSRunning = TRUE;
        LDR 	r4,=OSRunning            ; Indicate that multitasking has started
        MOV 	r5, #1
        STRB 	r5, [r4]                 ; OSRunning = true

;4.5. Restore all processor registers from the new task stack	and return 
;	remove by LQ
;		LDMFD 	sp!, {r4}                ; pop new task s spsr
;		MSR 	spsr_cxsf, r4
;	remove end
        LDMFD 	sp!, {r4}                ; pop new task s psr
        MSR 	cpsr_cxsf, r4
		LDMFD 	sp!, {r0-r12,lr,pc}      ; pop new task s r0-r12,lr & pc

;/***********************************************************************
;
; 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:
;   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
	EXPORT 	OS_TASK_SW
	IMPORT	OSPrioCur
	IMPORT	OSPrioHighRdy
	IMPORT	OSTCBCur
	IMPORT	OSTaskSwHook
	IMPORT	OSTCBHighRdy

OS_TASK_SW
OSCtxSw
;1.	保存当前处理器寄存器;	<<<
		STMFD 	sp!, {lr}				; push pc 实际上push lr 是为了在pop的时候 直接获得新pc值
		STMFD 	sp!, {r0-r12,lr}		; push lr & register file
		MRS 	r4, cpsr
		STMFD 	sp!, {r4}				; push current psr
		; move by LQ
;		MRS 	r4, spsr						
;		STMFD 	sp!, {r4}				; push current spsr
		; end of move by LQ

_OSCtxSw
;2.	将当前任务的堆栈指针保存到当前任务的OS_TCB中:OSTCBCur->OSTCBStkPtr = sp;
		LDR 	r4, =OSTCBCur		    ; Get current task TCB address
		LDR 	r5, [r4]
		STR 	sp, [r5]				 ; store sp in preempted tasks s TCB

;3.	调用用户定义的OSTaskSwHook();
		BL 	OSTaskSwHook		     ; call Task Switch Hook

;4.	OSTCBCur  = OSTCBHighRdy;
		LDR		r4, =OSTCBHighRdy
		LDR		r4, [r4]
		LDR		r5, =OSTCBCur
		STR		r4, [r5]				 ; OSTCBCur = OSTCBHighRdy

;5.	OSPrioCur = OSPrioHighRdy;
		LDR		r6, =OSPrioHighRdy
		LDRB	r6, [r6]
		LDR		r5, =OSPrioCur
		STRB	r6, [r5]				 ; OSPrioCur = OSPrioHighRdy

;6.	得到需要恢复的任务的堆栈指针: sp = OSTCBHighRdy->OSTCBStkPtr;
		LDR 	r6, =OSTCBHighRdy		; Get highest priority task TCB address
		LDR 	r6, [r6]
		LDR 	sp, [r6]				; get new task s stack pointer

;7.8.将寄存器从新任务的堆栈中恢复出来(切换现场并return);
		; move by LQ
;		LDMFD 	sp!, {r4}				; pop new task spsr
;		MSR 	spsr_cxsf, r4
		; end of move, by LQ
		LDMFD 	sp!, {r4}				; pop new task cpsr
		MSR 	cpsr_cxsf, r4
		LDMFD 	sp!, {r0-r12,lr,pc}     ; pop new task r0-r12,lr & pc
;	end of OSCtxSw

;/***********************************************************************
;
; 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:
;   Sets up the stacks and registers to call the task level
;   context switch
;
;*********************************************************************/
        EXPORT 	OSIntCtxSw

;/*
* SAVED_LR_IRQ,SAVED_LR_USR 两变量是用来转存不同mode(irq,user)下arm的lr值的 
* 因为无法使用sp传递 有要保护寄存器 所以地址范围只能在0x7fff范围类 这样就无法
* 使用data空间 所以移植的时候 必须注意这部分代码必须放在可以读写的SRAM/SDRAM中
;*/

SAVED_LR_IRQ	DCD   0
SAVED_LR_USR	DCD   0
		
OSIntCtxSw        
;0. 调整OSIntCtxSw被OSIntExit调用后产生的堆栈告别 
		ADD		sp,sp,#0xC		; !!! 警告 这部分数值和编译器很有关 这种方式也不是最好的

_OSIntCtxSw
;0. 修复ARM从IRQ模式切换为USER模式带来的sp和lr的自动改变 希望有人能提出更好的方法 pls tell me
	    LDMFD 	sp!, {r4}               ; pop spsr_irq
		MSR 	spsr_cxsf, r4
		LDMFD	sp!, {r0-r12, lr}       ; pop r0,r1,...

		STR		lr, SAVED_LR_IRQ         ; save lr_irq to SAVED_LR_IRQ
		ADDS	pc, pc, #0x4          	 ; force change cpsr to mode before irq

		STR     lr, SAVED_LR_USR         ; save lr_svc to SAVED_LR_SVC
		LDR		lr, SAVED_LR_IRQ         ; get lr_irq (where does the irq happend or the return of pc after irq)
		STMFD 	sp!, {lr}                ; push future task pc (lr_irq should be pushed in place of PC)
		LDR		lr, SAVED_LR_USR         ; get lr_svc value saved in SAVED_LR_SVC

        STMFD 	sp!, {r0-r12,lr}         ; push lr & r0-r12 register file
        MRS 	r4, cpsr
        STMFD 	sp!, {r4}                ; push current psr
        b		_OSCtxSw

;/***********************************************************************
;base on sky version :yangye 2003-2-14 -> OSISR
;
; Function OSISR
;	
; READ FIRST:
;	be GBA bios has a irq mode handler as flow:
;	1>	push {r0-r3,r12,lr}
;	2>	call *(0x3008000-4)(void)
;	3>	pop  {r0-r3,r12,lr}
;	4>	reti 						;SPSR->CPSR
;	so I had to resume register file at first in my OSISR 
;	and then force leave irq_mode
;
; Parameters void
;
; Outputs  None
;
; Returns  void
;
; Notes
;	GBA bios use the func-pointer that save in 0x3008000-4 
;	So I save the OSISR pointer in the space in boot.s
;	the isr-func-table also useful and OSTICKIRQ is IRQ_TIMER3
;
;*********************************************************************/;
		EXPORT	OSISR
		IMPORT	OSIntEnter
		IMPORT	irq_entry
		IMPORT	OSIntExit
OSISR
	ldmfd sp!,{r0-r3,r12,lr}		; 恢复中断发生时候现场(将GBA bios isr保护内容恢复)
;1. 保存处理器寄存器;
	SUB		lr, lr, #4				; lr-4 to push
	STMFD	sp!, {r0-r12, lr}       ; push r0-r12 register file and lr( pc return address )
    MRS 	r4, spsr
	STMFD 	sp!, {r4}               ; push current spsr_irq ( =cpsr_svc )
;2. 调用OSIntEnter() 告诉OS有中断发生
	BL	OSIntEnter

;3. 处理中断任务 本移植中将进入irq.c的14个中断服务函数 其中TICK源TIMER3 需要额外多执行OSTimeTick()函数
	BL	irq_entry                   

;4. 调用OSIntExit() 告诉OS中断完成 并且如果有必要将切换任务
	BL	OSIntExit

;5. 恢复处理器寄存器 & reti
	LDMFD 	sp!, {r4}                ; get cpsr_svc from stack
	MSR     spsr_cxsf, r4            ; prepare spsr to return svc mode
	LDMFD	sp!, {r0-r12, pc}^       ; reti it make spsr --> cpsr


;/***********************************************************************
;
; 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".
;
;*********************************************************************/

;/*
;
; 对GBA将REG_IME写○也可以停止全局中断 不过代码长度和关闭CPSR的中断位相等
;
;*/
	EXPORT 	ARMDisableInt

ARMDisableInt
	MRS	r0, cpsr
	STMFD	sp!, {r0}	         ; push current PSR
	ORR	r0, r0, #0x80
	MSR	cpsr_cxsf, r0		 ; disable IRQ Int s

	MOV	pc, lr

    ;------------------------------------------------------------------------
	EXPORT 	ARMEnableInt

ARMEnableInt
	LDMFD	sp!, {r0}                ; pop current PSR
	MSR	cpsr_c, r0               ; restore original cpsr

	MOV	pc, lr
    ;------------------------------------------------------------------------

	END	

⌨️ 快捷键说明

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