ucosii事件控制塊------消息郵箱與消息隊列


UCOSII 使用叫做事件控制塊(ECB)的數據結構來描述諸如信號量、郵箱(消息郵箱)和消息隊列這些事件

#define  OS_EVENT_EN           (((OS_Q_EN > 0u) && (OS_MAX_QS > 0u)) || (OS_MBOX_EN > 0u) || (OS_SEM_EN > 0u) || (OS_MUTEX_EN > 0u))

 事件控制塊類型定義:

typedef struct os_event {
    INT8U    OSEventType;                    /* Type of event control block (see OS_EVENT_TYPE_xxxx)    */
    void    *OSEventPtr;                     /* Pointer to message or queue structure                   */
    INT16U   OSEventCnt;                     /* Semaphore Count (not used if other EVENT type)          */
    OS_PRIO  OSEventGrp;                     /* Group corresponding to tasks waiting for event to occur */
    OS_PRIO  OSEventTbl[OS_EVENT_TBL_SIZE];  /* List of tasks waiting for event to occur                */

#if OS_EVENT_NAME_EN > 0u
    INT8U   *OSEventName;
#endif
} OS_EVENT;

消息郵箱:

向郵箱發送消息函數:INT8U  OSMboxPost (OS_EVENT  *pevent, void   *pmsg)其中 pevent 為消息郵箱的指針, msg 為消息指針

  該函數先檢查消息郵箱結構體成員指針變量OSEventPtr是否為0,若為0,則說明消息郵箱為空,為其賦值pevent->OSEventPtr = pmsg;否則返回對應錯誤代碼。

請求郵箱函數:void *OSMboxPend (OS_EVENT *pevent, INT16U timeout,INT8U *err) 其中 pevent 為請求郵箱指針, timeout 為等待時限, err 為錯誤信息。

  這個函數的主要作用就是查看郵箱指針 OSEventPtr 是否為 NULL,如果不是 NULL 就把郵箱中的消息指針返回給調用函數的任務,然后清空郵箱pevent->OSEventPtr = (void *)0;同時用 OS_NO_ERR 通過函數的參數 err 通知任務獲取消息成功。

果郵箱指針OSEventPtr NULL,則使任務進入等待狀態,並引發一次任務調度
創建消息郵箱:OS_EVENT  *OSMboxCreate (void *pmsg),
例如:

msg_key=OSMboxCreate((void*)0);	//創建郵箱並初始化為空

 

如果指針不為空,建立的消息郵箱將含有消息

 消息隊列:

與郵箱相比,消息隊列在OS_EVENT結構基礎之上添加了一循環隊列,可以同時容納多個消息,而郵箱只能容納一個。因此,可以將消息隊列看作同時接收多條消息的郵箱。

隊列控制塊類型定義:

 

typedef struct os_q {                   /* QUEUE CONTROL BLOCK                                         */
    struct os_q   *OSQPtr;              /* Link to next queue control block in list of free blocks     */
    void         **OSQStart;            /* Pointer to start of queue data                              */
    void         **OSQEnd;              /* Pointer to end   of queue data                              */
    void         **OSQIn;               /* Pointer to where next message will be inserted  in   the Q  */
    void         **OSQOut;              /* Pointer to where next message will be extracted from the Q  */
    INT16U         OSQSize;             /* Size of queue (maximum number of entries)                   */
    INT16U         OSQEntries;          /* Current number of entries in the queue                      */
} OS_Q;

 

 OSQSize:消息指針數組的大小

 OSQEntries:消息指針數組中當前存放的消息指針數量(對應消息數量)

 

 

 

1) 創建消息隊列函數
創建一個消息隊列首先需要定義一指針數組,然后把各個消息數據緩沖區的首地址存
入這個數組中,然后再調用函數 OSQCreate 來創建消息隊列。創建消息隊列函數 OSQCreate
的原型為: OS_EVENT *OSQCreate(void**start,INT16U size)。其中, start 為存放消息緩沖
區指針數組的地址, size 為該數組大小。該函數的返回值為消息隊列指針。
2) 請求消息隊列函數

請求消息隊列的目的是為了從消息隊列中獲取消息。任務請求消息隊列需要調用函數
OSQPend,該函數原型為: void*OSQPend(OS_EVENT*pevent,INT16U timeout,INT8U *err)
其中, pevent 為所請求的消息隊列的指針, timeout 為任務等待時限, err 為錯誤信息。

下面是函數的部分關鍵代碼:

pq = (OS_Q *)pevent->OSEventPtr;             /* Point at queue control block                       */
    if (pq->OSQEntries > 0u) {                   /* See if any messages in the queue                   */
        pmsg = *pq->OSQOut++;                    /* Yes, extract oldest message from the queue         */
        pq->OSQEntries--;                        /* Update the number of entries in the queue          */
        if (pq->OSQOut == pq->OSQEnd) {          /* Wrap OUT pointer if we are at the end of the queue */
            pq->OSQOut = pq->OSQStart;
        }
        OS_EXIT_CRITICAL();
        *perr = OS_ERR_NONE;
        return (pmsg);                           /* Return message received                            */
    }

3) 向消息隊列發送消息函數

任務可以通過調用函數 OSQPost OSQPostFront 兩個函數來向消息隊列發送消息。函數 OSQPost FIFO( 先進先出)的方式組織消息隊列,函數 OSQPostFront LIFO(后
進先出)的方式組織消息隊列。這兩個函數的原型分別為: INT8U OSQPost(OS_EVENT*pevent,void *msg)INT8U OSQPost(OS_EVENT*pevent,void*msg)
其中, pevent 為消息隊列的指針, msg 為待發消息的指針。

 pq = (OS_Q *)pevent->OSEventPtr;                   /* Point to queue control block                 */
    if (pq->OSQEntries >= pq->OSQSize) {               /* Make sure queue is not full                  */
        OS_EXIT_CRITICAL();
        return (OS_ERR_Q_FULL);
    }
    *pq->OSQIn++ = pmsg;                               /* Insert message into queue                    */
    pq->OSQEntries++;                                  /* Update the nbr of entries in the queue       */
    if (pq->OSQIn == pq->OSQEnd) {                     /* Wrap IN ptr if we are at end of queue        */
        pq->OSQIn = pq->OSQStart;
    }

  

 注:消息隊列用作消息緩沖區是明智的(適合於進程通信),可要是用它來作為接收批量數據的數據緩沖區就不行了,因為ucos中的消息隊列每次只能取出一條消息和每次只能放入一條消息。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM