shfeng
驱动牛犊
驱动牛犊
  • 注册日期2003-05-02
  • 最后登录2004-04-14
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
阅读:1427回复:1

uc/os源码的疑问

楼主#
更多 发布于:2003-05-03 17:26
小弟最近学习<>中遇到了问题,请大家帮忙,
在os_mbox.c中有这样一段:
/*
*********************************************************************************************************
*                                      PEND ON MAILBOX FOR A MESSAGE
*
* Description: This function waits for a message to be sent to a mailbox
*
* Arguments  : pevent        is a pointer to the event control block associated with the desired mailbox
*
*              timeout       is an optional timeout period (in clock ticks).  If non-zero, your task will
*                            wait for a message to arrive at the mailbox up to the amount of time
*                            specified by this argument.  If you specify 0, however, your task will wait
*                            forever at the specified mailbox or, until a message arrives.
*
*              err           is a pointer to where an error message will be deposited.  Possible error
*                            messages are:
*
*                            OS_NO_ERR         The call was successful and your task received a message.
*                            OS_TIMEOUT        A message was not received within the specified timeout
*                            OS_ERR_EVENT_TYPE Invalid event type
*                            OS_ERR_PEND_ISR   If you called this function from an ISR and the result
*                                              would lead to a suspension.
*
* Returns    : != (void *)0  is a pointer to the message received
*              == (void *)0  if no message was received or you didn\'t pass the proper pointer to the
*                            event control block.
*********************************************************************************************************
*/

void *OSMboxPend (OS_EVENT *pevent, INT16U timeout, INT8U *err)
{
    void  *msg;


    OS_ENTER_CRITICAL();
    if (pevent->OSEventType != OS_EVENT_TYPE_MBOX) {  /* Validate event block type                     */
        OS_EXIT_CRITICAL();
        *err = OS_ERR_EVENT_TYPE;
        return ((void *)0);
    }
    msg = pevent->OSEventPtr;
    if (msg != (void *)0) {                           /* See if there is already a message             */
        pevent->OSEventPtr = (void *)0;               /* Clear the mailbox                             */
        OS_EXIT_CRITICAL();
        *err = OS_NO_ERR;
    } else if (OSIntNesting > 0) {                    /* See if called from ISR ...                    */
        OS_EXIT_CRITICAL();                           /* ... can\'t PEND from an ISR                    */
        *err = OS_ERR_PEND_ISR;
    } else {
        OSTCBCur->OSTCBStat |= OS_STAT_MBOX;          /* Message not available, task will pend         */
        OSTCBCur->OSTCBDly   = timeout;               /* Load timeout in TCB                           */
        OSEventTaskWait(pevent);                      /* Suspend task until event or timeout occurs    */
        OS_EXIT_CRITICAL();
        OSSched();                                    /* Find next highest priority task ready to run  */
        OS_ENTER_CRITICAL();
        if ((msg = OSTCBCur->OSTCBMsg) != (void *)0) {     /* See if we were given the message         */
            OSTCBCur->OSTCBMsg      = (void *)0;           /* Yes, clear message received              */
            OSTCBCur->OSTCBStat     = OS_STAT_RDY;
            OSTCBCur->OSTCBEventPtr = (OS_EVENT *)0;       /* No longer waiting for event              */
            OS_EXIT_CRITICAL();
            *err                    = OS_NO_ERR;
        } else if (OSTCBCur->OSTCBStat & OS_STAT_MBOX) {   /* If status is not OS_STAT_RDY, timed out  */
            OSEventTO(pevent);                             /* Make task ready                          */
            OS_EXIT_CRITICAL();
            msg                     = (void *)0;           /* Set message contents to NULL             */
            *err                    = OS_TIMEOUT;          /* Indicate that a timeout occured          */
        } else {                                           /*????*/
            msg                     = pevent->OSEventPtr;  /*????*/ /* Message received      */
            pevent->OSEventPtr      = (void *)0;           /*????*/ /* Clear the mailbox   */
            OSTCBCur->OSTCBEventPtr = (OS_EVENT *)0;       /*????*/
            OS_EXIT_CRITICAL();                            /*????*/
            *err                    = OS_NO_ERR;           /*????*/
        }                                                  /*????*/
    }
    return (msg);                                          /* Return the message received (or NULL)    */
}
当某个任务(且称为Task1)调用OSMboxPend ()由于邮箱为空,OSEventTaskWait(pevent); OS_EXIT_CRITICAL();OSSched(); 执行完,我想应该只有两种可能使任务Task1重新运行:
1.时间节拍服务调用void OSTimeTick(void) (这个函数在os_core.c中),由于超时任务Task1重新运行。
2.其他的任务或中断子程序发送消息到邮箱INT8U OSMboxPost (OS_EVENT *pevent, void *msg)(在os_mbox.c中)然后调用OSSched()或OSIntCtxSw()实现任务切换。这时又有两种可能,

   2.a.Task1中OSTCBMsg!=0;
   2.b.Task1中OSTCBMsg=0;(调用INT8U OSMboxPost (OS_EVENT *pevent, void *msg)的任务或中断把*msg设置成0)。此时
