曲径通幽论坛

 找回密码
 立即注册
搜索
查看: 7089|回复: 0
打印 上一主题 下一主题

OS_CPU_A.ASM 文件

[复制链接]

4918

主题

5880

帖子

3万

积分

GROAD

曲径通幽,安觅芳踪。

Rank: 6Rank: 6

积分
34397
跳转到指定楼层
楼主
发表于 2009-4-14 00:11:01 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
一、OS_CPU_A.ASM 文件包含 4 个移植相关的函数
OSStartHighRdy();
OSCtxSw();
OSIntCtxSw();
OSTickISR();
OSStartHighRdy()
OSStartHighRdy() 仅由 OSStart() 启动多任务时调用一次,其意为启动优先级最高的任务。先看 OSStart() 代码:
void  OSStart (void)
{
    INT8U y;
    INT8U x;


    if (OSRunning == FALSE) {
        y             = OSUnMapTbl[OSRdyGrp];        /* 找到最高优先级任务优先级号 */
        x             = OSUnMapTbl[OSRdyTbl[y]];
        OSPrioHighRdy = (INT8U)((y << 3) + x);


        OSPrioCur     = OSPrioHighRdy;


        OSTCBHighRdy  = OSTCBPrioTbl[OSPrioHighRdy]; /* 指向已就绪的最高优先级任务TCB */
        OSTCBCur      = OSTCBHighRdy;
        OSStartHighRdy();                            /* 启动任务  */
    }
}
再看 OSStartHighRdy() 代码:
_OSStartHighRdy  PROC FAR

            MOV    AX, SEG _OSTCBHighRdy          ; 重装载 DS
            MOV    DS, AX                         ;
;
            CALL   FAR PTR _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                             ; Load task's context
            POP    ES                            
            POPA                                
;
            IRET                                  ; Run task

_OSStartHighRdy  ENDP
说明:
1、OSTCBHighRdy 是指向已就绪的最高优先级任务 TCB 的指针,是一个 32位的远指针--指针的段地址和偏移量都在指针内。因为 uC/OS-II是在大模式下编译的,所以缺省状态下产生的指针为远指针。每次使用远指针时,都要重装段寄存器,远指针的可选址目标不超过64K,因为远指针增减运算时,段地址不参与运算。所以,在 OSStartHighRdy 函数开头中有:
                                  MOV   AX, SEG _OSTCBHighRdy
                                  MOV   DS, AX                                             ;重装段寄存器
2、OSTaskSwHook
该函数是用户自定义函数,调用该函数时,中断必须禁止。
3、LES    BX, DWORD PTR DS:_OSTCBHighRdy
_OSTCBHighRdy 指针段地址(DS)存往 ES 中,偏移量存往 BX 中。
MOV    SS, ES:[BX+2]                  ;待运行任务 TCB 结构中第一个元素为其堆栈指针,此处取该指针的段地址
                                                    ;然后存往 SS 中

MOV    SP, ES:[BX+0]                  ;取该指针的偏移量存往 SP
三、_OSCtxSw
OSCtxSw 是任务切换的底层操作函数,其代码如下:
_OSCtxSw    PROC   FAR
;
            PUSHA                                    ;当前任务相关寄存器保存
            PUSH   ES                              ;
            PUSH   DS                              ;
;
            MOV    AX, SEG _OSTCBCur               ;重装在当起任务TCB的指针以防被改变
            MOV    DS, AX                          ;
;
            LES    BX, DWORD PTR DS:_OSTCBCur      ; OSTCBCur->OSTCBStkPtr = SS:SP
            MOV    ES:[BX+2], SS                   ;当前任务堆栈指针存往 TCB 中
            MOV    ES:[BX+0], SP                   ;
;
            CALL   FAR PTR _OSTaskSwHook           ; Call user defined task switch hook
;
            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]                   ;取出就绪即运行任务堆栈指针改写到SS:SP中
            MOV    SP, ES:[BX]                     ;
;
            POP    DS                              ;恢复新任务的上下文
            POP    ES                              ;
            POPA                                   ;
;
            IRET                                   ; Return to new task
;
_OSCtxSw    ENDP
四、OSIntCtxSw
在中断服务子程序最后,OSIntExit() 调用 OSIntCtxSw 做任务切换,故OSIntCtxSw 是中断级的任务切换。在使用 OSIntCtxSw 之前,中断已经发生,所以无需保存 CPU寄存器,堆栈指针也被服务子程序保存在任务控制块 OS_TCB 中。OSIntCtxSw 代码和 OSCtxSw 基本相同。
在代码中有一句,MOV AX, SEG _OSTCBCur
                            MOV DS, AX
说是重装 DS,以防被改变了。我认为像在 C 中的这些变量,至少是远指针变量,它们的段地址应该都是一样的。所以才有下面的 MOV AX,WORD PTR DS: _OSTCBHighRdy + 2。这里可以看到,OSTCBHighRdy 指针的段地址也是 DS 里的地址。
五、OSTickISR
PC 机的始终节拍中断向量为 0x08 处,但 uC/OS-II 则会让 0x80 这里的中断向量指向它的中断服务--OSTickISR,而原来的中断服务则将其安排到 0x81 处暂存起来。OSTickISR 的汇编代码如下:
_OSTickISR  PROC   FAR
;
            PUSHA                                ;中断进,保存CPU相关寄存器
            PUSH   ES
            PUSH   DS
;
            MOV    AX, SEG(_OSIntNesting)        ;取得OSIntNesting变量的段地址

            MOV    DS, AX
            INC    BYTE PTR DS:_OSIntNesting     ; OSIntNesting++


            CMP    BYTE PTR DS:_OSIntNesting, 1  ; if (OSIntNesting == 1)
            JNE    SHORT _OSTickISR1           
          

            MOV    AX, SEG(_OSTCBCur)            ;第一层中断则保存好当前任务堆栈指针

            MOV    DS, AX
            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 ;若达到DOS的中断则调到0x81进行中断处理
            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.
                                                             ;EOI-->end of interrupt,清中断
_OSTickISR3:
            CALL   FAR PTR _OSTimeTick           ; Process system tick
;
            CALL   FAR PTR _OSIntExit            ;中断结束,退出
;
            POP    DS                            ; Restore interrupted task's context
            POP    ES
            POPA
;
            IRET                                 ; Return to interrupted task
;
_OSTickISR  ENDP
;
            END


您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|曲径通幽 ( 琼ICP备11001422号-1|公安备案:46900502000207 )

GMT+8, 2025-6-18 01:43 , Processed in 0.088057 second(s), 22 queries .

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表