阅读:1499回复:1
uc/os源码的疑问
小弟最近学习<>中遇到了问题,请大家帮忙,
在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: |
|
最新喜欢:![]() |
沙发#
发布于: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 */ } |
|