?? os_cpu_a.asm
字號:
// os_cpu.asm
EXTERN OSRunning ; 外部參考
EXTERN OSPrioCur
EXTERN OSPrioHighRdy
EXTERN OSTCBCur
EXTERN OSTCBHighRdy
EXTERN OSIntNesting
EXTERN OSIntExit
EXTERN OSTaskSwHook
EXTERN OS_CPU_IRQ_ISR_Handler
EXTERN OS_CPU_FIQ_ISR_Handler
PUBLIC OS_CPU_SR_Save ; 本文件中定義的函數(shù)
PUBLIC OS_CPU_SR_Restore
PUBLIC OSStartHighRdy
PUBLIC OSCtxSw
PUBLIC OSIntCtxSw
PUBLIC OS_CPU_IRQ_ISR
PUBLIC OS_CPU_FIQ_ISR
NO_INT EQU 0xC0 ; 用于禁止FIQ和IRQ中斷的屏蔽碼
SVC32_MODE EQU 0x13
FIQ32_MODE EQU 0x11
IRQ32_MODE EQU 0x12
;*********************************************************************************************************
; 方式3函數(shù)的臨界部分
; 說明:通過保存中斷狀態(tài)來禁止/允許中斷。一般來說應(yīng)該將中斷禁止標志保存在變量cpu_sr中,然后禁止中斷。
; 將cpu_sr復(fù)制回CPU的狀態(tài)寄存器即可恢復(fù)中斷禁止狀態(tài)。
;
; 原型:OS_CPU_SR OS_CPU_SR_Save(void);
; void OS_CPU_SR_Restore(OS_CPU_SR cpu_sr);
;
; 注意::1) 函數(shù)一般使用方法容下:
; void Task (void *p_arg) {
; #if OS_CRITICAL_METHOD == 3 // 分配CPU狀態(tài)寄存器存儲單元
; OS_CPU_SR cpu_sr;
; #endif
; :
; :
; OS_ENTER_CRITICAL(); // cpu_sr = OS_CPU_SaveSR();
; :
; :
; OS_EXIT_CRITICAL(); // OS_CPU_RestoreSR(cpu_sr);
; :
; :
; }
;
; 2) OS_CPU_SaveSR() // 禁止中斷
;*********************************************************************************************************
RSEG CODE:CODE:NOROOT(2)
CODE32
OS_CPU_SR_Save
MRS R0,CPSR ; 設(shè)置CPSR中的IRQFIQ位以禁止所有中斷
ORR R1,R0,#NO_INT
MSR CPSR_c,R1
MRS R1,CPSR ; 確認CPSR中包含了合適的中斷禁止標志
AND R1,R1,#NO_INT
CMP R1,#NO_INT
BNE OS_CPU_SR_Save ; 沒有恰當禁止,重試
BX LR ; 已禁止
OS_CPU_SR_Restore
MSR CPSR_c,R0
BX LR
;*********************************************************************************************************
; 啟動多任務(wù)
; 原型:void OSStartHighRdy(void)
;
; 注意:1) OSStartHighRdy()函數(shù)必須:
; a) 調(diào)用 OSTaskSwHook(),
; b) 然后將 OSRunning 設(shè)置為 TRUE,
; c) 切換到最高優(yōu)先級任務(wù)
;*********************************************************************************************************
RSEG CODE:CODE:NOROOT(2)
CODE32
OSStartHighRdy
LDR R0, ??OS_TaskSwHook ; OSTaskSwHook();
MOV LR, PC
BX R0
MSR CPSR_cxsf, #0xD3 ; 切換到管理模式,禁止 IRQ 和 FIQ
LDR R4, ??OS_Running ; OSRunning = TRUE
MOV R5, #1
STRB R5, [R4]
; 切換到最高優(yōu)先級任務(wù)
LDR R4, ??OS_TCBHighRdy ; 獲得最高優(yōu)先級任務(wù)的TCB地址
LDR R4, [R4] ; 獲得堆棧指針
LDR SP, [R4] ; 切換到新堆棧
LDR R4, [SP], #4 ; 讀取SP的對應(yīng)地址的值, SP=SP+4, 彈出新任務(wù)的 CPSR
MSR SPSR_cxsf,R4 ; 屏蔽0-31位
LDMFD SP!, {R0-R12,LR,PC}^ ; 彈出新任務(wù)的上下文(context)
; 由于用戶堆棧的生長方向是向下的
; 因此在堆棧彈出時向上 FD參數(shù)用于遞減堆棧
; ^ 表示除裝載正常的多寄存器外,將SPSR拷貝到CPSR中
; ! 表示將最后的地址回寫到SP中
;*********************************************************************************************************
; 執(zhí)行任務(wù)切換(任務(wù)級) - OSCtxSw()
;
; 注意:1) OSCtxSw() 應(yīng)在禁止FIQ和IRQ中斷的條件下以系統(tǒng)模式調(diào)用
;
; 2) OSCtxSw() 的偽代碼如下:
; a) 將當前任務(wù)的上下文(context)保存到當前任務(wù)的堆棧中
; b) OSTCBCur->OSTCBStkPtr = SP;
; c) OSTaskSwHook();
; d) OSPrioCur = OSPrioHighRdy;
; e) OSTCBCur = OSTCBHighRdy;
; f) SP = OSTCBHighRdy->OSTCBStkPtr;
; g) 從新任務(wù)的堆棧中恢復(fù)新任務(wù)的上下文(context)
; h) 返回到新任務(wù)的代碼中
;
; 3) 入口:
; OSTCBCur 指向要掛起任務(wù)的 OS_TCB
; OSTCBHighRdy 指向要恢復(fù)任務(wù)的 OS_TCB
;*********************************************************************************************************
RSEG CODE:CODE:NOROOT(2)
CODE32
OSCtxSw
; 保存當前任務(wù)的上下文(CONTEXT)
STMFD SP!, {LR} ; 當前地址壓棧
STMFD SP!, {LR}
STMFD SP!, {R0-R12} ; 寄存器壓棧
MRS R4, CPSR ; 當前CPSR壓棧
TST LR, #1 ; 測試是否從Thumb模式下調(diào)用
ORRNE R4, R4, #0x20 ; 是,置1 T 標志
STMFD SP!, {R4}
LDR R4, ??OS_TCBCur ; OSTCBCur->OSTCBStkPtr = SP;
LDR R5, [R4]
STR SP, [R5]
LDR R0, ??OS_TaskSwHook ; OSTaskSwHook();
MOV LR, PC
BX R0
LDR R4, ??OS_PrioCur ; OSPrioCur = OSPrioHighRdy
LDR R5, ??OS_PrioHighRdy
LDRB R6, [R5]
STRB R6, [R4]
LDR R4, ??OS_TCBCur ; OSTCBCur = OSTCBHighRdy;
LDR R6, ??OS_TCBHighRdy
LDR R6, [R6]
STR R6, [R4]
LDR SP, [R6] ; SP = OSTCBHighRdy->OSTCBStkPtr;
; 恢復(fù)新任務(wù)的上下文(CONTEXT)
LDMFD SP!, {R4} ; 新任務(wù)的CPSR出棧
MSR SPSR_cxsf, R4
LDMFD SP!, {R0-R12,LR,PC}^ ; 新任務(wù)的下文(CONTEXT)出棧
;*********************************************************************************************************
; 執(zhí)行任務(wù)切換(中斷級) - OSIntCtxSw()
;
; 注意: 1) OSIntCtxSw() 應(yīng)在禁止FIQ和IRQ中斷的條件下以系統(tǒng)模式調(diào)用
;
; 2) OSCtxSw() 的偽代碼如下:
; a) OSTaskSwHook();
; b) OSPrioCur = OSPrioHighRdy;
; c) OSTCBCur = OSTCBHighRdy;
; d) SP = OSTCBHighRdy->OSTCBStkPtr;
; e) 從新任務(wù)的堆棧中恢復(fù)新任務(wù)的上下文(context)
; f) 返回到新任務(wù)的代碼中
;
; 3) 入口:
; OSTCBCur 指向要掛起任務(wù)的 OS_TCB
; OSTCBHighRdy 指向要恢復(fù)任務(wù)的 OS_TCB
;*********************************************************************************************************
RSEG CODE:CODE:NOROOT(2)
CODE32
OSIntCtxSw
LDR R0, ??OS_TaskSwHook ; OSTaskSwHook();
MOV LR, PC
BX R0
LDR R4,??OS_PrioCur ; OSPrioCur = OSPrioHighRdy
LDR R5,??OS_PrioHighRdy
LDRB R6,[R5]
STRB R6,[R4]
LDR R4,??OS_TCBCur ; OSTCBCur = OSTCBHighRdy;
LDR R6,??OS_TCBHighRdy
LDR R6,[R6]
STR R6,[R4]
LDR SP,[R6] ; SP = OSTCBHighRdy->OSTCBStkPtr;
; 恢復(fù)新任務(wù)的上下文(CONTEXT)
LDMFD SP!, {R4} ; 新任務(wù)的CPSR出棧
MSR SPSR_cxsf, R4
LDMFD SP!, {R0-R12,LR,PC}^ ; 新任務(wù)的上下文(context)出棧
;*********************************************************************************************************
; IRQ 中斷服務(wù)子程序
;*********************************************************************************************************
RSEG CODE:CODE:NOROOT(2)
CODE32
OS_CPU_IRQ_ISR
STMFD SP!, {R1-R3} ; 工作寄存器壓入IRQ堆棧
MOV R1, SP ; 保存IRQ堆棧指針
ADD SP, SP,#12 ; 調(diào)整IRQ堆棧指針
SUB R2, LR,#4 ; 調(diào)整PC返回地址
MRS R3, SPSR ; 將SPSR(即中斷任務(wù)的CPSR)復(fù)制到R3
MSR CPSR_c, #(NO_INT | SVC32_MODE) ; 切換到管理模式
; 將任務(wù)的上下文(CONTEXT)保存到任務(wù)堆棧
STMFD SP!, {R2} ; 任務(wù)的返回地址壓棧
STMFD SP!, {LR} ; 任務(wù)的LR壓棧
STMFD SP!, {R4-R12} ; 任務(wù)的R12-R4壓棧
LDMFD R1!, {R4-R6} ; 將任務(wù)的R1-R3從IRQ堆棧移動到管理堆棧
STMFD SP!, {R4-R6}
STMFD SP!, {R0} ; 任務(wù)的R0壓入任務(wù)堆棧
STMFD SP!, {R3} ; 任務(wù)的CPSR(即IRQ's SPSR)壓棧
; 處理嵌套計數(shù)器
LDR R0, ??OS_IntNesting ; OSIntNesting++;
LDRB R1, [R0]
ADD R1, R1,#1
STRB R1, [R0]
CMP R1, #1 ; if (OSIntNesting == 1) {
BNE OS_CPU_IRQ_ISR_1
LDR R4, ??OS_TCBCur ; OSTCBCur->OSTCBStkPtr = SP
LDR R5, [R4]
STR SP, [R5] ; }
OS_CPU_IRQ_ISR_1
MSR CPSR_c, #(NO_INT | IRQ32_MODE) ; 切換到IRQ模式(使用IRQ堆棧處理中斷)
LDR R0, ??OS_CPU_IRQ_ISR_Handler ; OS_CPU_IRQ_ISR_Handler();
MOV LR, PC
BX R0
MSR CPSR_c, #(NO_INT | SVC32_MODE) ; 切換到管理模式
LDR R0, ??OS_IntExit ; OSIntExit();
MOV LR, PC
BX R0
; 恢復(fù)新任務(wù)的上下文(CONTEXT)
LDMFD SP!, {R4} ; 新任務(wù)的CPSR出棧
MSR SPSR_cxsf, R4
LDMFD SP!, {R0-R12,LR,PC}^ ; 新任務(wù)的上下文(context)出棧
;*********************************************************************************************************
; FIQ 中斷服務(wù)子程序
;*********************************************************************************************************
RSEG CODE:CODE:NOROOT(2)
CODE32
OS_CPU_FIQ_ISR
STMFD SP!, {R1-R3} ; 工作寄存器壓入FIQ堆棧
MOV R1, SP ; 保存FIQ堆棧指針
ADD SP, SP,#12 ; 調(diào)整FIQ堆棧指針
SUB R2, LR,#4 ; 調(diào)整PC返回地址
MRS R3, SPSR ; 將SPSR(即中斷任務(wù)的CPSR)復(fù)制到R3
MSR CPSR_c, #(NO_INT | SVC32_MODE) ; 切換到管理模式
; 將任務(wù)的上下文(CONTEXT)保存到任務(wù)堆棧
STMFD SP!, {R2} ; 任務(wù)的返回地址壓棧
STMFD SP!, {LR} ; 任務(wù)的LR壓棧
STMFD SP!, {R4-R12} ; 任務(wù)的R12-R4壓棧
LDMFD R1!, {R4-R6} ; 將任務(wù)的R1-R3從IRQ堆棧移動到管理堆棧
STMFD SP!, {R4-R6}
STMFD SP!, {R0} ; 任務(wù)的R0壓入任務(wù)堆棧
STMFD SP!, {R3} ; 任務(wù)的CPSR(即FIQ's SPSR)壓棧
; 處理嵌套計數(shù)器
LDR R0, ??OS_IntNesting ; OSIntNesting++;
LDRB R1, [R0]
ADD R1, R1,#1
STRB R1, [R0]
CMP R1, #1 ; if (OSIntNesting == 1) {
BNE OS_CPU_FIQ_ISR_1
LDR R4, ??OS_TCBCur ; OSTCBCur->OSTCBStkPtr = SP
LDR R5, [R4]
STR SP, [R5] ; }
OS_CPU_FIQ_ISR_1
MSR CPSR_c, #(NO_INT | FIQ32_MODE) ; 切換到FIQ模式(使用FIQ堆棧處理中斷)
LDR R0, ??OS_CPU_FIQ_ISR_Handler ; OS_CPU_FIQ_ISR_Handler();
MOV LR, PC
BX R0
MSR CPSR_c, #(NO_INT | SVC32_MODE) ; 切換到管理模式
LDR R0, ??OS_IntExit ; OSIntExit();
MOV LR, PC
BX R0
; 恢復(fù)新任務(wù)的上下文(CONTEXT)
LDMFD SP!, {R4} ; 新任務(wù)的CPSR出棧
MSR SPSR_cxsf, R4
LDMFD SP!, {R0-R12,LR,PC}^ ; 新任務(wù)的上下文(context)出棧
;*********************************************************************************************************
; 變量的指針
;*********************************************************************************************************
DATA
??OS_TaskSwHook:
DC32 OSTaskSwHook
??OS_CPU_IRQ_ISR_Handler:
DC32 OS_CPU_IRQ_ISR_Handler
??OS_CPU_FIQ_ISR_Handler:
DC32 OS_CPU_FIQ_ISR_Handler
??OS_IntExit:
DC32 OSIntExit
??OS_IntNesting:
DC32 OSIntNesting
??OS_PrioCur:
DC32 OSPrioCur
??OS_PrioHighRdy:
DC32 OSPrioHighRdy
??OS_Running:
DC32 OSRunning
??OS_TCBCur:
DC32 OSTCBCur
??OS_TCBHighRdy:
DC32 OSTCBHighRdy
END
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -