从零开始学习UCOSII操作系统10--消息邮箱

从零开始学习UCOSII操作系统10--消息邮箱

1、什么是消息邮箱?

UCOSII中的另一种的通信机制,可以使得一个任务或者中断服务子程序向另一个任务发送一个指针型的变量,通常指针指向一个包含了消息的特定数据结构。

提供了6种操作邮箱的接口函数:
OSMboxCreate():创建邮箱也就是初始化邮箱的函数
OSMboxPend():请求邮箱的函数,也就是没有邮箱发送过来的话,就会一直处于等待的状态。
OSMboxPost():接收邮箱的函数,接收到邮箱的内容,就可以从邮箱的等待列表中移除,并把任务进入就绪的列表当中。
OSMboxPostOpt():

OSMboxAccept():无等待的邮箱接口

OSMboxQuery():查询邮箱的接口

2、怎么使用邮箱?

任务、中断服务子程序和邮箱之间的关系,沙漏表示OSMboxPend()所定义的超时时限。邮箱包含的内容是一个指向一条消息的指针。指针所指向的内容是可以指定的。
PS:一个邮箱只能包含一个这样的指针(邮箱为满的时候)或者一个指向NULL的指针(邮箱为空的时候,也就是不指向所有的内容)

注意的几点?
任务和中断服务子程序都可以调用函数OSMboxPost()或者OSMboxPostopt()
然而仅仅只有任务可以调用OSMboxDel(),OSMboxPend()以及OSMboxQuery()函数。

应用程序可以使用任意多个邮箱,其最大的数目就是由OS_CFG.h文件中的配置常数OS_MAX_EVENTS设定。

3、使用邮箱的API函数

(1)创建邮箱的函数OSMboxPend():使用邮箱之前,必须先建立邮箱,该操作可以通过调用OSMboxCreate()函数来完成,并且定义指针的初始值,一般情况下面,这个初始值是NULL,但是也可以初始化邮箱在最开始的时候就包含一条信息。

OS_EVENT *OSMboxCreate(void * msg)
{
    OS_EVENT * pevent;   //局部建立一个事件控制块列表

    pevent = OSEventFreeList;  //插入到事件控制块链表中
    if(OSEventFreeList != (OS_EVENT *)0)
    {
        OSEventFreeList = (OS_EVENT *)OSEventFreeList->OSEventPtr;

    }
    if(pevent != (OS_EVENT *)0)
    {
        pevent->OSEventType = OS_EVENT_TYPE_MBOX;
        pevent->OSEventCnt = 0;  //邮箱不用使用这个变量
        pevent->OSEventPtr = msg;
        OS_EventWaitListInit(pevent);
    }
    return (pevent);
}

(2)等待邮箱中的消息OSMboxPend()

PS:需要注意的是:如果邮箱中有消息的话,那么从邮箱中取出该消息,返回给调用函数,并将NULL指针存入邮箱中,同时OSMboxPend()函数将无措的代码返回给它的调用函数,这个返回结果表示,已经由另一个任务或者中断服务子程序将消息发送到邮箱中,这也是运行OSMboxPend()函数最快的情况。

如果邮箱为空的话,那么调用OSMboxPend函数的任务要进入睡眠状态,等待另一个任务,通过发送邮箱发送消息。允许定义一个最长等待时间作为他的参数,这样可以避免该任务无限期的等待邮箱消息。

void * OSMboxPend(OS_Event *pevent, INT16U timeout,INT8U *err)
{
    void *msg;
    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;
    OSEventTaskWait(pevent);
    OS_EXIT_CRITICAL();
    msg = OSTCBCur->OSTCBMsg;

    if(msg != (void *)0)
    {
        OSTCBCur->OSTCBMsg = (void *)0;
        OSTCBCur->OSTCBStat = OS_STAT_RDY;
        OSTCBCur->OSTCBEventPtr = (OS_EVENT *)0;
        *err = OS_NO_ERR;
        return msg;
    }
}

(3)向邮箱中发送一则消息OSMboxPost()

INT8U OSMboxPost(OS_EVENT * pevent, void *msg)
{
    //检查一下事件控制块中是否有任务等待
    if(pevent->OSEventGrp != 0x00)
    {
        //如果有的话就直接加入到事件队列中
        OS_EventTaskRdy(pevent, msg, OS_STAT_MBOX);

        //任务的切换
        OS_Sched();
        return (OS_NOE_ERR);
    }

    if(pevent->OSEventPtr != (void *)0)
    {
        //返回一个邮箱已满的信息,就是说不要重复覆盖邮箱的内容
        return OS_MBOX_FULL;
    }

    //前面的都没有了,所以传递一个邮箱进入
    pevent->OSEventPtr = msg;
    OS_EXIT_CRITICAL();
    return OS_NO_ERR;

}

4、怎么使用邮箱来进行延时

邮箱的等待超时的功能可以用来模仿OSTimeDly()函数的延时,如果在指定的时间段TIMEOUT内没有消息到来,Task1函数将继续执行,实质上,这与OSTimeDly(TimeOUT)内没有消息到来。

如果Task2在指定的时间结束之前,向该邮箱发送一个dummy消息,那么Task1就会提前开始继续执行,这与调用函数OSTimeDlyResume()功能是一样的。

注意:这里忽略了对返回消息的检查,因为此时并不需要从另一个任务或者中断服务子程序得到消息。


你可能感兴趣的:(UCOSII,从零开始的学习UCOSII)