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                                                                  
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

七七云享

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值