目录
UCOSIII(也称为μC/OS-III)中的消息队列是一种常用于任务间通信的数据结构,它允许任务之间异步地交换信息。以下是对UCOSIII消息队列的详细解析:
1. 基本概念
消息队列是由一系列消息按照一定的队列规则(如先进先出FIFO或后进先出LIFO)组成的数据结构。每个消息包含一个指向数据的指针、数据的大小以及时间戳等信息。通过消息队列,任务间可以传递不固定长度的消息,实现了任务间的异步通信。
2. 消息池
在UCOSIII中,消息池(Message Pool)是管理消息存储的核心结构。在系统初始化时,会创建一个大的数组并将其元素串成单向链表,形成消息池。这些元素(即消息)可以被系统中的所有消息队列共享和重用。消息池的大小由用户定义,并在os_cfg_app.h
头文件中通过宏 OS_CFG_MSG_POOL_SIZE
指定。
3. 消息队列的运作机制
- 创建消息队列:使用
OSQCreate()
函数创建消息队列,用户需要指定队列的名字、最大消息数等参数。 - 发送消息:使用
OSQPost()
函数向消息队列中发送消息。如果队列未满,UCOSIII会从消息池中取出一个消息,并将其挂载到队列的尾部(FIFO)或头部(LIFO),然后更新消息中的指针以指向要发送的数据。如果队列已满,则返回错误代码。 - 接收消息:使用
OSQPend()
函数从消息队列中获取消息。如果队列为空,接收消息的任务将被阻塞,直到队列中有新消息或者超时。用户可以指定阻塞的时间timeout
。 - 删除消息队列:使用
OSQDel()
函数删除消息队列,并释放与之相关的资源。
4. 阻塞机制
当任务尝试从空的消息队列中获取消息时,任务会被阻塞。UCOSIII提供了三种阻塞状态:
- 不等待:如果队列中没有消息,任务不会进入阻塞态,而是继续执行其他操作。
- 等待一段时间:任务会在指定的等待时间内尝试接收消息,如果在这段时间内接收到消息或超时,任务将退出阻塞态。
- 永久等待:任务会一直等待,直到接收到消息。
如果有多个任务阻塞在同一个消息队列上,这些任务将按照任务优先级进行排序,优先级高的任务将优先获得队列的访问权。
5. 消息队列的应用场景
消息队列在嵌入式系统中有着广泛的应用,特别是在需要任务间通信的场景中。通过使用消息队列,可以有效地避免资源竞争和同步问题,提高系统的稳定性和可靠性。
6. 注意事项
- 在使用消息队列时,需要注意消息的内存管理。由于消息是通过指针传递的,因此必须确保在消息被处理之前,其指向的数据仍然是有效的。
- 消息队列的创建和删除应该谨慎处理,避免在运行时删除内核对象。
- 消息队列阻塞的任务会进入阻塞态,不影响任务调度,等待接收到消息后会从阻塞态转变成就绪态。
7.代码实现
7.1 创建消息队列
#define DATAMSG_Q_NUM 4 //发送数据的消息队列的数量
OS_Q KEY_Msg; //定义一个消息队列,用于按键消息传递,模拟消息邮箱
OS_Q DATA_Msg; //定义一个消息队列,用于发送数据
//创建消息队列DATA_Msg
OSQCreate ((OS_Q* )&DATA_Msg,
(CPU_CHAR* )"DATA Msg",
(OS_MSG_QTY )DATAMSG_Q_NUM,
(OS_ERR* )&err);
创建一个名为DATA Msg的消息队列,长度为4。
7.2 请求消息
OS_MSG_SIZE size;
OS_ERR err;
//请求消息
p=OSQPend((OS_Q* )&DATA_Msg,
(OS_TICK )0,
(OS_OPT )OS_OPT_PEND_BLOCKING,
(OS_MSG_SIZE* )&size,
(CPU_TS* )0,
(OS_ERR* )&err);
请求消息队列,OS_TICK设置成0,表示一直等待,OS_OPT设置成OS_OPT_PEND_BLOCKING表示没有消息就阻塞任务,直到收到消息,size表示接收队列消息的长度。
OS_TICK和OS_OPT配合使用,如果设置的OS_OPT为OS_OPT_PEND_NON_BLOCKING表示不阻塞,那么等待时间设置的无效。
7.3 发送消息
u8 *pbuf;
static u8 msg_num;
OS_ERR err;
pbuf = mymalloc(SRAMIN,10); //申请10个字
sprintf((char*)pbuf,"TEST %d",msg_num);
//发送消息
OSQPost((OS_Q* )&DATA_Msg,
(void* )pbuf,
(OS_MSG_SIZE)10,
(OS_OPT )OS_OPT_POST_FIFO,
(OS_ERR* )&err);
发送队列消息,pbuf为要发送的内容,(OS_MSG_SIZE)10代表内容的大小是10,OS_OPT_POST_FIFO表示模式是先进先出模式。