消息 传递是线程之间的另一种基本通信模型。在消息传递模型中,一个线程显式发送数据,而另一个线程接收数据。该操作更像是某种I / O,而不是直接访问要共享的信息。在CMSIS-RTOS中,此机制称为s 消息 队列。数据以类似FIFO的操作从一个线程传递到另一个线程。使用消息队列功能,您可以控制,发送,接收或等待消息。要传递的数据可以是整数或指针类型:
与内存池相比,消息队列通常效率较低,但是可以解决更广泛的问题。有时,线程没有公共的地址空间,或者共享内存的使用引发了诸如互斥之类的问题。
注意:
可以从中断服务例程中调用函数osMessageQueuePut,osMessageQueueGet,osMessageQueueGetCapacity,osMessageQueueGetMsgSize,osMessageQueueGetCount,osMessageQueueGetSpace。
有关RTX5配置选项, 请参阅消息队列配置。
/// /消息队列结构体.
typedef struct {
const char *name; ///< 消息队列的名称
uint32_t attr_bits; ///< 属性位
void *cb_mem; ///< 控制块内存
uint32_t cb_size; ///< 为控制块提供的内存大小
void *mq_mem; ///< 用于数据存储的内存
uint32_t mq_size; ///< 为数据存储提供的内存大小
} osMessageQueueAttr_t;
资料栏位 | ||
---|---|---|
const char * | 名称 | 消息队列的名称 指向具有消息队列对象的可读名称(在调试过程中显示)的常量字符串。 默认值:NULL未指定名称。 |
uint32_t | attr_bits | 属性位 保留以备将来使用(必须将其设置为“ 0”,以便将来兼容)。 |
void * | cb_mem | 控制块存储器 指向消息队列控制块对象的内存的指针。 默认值:NULL,以将自动动态分配用于消息队列控制块。 |
uint32_t | cb_size | 控制块提供的内存大小 cb_mem传递的内存块的大小(以字节为单位)。对于RTX,最小值由osRtxMessageQueueCbSize定义(允许更高的值)。 默认值:0,因为默认值是cb_mem不提供内存。
|
void * | mq_mem | 数据存储存储器 指向消息队列数据的内存的指针。 默认值:NULL,以对内存池数据使用自动动态分配。 |
uint32_t | mq_size | 提供的用于数据存储的内存大小 通过mq_mem传递的内存块的大小(以字节为单位)。最小内存块大小为msg_count * msg_size(osMessageQueueNew函数的参数)。所述msg_size被向上舍入到双偶数,确保存储块的32位对齐。 默认值:0,因为默认值是mq_mem不提供内存。
|
osMessageQueueId_t osMessageQueueNew(
uint32_t msg_count,
uint32_t msg_size,
const osMessageQueueAttr_t * attr
)
参数:
[in] msg_count 队列中的最大消息数。 [in] msg_size 最大消息大小(以字节为单位)。 [in] attr 消息队列属性;NULL:默认值。
返回值:
消息队列ID以供其他功能参考,如果出错,则为NULL。
函数osMessageQueueNew创建并初始化消息队列对象。如果发生错误,该函数将返回消息队列对象标识符或NULL。
在内核使用osKernelInitialize初始化之后,可以调用该函数。在使用osKernelStart启动RTOS内核之前,可以创建消息队列对象。
消息队列数据所需的内存总量至少为msg_count * msg_size。所述msg_size被向上舍入到双偶数,确保存储块的32位对齐。
从消息队列分配的内存块具有使用参数定义的固定大小msg_size。
注意:
不能从中断服务程序中调用此函数。
代码示例:
请参考 osMessageQueuePut();
const char * osMessageQueueGetName(osMessageQueueId_t mq_id)
参数:
mq_id 为 osMessageQueueNew()获得的消息队列ID 。
返回值:
名称为以null终止的字符串。
出现错误时,函数osMessageQueueGetName返回指向由参数mq_id或NULL标识的消息队列的名称字符串的指针。
注意:
不能从中断服务程序中调用此函数。
osStatus_t osMessageQueuePut(
osMessageQueueId_t mq_id,
const void * msg_ptr,
uint8_t msg_prio,
uint32_t timeout
)
参数:
[in] mq_id osMessageQueueNew获得的消息队列ID 。 [in] msg_ptr 指向要放入队列的消息的缓冲区的指针。 [in] msg_prio 消息优先级。 [in] timeout 超时值;如果没有超时,则为 0。
返回值:
状态代码,指示功能的执行状态。
阻塞函数osMessageQueuePut将msg_ptr指向的消息放入参数mq_id指定的消息队列中。参数msg_prio用于根据插入时消息的优先级(数字越高表示优先级越高)对消息进行排序。
参数timeout指定系统等待将消息放入队列的时间。在系统等待时,正在调用此函数的线程进入BLOCKED状态。
参数超时可以具有以下值:
可能的osStatus_t返回值:
注意:
如果参数超时设置为0,则可以从中断服务例程中调用。
代码示例:
#include "cmsis_os2.h" // CMSIS RTOS header file
/*----------------------------------------------------------------------------
* Message Queue creation & usage
*---------------------------------------------------------------------------*/
#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
osThreadId_t tid_Thread_MsgQueue1; // thread id 1
osThreadId_t tid_Thread_MsgQueue2; // thread id 2
void Thread_MsgQueue1(void *argument); // thread function 1
void Thread_MsgQueue2(void *argument); // thread function 2
int Init_MsgQueue(void)
{
mid_MsgQueue = osMessageQueueNew(MSGQUEUE_OBJECTS, sizeof(MSGQUEUE_OBJ_t), NULL);
if (mid_MsgQueue == NULL)
{
; // Message Queue object not created, handle failure
}
tid_Thread_MsgQueue1 = osThreadNew(Thread_MsgQueue1, NULL, NULL);
if (tid_Thread_MsgQueue1 == NULL)
{
return (-1);
}
tid_Thread_MsgQueue2 = osThreadNew(Thread_MsgQueue2, NULL, NULL);
if (tid_Thread_MsgQueue2 == NULL)
{
return (-1);
}
return (0);
}
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
}
}
}
osStatus_t osMessageQueueGet(
osMessageQueueId_t mq_id,
void *msg_ptr,
uint8_t *msg_prio,
uint32_t timeout
)
参数:
[in] mq_id osMessageQueueNew获得的消息队列ID 。 [out] msg_ptr 指向从队列中获取消息的缓冲区的指针。 [out] msg_prio 指向消息优先级或NULL的缓冲区的指针。 [in] timeout 超时值;如果没有超时,则为 0。
返回值:
状态代码,指示功能的执行状态。
函数osMessageQueueGet从参数mq_id指定的消息队列中检索一条消息,并将其保存到参数msg_ptr指向的缓冲区中。如果不是令牌{NULL},则消息优先级存储到参数msg_prio。
参数timeout指定系统等待从队列中检索消息的时间。在系统等待时,正在调用此函数的线程进入BLOCKED状态。
参数超时可以具有以下值:
可能的osStatus_t返回值:
注意:
如果参数超时设置为0,则可以从中断服务例程中调用。
代码示例:
请参考osMessageQueuePut
uint32_t osMessageQueueGetCapacity(osMessageQueueId_t mq_id)
参数:
[in] mq_id osMessageQueueNew获得的消息队列ID 。
返回值:
最大消息数。
函数osMessageQueueGetCapacity返回错误消息中由参数mq_id指定的消息队列对象中的最大消息数或0。
注意:
可以从中断服务程序中调用此函数。
uint32_t osMessageQueueGetMsgSize(osMessageQueueId_t mq_id)
参数:
[in] mq_id osMessageQueueNew获得的消息队列ID 。
返回值:
最大消息大小(以字节为单位)。
函数osMessageQueueGetMsgSize返回错误消息中由参数mq_id指定的消息队列对象的最大消息大小(以字节为单位)或0。
注意:
可以从中断服务程序中调用此函数。
uint32_t osMessageQueueGetCount (osMessageQueueId_t mq_id)
参数:
[in] | mq_id | osMessageQueueNew获得的消息队列ID 。 |
返回值:
排队的消息数。
该函数osMessageQueueGetCount返回排队的消息在由参数指定的消息队列对象的数目mq_id或0中的错误的情况下。
注意:
可以从中断服务程序中调用此函数
uint32_t osMessageQueueGetSpace(osMessageQueueId_t mq_id)
参数:
[in] mq_id osMessageQueueNew获得的消息队列ID 。
返回值:
消息的可用插槽数。
该函数osMessageQueueGetSpace返回数字可用时隙用于在由参数指定的消息队列对象消息mq_id或0中的错误的情况下。
注意
可以从中断服务程序中调用此函数。
osStatus_t osMessageQueueReset(osMessageQueueId_t mq_id)
参数:
[in] mq_id osMessageQueueNew获得的消息队列ID 。
返回值:
状态代码,指示功能的执行状态。
函数osMessageQueueReset重置由参数mq_id指定的消息队列。
可能的osStatus_t返回值:
- osOK:消息队列已停止。
- osErrorParameter:参数mq_id为NULL或无效。
- osErrorResource:消息队列处于无效状态。
- osErrorISR: 不能从中断服务例程中调用osMessageQueueReset。
注意
不能从中断服务程序中调用此函数。
osStatus_t osMessageQueueDelete (osMessageQueueId_t mq_id)
参数:
[in] mq_id osMessageQueueNew获得的消息队列ID 。
返回值:
状态代码,指示功能的执行状态。
函数osMessageQueueDelete删除由参数mq_id指定的消息队列对象。它释放为消息队列处理而获得的内部存储器。调用之后,mq_id不再有效,无法使用。可以使用osMessageQueueNew函数再次创建消息队列。
可能的osStatus_t返回值:
- osOK:消息队列对象已被删除。
- osErrorParameter:参数mq_id为NULL或无效。
- osErrorResource:消息队列处于无效状态。
- osErrorISR: 不能从中断服务例程中调用osMessageQueueDelete。
注意
不能从中断服务程序中调用此函数。