|
UCOS等待一条消息函数中的疑惑,请高手赐教!!!
在一个消息队列中等待一条消息原函数如下:
void *OSQPend (OS_EVENT *pevent, INT16U timeout, INT8U *err)
{
void *msg;
OS_Q *pq;
OS_ENTER_CRITICAL();
if (pevent->OSEventType != OS_EVENT_TYPE_Q) { //不是事件块类型 (1)
OS_EXIT_CRITICAL();
*err = OS_ERR_EVENT_TYPE;
return ((void *)0);
}
pq = pevent->OSEventPtr; //取出队列控制块指针
if (pq->OSQEntries != 0) { //如果已经有可用消息就不用进入等待状态了
(2)
msg = *pq->OSQOut++; // (3)
pq->OSQEntries--; // (4)
if (pq->OSQOut == pq->OSQEnd) { (6)
}//消息队列是一个循环缓冲区,如果超出了队列中最末一个单元,发生
//这种越界时,就要将.OSQOut重新调整到指向队列的起始单元
OS_EXIT_CRITICAL();
*err = OS_NO_ERR;
} else if (OSIntNesting > 0) { (7)
OS_EXIT_CRITICAL();
*err = OS_ERR_PEND_ISR;
} else {//如果没有可用消息就要进入等待状态了,直到等到有消息为止
OSTCBCur->OSTCBStat |= OS_STAT_Q; //设置任务的TCB状态标志,
以表明等待消息队列消息的任务被挂起 (8)
OSTCBCur->OSTCBDly = timeout; //装载定时器到TCB
OSEventTaskWait(pevent);
//挂起任务直到消息到来或者超时。在用户进程中,调用此函数的任务
并不知道消息没有到来之前自己被挂起,队列接收到一则消息或者超时时
,此函数就会调用调度函数恢复运行
OS_EXIT_CRITICAL();
OSSched(); (9)
OS_ENTER_CRITICAL();
if ((msg = OSTCBCur->OSTCBMsg) != (void *)0) {//如果消息确实存在(10)
OSTCBCur->OSTCBMsg = (void *)0; //清除此次消息标志
OSTCBCur->OSTCBStat = OS_STAT_RDY; //就绪
OSTCBCur->OSTCBEventPtr = (OS_EVENT *)0; //不再等待事件了 (11)
OS_EXIT_CRITICAL();
*err = OS_NO_ERR;
} else if (OSTCBCur->OSTCBStat & OS_STAT_Q) { (12)
OSEventTO(pevent); //超时了 (13)
OS_EXIT_CRITICAL();
msg = (void *)0; (14)
*err = OS_TIMEOUT;
} else {要进入这里来,首先等待任务在刚刚开始的时候没有可用消息,从而且进入进入等待消息状态,然后任务调度,期间运行其他任务的时候,能进到这里来,必然是其他任务使他就绪了,如果是超时就绪,就运行上面(12)不会进入这里,如果其他任务发送消息,则会运行OSEventTaskRdy函数,之后符合上面的(10)条件,也不会进入这里来,那么是什么情况令系统进入这段代码来呢?
msg = *pq->OSQOut++; (15)
pq->OSQEntries--;// 队列中有效消息减一
if (pq->OSQOut == pq->OSQEnd) {
pq->OSQOut = pq->OSQStart;
}
OSTCBCur->OSTCBEventPtr = (OS_EVENT *)0; (16)
OS_EXIT_CRITICAL();
*err = OS_NO_ERR;
}
}
return (msg); (17)
}
问题一:(15)前面有一个else,那么是什么情况令系统进入这段代码来呢?
问题二:(15)这一句怎么理解?我的理解是把它分解为msg = *(pq->OSQOut); pq->OSQOut++; 不知道对不? |
阿莫论坛20周年了!感谢大家的支持与爱护!!
如果天空是黑暗的,那就摸黑生存;
如果发出声音是危险的,那就保持沉默;
如果自觉无力发光,那就蜷伏于牆角。
但是,不要习惯了黑暗就为黑暗辩护;
也不要为自己的苟且而得意;
不要嘲讽那些比自己更勇敢的人。
我们可以卑微如尘土,但不可扭曲如蛆虫。
|