king1314 发表于 2014-1-16 13:44:15

ucos 的疑问

我按照网上的方法自己移植了个ucos2.92版本的

void Task1(void *ppdata)
{
ppdata = ppdata;                                                                          
for(;;)
        {
        LED0 = ~LED0;                             
           OSTimeDly(OS_TICKS_PER_SEC);       
    }
}

void Task2(void *ppdata)   
{
ppdata = ppdata;                                
for(;;)
        {
        LED1=~LED1;
    OSTimeDly(OS_TICKS_PER_SEC*2);       
}
}
int main()
{
        CKCON = 0x38;
        Uart0_Init();
        OSInit();
        OSTaskCreate (Task1,(void *)0,&TaskStk,0);
        OSTaskCreate (Task2,(void *)0,&TaskStk,1);                       
        OSStart();
        return 0;       
}


我的问题是当task2运行到LED1=~LED1;
时发生了定时中断
执行
OSTickISR:      
      USING 0
      CLREA
      PUSHALL
      LCALL _?OSIntEnter         
      CLRTR0
      MOVTH0,#0E0H
      MOVTL0,#0C0H
      SETB TR0
                MOV WATCH,#0A1H         
      LCALL _?OSTimeTick
      LCALL _?OSIntExit
      POPALL      
      RETI

在定时中断里OSIntEnter ()--》OSTimeTick--》OSIntExit--》
voidOSIntExit (void)       reentrant
{
#if OS_CRITICAL_METHOD == 3u                               /* Allocate storage for CPU status register */
    OS_CPU_SRcpu_sr = 0u;
#endif
    if (OSRunning == OS_TRUE) {
      OS_ENTER_CRITICAL();
      if (OSIntNesting > 0u) {                           /* Prevent OSIntNesting from wrapping       */
            OSIntNesting--;
      }
      if (OSIntNesting == 0u) {                        /* Reschedule only if all ISRs complete ... */
            if (OSLockNesting == 0u) {                     /* ... and not locked.                      */
                OS_SchedNew();
                OSTCBHighRdy = OSTCBPrioTbl;
                if (OSPrioHighRdy != OSPrioCur) {          /* No Ctx Sw if current task is highest rdy */
#if OS_TASK_PROFILE_EN > 0u
                  OSTCBHighRdy->OSTCBCtxSwCtr++;         /* Inc. # of context switches to this task*/
#endif
                  OSCtxSwCtr++;                        /* Keep track of the number of ctx switches */
                   OSIntCtxSw();                        /* Perform interrupt level ctx switch       */                }
            }
      }
      OS_EXIT_CRITICAL();
    }
}

OSIntCtxSw_in:
      MOVA,SP
      CLRC
      SUBB A,#OSStkStart
      MOVR5,A
      MOVR0,#LOW (OSTCBCur)
      INCR0
      MOVDPH,@R0
      INCR0
      MOVDPL,@R0
      INCDPTR   
      MOVX A,@DPTR
      MOVR0,A
      INCDPTR
      MOVX A,@DPTR
      MOVR1,A
      MOVDPH,R0
      MOVDPL,R1
      MOVA,R5
      MOVX @DPTR,A   
      MOVR0,#OSStkStart

save_stack:   
      INCDPTR
      INCR0
      MOVA,@R0
      MOVX @DPTR,A
      DJNZ R5,save_stack
      INCDPTR
      MOVA,?C_XBP
      MOVX @DPTR,A
      INCDPTR
      MOVA,?C_XBP+1
      MOVX @DPTR,A
      LCALL         _?OSTaskSwHook
      MOVR0,#OSTCBCur
          MOVR1,#OSTCBHighRdy
          MOVA,@R1
      MOV@R0,A
      INCR0
          INCR1
          MOVA,@R1
      MOV@R0,A
      INCR0
          INCR1
          MOVA,@R1
      MOV@R0,A
      MOVR0,#OSPrioCur
          MOVR1,#OSPrioHighRdy
          MOVA,@R1
      MOV@R0,A      
      LJMP OSCtxSw_in
;-------------------------------------------------------------------------
      RSEG ?PR?OSIntCtxSw?OS_CPU_A
      
OSIntCtxSw:
      MOVA,SP
      CLRC
      SUBB A,#4
      MOVSP,A
      
      LJMP OSIntCtxSw_in

在保存堆栈时怎么没有保存pc的值到仿真栈中呢?只保存了栈长度 ACC   BDPL DPH等
那么在下次轮到task2执行时RETI时怎么返回到LED1=~LED1;的下一行代码接着执行呢

mitchell 发表于 2014-1-16 14:06:29

中断发生,程序跳转到ISR时,PC就自动入栈了。执行RETI指令时,栈顶的PC值被弹出。

xuxi2009 发表于 2014-1-16 14:09:38

mitchell 发表于 2014-1-16 14:06
中断发生,程序跳转到ISR时,PC就自动入栈了。执行RETI指令时,栈顶的PC值被弹出。 ...

楼上正解,这是处理器自身具备的功能,自动保存PC

king1314 发表于 2014-1-16 14:22:49

mitchell 发表于 2014-1-16 14:06
中断发生,程序跳转到ISR时,PC就自动入栈了。执行RETI指令时,栈顶的PC值被弹出。 ...

那我再保存堆栈的时候,就不用保存pc的值了吧?

如果我在中断中改变sp的值,是不是就有可能当RETI返回时不会 接着运行中断前的下一条代码???

还有当我在中断中调用一个子程序,sp的值如何变化呢?

期盼你的回答,谢谢

mitchell 发表于 2014-1-16 14:32:21

king1314 发表于 2014-1-16 14:22
那我再保存堆栈的时候,就不用保存pc的值了吧?

如果我在中断中改变sp的值,是不是就有可能当RETI返回时 ...

那我再保存堆栈的时候,就不用保存pc的值了吧?
——不用。

如果我在中断中改变sp的值,是不是就有可能当RETI返回时不会 接着运行中断前的下一条代码???
——如果保证执行RETI时和进入ISR时的SP值是相同的,就可以接着运行中断前的下一条代码。否则不行。

还有当我在中断中调用一个子程序,sp的值如何变化呢?
——子程序自己会管理堆栈,以保证子程序返回以后和进入之前,SP的值是相同的。

king1314 发表于 2014-1-16 17:45:49

mitchell 发表于 2014-1-16 14:32
那我再保存堆栈的时候,就不用保存pc的值了吧?
——不用。



在程序里有这样一句
?STACK SEGMENT IDATA
      RSEG ?STACK
OSStack:
      DS 40H
OSStkStart IDATA OSStack-1


定义一个预留的堆栈 且大小是40有什么用处呢?

pop或者push的时候,系统不是会自动分配的吗,

OSStkStart会随着硬件sp的变化而变化吗??

mitchell 发表于 2014-1-17 17:03:53

king1314 发表于 2014-1-16 17:45
在程序里有这样一句
?STACK SEGMENT IDATA
      RSEG ?STACK


你的问题太基础。建议你仔细研究《微机原理》。

king1314 发表于 2014-1-17 17:25:17

mitchell 发表于 2014-1-17 17:03
你的问题太基础。建议你仔细研究《微机原理》。

谢谢大侠指点,我是转行过来的,所以很多基础的东西不明白
页: [1]
查看完整版本: ucos 的疑问