RTX线程通信之——消息队列

本文详细介绍了CMSIS-RTOS RTX中的消息队列,包括其作为线程间数据交换机制的特点、API函数及使用步骤。消息队列采用FIFO原则,支持整型或指针类型数据传递。通过`osMessageQueueNew`创建,`osMessageQueuePut`和`osMessageQueueGet`进行数据操作,`osMessageQueueDelete`删除队列。文中提供了一个简单的使用案例,涉及两个线程间的通信。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Message Queue

我们知道,Thread and Event FlagsSemaphore,Mutex等通常用于触发线程的执行,并没有涉及到如何在两个线程之间交换数据。RTX提供了两种机制用于线程之间的数据传输。一个是消息队列(也称为管道),一个是邮箱队列(也称为内存池)。它们之间的区别在于消息队列一次传输一个整型或指针变量,而邮箱队列一次‘’传输‘’一个数据块

当然,本文的主人公是: 消息队列

消息队列

Message passing is another basic communication model between threads. In the message passing model, one thread sends data explicitly, while another thread receives it. The operation is more like some kind of I/O rather than a direct access to information to be shared. In CMSIS-RTOS, this mechanism is called message queue. The data is passed from one thread to another in a FIFO-like operation. Using message queue functions, you can control, send, receive, or wait for messages. The data to be passed can be of integer or pointer type:

在这里插入图片描述

抓重点,消息队列具有以下特点:

  • 类似FIFO的管道。一端负责数据传入,另一端负责数据读出,先进先出。
  • 数据类型只能是整型指针类型数据。

暂且了解这么多~

RTX 消息队列 API

类型

  • osMessageQueueAttr_t : 消息队列属性结构体
  • osMessageQueueId_t : 消息队列句柄

函数

在这里插入图片描述

osMessageQueueNew

osMessageQueueId_t osMessageQueueNew(uint32_t msg_count, uint32_t msg_size, const osMessageQueueAttr_t* attr)
// 输入
* msg_count : 消息队列中最大的消息数量
* msg_size : 消息的最大字节数
* attr : 消息队列属性,默认为NULL
// 输出
* 消息队列ID or NULL

osMessageQueueGetName

const char* osMessageQueueGetName(osMessageQueueId_t mq_id)
// 输入
* mq_id : 消息队列ID
// 输出
* 消息队列名字

osMessageQueuePut

osStatus_t osMessageQueuePut(osMessageQueueId_t mq_id,const void* msg_ptr,uint8_t msg_prio,uint32_t timeout)
// 输入
* mq_id : 消息队列ID
* msg_ptr: 指向待放入消息的指针
* msg_prio: 消息优先级
* timeout : 超时设定
// 输出
* 函数执行状态码: osOK、osErrorTimeout、osErrorResource、osErrorParameter

osMessageQueueGet

osStatus_t osMessageQueueGet(osMessageQueueId_t mq_id,void* msg_ptr,uint8_t* msg_prio,uint32_t timeout)
// 输入
* mq_id : 消息队列ID
* msg_ptr: 待放入对象的地址
* msg_prio : 消息优先级
* timeout: 超时设定
// 输出
* 函数执行状态码: osOK、osErrorTimeout、osErrorResource、osErrorParameter

osMessageQueueGetCapacity

uint32_t osMessageQueueGetCapacity(osMessageQueueId_t mq_id)
// 输入
* mq_id : 消息队列ID
// 输出
*  消息队列所能容纳的最大消息个数

osMessageQueueGetMsgSize

uint32_t osMessageQueueGetMsgSize(osMessageQueueId_t mq_id)
// 输入
* mq_id : 消息队列ID
// 输出
* 消息的最大字节数

osMessageGetCount

uint32_t osMessageQueueGetCount(osMessageQueueId_t mq_id)
// 输入
* mq_id : 消息队列ID
// 输出
* 压入消息队列的个数

osMessageQueueGetSpace

uint32_t osMessageQueueGetSpace(osMessageQueueId_t mq_id)
// 输入
* mq_id : 消息队列ID
// 输出
* 消息队列剩余可压入消息个数

osMessageQueueReset

osStatus_t osMessageQueueReset(osMessageQueueId_t mq_id)
// 输入
* mq_id : 消息队列ID
// 输出
* 函数执行状态: osOK、osErrorTimeout、osErrorResource、osErrorParameter

osMessageQueueDelete

osStatus_t osMessageQueueDelete(osMessageQueueId_t mq_id)
// 输入
* mq_id :消息队列c
// 输出
* 函数执行状态: osOK、osErrorTimeout、osErrorResource、osErrorParameter

使用案例

下面简单介绍使用消息队列的一些基本步骤~

1.首先,需要分配内存资源,建立消息队列属性结构体。

消息队列的属性结构体原型为:

static const osMessageQueueAttr_t  {
     const char *name;   ///< name of the message queue
     uint32_t attr_bits; ///< attribute bits
     void *cb_mem;       ///< memory for control block
     uint32_t cb_size;   ///< size of provided memory for control block
     void *mq_mem;       ///< memory for data storage
     uint32_t mq_size;   ///< size of provided memory for data storage
};

2.创建消息队列

创建消息队列

osMessageQueueId_t osMessageQueueNew(uint32_t msg_count, uint32_t msg_size, const osMessageQueueAttr_t* attr)

3.放入数据

将数据放入消息队列

osStatus_t osMessageQueuePut(osMessageQueueId_t mq_id,const void* msg_ptr,uint8_t msg_prio,uint32_t timeout)

4.读出数据

将数据从消息队列读出

osStatus_t osMessageQueueGet(osMessageQueueId_t mq_id,void* msg_ptr,uint8_t* msg_prio,uint32_t timeout)

官方案例

#define MSGQUEUE_OBJECTS 16                     // number of Message Queue Objects
typedef struct {                                // object data type
  uint8_t Buf[32];
  uint8_t Idx;
} MSGQUEUE_OBJ_t;
 
osMessageQueueId_t mid_MsgQueue;                // message queue id

mid_MsgQueue = osMessageQueueNew(MSGQUEUE_OBJECTS, sizeof(MSGQUEUE_OBJ_t), NULL);

void Thread_MsgQueue1 (void *argument) {
  MSGQUEUE_OBJ_t msg;
  while (1) {
    ; // Insert thread code here...
    msg.Buf[0] = 0x55U;                                         // do some work...
    msg.Idx    = 0U;
    osMessageQueuePut(mid_MsgQueue, &msg, 0U, 0U);
    osThreadYield();                                            // suspend thread
  }
}
 
void Thread_MsgQueue2 (void *argument) {
  MSGQUEUE_OBJ_t msg;
  osStatus_t status;
  while (1) {
    ; // Insert thread code here...
    status = osMessageQueueGet(mid_MsgQueue, &msg, NULL, 0U);   // wait for message
    if (status == osOK) {
      ; // process data
    }
  }
}

小结

本文主要简要介绍了RTX的消息队列,重点内容如下:

  • 消息队列的概念
  • 消息队列的函数接口
  • 消息队列的使用步骤

本文只是对消息队列的一个粗浅介绍,具体运用到项目中,还是多参考官方资料,好啦,就这么多~

【推荐阅读:☞RTX线程通信之——内存池

参考资料

☞官方入口

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Rob月初

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

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

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

打赏作者

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

抵扣说明:

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

余额充值