赞助论坛
  • 10255阅读
  • 0回复

学习单片机之---uCOS-II的移植代码 for 8051 [复制链接]

楼层直达
jswr  
发帖
339
精华
1
金币
264
威望
8
贡献
7
好评
15
注册
2008-06-30
楼主    jswr 发表于: 2008-08-05 14:43:37 
作者:电子牛

移植说明:

我没有移植uCOS前,再网上下了一些案例可是大部分都不能直接运行,而且有好多还都有错误。

还发现很多"移植者"是忠实的操洗者,并且还操错了。这个移植代码是我领会不少代码的长短根据自己的经验编制,绝对原著!!因为有好多与大多数移植代码不同之处,故帖出来共享,希望能对将要移植uCOS的人以启发和帮助。

由于我个人时间不多,所以没有写什么移植的"前因后果"

但:
移植的详细细节在程序中的注释部分已经非常详尽了,这里就不多说了。
如果那位大虾,能更有好的建议,请跟我联系,不胜感激!

也可以跟我索要全部移植代码,我将给你一个keil工程,你只需电击一下编译按扭,在软件仿真运行即可在串口1窗口里看到uCOS-II的风采!(不需任何编程,当然除了你以后要添加应用任务)

注意不要将本移植代码应用于商业!!

如果那位大虾,能更有好的建议,请跟我联系,不胜感激!

我的联系方式:

QQ:   75011221     呢称:电子牛
EMAIL:   [email]niuyimail@126.com[/email]


OS_CPU_C.C

/*
********************************************************************************
*************************
*                           INITIALIZE A TASK'S STACK
*
* Description: This function is called by either OSTaskCreate() or
OSTaskCreateExt() to initialize the
*         stack frame of the task being created. This function is highly
processor specific.
*
* Arguments : task       is a pointer to the task code
*
*         os_pdata       is a pointer to a user supplied data area that
will be passed to the task
*                   when the task first executes.
*
*         ptos       is a pointer to the top of stack. It is assumed
that 'ptos' points to
*                   a 'free' entry on the task stack. If
OS_STK_GROWTH is set to 1 then
*                   'ptos' will contain the HIGHEST valid address of
the stack. Similarly, if
*                   OS_STK_GROWTH is set to 0, the 'ptos' will
contains the LOWEST valid address
*                   of the stack.
*
*         opt       specifies options that can be used to alter the
behavior of OSTaskStkInit().
*                   (see uCOS_II.H for OS_TASK_OPT_???).
*
* Returns   : Always returns the location of the new top-of-stack' once the
processor registers have
*         been placed on the stack in the proper order.
*
* Note(s)   : Interrupts are enabled when your task starts executing. You can
change this by setting the
*         PSW to 0x0002 instead. In this case, interrupts would be
disabled upon task startup. The
*         application code would be responsible for enabling interrupts at
the beginning of the task
*         code. You will need to modify OSTaskIdle() and OSTaskStat() so
that they enable
*         interrupts. Failure to do this will make your system crash!
********************************************************************************
*************************
*/
/*
at89c55wd PDL(sp form LOW to HIGH):     (堆栈指针所指的栈顶数据为有效数
据)
                  装入堆栈指
针ptos到stk
           
          stk-->     入栈:task底\高  
            (高内存)
          入   ||     入栈:ACC
          栈   ||     入栈:B
          顺   ||     入栈:DPH  
  //暂时忽略第二指针
          序   ||       入栈:DPL
          | \/   |   入栈:PSW
          |     |   入栈:R7-
R4
          |______|   入栈:os_pdata(R3,R2,R1)用寄存
器传递os_pdata
                  入栈:R0  
                (底内存)

        //           入栈:
DPS??     //双数据指针选择寄存器??
        //           入栈:PC
自己应该参照编译器定义入栈/出栈顺序,写出来备以后查阅
*/
OS_STK *OSTaskStkInit (void (*task)(void *pd)LG_REENTRANT, void *os_pdata,
OS_STK *ptos, INT16U opt) LG_REENTRANT
{
  //INT16U *stk;
  OS_STK   *stk;

  opt   = opt;                   /* 'opt' is not used, prevent
warning               */
  stk   = (OS_STK *)ptos;           /* Load stack
pointer                         */
                   
        //装入堆栈指针ptos到stk

  *stk = 0;                  
  //入栈:R0
  stk           -= sizeof(void *);
  *(void **)stk   = (void *)os_pdata;     //用寄存器传递
os_pdata
  *--stk = 4;                
    //入栈:R4-R7
  *--stk = 5;
  *--stk = 6;
  *--stk = 7;                
   

  *--stk = PSW;                
  //入栈:PSW
  *--stk = 'L';                
  //入栈:DPL
  *--stk = 'H';                
  //入栈:DPH     //暂时忽略第二指针
  *--stk = 'B';                
  //入栈:B
  *--stk = 'A';                
  //入栈:ACC

  *--stk   = ((INT16U)task & 0xff00) >> 8;   //保存任务地址
  *--stk   = (INT16U)task & 0x00ff;

  *--stk = 15;                
  //入栈个数
                   
        //END
  return ((OS_STK *)stk);
}

/*$PAGE*/
/*
********************************************************************************
*************************
*                 INITIALIZE A TASK'S STACK FOR FLOATING POINT EMULATION
*
********************************************************************************
*************************
*/

/*$PAGE*/
//void OSTaskStkInit_FPE_x86 (OS_STK **pptos, OS_STK **ppbos, INT32U *psize)
//{
//}

/*$PAGE*/
/*
********************************************************************************
*************************
*                             TASK SWITCH HOOK
*
* Description: This function is called when a task switch is performed. This
allows you to perform other
*         operations during a context switch.
*
* Arguments : none
*
* Note(s)   : 1) Interrupts are disabled during this call.
*         2) It is assumed that the global pointer 'OSTCBHighRdy' points
to the TCB of the task that
*           will be 'switched in' (i.e. the highest priority task)
and, 'OSTCBCur' points to the
*           task being switched out (i.e. the preempted task).
********************************************************************************
*************************
*/
#if OS_CPU_HOOKS_EN > 0
void OSTaskSwHook (void) LG_REENTRANT
{
}
#endif

/*
********************************************************************************
*************************
*                             OSTCBInit() HOOK
*
* Description: This function is called by OS_TCBInit() after setting up most of
the TCB.
*
* Arguments : ptcb   is a pointer to the TCB of the task being created.
*
* Note(s)   : 1) Interrupts may or may not be ENABLED during this call.
********************************************************************************
*************************
*/
#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203
void OSTCBInitHook (OS_TCB *ptcb) LG_REENTRANT
{
  ptcb = ptcb;                             /* Prevent Compiler
warning           */
}
#endif


/*
********************************************************************************
*************************
*                               TICK HOOK
*
* Description: This function is called every tick.
*
* Arguments : none
*
* Note(s)   : 1) Interrupts may or may not be ENABLED during this call.
********************************************************************************
*************************
*/
#if OS_CPU_HOOKS_EN > 0
void OSTimeTickHook (void) LG_REENTRANT
{
}
#endif


/*
********************************************************************************
*************************
*                    
          中断服务程序外挂
*     NOTE : 注意:所有中断外挂都在临界区之外,用户可以自行控制进/退
临界区
********************************************************************************
*************************
*/
#if OS_ISR_T1_EN > 0
void   OSISR_T1HOOK (void) LG_REENTRANT
{

    /* 请在这里输入中断服务程序        
  */

}
#endif

#if OS_ISR_INT0_EN > 0
void   OSISR_INT0HOOK (void) LG_REENTRANT
{

    /* 请在这里输入中断服务程序        
  */

}
#endif

#if OS_ISR_INT1_EN > 0
void   OSISR_INT1HOOK (void) LG_REENTRANT
{

    /* 请在这里输入中断服务程序        
  */

}
#endif

#if OS_ISR_S0_EN > 0
void   OSISR_S0HOOK (void) LG_REENTRANT
{

    /* 请在这里输入中断服务程序        
  */

   

}
#endif

----------------

[dvnews_page=OS_CPU_A.ASM之的中断管理部分]


;*******************************************************************************
*************************
;                               uC/OS-II
;                           The Real-Time Kernel
;
;                 (c) Copyright 1992-2002, Jean J. Labrosse, Weston, FL
;                             All Rights Reserved
;
;
;                           at89c55wd Specific code
;                             LARGE MEMORY MODEL
;
;                             keil C/C++ V7.2
;                           (at89c55wd Compatible Target)
;
; File       : OS_CPU_A.ASM
; By       : Jean J. Labrosse
; Port by     : 牛毅   2005-04-25->2005-04-28  
  QQ:75011221   [email]niuyimail@126.com[/email]
;     修补 : 2005-05-02-01:30 (增加了中断管理和临界区宏)
;     修补 : 2005-05-16-13:00 (修补_CopySPtoC_XBP的漏洞, 有标记
处%%%%????%%%%%%)
;*******************************************************************************
*************************
#include   "OS_CFG.H"

        NAME   OS_CPU_A

;*******************************************************************************
*************************
;                         要使用的外部函数和公共数据
;*******************************************************************************
*************************
        EXTRN CODE (_?OSIntExit)
        EXTRN CODE (_?OSTimeTick)
        EXTRN CODE (_?OSTaskSwHook)

IF   OS_ISR_T1_EN <> 0
    EXTRN CODE   (_?OSISR_T1HOOK)
ENDIF
IF   OS_ISR_INT0_EN <> 0
    EXTRN CODE   (_?OSISR_INT0HOOK)
ENDIF
IF   OS_ISR_INT1_EN <> 0
    EXTRN CODE   (_?OSISR_INT1HOOK)
ENDIF
IF   OS_ISR_S0_EN <> 0
    EXTRN CODE   (_?OSISR_S0HOOK)
ENDIF

    EXTRN DATA   (?C_XBP)
;DT?C_XBP   SEGMENT   DATA
;     RSEG   DT?C_XBP
;?C_XBP:
;C_XBP:
;   DS   1
    ?STACK   SEGMENT IDATA
    RSEG   ?STACK
    ;?STACK:
    Stack:
    DS   40  

        EXTRN BIT   (OSRunning)
        EXTRN XDATA (OSIntNesting)
;         EXTRN XDATA (OSTickDOSCtr)
        EXTRN XDATA (OSPrioHighRdy)
        EXTRN XDATA (OSPrioCur)
    EXTRN XDATA (OSTCBCur)    
        EXTRN XDATA (OSTCBHighRdy)

;*******************************************************************************
*************************
;                               MACRO DEFINE
;*******************************************************************************
*************************
PUSHALL   MACRO
  ;PUSH   PC  
  PUSH   ACC
  PUSH   B
  PUSH   DPH
  PUSH   DPL
  PUSH   PSW
  IRP   REG,   <R7, R6, R5, R4, R3, R2, R1, R0>
  MOV   A,   REG
  PUSH   ACC
  ENDM
  ENDM

POPALL   MACRO
  IRP   REG,   <R0, R1, R2, R3, R4, R5, R6, R7>
  POP   ACC
  MOV   REG,   A
  ENDM
  POP   PSW
  POP   DPL
  POP   DPH
  POP   B
  POP   ACC
  ;RET/RETI
  ENDM

OS_ENTER_CRITICAL   MACRO
  MOV   B,IE           ;因为所有程序没有使用
B寄存器,所以使用了B寄存器作为IE暂存
  CLR   EA
  ENDM
OS_EXIT_CRITICAL   MACRO
  MOV   IE,B           ;因为所有程序没有使用
B寄存器,所以使用了B寄存器作为IE暂存
  ENDM
;*******************************************************************************
*************************
;                             供外部使用的函数
;*******************************************************************************
*************************
        PUBLIC   _?OSTickISR
        PUBLIC   _?OSStartHighRdy
        PUBLIC   _?OSCtxSw
        PUBLIC   _?OSIntCtxSw
/*$PAGE*/
;*******************************************************************************
*************************
;                         函数体段
;*******************************************************************************
*************************
;*******************************************************************************
**************************
;                 用户中断程序区     之   定时器中断
1 OSISR_T1()
;*******************************************************************************
**************************
IF OS_ISR_T1_EN <> 0
    CSEG   AT   001BH     ;设置T0中断向量
    LJMP   _OSISR_T1

  ?PR?_OSISR_T1?OS_CPU_A         SEGMENT CODE
  RSEG   ?PR?_OSISR_T1?OS_CPU_A
_OSISR_T1:
  OS_ENTER_CRITICAL
  ;(1)保存处理器寄存器 先PUSH到SP在COPY到?C_XBP
  PUSHALL
  LCALL   _CopySPtoC_XBP         ;COPY SP 的内容到?
C_XBP

  ;(2)记忆中断的嵌套层OSIntNesting++   进入中断
  ;(3) if (OSIntNesting == 1)
  ;   OSTCBCur->OSTCBStkPtr <= ?C_XBP
  LCALL   _Enter_INT
  OS_EXIT_CRITICAL  

  ;(4)调用中断服务外挂
  LCALL   _?OSISR_T1HOOK         ;在这里进行中断服务

  OS_ENTER_CRITICAL
  ;(5) Call OSTimeTick();
  LCALL   _?OSTimeTick

  ;(6) Call OSIntExit();
  LCALL   _?OSIntExit

  ;(7) 恢复处理器寄存器         ;没有高优先级任务在就
绪队列中
  ;LCALL   _ComCtxSw2
  LCALL   _CopyC_XBPtoSP
  POPALL
 
  OS_EXIT_CRITICAL
  RETI
ENDIF
;*******************************************************************************
**************************
;                 用户中断程序区     之   外部中断0
OSISR_INT0()
;*******************************************************************************
**************************
IF OS_ISR_INT0_EN <> 0
    CSEG   AT   0003H     ;设置T0中断向量
    LJMP   _OSISR_INT0

  ?PR?_OSISR_INT0?OS_CPU_A         SEGMENT CODE
  RSEG   ?PR?_OSISR_INT0?OS_CPU_A
_OSISR_INT0:
  OS_ENTER_CRITICAL
  ;(1)保存处理器寄存器 先PUSH到SP在COPY到?C_XBP
  PUSHALL
  LCALL   _CopySPtoC_XBP         ;COPY SP 的内容到?
C_XBP

  ;(2)记忆中断的嵌套层OSIntNesting++   进入中断
  ;(3) if (OSIntNesting == 1)
  ;   OSTCBCur->OSTCBStkPtr <= ?C_XBP
  LCALL   _Enter_INT  
  OS_EXIT_CRITICAL
 
  ;(4)调用中断服务外挂
  LCALL   _?OSISR_INT0HOOK         ;在这里进行中断服务

  OS_ENTER_CRITICAL
  ;(5) Call OSTimeTick();
  LCALL   _?OSTimeTick

  ;(6) Call OSIntExit();
  LCALL   _?OSIntExit

  ;(7) 恢复处理器寄存器     ;没有高优先级任务在就绪队列中
  ;LCALL   _ComCtxSw2
  LCALL   _CopyC_XBPtoSP
  POPALL
  OS_EXIT_CRITICAL
  RETI
ENDIF
;*******************************************************************************
**************************
;                 用户中断程序区     之   外部中断1
OSISR_INT1()
;*******************************************************************************
**************************
IF OS_ISR_INT1_EN <> 0
    CSEG   AT   0013H     ;设置T0中断向量
    LJMP   _OSISR_INT1

  ?PR?_OSISR_INT1?OS_CPU_A         SEGMENT CODE
  RSEG   ?PR?_OSISR_INT1?OS_CPU_A
_OSISR_INT1:
  OS_ENTER_CRITICAL
  ;(1)保存处理器寄存器 先PUSH到SP在COPY到?C_XBP
  PUSHALL
  LCALL   _CopySPtoC_XBP         ;COPY SP 的内容到?
C_XBP

  ;(2)记忆中断的嵌套层OSIntNesting++   进入中断
  ;(3) if (OSIntNesting == 1)
  ;   OSTCBCur->OSTCBStkPtr <= ?C_XBP
  LCALL   _Enter_INT
  OS_EXIT_CRITICAL
 
  ;(4)调用中断服务外挂
  LCALL   _?OSISR_INT1HOOK         ;在这里进行中断服务

  OS_ENTER_CRITICAL
  ;(5) Call OSTimeTick();
  LCALL   _?OSTimeTick

  ;(6) Call OSIntExit();
  LCALL   _?OSIntExit

  ;(7) 恢复处理器寄存器     ;没有高优先级任务在就绪队列中
  ;LCALL   _ComCtxSw2
  LCALL   _CopyC_XBPtoSP
  POPALL
  OS_EXIT_CRITICAL
  RETI
ENDIF
;*******************************************************************************
**************************
;                 用户中断程序区     之   串口中断0
OSISR_S0()
;*******************************************************************************
**************************
IF OS_ISR_S0_EN <> 0
    CSEG   AT   0023H     ;设置T0中断向量
    LJMP   _OSISR_S0

  ?PR?_OSISR_S0?OS_CPU_A         SEGMENT CODE
  RSEG   ?PR?_OSISR_S0?OS_CPU_A
