?? os_cpu_a.s
字號:
;/*
;************************************************************************************************************
;* (c) Copyright ARM Limited 1999. All rights reserved.
;*
;* ARM 專用代碼
;*
;* 文件名稱: os_cpu_a.s
;*
;* 文件說明: 該模塊中的函數(shù)說明
;*
;* void OSIntCtxSw 中斷中的任務(wù)切換
;* void OSCtxSw 任務(wù)切換
;* void OSCPUSaveSR 保存中斷前的寄存器狀態(tài)
;* void OSCPURestoreSR 中斷完成后,恢復中斷前的狀態(tài)
;* void OSStartHighRdy 啟動最高優(yōu)先級任務(wù)
;************************************************************************************************************
;*/
;/**********************************異常模式下的向量定義****************************************/
SwiV EQU 0x08
IrqV EQU 0x18
FiqV EQU 0x1c
NoInt EQU 0xc0
SVC32Mode EQU 0x13
IRQ32Mode EQU 0x12
FIQ32Mode EQU 0x11
OSEnterSWI EQU 0x00
AREA |subr|, CODE, READONLY
;/*
;*********************************************************************************************************
; 啟動多任務(wù)
; void OSStartHighRdy(void)
;
; 注釋 : OSStartHighRdy() 函數(shù)必須:
; a) 在 OSTaskSwHook() 之后調(diào)用,
; b) 設(shè)定 OSRunning 為真,
; c) 切換到最高優(yōu)先級.
;*********************************************************************************************************
;*/
IMPORT OSTCBCur
IMPORT OSTaskSwHook
IMPORT OSRunning
IMPORT OSTCBHighRdy
EXPORT OSStartHighRdy
OSStartHighRdy ;// 尋找最高級任務(wù)開始
bl OSTaskSwHook ;// 調(diào)用用戶定義的任務(wù)鉤子函數(shù)
ldr r4,=OSRunning ;//設(shè)定多任務(wù)開始標志
mov r5,#1
strb r5,[r4]
ldr r4,=OSTCBCur
ldr r5,=OSTCBHighRdy ;// 得到最高優(yōu)先級任務(wù)的 TCB 地址
ldr r5,[r5] ;// 得到任務(wù)堆棧指針
ldr sp,[r5]
str r5,[r4] ;// 把得到的TCB地址指針給當前的TCB
;// 切換到新任務(wù)
ldmfd sp!,{r4} ;// 彈出新任務(wù)的SPSR
msr SPSR_cxsf,r4 ;// 寫入當前狀態(tài)寄存器
ldmfd sp!,{r4} ;// 彈出新任務(wù)的 psr
msr CPSR_cxsf,r4 ;// 寫入當前狀態(tài)寄存器
ldmfd sp!,{r0-r12,lr,pc} ;// 彈出新任務(wù)的 r0-r12,lr & pc
;/*
;***********************************************************************************************************
; 執(zhí)行任務(wù)切換 (任務(wù)級)
; void OSCtxSw(void)
;
; 注釋 : OSTCBCur 指向掛起的任務(wù)的OS_TCB
; OSTCBHighRdy 指向恢復的任務(wù)的OS_TCB
;
;************************************************************************************************************
;*/
IMPORT OSTCBCur
IMPORT OSTaskSwHook
IMPORT OSTCBHighRdy
IMPORT OSPrioCur
IMPORT OSPrioHighRdy
EXPORT OSCtxSw
OSCtxSw ;// 任務(wù)切換
stmfd sp!,{lr} ;// 壓入PC (lr 應(yīng)代替 PC被壓入)
stmfd sp!,{r0-r12,lr} ;// 壓入 lr & register file
mrs r4,cpsr
stmfd sp!,{r4} ;// 壓入CPSR
mrs r4,spsr
stmfd sp!,{r4} ;// 壓入 spsr
;// OSPrioCur = OSPrioHighRdy
ldr r4,=OSPrioCur
ldr r5,=OSPrioHighRdy
ldrb r6,[r5]
strb r6,[r4]
;// 得到當前的TCB的地址
ldr r4,=OSTCBCur
ldr r5,[r4]
str sp,[r5] ;// 在任務(wù)TCB中的存放當前任務(wù)控制塊的棧底指針
bl OSTaskSwHook ;// 調(diào)用任務(wù)的鉤子函數(shù)
;// 得到最高優(yōu)先級TCB的地址
ldr r6,=OSTCBHighRdy
ldr r6,[r6]
ldr sp,[r6] ;// 得到新任務(wù)的堆棧棧底指針
;// OSTCBCur = OSTCBHighRdy
str r6,[r4] ;// 設(shè)定新任務(wù)TCB的地址
ldmfd sp!,{r4} ;// 彈出新任務(wù)的 spsr
msr SPSR_cxsf,r4
ldmfd sp!,{r4} ;// 彈出新任務(wù)的 psr
msr CPSR_cxsf,r4
ldmfd sp!,{r0-r12,lr,pc} ;// 彈出新任務(wù)的 r0-r12,lr & pc
;/*
;************************************************************************************************************
; 執(zhí)行任務(wù)切換 (中斷級)
; void OSIntCtxSw(void)
;
; 注釋 : 該函數(shù)針對中斷服務(wù)子程序Handler僅設(shè)定標志為真。
;
;************************************************************************************************************
;*/
IMPORT OSIntCtxSwFlag
EXPORT OSIntCtxSw
OSIntCtxSw
ldr r0,=OSIntCtxSwFlag
mov r1,#1
str r1,[r0]
mov pc,lr
;/*
;************************************************************************************************************
; IRQ HANDLER
;
; 該段處理所有的 IRQs
; 注意: FIQ Handler 段應(yīng)該近似此段編程
;
;************************************************************************************************************
;*/
IMPORT C_IRQHandler ;//target.c中定義
IMPORT OSIntEnter
IMPORT OSIntExit
IMPORT OSIntCtxSwFlag
IMPORT OSTCBCur
IMPORT OSTaskSwHook
IMPORT OSTCBHighRdy
IMPORT OSPrioCur
IMPORT OSPrioHighRdy
NOINT EQU 0xc0
EXPORT UCOS_IRQHandler
UCOS_IRQHandler
stmfd sp!,{r0-r3,r12,lr} ;// 保存CPU寄存器內(nèi)容,進入IRQ后,CPSR 為1,禁止IRQ
bl OSIntEnter ;// 內(nèi)核進入ISR函數(shù)
bl C_IRQHandler
bl OSIntExit ;// 內(nèi)核退出ISR函數(shù)時,如果需要切換到更高優(yōu)先級中去,該函數(shù)在OSIntCtxSw()中,
;// 使OSIntCtxSwFlag為1。
ldr r0,=OSIntCtxSwFlag
ldr r1,[r0]
cmp r1,#1
beq _IntCtxSw ;// 判斷是否在中斷中發(fā)生任務(wù)切換?
ldmfd sp!,{r0-r3,r12,lr} ;// 否,則恢復CPU寄存器內(nèi)容
subs pc,lr,#4 ;// 從IRQ中返回
_IntCtxSw ;// 是, 則發(fā)生中斷級任務(wù)切換
mov r1,#0
str r1,[r0] ;// 清OSIntCtxSwFlag,使它為1
ldmfd sp!,{r0-r3,r12,lr} ;//清IRQ中斷堆棧
stmfd sp!,{r0-r3} ;//將要使用R0,R1,R2,R3為暫時寄存器
mov r1,sp ;// 保存IRQ的中斷堆棧指針
add sp,sp,#16 ;// 回到IRQ的堆棧棧頂
sub r2,lr,#4 ;// 保存PC的返回地址
mrs r3,spsr ;// 保存被中斷的任務(wù)的SPSR
orr r0,r3,#NOINT ;//當返回到SVC或SYS模式下,禁止中斷
msr spsr_c,r0
ldr r0,=.+8
movs pc,r0 ;//返回到SVC或SYS模式,禁止中斷,即把spsr_c裝入了cpsr中
stmfd sp!,{r2} ;//此時的SP為SVC或SYS的堆棧指針, 壓入被中斷的任務(wù)的 pc
stmfd sp!,{r4-r12,lr} ;// 壓入被中斷的任務(wù)的 lr,r12-r4
mov r4,r1 ;//保存IRQ的中斷堆棧指針到R4
mov r5,r3 ;//保存被中斷的任務(wù)的SPSR到R5
ldmfd r4!,{r0-r3} ;//從IRQ的中斷堆棧中彈出被中斷的任務(wù)的 r3-r0 到CPU的寄存器中
stmfd sp!,{r0-r3} ;// 壓入被中斷的任務(wù)的 r3-r0 到SVC或SYS模式的堆棧中
stmfd sp!,{r5} ;// 壓入被中斷的任務(wù)的 Cpsr
mrs r4,spsr
stmfd sp!,{r4} ;// 壓入被中斷的任務(wù)的 spsr 系統(tǒng)模式下,沒有spsr
;// OSPrioCur = OSPrioHighRdy
ldr r4,=OSPrioCur
ldr r5,=OSPrioHighRdy
ldrb r5,[r5]
strb r5,[r4]
;// 得到當前的TCB的地址
ldr r4,=OSTCBCur
ldr r5,[r4]
str sp,[r5] ;// 在任務(wù)TCB中的存放當前任務(wù)控制塊的指針
bl OSTaskSwHook ;// 調(diào)用任務(wù)的鉤子函數(shù)
;// 得到最高優(yōu)先級TCB的地址
ldr r6,=OSTCBHighRdy
ldr r6,[r6]
ldr sp,[r6] ;// 得到新任務(wù)的堆棧指針
;// OSTCBCur = OSTCBHighRdy
str r6,[r4] ;// 設(shè)定新任務(wù)TCB的地址
ldmfd sp!,{r4} ;// 彈出新任務(wù)的 spsr
msr SPSR_cxsf,r4
ldmfd sp!,{r4} ;// 彈出新任務(wù)的 cpsr
msr CPSR_cxsf,r4
ldmfd sp!,{r0-r12,lr,pc} ;// 彈出新任務(wù)的 r0-r12,lr & pc
;/*
;************************************************************************************************************
; 臨界段代碼的實現(xiàn)方式3
;
; 函數(shù)描述 : 通過預設(shè)定中斷的狀態(tài)來開關(guān)中斷。在局部變量'cpu_sr'中保存中斷標志,之后關(guān)閉中斷。 'cpu_sr' 分配
; 給所有需要關(guān)中斷的 uC/OS-II'的函數(shù)。通過把'cpu_sr' 復制到CPU的狀態(tài)寄存器中來恢復關(guān)中斷前的狀態(tài)。
;
; OS_CPU_SR OSCPUSaveSR()
; 輸入?yún)?shù) : 無
;
; 返回值 : OS_CPU_SR
;
; OSCPURestoreSR(OS_CPU_SR cpu_sr)
; 輸入?yún)?shù) : OS_CPU_SR
;
; 返回值 : 無
;
; 注釋 : 該函數(shù)使用如下
;
; 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,#NOINT
msr CPSR_c,r1
mov pc,lr
EXPORT OSCPURestoreSR
OSCPURestoreSR
msr CPSR_c,r0
mov pc,lr
END
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -