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 爲消息指針 spa

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

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

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

果郵箱指針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中的消息隊列每次只能取出一條消息和每次只能放入一條消息。

相關文章
相關標籤/搜索