_OSISR_S0:
  OS_ENTER_CRITICAL
  ;(1)保存处理器寄存器 先PUSH到SP在COPY到?C_XBP
  PUSHALL
  LCALL   _CopySPtoC_XBP         ;COPY SP 的内容到?
C_XBP

  ;(2)记忆中断的嵌套层OSIntNesting++   进入中断
  ;(3) if (OSIntNesting == 1)
  ;   OSTCBCur->OSTCBStkPtr <= ?C_XBP
  LCALL   _Enter_INT
  OS_EXIT_CRITICAL
 
  ;(4)调用中断服务外挂
  LCALL   _?OSISR_S0HOOK         ;在这里进行中断服务

  OS_ENTER_CRITICAL
  ;(5) Call OSTimeTick();
  LCALL   _?OSTimeTick

  ;(6) Call OSIntExit();
  LCALL   _?OSIntExit

  ;(7) 恢复处理器寄存器     ;没有高优先级任务在就绪队列中
  ;LCALL   _ComCtxSw2
  LCALL   _CopyC_XBPtoSP
  POPALL

  OS_EXIT_CRITICAL
  RETI
ENDIF


[dvnews_page=OS_CPU_A.ASM之的内核代码部分1]


;*******************************************************************************
**************************
;                             START MULTITASKING
;                           void OSStartHighRdy(void) LG_REENTRANT
;出栈后就意味着启动了第一个任务
; The stack frame is assumed to look as follows:
;
;         出   /\         出栈:task
底\高       (高内存)
;         栈   ||         出栈:ACC
;         顺   ||         出栈:B
;         序   ||         出栈:DPH  
  //暂时忽略第二指针
;         |   ||   |     出栈:DPL
;         |       |     出栈:PSW
;         |______________|     出栈:R7-R4
;                   出栈:
os_pdata(R3,R2,R1)用寄存器传递os_pdata
;         OSTCBHighRdy->OSTCBStkPtr -->   出栈:R0  
  (底内存)
;
; Note : OSStartHighRdy() MUST:
;       a) Call OSTaskSwHook() then,
;       b) Set OSRunning to TRUE,
;       c) Switch to the highest priority task.
;*******************************************************************************
**************************
  ?PR?_?OSStartHighRdy?OS_CPU_A     SEGMENT CODE  
                ;第3个问号表示重入函

  RSEG   ?PR?_?OSStartHighRdy?OS_CPU_A   ;函数体段

_?OSStartHighRdy:
  USING   0
  ;OS_ENTER_CRITICAL
  LCALL   _?OSTaskSwHook         ;调用OSTaskSwHook();
  SETB   OSRunning         ;OSRunning= TRUE;
  ;切换到最高优先级的任务
  JMP   CtxSw           ;MOV   ?C_XBP,0

;*******************************************************************************
**************************
;                     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:
;
;     出   /\   用RET     出栈:task底\高地址   (高内存)
;     栈   ||         出栈:ACC
;     顺   ||         出栈:B
;     序   ||         出栈:DPH  
  //暂时忽略第二指针
;       |   ||   |     出栈:DPL
;       |       |     出栈:PSW
;       |______________|     出栈:R0
;                 出栈:os_pdata
(R1,R2,R3)用寄存器传递os_pdata
;     OSTCBHighRdy->OSTCBStkPtr -->   出栈:R4-R7  
  (底内存)
;                               Flags to load in
PSW         (High memory)
;任务级切换:
;1:PUSHALL
;2:?C_BXP<=(SP)
;3:OSTCBCur->OSTCBStkPtr<=?C_BXP
;4:   ...
;5:?C_BXP<=OSTCBHighRdy->OSTCBStkPtr
;6:(SP)<=?C_BXP
;7:POPALL
;8:RET
;*******************************************************************************
**************************
  ?PR?_?OSCtxSw?OS_CPU_A         SEGMENT CODE
  RSEG   ?PR?_?OSCtxSw?OS_CPU_A
