第十一章 CMSIS-RTOS2消息队列

描述

消息 传递是线程之间的另一种基本通信模型。在消息传递模型中,一个线程显式发送数据,而另一个线程接收数据。该操作更像是某种I / O,而不是直接访问要共享的信息。在CMSIS-RTOS中,此机制称为s 消息 队列。数据以类似FIFO的操作从一个线程传递到另一个线程。使用消息队列功能,您可以控制,发送,接收或等待消息。要传递的数据可以是整数或指针类型:

第十一章 CMSIS-RTOS2消息队列_第1张图片

CMSIS-RTOS消息队列

与内存池相比,消息队列通常效率较低,但是可以解决更广泛的问题。有时,线程没有公共的地址空间,或者共享内存的使用引发了诸如互斥之类的问题。

注意:

可以从中断服务例程中调用函数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不提供内存。

 


主要函数API解析

1.创建并初始化消息队列对象。

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();


2.获取消息队列对象的名称。

const char * osMessageQueueGetName(osMessageQueueId_t mq_id)

参数:

mq_id 为 osMessageQueueNew()获得的消息队列ID 。

返回值:

名称为以null终止的字符串。

出现错误时,函数osMessageQueueGetName返回指向由参数mq_idNULL标识的消息队列的名称字符串的指针。

注意:

不能从中断服务程序中调用此函数。


3.消息放入队列

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状态。

参数超时可以具有以下值:

  • timeout0时,该函数立即返回(即尝试语义)。
  • 超时设置为osWaitForever时,该函数将等待无限的时间,直到消息被传递为止(即,等待语义)。
  • 所有其他值在内核滴答中指定一个超时时间(即,定时等待语义)。

可能的osStatus_t返回值:

  • osOK:消息已放入队列。
  • osErrorTimeout:无法在给定的时间内将消息放入队列(等待定时的语义)。
  • osErrorResource:队列中没有足够的空间(尝试语义)。
  • osErrorParameter:参数mq_idNULL或ISR中指定的无效非零超时。

注意:

如果参数超时设置为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
        }
    }
}

4.从队列中获取消息

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状态。

参数超时可以具有以下值:

  • timeout0时,该函数立即返回(即尝试语义)。
  • 超时设置为osWaitForever时,该函数将等待无限的时间,直到检索到消息为止(即,等待语义)。
  • 所有其他值在内核滴答中指定一个超时时间(即,定时等待语义)。

可能的osStatus_t返回值:

  • osOK:已从队列中检索到消息。
  • osErrorTimeout:在给定的时间内无法从队列中检索消息(定时等待语义)。
  • osErrorResource:从队列中什么也得不到(尝试语义)。
  • osErrorParameter:参数mq_idNULL或ISR中指定的无效非零超时。

注意:

如果参数超时设置为0,则可以从中断服务例程中调用。

代码示例:

请参考osMessageQueuePut


5.获取消息队列中的最大消息数

uint32_t osMessageQueueGetCapacity(osMessageQueueId_t 	mq_id)

参数:

[in] mq_id osMessageQueueNew获得的消息队列ID 。

返回值:

最大消息数。

函数osMessageQueueGetCapacity返回错误消息中由参数mq_id指定的消息队列对象中的最大消息数或0

注意:

可以从中断服务程序中调用此函数。


6.获取内存池中的最大消息大小

uint32_t osMessageQueueGetMsgSize(osMessageQueueId_t 	mq_id)

参数:

[in] mq_id osMessageQueueNew获得的消息队列ID 。

返回值:

最大消息大小(以字节为单位)。

函数osMessageQueueGetMsgSize返回错误消息中由参数mq_id指定的消息队列对象的最大消息大小(以字节为单位)0

注意:

可以从中断服务程序中调用此函数。


7.获取消息队列中排队的消息数

uint32_t osMessageQueueGetCount	(osMessageQueueId_t 	mq_id)	

参数:

[in] mq_id osMessageQueueNew获得的消息队列ID 。

返回值:

排队的消息数。

该函数osMessageQueueGetCount返回排队的消息在由参数指定的消息队列对象的数目mq_id0中的错误的情况下。

注意:

可以从中断服务程序中调用此函数


8.获取消息队列中消息的可用插槽数

uint32_t osMessageQueueGetSpace(osMessageQueueId_t mq_id)

参数:

[in] mq_id osMessageQueueNew获得的消息队列ID 。

返回值:

消息的可用插槽数。

该函数osMessageQueueGetSpace返回数字可用时隙用于在由参数指定的消息队列对象消息mq_id0中的错误的情况下。

注意

可以从中断服务程序中调用此函数。


9.将消息队列重置为初始空状态

osStatus_t osMessageQueueReset(osMessageQueueId_t 	mq_id)	

参数:

[in] mq_id osMessageQueueNew获得的消息队列ID 。

返回值:

状态代码,指示功能的执行状态。

函数osMessageQueueReset重置由参数mq_id指定的消息队列。

可能的osStatus_t返回值:

  • osOK:消息队列已停止。
  • osErrorParameter:参数mq_idNULL或无效。
  • osErrorResource:消息队列处于无效状态。
  • osErrorISR: 不能从中断服务例程中调用osMessageQueueReset

注意

不能从中断服务程序中调用此函数。


10.删除消息队列对象

osStatus_t osMessageQueueDelete	(osMessageQueueId_t 	mq_id)

参数:

[in] mq_id osMessageQueueNew获得的消息队列ID 。

返回值:

状态代码,指示功能的执行状态。

函数osMessageQueueDelete删除由参数mq_id指定的消息队列对象。它释放为消息队列处理而获得的内部存储器。调用之后,mq_id不再有效,无法使用。可以使用osMessageQueueNew函数再次创建消息队列。

可能的osStatus_t返回值:

  • osOK:消息队列对象已被删除。
  • osErrorParameter:参数mq_idNULL或无效。
  • osErrorResource:消息队列处于无效状态。
  • osErrorISR: 不能从中断服务例程中调用osMessageQueueDelete

注意

不能从中断服务程序中调用此函数。

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

你可能感兴趣的:(CMSIS)