uCOS-II邮箱和消息队列

 

1、 uCOS-II邮箱和消息队列
          邮箱和消息队列是uCOS-II中任务间的通讯机制,它可以使一个任务或者中断服务子程序向另一个任务发送以指针方式定义的变量。因具体的应用有所不同,每个指针指向的数据结构变量也有所不同。两者都基于事件控制块OS_EVENT。与邮箱相比,消息队列在OS_EVENT基础上加了个循环队列,可以存放多个消息,而邮箱只能存放一个消息。消息队列可以看成是多个邮箱的组合。因此,两者除了创建时有些差别外,其他的操作都很相似。

1.1、 uCOS-II邮箱
           在事件控制块OS_EVENT中有一个域OSEventPtr,这个域是一个用来存放消息的指针。由于邮箱是由操作系统维护的,因此使用指针可以避免消息的复制,提供操作系统效率。uCOS-II中对邮箱有五种操作:OSMboxCreate(),OSMboxPend() , OSMboxPost(),OSMboxAccept()和OSMboxQuery()。其中OSMboxAccept()是无等待的接受一个消息。在创建一个邮箱时,一般初始化为空邮箱,但是也可以让邮箱一开始就包含一条消息。如果该邮箱用于通知某个事件的发生,那么就应该初始化为空邮箱;如果用于共享某些资源,那么就应该让其包含一条消息。

1.2、 uCOS-II消息队列
           与邮箱不同,当事件控制块OS_EVENT被用于消息队列时,域OSEventPtr指向一个循环队列的队列控制块(OS_Q)而不是指向一个消息。循环队列由队列控制块(OS_Q)进行维护,该数据结构详细信息如下:struct os_q { struct os_q *OSQPtr; void **OSQStart; //指向消息队列的指针数组的起始地址的指针 void **OSQEnd; //指向消息队列结束单元的下一个地址的指针 void **OSQIn; //指向消息队列中插入下一条消息的位置的指针 void **OSQOut; //指向消息队列中下一个取出消息位置的指针 INT16U OSQSize; //消息队列中总的单元数 INT16U OSQEntries; //消息队列中当前的消息数量 } OS_Q;

uCOS-II 提供了7 个对消息队列进行操作的函数:OSQCreate(),OSQPend(),OSQPost(),OSQPostFront(),OSQAccept(),OSQFlush()和OSQQuery()函数。在这里只对OSQCreate()、OSQFlush()和OSQPostFront()进行说明。

OS_EVENT *OSQCreate (void **start, INT16U size)
          创建一个消息队列,第一个参数是一个二重指针,该指针指向容纳各个消息的指针的指针数组的起始地址。在创建消息队列之前,首先需要定义一个指针数组,该数组的元素个数必须和消息队列最大消息数相等。然后把这个数组的起始地址传给OSQCreate。这里需要注意的是该数组必须是void类型。第二个参数是消息队列最大消息数,即指针数组的大小。

INT8U OSQFlush (OS_EVENT *pevent)
          清空消息队列中所有的消息,重新开始使用。函数参数是指向需要清空消息队列的指针。

INT8U OSQPostFront (OS_EVENT *pevent, void *msg)
          OSQPostFront()函数和OSQPost()基本上是一样的,只是在插入新的消息到消息队列中时,使用OSQOut 作为指向下一个插入消息的单元的指针,而不是OSQIn。由于OSQPend()取出的消息是OSQPostFront()刚刚插入的,因此OSQPostFront()函数实现了一个LIFO队列。

2、 实例
         该实例使用两个任务模拟嵌入式系统中对模拟量的监控以及出错处理功能。第一个任务读取并检查模拟输入量的值(如气压、温度、电压等),如果其超过了一定的阈值,就向第二个任务发送一个消息。该消息中含有时间信息、出错的通道号和错误代码等信息。第二个任务接收消息并负责错误处理(显示错误信息、改正错误),任何任务、中断服务子程序都可以向该任务发送出错消息。

实例源码:
点击此处下载TEST.C (文件大小:2K)

你可能感兴趣的:(嵌入式)