搜索
bottom↓
回复: 28

我对OSCtxSW()任务级任务切换函数的理解(以图例的方式)

[复制链接]

出0入0汤圆

发表于 2009-4-13 11:21:12 | 显示全部楼层 |阅读模式
;*********************************************************************************************************
;                                PERFORM A CONTEXT SWITCH (From task level)
;                                           void OSCtxSw(void)
;
; Note(s): 1) Upon entry,
;             OSTCBCur     points to the OS_TCB of the task to suspend
;             OSTCBHighRdy points to the OS_TCB of the task to resume
;
;          2) The stack frame of the task to suspend looks as follows:
;
;                 SP -> OFFSET  of task to suspend    (Low memory)
;                       SEGMENT of task to suspend
;                       PSW     of task to suspend    (High memory)
;
;          3) The stack frame of the task to resume looks as follows:
;
;                 OSTCBHighRdy->OSTCBStkPtr --> DS                               (Low memory)
;                                               ES
;                                               DI
;                                               SI
;                                               BP
;                                               SP
;                                               BX
;                                               DX
;                                               CX
;                                               AX
;                                               OFFSET  of task code address
;                                               SEGMENT of task code address
;                                               Flags to load in PSW             (High memory)
;*********************************************************************************************************


_OSCtxSw    PROC   FAR
;
            PUSHA                                  ; Save current task's context
            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           ; 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]                   ;
            MOV    SP, ES:[BX]                     ;
;
            POP    DS                              ; Load new task's context
            POP    ES                              ;
            POPA                                   ;
;
            IRET                                   ; Return to new task


 问题:
  1、
            LES    BX, DWORD PTR DS:_OSTCBHighRdy  ; SS:SP = OSTCBHighRdy->OSTCBStkPtr
            MOV    SS, ES:[BX+2]                   ;
            MOV    SP, ES:[BX]                     ;
        执行上面3条语句,得到高优先级任务(准备运行任务)私栈的栈项指针SS:SP
  2、     POP    DS                              ; Load new task's context
            POP    ES                              ;
            POPA                                   ;
    执行上面3条语句,将高优先级任务私栈中上次保存的现场恢复到CPU相关寄存器中
  3、现在主要问题集中在POPA 这条语句上
     由于POPA是80386指令,是
;              POP   DI
;              POP   SI
;              POP   BP
;              POP  SP
;              POP   BX
;              POP  DX
;              POP   CX
;              POP   AX
          的简写。
    既然前面SS:SP已经指向高优先级任务(准备运行任务)私栈的栈项,那么当执行POP SP时,又将SP指向了另外一个位置,
 又怎么能继续从高优先级任务私栈中弹出其余的BX、DX、CX、AX寄存器呢?  

阿莫论坛20周年了!感谢大家的支持与爱护!!

如果想吃一顿饺子,就得从冰箱里取出肉,剁馅儿,倒面粉、揉面、醒面,擀成皮儿,下锅……
一整个繁琐流程,就是为了出锅时那一嘴滚烫流油的热饺子。

如果这个过程,禁不住饿,零食下肚了,饺子出锅时也就不香了……《非诚勿扰3》

出0入0汤圆

 楼主| 发表于 2009-4-13 11:21:26 | 显示全部楼层
