您的位置:首页 > 其它

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

2017-05-19 14:24 471 查看
;**********************************************************************************
;*
;*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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  ucos 源码 解析