?? os_cpu_a.asm
字號:
;/*
;*********************************************************************************************************
;* uC/OS-II
;* 實時內核
;*
;* (c) Copyright 1992-1998, Jean J. Labrosse, Plantation, FL
;* 版權所有
;*
;* MCU-51 專用代碼
;* KEIL C51大模式編譯
;*
;* 文件名 : OS_CPU_A.ASM
;* 作者 : Jean J. Labrosse
;* 改編 : 高偉能,根據《基于單片機8051的嵌入式系統開發指南》
;*********************************************************************************************************
;*/
;偽指令詳細用法請查A51.PDF文件
;程序結構詳見《uC/OS-II》193-198頁
;不用此語句?。?! $CASE ;標號和變量名區分大小寫
$NOMOD51
EA BIT 0A8H.7
SP DATA 081H
B DATA 0F0H
ACC DATA 0E0H
DPH DATA 083H
DPL DATA 082H
PSW DATA 0D0H
NAME OS_CPU_A ;模塊名
;定義重定位段
?PR?OSStartHighRdy?OS_CPU_A SEGMENT CODE
?PR?OSCtxSw?OS_CPU_A SEGMENT CODE
?PR?OSIntCtxSw?OS_CPU_A SEGMENT CODE
;聲明引用全局變量和外部子程序
EXTRN DATA (?C_XBP) ;仿真堆棧指針用于重入局部變量保存,為V2.51能被C使用定義在本模塊中
EXTRN IDATA (OSTCBCur)
EXTRN IDATA (OSTCBHighRdy)
EXTRN IDATA (OSRunning)
EXTRN IDATA (OSPrioCur)
EXTRN IDATA (OSPrioHighRdy)
EXTRN CODE (_?OSTaskSwHook)
;對外聲明不可重入函數
PUBLIC OSStartHighRdy
PUBLIC OSCtxSw
PUBLIC OSIntCtxSw
;分配堆棧空間。只關心大小,堆棧起點由keil決定,通過標號可以獲得keil分配的SP起點。
?STACK SEGMENT IDATA
RSEG ?STACK
OSStack:
DS 40H
OSStkStart IDATA OSStack-1
;定義壓棧出棧宏
PUSHALL MACRO
PUSH ACC
PUSH B
PUSH DPH
PUSH DPL
PUSH PSW
PUSH AR0
PUSH AR1
PUSH AR2
PUSH AR3
PUSH AR4
PUSH AR5
PUSH AR6
PUSH AR7
ENDM
POPALL MACRO
POP AR7
POP AR6
POP AR5
POP AR4
POP AR3
POP AR2
POP AR1
POP AR0
POP PSW
POP DPL
POP DPH
POP B
POP ACC
ENDM
;子程序
;-------------------------------------------------------------------------
RSEG ?PR?OSStartHighRdy?OS_CPU_A
OSStartHighRdy:
USING 0 ;上電后51自動關中斷,此處不必用CLR EA指令,因為到此處還未開中斷,本程序退出后,開中斷。
LCALL _?OSTaskSwHook
OSCtxSw_in:
;OSTCBCur ===> DPTR 獲得當前TCB指針,詳見C51.PDF第178頁
MOV R0,#LOW (OSTCBCur) ;獲得OSTCBCur指針低地址,指針占3字節。+0類型+1高8位數據+2低8位數據
INC R0
MOV DPH,@R0 ;全局變量OSTCBCur在IDATA中
INC R0
MOV DPL,@R0
;OSTCBCur->OSTCBStkPtr ===> DPTR 獲得用戶堆棧指針
INC DPTR ;指針占3字節。+0類型+1高8位數據+2低8位數據
MOVX A,@DPTR ;.OSTCBStkPtr是void指針
MOV R0,A
INC DPTR
MOVX A,@DPTR
MOV R1,A
MOV DPH,R0
MOV DPL,R1
;*UserStkPtr ===> R5 用戶堆棧起始地址內容(即用戶堆棧長度放在此處) 詳見文檔說明 指針用法詳見C51.PDF第178頁
MOVX A,@DPTR ;用戶堆棧中是unsigned char類型數據
MOV R5,A ;R5=用戶堆棧長度
;恢復現場堆棧內容
MOV R0,#OSStkStart
restore_stack:
INC DPTR
INC R0
MOVX A,@DPTR
MOV @R0,A
DJNZ R5,restore_stack
;恢復堆棧指針SP
MOV SP,R0
;恢復仿真堆棧指針?C_XBP
INC DPTR
MOVX A,@DPTR
MOV ?C_XBP,A ;?C_XBP 仿真堆棧指針高8位
INC DPTR
MOVX A,@DPTR
MOV ?C_XBP+1,A ;?C_XBP 仿真堆棧指針低8位
;OSRunning=TRUE
MOV R0,#LOW (OSRunning)
MOV @R0,#01
POPALL
SETB EA ;開中斷
RETI
;-------------------------------------------------------------------------
RSEG ?PR?OSCtxSw?OS_CPU_A
OSCtxSw:
PUSHALL
OSIntCtxSw_in:
;獲得堆棧長度和起址
MOV A,SP
CLR C
SUBB A,#OSStkStart
MOV R5,A ;獲得堆棧長度
;OSTCBCur ===> DPTR 獲得當前TCB指針,詳見C51.PDF第178頁
MOV R0,#LOW (OSTCBCur) ;獲得OSTCBCur指針低地址,指針占3字節。+0類型+1高8位數據+2低8位數據
INC R0
MOV DPH,@R0 ;全局變量OSTCBCur在IDATA中
INC R0
MOV DPL,@R0
;OSTCBCur->OSTCBStkPtr ===> DPTR 獲得用戶堆棧指針
INC DPTR ;指針占3字節。+0類型+1高8位數據+2低8位數據
MOVX A,@DPTR ;.OSTCBStkPtr是void指針
MOV R0,A
INC DPTR
MOVX A,@DPTR
MOV R1,A
MOV DPH,R0
MOV DPL,R1
;保存堆棧長度
MOV A,R5
MOVX @DPTR,A
MOV R0,#OSStkStart ;獲得堆棧起址
save_stack:
INC DPTR
INC R0
MOV A,@R0
MOVX @DPTR,A
DJNZ R5,save_stack
;保存仿真堆棧指針?C_XBP
INC DPTR
MOV A,?C_XBP ;?C_XBP 仿真堆棧指針高8位
MOVX @DPTR,A
INC DPTR
MOV A,?C_XBP+1 ;?C_XBP 仿真堆棧指針低8位
MOVX @DPTR,A
;調用用戶程序
LCALL _?OSTaskSwHook
;OSTCBCur = OSTCBHighRdy
MOV R0,#OSTCBCur
MOV R1,#OSTCBHighRdy
MOV A,@R1
MOV @R0,A
INC R0
INC R1
MOV A,@R1
MOV @R0,A
INC R0
INC R1
MOV A,@R1
MOV @R0,A
;OSPrioCur = OSPrioHighRdy 使用這兩個變量主要目的是為了使指針比較變為字節比較,以便節省時間。
MOV R0,#OSPrioCur
MOV R1,#OSPrioHighRdy
MOV A,@R1
MOV @R0,A
LJMP OSCtxSw_in
;-------------------------------------------------------------------------
RSEG ?PR?OSIntCtxSw?OS_CPU_A
OSIntCtxSw:
;調整SP指針去掉在調用OSIntExit(),OSIntCtxSw()過程中壓入堆棧的多余內容
;SP=SP-4
MOV A,SP
CLR C
SUBB A,#4
MOV SP,A
LJMP OSIntCtxSw_in
END
;-------------------------------------------------------------------------
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -