搜索
bottom↓
回复: 7

ucos 的疑问

[复制链接]

出0入0汤圆

发表于 2014-1-16 13:44:15 | 显示全部楼层 |阅读模式
我按照网上的方法自己移植了个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][0],0);
        OSTaskCreate (Task2,(void *)0,&TaskStk[1][0],1);                       
        OSStart();
        return 0;       
}


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

在定时中断里OSIntEnter ()--》OSTimeTick--》OSIntExit--》
void  OSIntExit (void)         reentrant
{
#if OS_CRITICAL_METHOD == 3u                               /* Allocate storage for CPU status register */
    OS_CPU_SR  cpu_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[OSPrioHighRdy];
                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:
        MOV  A,SP
        CLR  C
        SUBB A,#OSStkStart
        MOV  R5,A
        MOV  R0,#LOW (OSTCBCur)
        INC  R0
        MOV  DPH,@R0
        INC  R0
        MOV  DPL,@R0
        INC  DPTR     
        MOVX A,@DPTR  
        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
        INC  DPTR
        MOV  A,?C_XBP
        MOVX @DPTR,A
        INC  DPTR
        MOV  A,?C_XBP+1
        MOVX @DPTR,A
        LCALL         _?OSTaskSwHook
        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
        MOV  R0,#OSPrioCur
            MOV  R1,#OSPrioHighRdy
            MOV  A,@R1
        MOV  @R0,A        
        LJMP OSCtxSw_in
;-------------------------------------------------------------------------
        RSEG ?PR?OSIntCtxSw?OS_CPU_A
        
OSIntCtxSw:
        MOV  A,SP
        CLR  C
        SUBB A,#4
        MOV  SP,A
        
        LJMP OSIntCtxSw_in

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

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

曾经有一段真挚的爱情摆在我的面前,我没有珍惜,现在想起来,还好我没有珍惜……

出0入0汤圆

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

出0入0汤圆

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

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

出0入0汤圆

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

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

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

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

期盼你的回答,谢谢

出0入0汤圆

发表于 2014-1-16 14:32:21 | 显示全部楼层
king1314 发表于 2014-1-16 14:22
那我再保存堆栈的时候,就不用保存pc的值了吧?

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

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

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

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

出0入0汤圆

 楼主| 发表于 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的变化而变化吗??

出0入0汤圆

发表于 2014-1-17 17:03:53 | 显示全部楼层
king1314 发表于 2014-1-16 17:45
在程序里有这样一句
?STACK SEGMENT IDATA
        RSEG ?STACK

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

出0入0汤圆

 楼主| 发表于 2014-1-17 17:25:17 | 显示全部楼层
mitchell 发表于 2014-1-17 17:03
你的问题太基础。建议你仔细研究《微机原理》。

谢谢大侠指点,我是转行过来的,所以很多基础的东西不明白
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片。注意:要连续压缩2次才能满足要求!!】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

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

GMT+8, 2024-8-26 04:20

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

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