我先自己分析一下详细过程:假定高优先级任务为任务A


  (1)、当高优先级任务A正在运行时,此时由于“中断服务程序”或者“等待信号量”或者“时钟节拍”或者调用“延时函数”,使任务A挂起,进行任务切换,此时堆栈示意图如下:

           任务A的私栈   
   -----------------------------------
      |                                 |
   -----------------------------------
      |                                 |
   -----------------------------------
      |                                 |
   -----------------------------------
      |                                 |
   -----------------------------------
      |                                 |
   -----------------------------------
      |                                 |
   -----------------------------------
      |                                 |
   -----------------------------------
      |                                 |
   -----------------------------------
      |                                 |
   -----------------------------------
      |                                 |
   -----------------------------------
      |                                 |
   -----------------------------------
      |                                 |   <--------- SP
   -----------------------------------
        图1

 (2)、执行OS_TASK_SW(),也就是说执行了一条软件中断指令(INT80H)
     ,此时任务A堆栈示意图如下:

           任务A的私栈   
   -----------------------------------
      |                                 |
   -----------------------------------
      |                                 |
   -----------------------------------
      |                                 |
   -----------------------------------
      |                                 |
   -----------------------------------
      |                                 |
   -----------------------------------
      |                                 |
   -----------------------------------
      |                                 |
   -----------------------------------
      |                                 |
   -----------------------------------
      |                                 |
   -----------------------------------
      |      OFF task A (断点位置)      |  <--------- SP
   -----------------------------------
      |      SEG task A(断点位置)     |
   -----------------------------------
      |       PSW                       |   
   -----------------------------------
        图2

  (3)、进入OSCtxSW()函数后,执行PUSHA/PUSH ES/PUSH DS

           任务A的私栈   
   -----------------------------------
      |                                 |
   -----------------------------------
      |                                 |
   -----------------------------------
      |                                 |
   -----------------------------------
      |                                 |
   -----------------------------------
      |                                 |
   -----------------------------------
      |      BX                         |  <-------------- SP
   -----------------------------------
      |      DX                         |
   -----------------------------------
      |      CX                         |
   -----------------------------------
      |      AX                         |
   -----------------------------------
      |      OFF task A (断点位置)      |  
   -----------------------------------
      |      SEG task A(断点位置)     |
   -----------------------------------
      |       PSW                       |   
   -----------------------------------
        图3

(4)当执行PUSH SP时,把此时堆栈指针SP的位置记录下来,堆栈中记录的是SP_BX(此时SP指向BX存储单元)


           任务A的私栈   
   -----------------------------------
      |                                 |
   -----------------------------------
      |                                 |
   -----------------------------------
      |                                 |
   -----------------------------------
      |                                 |
   -----------------------------------
      |      SP = SP_BX                 |  <-------------- SP
   -----------------------------------
      |      BX                         |  <-------------- SP_BX
   -----------------------------------
      |      DX                         |
   -----------------------------------
      |      CX                         |
   -----------------------------------
      |      AX                         |
   -----------------------------------
      |      OFF task A (断点位置)      |  
   -----------------------------------
      |      SEG task A(断点位置)     |
   -----------------------------------
      |       PSW                       |   
   -----------------------------------
        图4

  (5)继续执行PUSHA/PUSH ES/PUSH DS

            任务A的私栈   
   -----------------------------------
      |      DS                         |  <-------------- SP
   -----------------------------------
      |      ES                         |
   -----------------------------------
      |      DI                         |
   -----------------------------------
      |      SI                         |
   -----------------------------------
      |      BP                         |
   -----------------------------------
      |      SP = SP_BX                 |   
   -----------------------------------
      |      BX                         |  <-------------- SP_BX
   -----------------------------------
      |      DX                         |
   -----------------------------------
      |      CX                         |
   -----------------------------------
      |      AX                         |
   -----------------------------------
      |      OFF task A (断点位置)      |  
   -----------------------------------
      |      SEG task A(断点位置)     |
   -----------------------------------
      |       PSW                       |   
   -----------------------------------
        图5

  (6)、执行 LES    BX, DWORD PTR DS:_OSTCBCur      ; OSTCBCur->OSTCBStkPtr = SS:SP  
            MOV    ES:[BX+2], SS                   ;  
            MOV    ES:[BX+0], SP                   ;  
      将堆栈指针位置SP(见上图5中的SP)保存到任务A的任务控制块OS_TCB的OSTCBStkPtr成员中。


(7)当任务A再次得到CPU的控制权后,进入OSCtxSW()函数,执行
            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]               
       将任务A的私栈的堆栈指针从任务A的任务控制块OS_TCB的在成员OSTCBStkPtr中取出来,

出0入0汤圆

 楼主| 发表于 2009-4-13 11:22:31 | 显示全部楼层
任务A的私栈     
   -----------------------------------  
      |      DS                         |  <-------------- SP  
   -----------------------------------  
      |      ES                         |  
   -----------------------------------  
      |      DI                         |  
   -----------------------------------  
      |      SI                         |  
   -----------------------------------  
      |      BP                         |  
   -----------------------------------  
      |      SP = SP_BX                 |   
   -----------------------------------  
      |      BX                         |  <-------------- SP_BX  
   -----------------------------------  
      |      DX                         |  
   -----------------------------------  
      |      CX                         |  
   -----------------------------------  
      |      AX                         |  
   -----------------------------------  
      |      OFF task A (断点位置)      |   
   -----------------------------------  
      |      SEG task A(断点位置)     |  
   -----------------------------------  
      |       PSW                       |     
   -----------------------------------  
        图6 当任务A再次获得CPU ,执行
          LES    BX, DWORD PTR DS:_OSTCBHighRdy  ; SS:SP = OSTCBHighRdy->OSTCBStkPtr   
                MOV    SS, ES:[BX+2]                   ;   
                MOV    SP, ES:[BX]            
         从高优先级任务控制块OSTCBHighRdy的OSTCBStkPtr成员中取出任务A私栈的堆栈指针,见图6中的SP


(8)依次执行POP DS/POP ES/POPA,从任务A的私栈中恢复相关寄存器的内容到CPU的相关寄存器中。
   当执行完(POPA)的POP BP时的堆栈示意图如下:

          任务A的私栈      
   -----------------------------------   
      |                                 |   
   -----------------------------------   
      |                                 |   
   -----------------------------------   
      |                                 |   
   -----------------------------------   
      |                                 |   
   -----------------------------------   
      |                                 |   
   -----------------------------------   
      |      SP = SP_BX                 |    <-------------- SP   
   -----------------------------------   
      |      BX                         |  
   -----------------------------------   
      |      DX                         |   
   -----------------------------------   
      |      CX                         |   
   -----------------------------------   
      |      AX                         |   
   -----------------------------------   
      |      OFF task A (断点位置)      |   
   -----------------------------------   
      |      SEG task A(断点位置)     |   
   -----------------------------------   
      |       PSW                       |      
   -----------------------------------   


(9)由于任务A的私栈中,堆栈指针SP指向单元的内容(SP=SP_BX)为BX存储单元,因此执行POP SP后,堆栈指针位置如下:

        任务A的私栈      
   -----------------------------------   
      |                                 |   
   -----------------------------------   
      |                                 |   
   -----------------------------------   
      |                                 |   
   -----------------------------------   
      |                                 |   
   -----------------------------------   
      |                                 |   
   -----------------------------------   
      |                            |     
   -----------------------------------   
      |      BX                         |  <-------------- SP   
   -----------------------------------   
      |      DX                         |   
   -----------------------------------   
      |      CX                         |   
   -----------------------------------   
      |      AX                         |   
   -----------------------------------   
      |      OFF task A (断点位置)      |     
   -----------------------------------   
      |      SEG task A(断点位置)     |   
   -----------------------------------   
      |       PSW                       |      
   -----------------------------------   


(10)继续执行完POPA指令其余的弹栈指令后,堆栈指针位置如下:

        任务A的私栈      
   -----------------------------------   
      |                                 |   
   -----------------------------------   
      |                                 |   
   -----------------------------------   
      |                                 |   
   -----------------------------------   
      |                                 |   
   -----------------------------------   
      |                                 |   
   -----------------------------------   
      |                            |     
   -----------------------------------   
      |                                 |   
   -----------------------------------   
      |                                 |   
   -----------------------------------   
      |                                 |   
   -----------------------------------   
      |                                 |   
   -----------------------------------   
      |      OFF task A (断点位置)      |    <-------------- SP   
   -----------------------------------   
      |      SEG task A(断点位置)     |   
   -----------------------------------   
      |       PSW                       |      
   -----------------------------------   

(11)执行IRET中断返回指令,依次从任务A的私栈中弹出:
   (a)、任务A上次断点地址的偏移地址到IP寄存器
   (b)、任务A上次断点地址的段移地址到CS寄存器
   (c)、程序状态字PSW(中断是开放的)
      然后跳转到CS:IP位置处(上次断点位置)继续执行任务A的代码。

        任务A的私栈        
   -----------------------------------     
      |                                 |     
   -----------------------------------     
      |                                 |     
   -----------------------------------     
      |                                 |     
   -----------------------------------     
      |                                 |     
   -----------------------------------     
      |                                 |     
   -----------------------------------     
      |                            |      
   -----------------------------------     
      |                                 |   
   -----------------------------------     
      |                                 |     
   -----------------------------------     
      |                                 |     
   -----------------------------------     
      |                                 |     
   -----------------------------------     
      |                               |   
   -----------------------------------     
      |                     |     
   -----------------------------------     
      |                                 |    <-------------- SP         
   -----------------------------------

