?? os_cpu_a.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 + -