_?OSCtxSw:
  USING   0
  ;OS_ENTER_CRITICAL
  ;(1)保存处理器的寄存器
  PUSHALL

  ;(2)拷贝SP(系统)堆栈中的内容到?C_XBP,     SP   满向上
    ;然后清空它(即MOV SP,#?STACK-1)         ?C_XBP   满向下
  LCALL   _CopySPtoC_XBP         ;COPY SP 的内容到?
C_XBP

  ;(3)在当前任务的任务控制块中保存当前任务(旧任务)的堆栈指针
    ;OSTCBCur->OSTCBStkPtr=?C_XBP
  MOV   DPH,#HIGH(OSTCBCur)
  MOV   DPL, #LOW(OSTCBCur)

  INC   DPTR           ;指针是3字节的
把我害死了
  MOVX   A,@DPTR
  MOV   R1,A
  INC   DPTR
  MOVX   A,@DPTR
  MOV   DPH,R1
  MOV   DPL,A
 
  INC   DPTR           ;指针是3字节的
把我害死了
  MOV   A,?C_XBP
  MOVX   @DPTR,A
  INC   DPTR
  MOV   A,?C_XBP+1
  MOVX   @DPTR,A
  IntCtxSw:
  ;(4)调用OSTaskSwHook();
  ;(5)OSTCBCur   = OSTCBHighRdy;
      ;(6)OSPrioCur   = OSPrioHighRdy;
    LCALL   _ComCtxSw1

  ;(7)得到将要重新开始运行的任务(新任务)的堆栈指针
  ;?C_XBP   = OSTCBHighRdy->OSTCBStkPtr;(0x0217)
  ;(8)拷贝原任务(新任务)中的?C_XBP到SP(系统)堆栈中   SP   满向上
    ;然后清空它(即?C_XBP中的原堆栈内容)         ?C_XBP
  满向下
  CtxSw:
    LCALL   _ComCtxSw2
  LCALL   _CopyC_XBPtoSP

      ;(9)从新任务堆栈中恢复处理器所有寄存器的值
  POPALL
  ;OS_EXIT_CRITICAL
  ;(10)执行返回指令
  SETB   EA         ;强行开中断!
  RET
/*$PAGE*/
;*******************************************************************************
**************************
;                     PERFORM A CONTEXT SWITCH (From an ISR)
;                           void OSIntCtxSw(void)
;   ;中断级切换:在OSInExit()中已判断了有高优先级的任务在就绪队列中,所以直接切
换到高优先级任务
;*******************************************************************************
**************************

  ?PR?_?OSIntCtxSw?OS_CPU_A         SEGMENT CODE
  RSEG   ?PR?_?OSIntCtxSw?OS_CPU_A
_?OSIntCtxSw:
  USING   0
  ;OS_ENTER_CRITICAL
  ACALL   _IntRETI
  JMP   IntCtxSw    
_IntRETI:
  RETI
;*******************************************************************************
**************************
;                             HANDLE TICK ISR
;*******************************************************************************
**************************
    CSEG   AT   000BH     ;设置T0中断向量
    LJMP   _?OSTickISR

  ?PR?_?OSTickISR?OS_CPU_A         SEGMENT CODE
  RSEG   ?PR?_?OSTickISR?OS_CPU_A
_?OSTickISR:
  USING   0
  CLR   EA
  ;(1)保存处理器寄存器 先PUSH到SP在COPY到?C_XBP OSTCBHighRdy
  PUSHALL
  LCALL   _CopySPtoC_XBP         ;COPY SP 的内容到?
C_XBP

  ;(2)记忆中断的嵌套层OSIntNesting++   进入中断
  ;(3) if (OSIntNesting == 1)
  ;   OSTCBCur->OSTCBStkPtr <= ?C_XBP
  LCALL   _Enter_INT

  ;(4)Clear inter
  CLR   TR0           ;TR0;清中断
  ;(5)[TH0,TL0]<= New Value
  MOV   TH0,#3CH         ;TH0=0x3ch;
  MOV   TL0,#0B0H         ;TL0=0x0b0h;
  SETB   TR0
  ;MOV   P1,0

  ;(6) Call OSTimeTick();
  LCALL   _?OSTimeTick

  ;(7) Call OSIntExit();
  LCALL   _?OSIntExit

  ;(8) 恢复处理器寄存器     ;没有高优先级任务在就绪队列中
  ;LCALL   _ComCtxSw2
  LCALL   _CopyC_XBPtoSP
  POPALL
  SETB   EA
  ;(9) 执行中断返回指令
  RETI

;*******************************************************************************
***************************
;             内部函数 : ComCtxSw1()
;   ;(4)调用OSTaskSwHook();
;   ;(5)OSTCBCur   = OSTCBHighRdy;
;       ;(6)OSPrioCur   = OSPrioHighRdy;
;*******************************************************************************
***************************
  ?PR?_ComCtxSw1?OS_CPU_A         SEGMENT CODE
  RSEG   ?PR?_ComCtxSw1?OS_CPU_A
_ComCtxSw1:
  ;调用OSTaskSwHook();
    LCALL   _?OSTaskSwHook         ;中断是关着的

  ;OSTCBCur   = OSTCBHighRdy;
  MOV   DPH,#HIGH(OSTCBHighRdy)
  MOV   DPL, #LOW(OSTCBHighRdy)
  MOVX   A,@DPTR
  MOV     R3,A
  INC     DPTR
  MOVX   A,@DPTR
  MOV     R2,A
  INC     DPTR
  MOVX   A,@DPTR
  MOV     R1,A

  MOV   DPH,#HIGH(OSTCBCur)
  MOV   DPL, #LOW(OSTCBCur)
  MOV     A,R3
  MOVX   @DPTR,A
  INC     DPTR
  MOV     A,R2
  MOVX   @DPTR,A
  INC     DPTR
  MOV     A,R1
  MOVX   @DPTR,A


      ;OSPrioCur   = OSPrioHighRdy;
  MOV   DPH,#HIGH(OSPrioHighRdy)
  MOV   DPL, #LOW(OSPrioHighRdy)
  MOVX   A,@DPTR
  MOV     R7,A

  MOV   DPH,#HIGH(OSPrioCur)
  MOV   DPL, #LOW(OSPrioCur)
  MOV     A,R7
  MOVX   @DPTR,A

  RET
;*******************************************************************************
***************************
;             内部函数 : ComCtxSw2()
;   ;(7)得到将要重新开始运行的任务(新任务)的堆栈指针
;   ;?C_XBP   = OSTCBHighRdy->OSTCBStkPtr;(0x0217)
;*******************************************************************************
***************************
  ?PR?_ComCtxSw2?OS_CPU_A         SEGMENT CODE
  RSEG   ?PR?_ComCtxSw2?OS_CPU_A
_ComCtxSw2:

  POP   ACC           ;因为函数调用而调整
SP,并保存到R1,R2
  MOV   R1,ACC
  POP   ACC
  MOV   R2,ACC

  ;得到将要重新开始运行的任务(新任务)的堆栈指针
  ;C_XBP   = OSTCBHighRdy->OSTCBStkPtr;(0x0217)
  MOV   DPH,#HIGH(OSTCBCur)     ;结构:OSTCBHighRdy-
>OSTCBStkPtr{[][H][L]}->?C_XBP
  MOV   DPL, #LOW(OSTCBCur)
  INC   DPTR           ;跳过指针类型编号
  MOVX   A,@DPTR
  INC   DPTR
  MOV   R3,A           ;读出高字节     为
了得到新任务的任务栈指针
  MOVX   A,@DPTR           ;读出底字节
  MOV   DPH,R3
  MOV   DPL,A

  INC   DPTR
  MOVX   A,@DPTR
  MOV   ?C_XBP,A
  INC   DPTR
  MOVX   A,@DPTR
  MOV   ?C_XBP+1,A

  MOV   ACC,R2           ;从R1,R2中恢复SP
  PUSH   ACC
  MOV   ACC,R1
  PUSH   ACC
 
  RET

[dvnews_page=OS_CPU_A.ASM之的内核代码部分2]


;*******************************************************************************
***************************
;             内部函数 : CopyC_XBPtoSP()
;   ?C_XBP => SP
;   ;拷贝原任务(新任务)中的?C_XBP到SP(系统)堆栈中   SP   满向上
;     ;然后清空它(即?C_XBP中的原堆栈内容)     ?C_XBP   满向下
;*******************************************************************************
***************************
  ?PR?_CopyC_XBPtoSP?OS_CPU_A         SEGMENT CODE
  RSEG   ?PR?_CopyC_XBPtoSP?OS_CPU_A
_CopyC_XBPtoSP:
                ;OSTCBHighRdy
  POP   ACC           ;因为函数调用而调整
SP,并保存到R1,R2
  MOV   R1,ACC
  POP   ACC
  MOV   R2,ACC

      MOV   DPH,?C_XBP
  MOV   DPL,?C_XBP+1

  MOVX   A,@DPTR
  MOV   R7,A           ;读出SP栈元素的总数
  MOV   SP,#?STACK-1
  COPYCXBP_TO_SP:           ;拷贝?C_XBP的内容到SP中
  INC   DPTR
  MOVX   A,@DPTR
  PUSH   ACC
  DJNZ   R7,COPYCXBP_TO_SP

  INC   DPTR
 
  MOV   A,DPH
  MOV   ?C_XBP,A
  MOV   A,DPL
  MOV   ?C_XBP+1,A

  MOV   ACC,R2           ;从R1,R2中恢复SP
  PUSH   ACC
  MOV   ACC,R1
  PUSH   ACC

  RET
;*******************************************************************************
***************************
;             内部函数 : CopySPtoC_XBP()
;   ?C_XBP <= SP
;   ;(2)拷贝SP(系统)堆栈中的内容到?C_XBP,     SP         满向上
;     ;然后清空它(即MOV SP,#?STACK-1)       ?C_XBP   满向下
;
;*******************************************************************************
***************************
  ?PR?_CopySPtoC_XBP?OS_CPU_A         SEGMENT CODE
  RSEG   ?PR?_CopySPtoC_XBP?OS_CPU_A
_CopySPtoC_XBP:             ;OSTCBHighRdy

  POP   ACC           ;因为函数调用而调整
SP,并保存到R1,R2
  MOV   R1,ACC
  POP   ACC
  MOV   R2,ACC

  MOV   DPH,?C_XBP
  MOV   DPL,?C_XBP+1

  MOV   R7,#?STACK-1
  MOV   A,SP
  SUBB   A,R7           ;因为SP-(?STACK-1)不
可能为零所以不用判断0
  MOV   R7,A
  MOV   R6,A
  ;INC   DPTR;%%%%????%%%%%%     ;不用防止!   以前的注释:防止
多减一个单元
  COPYSP_TO_CXBP:           ;拷贝SP的内容到?C_XBP中
    MOV   A,DPL
  SUBB   A,0
  JNZ   NOZERO
  DEC   DPH
  NOZERO:
    DEC   DPL
  POP   ACC
  MOVX   @DPTR,A
  DJNZ   R7,COPYSP_TO_CXBP

    MOV   A,DPL
  SUBB   A,0
  JNZ   NOZERO2
  DEC   DPH
  NOZERO2:
    DEC   DPL
  MOV   A,R6
  MOVX   @DPTR,A           ;?C_XBP栈顶保存的是
SP栈元素的总数

  MOV   A,DPH           ;?C_XBP是满向下不用
减了
  MOV   ?C_XBP,A
  MOV   A,DPL
  MOV   ?C_XBP+1,A

  MOV   ACC,R2           ;从R1,R2中恢复SP
  PUSH   ACC
  MOV   ACC,R1
  PUSH   ACC

  RET
;*******************************************************************************
***************************
;                 内部函数 : Enter_INT
()
;
;   ;(2)记忆中断的嵌套层OSIntNesting++   进入中断
;   ;(3) if (OSIntNesting == 1)
;   ;   OSTCBCur->OSTCBStkPtr <= ?C_XBP
;*******************************************************************************
***************************
  ?PR?_Enter_INT?OS_CPU_A         SEGMENT CODE
  RSEG   ?PR?_Enter_INT?OS_CPU_A
_Enter_INT:

  ;(2)记忆中断的嵌套层OSIntNesting++   进入中断
  MOV   DPH,#HIGH(OSIntNesting)
  MOV   DPL, #LOW(OSIntNesting)
  MOVX   A,@DPTR
  INC   A
  MOVX   @DPTR,A

  ;(3) if (OSIntNesting == 1)
  ;   OSTCBCur->OSTCBStkPtr <= C_XBP
  DEC   A
  JNZ   NOONE

  MOV   DPH,#HIGH(OSTCBCur)
  MOV   DPL, #LOW(OSTCBCur)

  INC   DPTR           ;指针是3字节的
把我害死了
  MOVX   A,@DPTR
  MOV   R1,A
  INC   DPTR
  MOVX   A,@DPTR
  MOV   DPH,R1
  MOV   DPL,A
 
  INC   DPTR           ;指针是3字节的
把我害死了
  MOV   A,?C_XBP
  MOVX   @DPTR,A
  INC   DPTR
  MOV   A,?C_XBP+1
  MOVX   @DPTR,A
  NOONE:

    RET
        END
;*******************************************************************************
***************************
;             文件结束
;*******************************************************************************
***************************