uC/OS-II源碼解析(os_cpu_a.asm)

;**********************************************************************************
;*
;*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
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章