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

转自:https://blog.csdn.net/u010650845/article/details/7252

;**********************************************************************************
;*
;*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

8764

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值