原创 UCOS-II中消息队列学习笔记(4)

2011-12-7 22:46 2484 16 16 分类: MCU/ 嵌入式

 

6.任务等待消息队列的消息

void  *OSQPend (OS_EVENT *pevent,INT16U timeout, INT8U *err) reentrant

{

    OS_ENTER_CRITICAL();

    pq = (OS_Q*)pevent->OSEventPtr;            /*   队列指针=当前事件指针                    */

    if (pq->OSQEntries != 0){                   /*     当前消息队列中消息数 > 0,有消息       */

        msg =*pq->OSQOut++;                    /*     OSQOut将对应的地址的消息复制到msg    */

        pq->OSQEntries--;                        /*    当前队列消息数减1       */

        if (pq->OSQOut ==pq->OSQEnd) {          /* 当取出指针= =最高消息队列单元时 */

            pq->OSQOut =pq->OSQStart;                           //取出指针跳转到起始单元

        }

        OS_EXIT_CRITICAL();

        *err = OS_NO_ERR;

        return (msg);                            /* Return messagereceived                            */

    }                                             //以下无消息情况

    OSTCBCur->OSTCBStat |=OS_STAT_Q;            /* 将事件进入睡眠状态,由消息队列唤醒 */

    OSTCBCur->OSTCBDly   = timeout;              /*      等待时间置入任务控制中                   */

   OS_EventTaskWait(pevent);                    /*   使任务进入等待消息队列状态     */

    OS_EXIT_CRITICAL();

    OS_Sched();                                  /*  任务调度函数,调用一个就绪的高优先级任务运行    */

    OS_ENTER_CRITICAL();

    msg = OSTCBCur->OSTCBMsg;                    //接收消息=指向当前任务的消息指针

    if (msg != (void *)0) {                      /* Did we get amessage?                              */

       OSTCBCur->OSTCBMsg      = (void*)0;     /*   传递给消息的指针为空   */

       OSTCBCur->OSTCBStat     =OS_STAT_RDY;//表示任务处于就绪状态

       OSTCBCur->OSTCBEventPtr = (OS_EVENT *)0; /* No longer waiting forevent                        */

        OS_EXIT_CRITICAL();

        *err                    = OS_NO_ERR;//成功等待消息队列

        return (msg);                            /* Return messagereceived                            */

}

//以下为超时的情况

    OS_EventTO(pevent);                          /* Timed out                                          */

    OS_EXIT_CRITICAL();

    *err = OS_TIMEOUT;                           /* Indicate atimeout occured                        */

    return ((void *)0);                          /* No messagereceived                               */

}

如果调用OSQPend()函数时队列中已经存在需要的消息,那么该消息被返回给OSQPend()函数的调用者,队列中清除该消息.如果调用OSQPend()函数时队列中没有需要的消息,OSQPend()函数挂起当前任务直到得到需要的消息或超出定义的超时时间.

 

7.任务无等待的从消息队列中获取消息

void  *OSQAccept (OS_EVENT*pevent) reentrant

{

..............................................

    OS_ENTER_CRITICAL();

    pq = (OS_Q*)pevent->OSEventPtr;             /*Point at queue control block   队列指针=当前事件指针                    */

    if (pq->OSQEntries != 0){                   /* See if anymessages in the queue                  */

        msg = *pq->OSQOut++;                     /* Yes, extract oldestmessage from the queue         */

        pq->OSQEntries--;                        /* Update the number ofentries in the queue          */

        if (pq->OSQOut ==pq->OSQEnd) {          /* Wrap OUTpointer if we are at the end of the queue 当输出指针=结束指针*/

            pq->OSQOut =pq->OSQStart;                                             //输出指针跳转到起始指针

        }

    } else {

        msg = (void *)0;                         /* Queue is empty                                     */

    }

    OS_EXIT_CRITICAL();

    return (msg);                                /* Returnmessage received (or NULL)                 */

}

 
 

文章评论0条评论)

登录后参与讨论
我要评论
0
16
关闭 站长推荐上一条 /2 下一条