OSEventPendMulti因使用不当导致的软件偶发性监听不到某个事件

前言

公司的一款产品,使用ucosii操作系统,任务间的整体通讯思路是依赖OSEventPendMulti函数完成不同任务之间的消息传递.而某个任务的OSEventPendMulti函数经常性的收不到特定消息.

分析

分析这个OSEventPendMulti函数等待的事件,一共等待4个事件,分别是两个来自其他任务的事件,和systick每隔200ms发出的空消息邮箱事件(做200ms定时器功能), 以及RTC每隔1秒发出的空消息邮箱事件(做1000ms定时器使用). 其中RTC发出的事件,经常性的收不到.对发消息和收消息处展开分析,最终定位到了问题所在.假定有bug的那个任务为任务L,

RTC中断中一共发送3个消息给到不同的任务,任务L的优先级是最低的.由于RTC是在中断中发消息,消息发送后并不会立即产生调度,而是等到中断退出时才会产生调度.所以中断退出时并不会立即调度到任务L,而是调度到其他优先级更高的任务.

给任务L发送消息时,在发送消息函数内部调用OS_EventTaskRdy 其中ptcb->OSTCBEventMultiRdy = (OS_EVENT *)pevent;任务L保存了这个事件,看到这里,一下子想到,OSEventPendMulti不会单次仅返回一个就绪事件吧.

OS_EventTaskRdy函数内部.
#if (OS_EVENT_MULTI_EN > 0u)
    if (ptcb->OSTCBEventMultiPtr != (OS_EVENT **)0) {   /* Remove this task from events' wait lists    */
        OS_EventTaskRemoveMulti(ptcb, ptcb->OSTCBEventMultiPtr);
        ptcb->OSTCBEventMultiPtr  = (OS_EVENT **)0;     /* No longer pending on multi list             */
        ptcb->OSTCBEventMultiRdy  = (OS_EVENT  *)pevent;/* Return event as first multi-pend event ready*/
    }
#endif

经查验果然如此.问题到此逐渐明朗,任务L虽然已就绪,但是还要等待其他高优先级的任务调度完成才能调度.而此时其他高优先级的任务运行又比较耗时.所以任务还没有得到调度时. systick中断中又向任务发送了一个消息, 导致OSTCBCur->OSTCBEventMultiRdy被新的消息覆盖. 等到任务L得以调度时,RTC发出的消息已经被覆盖,所以没有得以运行.

switch (OSTCBCur->OSTCBStatPend) {                  /* Handle event posted, aborted, or timed-out  */
    case OS_STAT_PEND_OK:
    case OS_STAT_PEND_ABORT:
    // 获取到OSTCBEventMultiRdy指向的事件. 
         pevent = OSTCBCur->OSTCBEventMultiRdy; 
         if (pevent != (OS_EVENT *)0) {             /* If task event ptr != NULL, ...              */
            *pevents_rdy++   =  pevent;             /* ... return available event ...              */
            *pevents_rdy     = (OS_EVENT *)0;       /* ... & NULL terminate return event array     */
            events_rdy_nbr =  1;

         } else {                                   /* Else NO event available, handle as timeout  */
             OSTCBCur->OSTCBStatPend = OS_STAT_PEND_TO;
             OS_EventTaskRemoveMulti(OSTCBCur, pevents_pend);
         }
         break;

解决

问题的解决方案有很多,知道了OSEventPendMulti的这个特性,在使用时就要多加注意,在这个项目中因为收到消息处理的事务并不多,我就直接删除了RTC发送的那个消息.让L任务中每隔一秒运行的事件,放在200ms事件中累加5次后运行。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值