(转载)ucos ii2.86版本bug,2.52与2.86相同

转载:https://www.amobbs.com/thread-5635959-1-1.html

ucos2.86在cortex-M3出现的bug,具体现象,可参考下面的链接。
ucos中的这个问题(BUG),
[url]http://blog.csdn.net/sunlei_telchina/article/details/6205515


2.88修正了bug,下面列出2.88和2.86的不同点。
2.86中的代码是这样的:
     if (OSLockNesting == 0) {                      /* ... scheduler is not locked                  */
            OS_SchedNew();
            if (OSPrioHighRdy != OSPrioCur) {          /* No Ctx Sw if current task is highest rdy     */
                OSTCBHighRdy = OSTCBPrioTbl[OSPrioHighRdy];
                OSCtxSwCtr++;                          /* Increment context switch counter             */
                OS_TASK_SW();                          /* Perform a context switch                     */
            }
2.88中的代码是这样的:   
    if (OSLockNesting == 0u) {                     /* ... scheduler is not locked                  */
            OS_SchedNew();
            OSTCBHighRdy = OSTCBPrioTbl[OSPrioHighRdy];
            if (OSPrioHighRdy != OSPrioCur) {          /* No Ctx Sw if current task is highest rdy     */
                OSCtxSwCtr++;                          /* Increment context switch counter             */
                OS_TASK_SW();                          /* Perform a context switch                     */
            }
        }
---------------------------------------------------------
原文是这样的

OS_CORE.C:

OSIntExit() and OS_Sched() have changed slightly because of a boundary condition found with the Cortex-M3 port. Specifically, we needed to move the statement:

OSTCBHighRdy = OSTCBPrioTbl[OSPrioHighRdy];

Before testing for the priority.

-----------------------------------------------
下面开始分析原因          xcj 2015/10/31 15:52

假设有两个任务程序 A 和 B,任务A的优先级比任务B的优先级要高。

正在运行的任务A执行了一个OSTimeDly(1)来延时,OSTimeDly(1)调用OS_Sched()
            
       OS_ENTER_CRITICAL();
        if (OSIntNesting == 0u) {                       
             if (OSLockNesting == 0u) {   
              OS_SchedNew();                   // <----执行完该语句后,OSPrioHighRdy = B,
            if (OSPrioHighRdy != OSPrioCur)   //<------由于OSPrioCur =A,与OSPrioHighRdy不相等
             {
                    OSTCBHighRdy = OSTCBPrioTbl[OSPrioHighRdy]; //<----所以,OSTcbHighRdy = B
                    OSCtxSwCtr++;
                    OS_TASK_SW();  //<-- 在Cortex-M3上会触发一个PendSV,在PendSV中执行任务切换。
            }                                   //<----由于中断关闭,所以必须等中断打开才能
        }                                      //<---假设刚好运行到此处发生SysTick中断,但是由于前面已经关闭中断了,所以不会响应SysTick中断。
      }                                       // <------此时,有两个中断在排队了,SysTick中断和PendSV,假设SysTick中断的优先级比PendSV的高。
      OS_ENTER_CRITICAL();  // <------一旦执行了该行,意味着立马进入SysTick中断。
   
     记住此时:OSPrioCur          = A ,   OSTCBCur         = A
                        OSPrioHighRdy = B,   OSTCBHighRdy = B


在SysTick中会发现任务A的延时到期了。任务A又会进入就绪表,所以在OSIntExit()调用OS_Sched()时
     
  OS_ENTER_CRITICAL();
        if (OSIntNesting == 0u) {                       
             if (OSLockNesting == 0u) {   
             OS_SchedNew();                    <---由于任务A延时到了,所以OSPrioHighRdy = A,
            if (OSPrioHighRdy != OSPrioCur)   <-----而此时OSPrioCur =A,与OSPrioHighRdy相等所以不会执行下面括号里的语句。
             {
                    OSTCBHighRdy = OSTCBPrioTbl[OSPrioHighRdy];
                    OSCtxSwCtr++;
                    OSIntCtxSw();  <-- 该句子不执行,不触发PendSV。
            }      <----此时,OSTCBHighRdy =B                        
        }                                    
      }                                      
      OS_ENTER_CRITICAL();   <-----从SysTick退出后,会立马进入PendSV中断(由A.OSTimeDly(1)触发的)
注意此时:
                     OSPrioCur          = A,   OSTCBCur         = A
                       OSPrioHighRdy = A,   OSTCBHighRdy = B


在PendSV的程序中,只执行任务切换

    OSPrioCur  <= OSPrioHighRdy;
    OSTCBCur <= OSTCBHighRdy;
   任务寄存器出栈。
跑到任务程序里面发现:
          OSPrioCur = A,  OSTCBCur =B;

也就是说虽然当前运行的实际任务是B,但是当前的优先级却是A。这也就是是为什么最后程序运行到一个低级的程序出不来。高级的程序无法运行的原因。

同样的情况也可能发生在下面这种情况:
(1)正在运行的A调用系统函数SemPend(),semPend()执行完后会OSPrioHighRdy = B, OSTCBHighRdy = B。
(2) 在SemPend()中执行OSched()中过程中发生了外部中断。OSChed()运行完立即进去外部中断程序(而不是PendSV程序)。
(3)而在外部中断中调用了SemPost(),又让A就绪了。执行外部中断的SemPost的OSChed()中会让OSPrioRdy = A,OSTCBHighRdy = B(因为OSPrioHighRdy≠OSPrioCur不成立)
(4)从外部中断后退出,直接进入PendSV中断,PendSV中断直接将 OSPrioCur  <= OSPrioHighRdy;    OSTCBCur <= OSTCBHighRdy;
(5) PendSV返回后,实际运行的任务堆栈OSTCBCur =B,而其优先级OSPrioCur =A(任务B占着A的优先级)。

这样任务A永远无法运行(即使任务B延迟自己)。只能让更低优先级任务B运行。

  把程序修改一下,使OSTCBHighRdy与OSPrioHighRdy同步更新,就不会出现上述的bug。
  if (OSLockNesting == 0u) {                     /* ... scheduler is not locked                  */
            OS_SchedNew();
            OSTCBHighRdy = OSTCBPrioTbl[OSPrioHighRdy];
            if (OSPrioHighRdy != OSPrioCur) {          /* No Ctx Sw if current task is highest rdy     */
                OSCtxSwCtr++;                          /* Increment context switch counter             */
                OS_TASK_SW();                          /* Perform a context switch                     */
            }
        }

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值