⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 os_mbox.c

📁 ucos_ii在S3C2410上的移植
💻 C
📖 第 1 页 / 共 2 页
字号:
/*
*********************************************************************************************************
*                                                uC/OS-II 实时内核
*                                                 消息邮箱管理
*
*                            (c) 版权 1992-2002, 所有版权归Jean J. Labrosse, Weston, FL 所有
*                                         
*
* 文件名称 :          OS_MBOX.C
* 程序作者 :          Jean J. Labrosse 
*********************************************************************************************************
*/

#ifndef  OS_MASTER_FILE
#include "includes.h"
#endif

#if OS_MBOX_EN > 0
/*
*********************************************************************************************************
*                                     从邮箱中获取消息
*
* 函数描述: 该函数检查邮箱看消息是否有效。不象 OSMboxPend(),如果消息无效,函数OSMboxAccept()不会挂起
*           调用的函数
*
* 输入参数  : pevent        指向ECB的指针
*
* 返回值    : != (void *)0   如果有效是邮箱中的消息。  OSMboxAccept()再次被调用则邮箱清零,邮箱为空。
*             == (void *)0  邮箱为空,
*                            'pevent' 是空指针,
*                             没有传递适当的事件类型指针
*********************************************************************************************************
*/

#if OS_MBOX_ACCEPT_EN > 0
 void  *OSMboxAccept (OS_EVENT *pevent)
 {
#if OS_CRITICAL_METHOD == 3                      /* 为CPU状态寄存器分配存储变量           */
    OS_CPU_SR  cpu_sr;
#endif    
    void      *msg;


#if OS_ARG_CHK_EN > 0
    if (pevent == (OS_EVENT *)0) 
    {                                                   /* 无效的 'pevent'                         */
        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*/
/*
*********************************************************************************************************
*                                        创建一个消息邮箱
*
* 函数描述: 如果空余ECB有效,该函数创建一个消息邮箱。
*
* 输入参数  : msg           指向存放在邮箱中消息的指针。  如果设定该值为空指针,那么邮箱将为空。
*
* 返回值    : != (OS_EVENT *)0  指向带有创建消息邮箱的ECB。
*             == (OS_EVENT *)0  无有效的ECB。
*********************************************************************************************************
*/

OS_EVENT  *OSMboxCreate (void *msg)
{
#if OS_CRITICAL_METHOD == 3                      /* 为CPU状态寄存器分配存储变量           */
    OS_CPU_SR  cpu_sr;
#endif    
    OS_EVENT  *pevent;


    if (OSIntNesting > 0) 
    {                                              /* 如果调用来自 ISR ...                         */
        return ((OS_EVENT *)0);                  /* ... 从ISR中不能创建                       */
    }
    OS_ENTER_CRITICAL();
    pevent = OSEventFreeList;                                        /* 得到空余的ECB。                */
    if (OSEventFreeList != (OS_EVENT *)0) 
    {                                                                 /* 看是否空余ECB池为空            */
        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;               /* 在ECB 中存储消息指针             */
        OS_EventWaitListInit(pevent);
    }
    return (pevent);                             /* 返回ECB 的指针              */
}
/*$PAGE*/
/*
*********************************************************************************************************
*                                         删除一个邮箱
*
* 函数描述: 该函数删除一个邮箱和就绪等待消息邮箱的所有任务。
*
* 输入参数  : pevent        指向带有期望邮箱的ECB的指针。
*
*              opt           决定删除的选项:
*                            opt == OS_DEL_NO_PEND   只在无任务等待时,才删除邮箱
*                            opt == OS_DEL_ALWAYS    即使有任务等待,也要删除邮箱。
*                                                    该种情况下,所有等待任务将就绪。
*
*              err           指向下列值之一的出错代码的指针:
*                            OS_NO_ERR               调用成功,邮箱被删除
*                            OS_ERR_DEL_ISR          从 ISR中删除邮箱
*                            OS_ERR_INVALID_OPT      指定选项无效
*                            OS_ERR_TASK_WAITING     一个或更多的任务正等待邮箱
*                            OS_ERR_EVENT_TYPE       没有传递一个指向邮箱类型的指针
*                            OS_ERR_PEVENT_NULL      'pevent' 是一个空指针
*
* 返回值     : pevent        upon error
*              (OS_EVENT *)0 邮箱成功删除
*
* Note(s)    : 1) 该函数使用时要小心。期望消息邮箱的任务一定要检查OSMboxPend()的返回值。
*              2) OSMboxAccept()的调用函数将不会知道消息邮箱已被删除。
*              3) 这种调用潜在的关闭中断很长时间。中断关闭时间直接正比于等待消息邮箱的任务的数量。
*              4) 由于所有等待邮箱的任务将被就绪。所以,必须小心处理邮箱用在互斥上,因为资源不再受邮箱保护。
*************************************************************************************************************
*/

#if OS_MBOX_DEL_EN > 0
OS_EVENT  *OSMboxDel (OS_EVENT *pevent, INT8U opt, INT8U *err)
{
#if OS_CRITICAL_METHOD == 3                                /* 为CPU状态寄存器分配存储变量 */
    OS_CPU_SR  cpu_sr;
#endif    
    BOOLEAN    tasks_waiting;


    if (OSIntNesting > 0) 
    {                                                       /* 如果调用来自 ISR ...               */
        *err = OS_ERR_DEL_ISR;                             /* ... 从ISR中不能删除             */
        return (pevent);
    }
#if OS_ARG_CHK_EN > 0
    if (pevent == (OS_EVENT *)0) 
    {                                                      /* 无效的 'pevent'                        */
        *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;    /* 返回ECB到空余链表中  */
                 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;        /* 返回ECB到空余链表中  */
             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*/
/*
*********************************************************************************************************
*                                      等待邮箱中的消息
*
* 函数描述:   该函数等待发送到邮箱中的消息
*
* 输入参数  : pevent         指向带有期望邮箱的ECB的指针
*
*             timeout        选择延时时间。如果非0,则任务将在指定的延时时间内等待到达邮箱中的消息。如果为0,
*                            则任务将一直等待邮箱中消息的到来。
*             err            指向出错代码的指针。其值为:
*
*                            OS_NO_ERR           调用成功,任务收到消息。
*                            OS_TIMEOUT          在指定的延时时间内,没有收到消息
*                            OS_ERR_EVENT_TYPE   无效的事件类型
*                            OS_ERR_PEND_ISR     从ISR中调用该函数,将导致挂起
*                            OS_ERR_PEVENT_NULL  'pevent' 是一个空指针
*
* 返回值    : != (void *)0   指向接收到消息的指针
*             == (void *)0   没有消息接收,
*                            'pevent' 是一个空指针,
*                            没有传递给ECB一个恰当的指针.
*********************************************************************************************************
*/

void  *OSMboxPend (OS_EVENT *pevent, INT16U timeout, INT8U *err)
{
#if OS_CRITICAL_METHOD == 3                                /* 为CPU状态寄存器分配存储变量           */
    OS_CPU_SR  cpu_sr;
#endif    
    void      *msg;


    if (OSIntNesting > 0) 
    {                                                    /* 如果调用来自 ISR ...                    */
        *err = OS_ERR_PEND_ISR;                           /* ... 从ISR中不能挂起                    */
        return ((void *)0);
    }
#if OS_ARG_CHK_EN > 0
    if (pevent == (OS_EVENT *)0) 
    {                                                    /* 无效的 'pevent'                           */
        *err = OS_ERR_PEVENT_NULL;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -