;**********************************************************************************
;*
;*ver : 2.52
;* file : os_cpu_a.asm
;* brief : 處理器相關彙編文件
;*
;***********************************************************************************
;***********************************************************************************
; 聲明&定義
;***********************************************************************************
PUBLIC _OSTickISR ;時鐘節拍中斷服務函數
PUBLIC _OSStartHighRdy ;最高優先級任務就緒函數
PUBLIC _OSCtxSw ;任務級的上下文切換
PUBLIC _OSIntCtxSw ;中斷級的上下文切換
EXTRN _OSIntExit:FAR ;聲明函數OSIntExit()
EXTRN _OSTimeTick:FAR ;聲明函數OSTimeTick()
EXTRN _OSTaskSwHook:FAR ;聲明函數OSTaskSwHook()
EXTRN _OSIntNesting:BYTE ;聲明變量OSIntNesting
EXTRN _OSTickDOSCtr:BYTE ;聲明變量OSTickDOSCtr
EXTRN _OSPrioHighRdy:BYTE ;聲明變量OSPrioHighRdy
EXTRN _OSPrioCur:BYTE ;聲明變量OSPrioCur
EXTRN _OSRunning:BYTE ;聲明變量OSRunning
EXTRN _OSTCBCur:DWORD ;聲明變量OSTCBCur
EXTRN _OSTCBHighRdy:DWORD ;聲明變量OSTCBHighRdy
.MODEL LARGE
.CODE
.186
PAGE ; /*$PAGE*/
;************************************************************************************
; 就緒態最高優先級任務啓動函數
; void OSStartHighRdy(void)
;
; 堆棧結構如下 :
;
; OSTCBHighRdy->OSTCBStkPtr --> DS (低地址)
; ES
; DI
; SI
; BP
; SP
; BX
; DX
; CX
; AX
; OFFSET of task code address
; SEGMENT of task code address
; Flags to load in PSW
; OFFSET of task code address
; SEGMENT of task code address
; OFFSET of 'pdata'
; SEGMENT of 'pdata' (高地址)
;
; Note : OSStartHighRdy() 示意性代碼:
; a) 調用OSTaskSwHook(),
; b) OSRunning = TRUE,
; c) 得到將要恢復運行任務的堆棧指針,
; Stack pointer = OSTCBHighRdy->OSTCBStkPtr;
; d) 從新任務的堆棧中恢復處理器的所有寄存器
; f) 執行中斷返回指令
;**************************************************************************************
_OSStartHighRdy PROC FAR
MOV AX, SEG _OSTCBHighRdy ;
MOV DS, AX ;
;
CALL FAR PTR _OSTaskSwHook ; 調用用戶自定義函數 OSTaskSwHook()
;
MOV AL, 1 ; 置變量 OSRunning 爲 TRUE
MOV BYTE PTR DS:_OSRunning, AL ; 表明多任務已經啓動
; 得到待運行任務的堆棧指針
LES BX, DWORD PTR DS:_OSTCBHighRdy ; SS:SP = OSTCBHighRdy->OSTCBStkPtr
MOV SS, ES:[BX+2] ;
MOV SP, ES:[BX+0] ;
;
POP DS ; 彈出寄存器
POP ES ; 必須按照OSTaskStkInit()中相反方向彈出
POPA ;
;
IRET ; 中斷返回彈出程序指針、狀態寄存器
_OSStartHighRdy ENDP
PAGE ; /*$PAGE*/
;****************************************************************************************
; 任務切換 (任務級)
; void OSCtxSw(void)
;
; Note(s) : 示意性代碼如下:
; 1) 保存處理器寄存器
; 2) 在當前任務的TCB中保存當前任務的堆棧指針
; OSTCBCur->OSTCBStkPtr = Stack pointer
; 3) OSTaskSwHook()
; 4) OSTCBCur = OSTCBHighRdy
; 5) OSPrioCur = OSPrioHighRdy
; 6) 得到將要開始重新運行的任務的堆棧指針
; Stack pointer = OSTCBHighRdy->OSTCBStkPtr;
; 7) 從新任務的任務堆棧中恢復處理器所有寄存器的值
; 8) 執行中斷返回指令
;
;****************************************************************************************
_OSCtxSw PROC FAR
;
PUSHA ; 保存處理器寄存器
PUSH ES ;
PUSH DS ;
;
MOV AX, SEG _OSTCBCur ; Reload DS in case it was altered
MOV DS, AX ;
; 將堆棧指針保存在任務控制塊中
LES BX, DWORD PTR DS:_OSTCBCur ; OSTCBCur->OSTCBStkPtr = SS:SP
MOV ES:[BX+2], SS ;
MOV ES:[BX+0], SP ;
;
CALL FAR PTR _OSTaskSwHook ; 調用用戶自定義函數OSTaskSwHook()
; 新任務控制塊賦值給當前任務控制塊
MOV AX, WORD PTR DS:_OSTCBHighRdy+2 ; OSTCBCur = OSTCBHighRdy
MOV DX, WORD PTR DS:_OSTCBHighRdy ;
MOV WORD PTR DS:_OSTCBCur+2, AX ;
MOV WORD PTR DS:_OSTCBCur, DX ;
; 新任務優先級賦值給當前任務優先級
MOV AL, BYTE PTR DS:_OSPrioHighRdy ; OSPrioCur = OSPrioHighRdy
MOV BYTE PTR DS:_OSPrioCur, AL ;
; 得到新的任務堆棧指針
LES BX, DWORD PTR DS:_OSTCBHighRdy ; SS:SP = OSTCBHighRdy->OSTCBStkPtr
MOV SS, ES:[BX+2] ;
MOV SP, ES:[BX] ;
;
POP DS ; 從新任務堆棧中恢復cpu寄存器
POP ES ;
POPA ;
;
IRET ; 中斷返回指令,彈出程序指針和狀態寄存器
;
_OSCtxSw ENDP
PAGE ; /*$PAGE*/
;****************************************************************************************
; 任務切換 (中斷級)
; void OSIntCtxSw(void)
;
; Note(s): 示意性代碼如下:
; 1) 調用用戶自定義 OSTaskSwHook()
; 2) OSTCBCur = OSTCBHighRdy
; 3) OSPrioCur = OSPrioHighRdy
; 4) 得到將要重新執行的任務的堆棧指針
; Stack pointer = OSTCBHighRdy->OSTCBStkPtr
; 5) 從新任務的堆棧中恢復所有處理器寄存器
; 6) 執行中斷返回指令
;*****************************************************************************************
_OSIntCtxSw PROC FAR
;
CALL FAR PTR _OSTaskSwHook ; 調用用戶自定義函數OSTaskSwHook()
;
MOV AX, SEG _OSTCBCur ;
MOV DS, AX ;
; 新任務控制塊賦值給當前任務控制塊
MOV AX, WORD PTR DS:_OSTCBHighRdy+2 ; OSTCBCur = OSTCBHighRdy
MOV DX, WORD PTR DS:_OSTCBHighRdy ;
MOV WORD PTR DS:_OSTCBCur+2, AX ;
MOV WORD PTR DS:_OSTCBCur, DX ;
; 新任務優先級賦值給當前任務優先級
MOV AL, BYTE PTR DS:_OSPrioHighRdy ; OSPrioCur = OSPrioHighRdy
MOV BYTE PTR DS:_OSPrioCur, AL
; 得到將要重新運行的任務堆棧指針
LES BX, DWORD PTR DS:_OSTCBHighRdy ; SS:SP = OSTCBHighRdy->OSTCBStkPtr
MOV SS, ES:[BX+2] ;
MOV SP, ES:[BX] ;
;
POP DS ; 從新任務堆棧中恢復所有處理器寄存器
POP ES ;
POPA ;
;
IRET ; 執行中斷返回指令彈出程序指針和狀態寄存器
;
_OSIntCtxSw ENDP
PAGE ; /*$PAGE*/
;*****************************************************************************************
; 時鐘節拍中斷服務子程序
;
; brief : _OSTickISR1和_OSTickISR2是和PC DOS相關的操作,無需關注
;
; Note(s) : 需要關注的示意性代碼如下:
;
; 保存處理器寄存器;
; 調用OSIntEnter()或者直接給OSIntNexting加1
; if (OSIntNesting == 1) {
; OSTCBCur->OSTCBStkPtr = Stack pointer
; }
; 給產生中斷的設備清中斷
; 重新允許中斷(可選)
; OSTimeTick();
; OSIntExit();
; 恢復處理器寄存器
; 執行中斷返回指令
;******************************************************************************************
;
_OSTickISR PROC FAR
;
PUSHA ; 保存處理器寄存器
PUSH ES
PUSH DS
;
MOV AX, SEG(_OSIntNesting) ;
MOV DS, AX
INC BYTE PTR DS:_OSIntNesting ; OSIntNesting加1
;
CMP BYTE PTR DS:_OSIntNesting, 1 ; if (OSIntNesting == 1)
JNE SHORT _OSTickISR1
MOV AX, SEG(_OSTCBCur) ;
MOV DS, AX ; 堆棧指針保存到TCB中
LES BX, DWORD PTR DS:_OSTCBCur ; OSTCBCur->OSTCBStkPtr = SS:SP
MOV ES:[BX+2], SS ;
MOV ES:[BX+0], SP ;
;
_OSTickISR1:
MOV AX, SEG(_OSTickDOSCtr) ; Reload DS
MOV DS, AX
DEC BYTE PTR DS:_OSTickDOSCtr
CMP BYTE PTR DS:_OSTickDOSCtr, 0
JNE SHORT _OSTickISR2 ; Every 11 ticks (~199.99 Hz), chain into DOS
;
MOV BYTE PTR DS:_OSTickDOSCtr, 11
INT 081H ; Chain into DOS's tick ISR
JMP SHORT _OSTickISR3
_OSTickISR2:
MOV AL, 20H ; Move EOI code into AL.
MOV DX, 20H ; Address of 8259 PIC in DX.
OUT DX, AL ; Send EOI to PIC if not processing DOS timer.
;
_OSTickISR3:
CALL FAR PTR _OSTimeTick ; 調用 OSTimeTick()
;
CALL FAR PTR _OSIntExit ; 調用 OSInitExit()
;
POP DS ; 恢復處理器寄存器
POP ES
POPA
;
IRET ; 中斷返回彈出程序指針和狀態寄存器
_OSTickISR ENDP
;
END
uC/OS-II源碼解析(os_cpu_a.asm)
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.