uC/OS-II源碼解析(os_mbox.c)

/*
** ver   : 2.52
** file  : os_mbox.c
** brief : 消息郵箱相關函數 C 文件
*/

#ifndef  OS_MASTER_FILE
#include "includes.h"         /* 包含頭文件 */
#endif

#if OS_MBOX_EN > 0
/*
**************************************************************************************
*                                     無等待的請求消息郵箱
*
* brief     : 該函數用於無等待的請求消息郵箱
*
* pevent    : 指向事件控制塊的指針
*
* returns   : != (void *)0  郵箱內消息有效,返回後清空郵箱
*             == (void *)0  未得到消息
*
* note      : 該函數的另一個作用是清空消息郵箱
*****************************************************************************************
*/

#if OS_MBOX_ACCEPT_EN > 0
void  *OSMboxAccept (OS_EVENT *pevent)
{
#if OS_CRITICAL_METHOD == 3                    
    OS_CPU_SR  cpu_sr;
#endif    
    void      *msg;


#if OS_ARG_CHK_EN > 0
    if (pevent == (OS_EVENT *)0) {                        /* 無效的事件控制塊指 */
        return ((void *)0);
    }
    if (pevent->OSEventType != OS_EVENT_TYPE_MBOX) {      /* 錯誤的事件類型      */
        return ((void *)0);
    }
#endif
    OS_ENTER_CRITICAL();
    msg                = pevent->OSEventPtr;              /* 獲取消息     */
    pevent->OSEventPtr = (void *)0;                       /* 清空消息     */
    OS_EXIT_CRITICAL();
    return (msg);                                    
}
#endif
/*$PAGE*/
/*
*******************************************************************************************
*                                        創建消息郵箱
*
* brief   : 該函數用於創建消息郵箱
*
* msg     : 指向消息的指針
*
* Returns : != (OS_EVENT *)0  成功
*           == (OS_EVENT *)0  失敗
******************************************************************************************
*/

OS_EVENT  *OSMboxCreate (void *msg)
{
#if OS_CRITICAL_METHOD == 3                     
    OS_CPU_SR  cpu_sr;
#endif    
    OS_EVENT  *pevent;


    if (OSIntNesting > 0) {                      /* 不允許中斷內創建郵箱 */
        return ((OS_EVENT *)0);                
    }
    OS_ENTER_CRITICAL();
    pevent = OSEventFreeList;                    /* 獲取事件控制塊       */
    if (OSEventFreeList != (OS_EVENT *)0) {      /* 調整事件控制塊鏈表  */
        OSEventFreeList = (OS_EVENT *)OSEventFreeList->OSEventPtr;
    }
    OS_EXIT_CRITICAL();
    if (pevent != (OS_EVENT *)0) {
        pevent->OSEventType = OS_EVENT_TYPE_MBOX;
        pevent->OSEventCnt  = 0;
        pevent->OSEventPtr  = msg;               /* 消息 */
        OS_EventWaitListInit(pevent);
    }
    return (pevent);                           
}
/*$PAGE*/
/*
*****************************************************************************************
*                                         刪除消息郵箱
*
* brief     : 該函數用於刪除消息郵箱
*
* pevent    : 指向事件控制塊的指針
*
* opt       : 刪除選項:
*               opt == OS_DEL_NO_PEND   無任務等待時刪除
*               opt == OS_DEL_ALWAYS    無條件刪除                                           
*
* err       : 指向錯誤代碼的指針:
*               OS_NO_ERR               成功
*               OS_ERR_DEL_ISR          不允許中斷內刪除消息郵箱
*               OS_ERR_INVALID_OPT      無效的刪除選項
*               OS_ERR_TASK_WAITING     有任務正在等待消息郵箱
*               OS_ERR_EVENT_TYPE       錯誤的事件類型
*               OS_ERR_PEVENT_NULL      無效的事件控制塊指針
*
* Returns    : pevent        刪除失敗 
*              (OS_EVENT *)0 刪除成功
*
****************************************************************************************
*/

#if OS_MBOX_DEL_EN > 0
OS_EVENT  *OSMboxDel (OS_EVENT *pevent, INT8U opt, INT8U *err)
{
#if OS_CRITICAL_METHOD == 3                               
    OS_CPU_SR  cpu_sr;
#endif    
    BOOLEAN    tasks_waiting;


    if (OSIntNesting > 0) {                                /* 不能在中斷中刪除         */
        *err = OS_ERR_DEL_ISR;                             
        return (pevent);
    }
#if OS_ARG_CHK_EN > 0
    if (pevent == (OS_EVENT *)0) {                         /* 無效的事件控制塊指針     */
        *err = OS_ERR_PEVENT_NULL;
        return (pevent);
    }
    if (pevent->OSEventType != OS_EVENT_TYPE_MBOX) {       /* 錯誤的事件類型           */
        *err = OS_ERR_EVENT_TYPE;
        return (pevent);
    }
#endif
    OS_ENTER_CRITICAL();
    if (pevent->OSEventGrp != 0x00) {                 
        tasks_waiting = TRUE;                              /* 有任務等待               */
    } else {
        tasks_waiting = FALSE;                             /* 無任務等待               */
    }
    switch (opt) {
        case OS_DEL_NO_PEND:                               /* 無任務等待時刪除         */
             if (tasks_waiting == FALSE) {
                 pevent->OSEventType = OS_EVENT_TYPE_UNUSED;
                 pevent->OSEventPtr  = OSEventFreeList;    /* 返還事件控制塊           */
                 OSEventFreeList     = pevent;             
                 OS_EXIT_CRITICAL();
                 *err = OS_NO_ERR;
                 return ((OS_EVENT *)0);                   
             } else {
                 OS_EXIT_CRITICAL();
                 *err = OS_ERR_TASK_WAITING;
                 return (pevent);
             }

        case OS_DEL_ALWAYS:                                /* 無條件刪除               */
             while (pevent->OSEventGrp != 0x00) {          /* 就緒所有等待任務         */
                 OS_EventTaskRdy(pevent, (void *)0, OS_STAT_MBOX);
             }
             pevent->OSEventType = OS_EVENT_TYPE_UNUSED;
             pevent->OSEventPtr  = OSEventFreeList;        /* 返還事件控制塊          */
             OSEventFreeList     = pevent;                 
             OS_EXIT_CRITICAL();
             if (tasks_waiting == TRUE) {                  
                 OS_Sched();                               /* 任務調度                */
             }
             *err = OS_NO_ERR;
             return ((OS_EVENT *)0);                       

        default:
             OS_EXIT_CRITICAL();
             *err = OS_ERR_INVALID_OPT;
             return (pevent);
    }
}
#endif

/*$PAGE*/
/*
************************************************************************************
*                                      請求消息郵箱
*
* brief   : 該函數用來請求消息郵箱
*
* pevent  : 指向事件控制塊的指針
*
* timeout : 等待超時.
*
* err     : 指向錯誤代碼的指針,可能取值:
*
*             OS_NO_ERR           成功
*             OS_TIMEOUT          超時
*             OS_ERR_EVENT_TYPE   錯誤的事件類型
*             OS_ERR_PEND_ISR     不允許在中斷中請求
*             OS_ERR_PEVENT_NULL  無效的事件控制塊指針
*
**************************************************************************************
*/

void  *OSMboxPend (OS_EVENT *pevent, INT16U timeout, INT8U *err)
{
#if OS_CRITICAL_METHOD == 3                   
    OS_CPU_SR  cpu_sr;
#endif    
    void      *msg;


    if (OSIntNesting > 0) {                           /* 中斷內不允許請求消息    */
        *err = OS_ERR_PEND_ISR;                                 
        return ((void *)0);
    }
#if OS_ARG_CHK_EN > 0
    if (pevent == (OS_EVENT *)0) {                    /* 無效的事件控制塊指針    */
        *err = OS_ERR_PEVENT_NULL;
        return ((void *)0);
    }
    if (pevent->OSEventType != OS_EVENT_TYPE_MBOX) {  /* 錯誤的事件類型          */
        *err = OS_ERR_EVENT_TYPE;
        return ((void *)0);
    }
#endif
    OS_ENTER_CRITICAL();
    msg = pevent->OSEventPtr;
    if (msg != (void *)0) {                           /* 郵箱有消息             */
        pevent->OSEventPtr = (void *)0;               /* 消息返回,清空郵箱     */
        OS_EXIT_CRITICAL();
        *err = OS_NO_ERR;
        return (msg);                                
    }
    OSTCBCur->OSTCBStat |= OS_STAT_MBOX;              /* 等待消息       */
    OSTCBCur->OSTCBDly   = timeout;                   /* 記錄超時       */
    OS_EventTaskWait(pevent);                         /* 是任務等待     */
    OS_EXIT_CRITICAL();
    OS_Sched();                                       /* 任務調度       */
    OS_ENTER_CRITICAL();
    msg = OSTCBCur->OSTCBMsg;
    if (msg != (void *)0) {                           /* 獲得消息       */
        OSTCBCur->OSTCBMsg      = (void *)0;          /* 清空郵箱       */
        OSTCBCur->OSTCBStat     = OS_STAT_RDY;
        OSTCBCur->OSTCBEventPtr = (OS_EVENT *)0;      /* 取消TCB ECB關聯 */
        OS_EXIT_CRITICAL();
        *err                    = OS_NO_ERR;
        return (msg);                                           
    }
    OS_EventTO(pevent);                               /* 超時使任務就緒  */
    OS_EXIT_CRITICAL();
    *err = OS_TIMEOUT;                              
    return ((void *)0);                                 
}
/*$PAGE*/
/*
*************************************************************************************
*                                       向郵箱發送一則消息
*
* brief    : 該函數用於向消息郵箱發送一則消息
*
* pevent   : 指向事件控制塊的指針
*
* msg      : 消息
*
* Returns    : OS_NO_ERR            成功
*              OS_MBOX_FULL         郵箱中已經存在消息
*              OS_ERR_EVENT_TYPE    錯誤的事件類型
*              OS_ERR_PEVENT_NULL   無效的事件控制塊指針
*              OS_ERR_POST_NULL_PTR 消息爲空
**************************************************************************************
*/

#if OS_MBOX_POST_EN > 0
INT8U  OSMboxPost (OS_EVENT *pevent, void *msg)
{
#if OS_CRITICAL_METHOD == 3                    
    OS_CPU_SR  cpu_sr;
#endif    


#if OS_ARG_CHK_EN > 0
    if (pevent == (OS_EVENT *)0) {                    /* 無效的事件控制塊指針 */
        return (OS_ERR_PEVENT_NULL);
    }
    if (msg == (void *)0) {                           /* 發送的消息不能爲空  */
        return (OS_ERR_POST_NULL_PTR);
    }
    if (pevent->OSEventType != OS_EVENT_TYPE_MBOX) {  /* 錯誤的事件類型       */
        return (OS_ERR_EVENT_TYPE);
    }
#endif
    OS_ENTER_CRITICAL();
    if (pevent->OSEventGrp != 0x00) {                 /* 是否有任務等待消息        */
        OS_EventTaskRdy(pevent, msg, OS_STAT_MBOX);   /* 使最高優先級等待任務就緒  */
        OS_EXIT_CRITICAL();
        OS_Sched();                                   /* 任務調度  */
        return (OS_NO_ERR);
    }
    if (pevent->OSEventPtr != (void *)0) {            /* 郵箱中不應該已經存在消息  */
        OS_EXIT_CRITICAL();
        return (OS_MBOX_FULL);
    }
    pevent->OSEventPtr = msg;                         /* 將消息置郵箱內             */
    OS_EXIT_CRITICAL();
    return (OS_NO_ERR);
}
#endif

/*$PAGE*/
/*
**************************************************************************************
*                                       向郵箱發送一則消息
*
* brief    : 該函數用於向郵箱發送一則消息
*
* pevent   : 指向事件控制塊的指針
*
* msg      : 發送到郵箱的消息指針  
*
* opt      : 發送選項
*              OS_POST_OPT_NONE         消息發送給最高優先級就緒任務
*              OS_POST_OPT_BROADCAST    消息發送給所有等待任務
*
* Returns    : OS_NO_ERR            成功
*              OS_MBOX_FULL         郵箱滿
*              OS_ERR_EVENT_TYPE    錯誤的事件類型.
*              OS_ERR_PEVENT_NULL   無效的事件控制塊指針
*              OS_ERR_POST_NULL_PTR 發送的消息不能爲空
*
*****************************************************************************************
*/

#if OS_MBOX_POST_OPT_EN > 0
INT8U  OSMboxPostOpt (OS_EVENT *pevent, void *msg, INT8U opt)
{
#if OS_CRITICAL_METHOD == 3                      
    OS_CPU_SR  cpu_sr;
#endif    


#if OS_ARG_CHK_EN > 0
    if (pevent == (OS_EVENT *)0) {                    /* 無效的事件控制塊指針 */
        return (OS_ERR_PEVENT_NULL);
    }
    if (msg == (void *)0) {                           /* 發送的消息不能爲空   */
        return (OS_ERR_POST_NULL_PTR);
    }
    if (pevent->OSEventType != OS_EVENT_TYPE_MBOX) {  /* 錯誤的事件類型       */
        return (OS_ERR_EVENT_TYPE);
    }
#endif
    OS_ENTER_CRITICAL();
    if (pevent->OSEventGrp != 0x00) {                 /* 是否有任務等待消息   */
        if ((opt & OS_POST_OPT_BROADCAST) != 0x00) {  /* 是否廣播消息         */
            while (pevent->OSEventGrp != 0x00) {      /* 就緒所有等待任務     */           
                OS_EventTaskRdy(pevent, msg, OS_STAT_MBOX);    
            }
        } else {
            OS_EventTaskRdy(pevent, msg, OS_STAT_MBOX);/* 就緒最高優先級等待任務 */
        }
        OS_EXIT_CRITICAL();
        OS_Sched();                                    /* 任務調度     */
        return (OS_NO_ERR);
    }
    if (pevent->OSEventPtr != (void *)0) {            /* 確保郵箱爲空  */
        OS_EXIT_CRITICAL();
        return (OS_MBOX_FULL);
    }
    pevent->OSEventPtr = msg;                         /* 消息置於郵箱內 */
    OS_EXIT_CRITICAL();
    return (OS_NO_ERR);
}
#endif

/*$PAGE*/
/*
*****************************************************************************************
*                                        查詢郵箱
*
* brief     : 該函數用於查詢消息郵箱
*
* pevent    : 指向事件控制塊的指針
*
* pdata     : 保存郵箱信息的數據結構指針
*
* Returns   : OS_NO_ERR           成功
*             OS_ERR_EVENT_TYPE   錯誤的事件類型
*             OS_ERR_PEVENT_NULL  無效的事件控制塊指針
*****************************************************************************************
*/

#if OS_MBOX_QUERY_EN > 0
INT8U  OSMboxQuery (OS_EVENT *pevent, OS_MBOX_DATA *pdata)
{
#if OS_CRITICAL_METHOD == 3                     
    OS_CPU_SR  cpu_sr;
#endif    
    INT8U     *psrc;
    INT8U     *pdest;


#if OS_ARG_CHK_EN > 0
    if (pevent == (OS_EVENT *)0) {                         /* 無效的事件控制塊指針   */
        return (OS_ERR_PEVENT_NULL);
    }
    if (pevent->OSEventType != OS_EVENT_TYPE_MBOX) {       /* 錯誤的時間類型         */
        return (OS_ERR_EVENT_TYPE);
    }
#endif
    OS_ENTER_CRITICAL();
    pdata->OSEventGrp = pevent->OSEventGrp;                /* 複製等待任務鏈表       */
    psrc              = &pevent->OSEventTbl[0];
    pdest             = &pdata->OSEventTbl[0];

#if OS_EVENT_TBL_SIZE > 0
    *pdest++          = *psrc++;
#endif

#if OS_EVENT_TBL_SIZE > 1
    *pdest++          = *psrc++;
#endif

#if OS_EVENT_TBL_SIZE > 2
    *pdest++          = *psrc++;
#endif

#if OS_EVENT_TBL_SIZE > 3
    *pdest++          = *psrc++;
#endif

#if OS_EVENT_TBL_SIZE > 4
    *pdest++          = *psrc++;
#endif

#if OS_EVENT_TBL_SIZE > 5
    *pdest++          = *psrc++;
#endif

#if OS_EVENT_TBL_SIZE > 6
    *pdest++          = *psrc++;
#endif

#if OS_EVENT_TBL_SIZE > 7
    *pdest            = *psrc;
#endif
    pdata->OSMsg = pevent->OSEventPtr;                     /* 複製郵箱內消息 */
    OS_EXIT_CRITICAL();
    return (OS_NO_ERR);
}
#endif                                                                        
#endif                                                                  
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章