当1发生时,没问题,2.a发生时也没问题。
2.b发生时我在行后标了/*????*/的一段就要执行了。也就是说Task1得到了一个为0的message(pevent->OSEventPtr也为0,由于Task1在等,消息不会发到pevent->OSEventPtr),却反回了OS_NO_ERR!!并且这样这一段显然没不能实现注释中的功能,邵贝贝的中文译本也是说(原文说:如果OS_STAT_MBOX位没被置1,说明所等待的消息已发出。OSMboxPend()的调用函数得到指向消息的指针。此后,OSMboxPend()函数通过邮箱事件控制块的.OSEventPrt域置为NULL清空该邮箱,....)。
而我认为执行执行这一块时msg,pevent->OSEventPtr(由于Task1在等消息不会发到这里)都是0,这段代码有什么意义呢?
当然我想应该是我前面的设想都是存在问题的,应该是我没能理解Jean J. Labrosse和邵贝贝的意思。希望大家帮忙   :mad:

最新喜欢:

xiangshifuxiangs...
John_Lee
驱动牛犊
驱动牛犊
  • 注册日期2002-03-27
  • 最后登录2003-08-10
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
沙发#
发布于:2003-07-30 13:10
那段代码是没有意义的。实际上在V2.51的版本中已经去掉了那段代码。V2.51中是这样的:
void  *OSMboxPend (OS_EVENT *pevent, INT16U timeout, INT8U *err)
{
#if OS_CRITICAL_METHOD == 3                      /* Allocate storage for CPU status register           */
    OS_CPU_SR  cpu_sr;
#endif    
    void      *msg;

#if OS_ARG_CHK_EN > 0
    if (pevent == (OS_EVENT *)0) {                    /* Validate \'pevent\'                             */
        *err = OS_ERR_PEVENT_NULL;
        return ((void *)0);
    }
    if (pevent->OSEventType != OS_EVENT_TYPE_MBOX) {  /* Validate event block type                     */
        *err = OS_ERR_EVENT_TYPE;
        return ((void *)0);
    }
#endif
    OS_ENTER_CRITICAL();
    msg = pevent->OSEventPtr;
    if (msg != (void *)0) {                           /* See if there is already a message             */
        pevent->OSEventPtr = (void *)0;               /* Clear the mailbox                             */
        OS_EXIT_CRITICAL();
        *err = OS_NO_ERR;
        return (msg);                                 /* Return the message received (or NULL)         */
    }
    OSTCBCur->OSTCBStat |= OS_STAT_MBOX;              /* Message not available, task will pend         */
    OSTCBCur->OSTCBDly   = timeout;                   /* Load timeout in TCB                           */
    OS_EventTaskWait(pevent);                         /* Suspend task until event or timeout occurs    */
    OS_EXIT_CRITICAL();
    OS_Sched();                                       /* Find next highest priority task ready to run  */
    OS_ENTER_CRITICAL();
    msg = OSTCBCur->OSTCBMsg;
    if (msg != (void *)0) {                           /* See if we were given the message              */
        OSTCBCur->OSTCBMsg      = (void *)0;          /* Yes, clear message received                   */
        OSTCBCur->OSTCBStat     = OS_STAT_RDY;
        OSTCBCur->OSTCBEventPtr = (OS_EVENT *)0;      /* No longer waiting for event                   */
        OS_EXIT_CRITICAL();
        *err                    = OS_NO_ERR;
        return (msg);                                 /* Return the message received                   */
    }
    OS_EventTO(pevent);                               /* Timed out, Make task ready                    */
    OS_EXIT_CRITICAL();
    *err = OS_TIMEOUT;                                /* Indicate that a timeout occured               */
    return ((void *)0);                               /* Return a NULL message                         */
}
游客

返回顶部