出0入0汤圆

 楼主| 发表于 2009-7-29 13:55:05 | 显示全部楼层
如果大家看懂了上述切换过程,就明白了任务级切换了。
头像被屏蔽

出0入0汤圆

发表于 2010-2-14 21:19:54 | 显示全部楼层
以下蓝色文字由坛主:armok 于:2010-02-14,21:19:54 加入。
<font color=black>请发贴人注意:
本贴放在这分区不合适,即将移走
原来分区:[3015]成都理工大学测控技术与仪器
即将移去的分区:[3004]嵌入式操作系统
移动执行时间:自本贴发表0小时后

任何的疑问或咨询,请可随时联系站长。谢谢你的支持!
</font>

出0入0汤圆

 楼主| 发表于 2010-4-23 13:13:28 | 显示全部楼层
我顶

出0入0汤圆

发表于 2010-5-3 14:59:58 | 显示全部楼层
哈哈

出0入264汤圆

发表于 2010-5-3 18:27:59 | 显示全部楼层
学习

出0入0汤圆

发表于 2010-5-30 21:34:00 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-5-31 00:08:13 | 显示全部楼层
嘿~写得好!

出0入0汤圆

发表于 2010-5-31 00:49:32 | 显示全部楼层
正在学习ucos

出0入0汤圆

发表于 2010-6-15 15:18:22 | 显示全部楼层
学习

出0入0汤圆

发表于 2010-6-25 16:32:51 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-6-26 09:48:58 | 显示全部楼层
请教一下,我正在把UCOS移植到瑞萨的16位单片机H8S2218上,移植后我建立了最简单的LED任务,单步执行时,我发现程序到了OSCtxSw的最后一条返回指令时,程序跑飞了,请问这种情况的话,一般问题出在哪?谢谢!

出0入0汤圆

发表于 2010-7-28 15:57:36 | 显示全部楼层
回复【2楼】ba_wang_mao
-----------------------------------------------------------------------

学习

出0入0汤圆

发表于 2010-7-30 10:33:04 | 显示全部楼层
1#图4 对我理解很有帮助。谢谢!

出0入0汤圆

发表于 2010-12-14 11:50:46 | 显示全部楼层
LZ,你这个图很好,我遇到一个问题,在
OSIntExit()
{
   -------
   ————
   ————
   OSIntCtxSW();   

OS_EXIT_CRITICAL();
}

中断级任务切换中OSIntCtxSW()最后的RETI指令,已经完成了将PC指向待运行的任务,可是,OS_EXIT_CRITICAL()怎么执行呢,请LZ指教。给一个详细点问题的链接
http://www.ourdev.cn/bbs/bbs_content.jsp?bbs_sn=4452318&bbs_page_no=1&bbs_id=3004

出0入0汤圆

发表于 2010-12-28 00:37:53 | 显示全部楼层
学习

出0入0汤圆

发表于 2011-1-8 14:16:20 | 显示全部楼层
学习中。。。。。。

出0入0汤圆

发表于 2011-1-8 14:53:21 | 显示全部楼层
标记

出0入0汤圆

发表于 2011-1-8 15:53:41 | 显示全部楼层
mark

出0入0汤圆

发表于 2011-2-9 11:44:57 | 显示全部楼层
好!

出0入0汤圆

发表于 2011-8-20 20:39:13 | 显示全部楼层
mark

出0入0汤圆

发表于 2011-8-23 02:28:25 | 显示全部楼层
mark

出0入0汤圆

发表于 2011-10-7 13:48:06 | 显示全部楼层
mark!!!

出0入0汤圆

发表于 2012-4-1 16:56:58 | 显示全部楼层
OSIntCtxSW();   与OSCtxSW();什么区别啊

出0入0汤圆

发表于 2014-6-12 22:44:46 | 显示全部楼层
果断mark一下

出0入0汤圆

发表于 2014-10-26 22:28:33 | 显示全部楼层
好 我会花时间好好看看。今晚先到这里了。。。

出0入0汤圆

发表于 2014-11-14 15:29:45 | 显示全部楼层
正在学习UCOS。
                                                                                      
                                                                                 
                                                                                   
            
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-3-28 17:57

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

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