⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ucos51 移植心得.txt

📁 uCOS51 移植心得,从中可得到很多启发
💻 TXT
📖 第 1 页 / 共 2 页
字号:
              INC  R0
              MOV  DPH,@R0    ;全局变量OSTCBCur在IDATA中
              INC  R0
              MOV  DPL,@R0
          
              ;OSTCBCur->OSTCBStkPtr ===> DPTR  获得用户堆栈指针
              INC  DPTR        ;指针占3字节。+0类型+1高8位数据+2低8位数据
              MOVX A,@DPTR     ;.OSTCBStkPtr是void指针
              MOV  R0,A
              INC  DPTR
              MOVX A,@DPTR
              MOV  R1,A
              MOV  DPH,R0
              MOV  DPL,R1
          
              ;*UserStkPtr ===> R5  用户堆栈起始地址内容(即用户堆栈长度放在此处)  详见文档说明  
      指针用法详见C51.PDF第169页    
              MOVX A,@DPTR     ;用户堆栈中是unsigned char类型数据
              MOV  R5,A        ;R5=用户堆栈长度
          
              ;恢复现场堆栈内容
              MOV  R0,#OSStkStart
              
      restore_stack:
          
              INC  DPTR
              INC  R0
              MOVX A,@DPTR
              MOV  @R0,A
              DJNZ R5,restore_stack
          
              ;恢复堆栈指针SP
              MOV  SP,R0
          
              ;OSRunning=TRUE
              MOV  R0,#LOW (OSRunning)
              MOV  @R0,#01
          
              POPALL
              SETB EA    ;开中断
              RETI
      ;-------------------------------------------------------------------------
              RSEG ?PR?OSCtxSw?OS_CPU_A
      OSCtxSw:    
              PUSHALL
          
      OSIntCtxSw_in:
          
              ;获得堆栈长度和起址
              MOV  A,SP
              CLR  C
              SUBB A,#OSStkStart
              MOV  R5,A     ;获得堆栈长度        
          
              ;OSTCBCur ===> DPTR  获得当前TCB指针,详见C51.PDF第178页
              MOV  R0,#LOW (OSTCBCur) ;获得OSTCBCur指针低地址,指针占3字节。+0类型+1高8位数据+2低8位数据
              INC  R0
              MOV  DPH,@R0    ;全局变量OSTCBCur在IDATA中
              INC  R0
              MOV  DPL,@R0
          
              ;OSTCBCur->OSTCBStkPtr ===> DPTR  获得用户堆栈指针
              INC  DPTR        ;指针占3字节。+0类型+1高8位数据+2低8位数据
              MOVX A,@DPTR     ;.OSTCBStkPtr是void指针
              MOV  R0,A
              INC  DPTR
              MOVX A,@DPTR
              MOV  R1,A
              MOV  DPH,R0
              MOV  DPL,R1
              
              ;保存堆栈长度
              MOV  A,R5
              MOVX @DPTR,A
          
              MOV  R0,#OSStkStart  ;获得堆栈起址
      save_stack:
          
              INC  DPTR
              INC  R0
              MOV  A,@R0
              MOVX @DPTR,A
              DJNZ R5,save_stack
          
              ;调用用户程序
              LCALL _?OSTaskSwHook
              
              ;OSTCBCur = OSTCBHighRdy
              MOV  R0,#OSTCBCur
          MOV  R1,#OSTCBHighRdy
          MOV  A,@R1
              MOV  @R0,A
              INC  R0
          INC  R1
          MOV  A,@R1
              MOV  @R0,A
              INC  R0
          INC  R1
          MOV  A,@R1
              MOV  @R0,A
                      
              ;OSPrioCur = OSPrioHighRdy  使用这两个变量主要目的是为了使指针比较变为字节比较,以便节省时间。
              MOV  R0,#OSPrioCur
          MOV  R1,#OSPrioHighRdy
          MOV  A,@R1
              MOV  @R0,A
              
              LJMP OSCtxSw_in
      ;-------------------------------------------------------------------------
              RSEG ?PR?OSIntCtxSw?OS_CPU_A
              
      OSIntCtxSw:

              ;调整SP指针去掉在调用OSIntExit(),OSIntCtxSw()过程中压入堆栈的多余内容
              ;SP=SP-4

              MOV  A,SP
              CLR  C
              SUBB A,#4
              MOV  SP,A
              
              LJMP OSIntCtxSw_in
      ;-------------------------------------------------------------------------
              CSEG AT 000BH    ;OSTickISR
              LJMP OSTickISR   ;使用定时器0
              RSEG ?PR?OSTickISR?OS_CPU_A

      OSTickISR:        
              
              USING 0        
              PUSHALL
              
              CLR  TR0
              MOV  TH0,#70H    ;定义Tick=50次/秒(即0.02秒/次)
              MOV  TL0,#00H    ;OS_CPU_C.C  和  OS_TICKS_PER_SEC
              SETB TR0
              
              LCALL _?OSIntEnter
              LCALL _?OSTimeTick
              LCALL _?OSIntExit
              POPALL        
              RETI
      ;-------------------------------------------------------------------------
              CSEG AT 0023H    ;串口中断
              LJMP SerialISR   ;工作于系统态,无任务切换。
              RSEG ?PR?_?serial?OS_CPU_A
              
      SerialISR:
              
              USING 0        
              PUSHALL
              CLR  EA
              LCALL _?serial        
              SETB EA
              POPALL        
              RETI
      ;-------------------------------------------------------------------------
              END
      ;-------------------------------------------------------------------------

      文件名 : OS_CPU_C.C

      void *OSTaskStkInit (void (*task)(void *pd), void *ppdata, void *ptos, 
      INT16U opt) reentrant
      {    
          OS_STK *stk;

          ppdata = ppdata;
          opt    = opt;                           //opt没被用到,保留此语句防止告警产生    
          stk    = (OS_STK *)ptos;                //用户堆栈最低有效地址
          *stk++ = 15;                            //用户堆栈长度
          *stk++ = (INT16U)task & 0xFF;           //任务地址低8位
          *stk++ = (INT16U)task >> 8;             //任务地址高8位    
          *stk++ = 0x00;                          //PSW
          *stk++ = 0x0A;                          //ACC
          *stk++ = 0x0B;                          //B
          *stk++ = 0x00;                          //DPL
          *stk++ = 0x00;                          //DPH
          *stk++ = 0x00;                          //R0
          *stk++ = 0x01;                          //R1
          *stk++ = 0x02;                          //R2
          *stk++ = 0x03;                          //R3
          *stk++ = 0x04;                          //R4
          *stk++ = 0x05;                          //R5
          *stk++ = 0x06;                          //R6
          *stk++ = 0x07;                          //R7
                                                  //不用保存SP,任务切换时根据用户堆栈长度计算得出。    

          return ((void *)ptos);
      }

      #if OS_CPU_HOOKS_EN
      void OSTaskCreateHook (OS_TCB *ptcb) reentrant
      {
          ptcb = ptcb;                       /* Prevent compiler warning         
                                  */
      }

      void OSTaskDelHook (OS_TCB *ptcb) reentrant
      {
          ptcb = ptcb;                       /* Prevent compiler warning         
                                  */
      }

      void OSTimeTickHook (void) reentrant
      {
      }
      #endif

      //初始化定时器0
      void InitTimer0(void) reentrant
      {
          TMOD=TMOD&0xF0;
          TMOD=TMOD|0x01;    //模式1(16位定时器),仅受TR0控制
          TH0=0x70;    //定义Tick=50次/秒(即0.02秒/次)
          TL0=0x00;    //OS_CPU_A.ASM  和  OS_TICKS_PER_SEC
          ET0=1;       //允许T0中断
          TR0=1;   
      }

      文件名 : YY.C

      #include <includes.h>

      #define MAX_STK_SIZE 64

      void TaskStartyya(void *yydata) reentrant;
      void TaskStartyyb(void *yydata) reentrant;
      void TaskStartyyc(void *yydata) reentrant;

      OS_STK 
      TaskStartStkyya[MAX_STK_SIZE+1];//注意:我在ASM文件中设置?STACK空间为40H即64,不要超出范围。
      OS_STK TaskStartStkyyb[MAX_STK_SIZE+1];//用户栈多一个字节存长度
      OS_STK TaskStartStkyyc[MAX_STK_SIZE+1];

      void main(void)
      {
          OSInit();
          
          InitTimer0();
          InitSerial();
          InitSerialBuffer();
          
          OSTaskCreate(TaskStartyya, (void *)0, &TaskStartStkyya[0],2);
          OSTaskCreate(TaskStartyyb, (void *)0, &TaskStartStkyyb[0],3);
          OSTaskCreate(TaskStartyyc, (void *)0, &TaskStartStkyyc[0],4);
          
          OSStart();
      }


      void TaskStartyya(void *yydata) reentrant
      {
          yydata=yydata;
          clrscr();
          PrintStr("\n\t\t*******************************\n");
          PrintStr("\t\t*     Hello! The world.       *\n");
          PrintStr("\t\t*******************************\n\n\n");
          
          for(;;){
              PrintStr("\tAAAAAA111111 is active.\n");
              OSTimeDly(OS_TICKS_PER_SEC);    
          }    
      }

      void TaskStartyyb(void *yydata) reentrant
      {
          yydata=yydata; 
          
          for(;;){
              PrintStr("\tBBBBBB333333 is active.\n");
              OSTimeDly(3*OS_TICKS_PER_SEC);    
          }    
      }

      void TaskStartyyc(void *yydata) reentrant
      {
          yydata=yydata; 
          
          for(;;){
              PrintStr("\tCCCCCC666666 is active.\n");
              OSTimeDly(6*OS_TICKS_PER_SEC);    
          }    
      }  
       打印本文   关闭窗口   

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -