threadx学习笔记(8)消息队列

文章参考:

ThreadX学习(9)——消息队列_threadx消息队列-CSDN博客

消息队列是ThreadX中线程间(以及线程和中断间)通信的主要手段。 

为什么需要消息队列,而不直接使用全局数组?

在裸机编程时,使用全局数组的确比较方便,但是在加上 RTOS 后就是另一种情况了。

相比消息队列,使用全局数组主要有如下四个问题:

  • 使用消息队列可以有效管理线程,而全局数组无法做到,线程的超时机制需要用户自己去实现。
  • 使用全局数组要防止多线程的访问冲突,而使用消息队列则处理好了这个问题,用户无需担心。
  • 使用消息队列可以有效地解决中断服务程序与线程之间消息传递的问题。
  • FIFO 机制更有利于数据的处理。
1.tx_queue_create
TX_QUEUE queue_ptr;//先定义再创建

UINT  tx_queue_create(	TX_QUEUE *queue_ptr, 
						CHAR *name_ptr, 
						UINT message_size, 
						VOID *queue_start, 
						ULONG queue_size)

创建消息队列:

第 1 个参数 queue_ptr 是消息队列控制块指针。
第 2 个参数 name_ptr 是消息队列名称字符串。
第 3 个参数 message_size 是每个消息的大小。
第 4 个参数 queue_start 是消息队列缓冲区的起始地址。起始地址必须与ULONG数据类型的大小对齐。
第 5 个参数 queue_size 是消息队列的总大小。
返回值:
TX_SUCCESS:(0x00)成功创建消息队列。
TX_QUEUE_ERROR:(0x09)无效的消息队列指针。要么指针是NULL,要么队列已经创建。
TX_PTR_ERROR: (0x03)无效的消息队列起始地址。
TX_SIZE_ERROR: (0x05)消息队列大小无效。
TX_CALLER_ERROR:(0x13)无效的服务调用者。

消息队列创建函数需要在tx_application_define里定义。根据串口打印结果可以看到,已经成功创建消息队列。

VOID tx_application_define(void  *first_unused_memory)
{
	char buffer[256];
	
	UINT dd=tx_queue_create(&queue_ptr,"queue 0",16,first_unused_memory,128);
	huartsend(dd);
	
	UINT aa= tx_semaphore_create(&semaphore_ptr,"semaphore 0",1);
	snprintf(buffer,sizeof(buffer),"%u\n",aa);
	HAL_UART_Transmit(&huart1,(uint8_t *)buffer,strlen(buffer),HAL_MAX_DELAY);
	UINT bb = tx_event_flags_create(&group_ptr,"group 0");
	huartsend(bb);
	
	UINT cc= tx_event_flags_set_notify(&group_ptr, event_flags_notify_callback);
	//调用事件标志组设置通知函数
	huartsend(cc);
  tx_thread_create(&thread_0, "thread 0", thread_0_entry, 0,  
            thread_0_stack, DEMO_STACK_SIZE, 
            1, 1, 10, TX_AUTO_START);
	tx_thread_create(&thread_1, "Thread 1", thread_1_entry, 0,
                     thread_1_stack, DEMO_STACK_SIZE,
                     2, 2, TX_NO_TIME_SLICE, TX_AUTO_START);
}

 2.tx_queue_send 
UINT  tx_queue_send(TX_QUEUE *queue_ptr, 
					VOID *source_ptr, 
					ULONG wait_option)

发送消息:

第 1 个参数 queue_ptr 是消息队列控制块指针。
第 2 个参数 source_ptr 是需发送消息的指针。
第 3 个参数 wait_option 是等待选项:
TX_NO_WAIT (0x00000000),表示不管消息队列是否满,立即返回。如果在定时器组,初始
化或中断里面调用,必须要设置成这个参数。
TX_WAIT_FOREVER (0xFFFFFFFF),表示永久等待,直到消息队列有空间可用。
等待时间,范围 0x00000001 到 0xFFFFFFFE,单位为系统时钟节拍。
返回值:
TX_SUCCESS: (0x00)消息发送成功。
TX_DELETED: (0x01)线程挂起时消息队列被删除。
TX_QUEUE_FULL: (0x0B)在指定的等待时间内队列已满。
TX_WAIT_ABORTED: (0x1A)挂起被另一个线程、计时器或中断中止。
TX_QUEUE_ERROR:(0x09)无效的消息队列指针。
TX_PTR_ERROR:(0x03)消息的源指针无效。
TX_WAIT_ERROR: (0x04)在非线程调用时指定了TX_NO_WAIT以外的等待选项。

在线程0中线发送消息,再打印消息。

void    thread_0_entry(ULONG thread_input)
	//线程,串口发送数据
{
						CHAR *name;
						ULONG enqueued;
						ULONG available_storage;
						TX_THREAD *first_suspended;
						ULONG suspended_count;
						TX_QUEUE *next_queue;
	
	char message[] = "hello threadx!";
	UINT aa=tx_queue_send(&queue_ptr,&message,TX_NO_WAIT);
	huartsend(aa);
	UINT bb=tx_queue_info_get(&queue_ptr, 
						&name,
						&enqueued, 
						&available_storage,
						&first_suspended, 
						&suspended_count,
						&next_queue);
	char buffer[256];
	snprintf(buffer,sizeof(buffer),"queue name:%s\nenqueued:%lu\navailable_storage:%lu\nsuspended_count:%lu\n",name,enqueued,available_storage,suspended_count);\
	HAL_UART_Transmit(&huart1,(uint8_t *)buffer,strlen(buffer),HAL_MAX_DELAY);
	
}

3. tx_queue_receive
UINT tx_queue_receive(TX_QUEUE *queue_ptr,
                      VOID *destination_ptr, 
                      ULONG wait_option);

接收消息:

第 1 个参数 queue_ptr 是消息队列的指针。
第 2 个参数 destination_ptr 是接收消息存储的位置。
第 3 个参数 wait_option 是等待选项:
TX_NO_WAIT:(0 x00000000)
TX_WAIT_FOREVER: (0xFFFFFFFF)
等待时间:(0x00000001 ~ 0xFFFFFFFE)
返回值
TX_SUCCESS: (0x00)成功接收消息。
TX_DELETED: (0x01)线程挂起时消息队列被删除。
TX_QUEUE_EMPTY: (0x0A)等待时间内队列为空。
TX_WAIT_ABORTED: (0x1A)挂起被另一个线程、计时器或ISR中止。
TX_QUEUE_ERROR:(0x09)无效的消息队列指针。
TX_PTR_ERROR:(0x03)无效的接收消息存储指针。
TX_WAIT_ERROR: (0x04)在非线程调用时指定了TX_NO_WAIT以外的等待选项。

在之前的示例代码后面写消息队列接收函数,然后打印消息队列信息。

void    thread_0_entry(ULONG thread_input)
	//线程,串口发送数据
{
						CHAR *name;
						ULONG enqueued;
						ULONG available_storage;
						TX_THREAD *first_suspended;
						ULONG suspended_count;
						TX_QUEUE *next_queue;
	
	char message[] = "hello threadx!";
	UINT aa=tx_queue_send(&queue_ptr,&message,TX_NO_WAIT);
	huartsend(aa);
	UINT bb=tx_queue_info_get(&queue_ptr, 
						&name,
						&enqueued, 
						&available_storage,
						&first_suspended, 
						&suspended_count,
						&next_queue);
	huartsend(bb);
	char buffer[256];
	snprintf(buffer,sizeof(buffer),"queue name:%s\nenqueued:%lu\navailable_storage:%lu\nsuspended_count:%lu\n",name,enqueued,available_storage,suspended_count);\
	HAL_UART_Transmit(&huart1,(uint8_t *)buffer,strlen(buffer),HAL_MAX_DELAY);
	
	ULONG destination_ptr;
	
	UINT cc=tx_queue_receive(&queue_ptr,
                      &destination_ptr, 
                      TX_WAIT_FOREVER);
	huartsend(cc);
	
	UINT dd=tx_queue_info_get(&queue_ptr, 
						&name,
						&enqueued, 
						&available_storage,
						&first_suspended, 
						&suspended_count,
						&next_queue);
	huartsend(dd);
	snprintf(buffer,sizeof(buffer),"queue name:%s\nenqueued:%lu\navailable_storage:%lu\nsuspended_count:%lu\n",name,enqueued,available_storage,suspended_count);\
	HAL_UART_Transmit(&huart1,(uint8_t *)buffer,strlen(buffer),HAL_MAX_DELAY);
}

4.tx_queue_info_get
UINT tx_queue_info_get( TX_QUEUE *queue_ptr, 
						CHAR **name,
						ULONG *enqueued, 
						ULONG *available_storage
						TX_THREAD **first_suspended, 
						ULONG *suspended_count,
						TX_QUEUE **next_queue);
 

获取消息队列信息:

第 1 个参数 queue_ptr 是消息队列控制块指针。
第 2 个参数 name 是消息队列名字符串,获取后存储的指针。
第 3 个参数 enqueued 是消息队列中现有消息数量,所存储的指针。
第 4 个参数 available_storage 是消息队列中剩余空间,所存储的指针。
第 5 个参数 first_suspended 是消息队列挂起列表的第一个线程,所存储的指针。
第 6 个参数 suspended_count 是消息队列挂起列表的线程数,所存储的指针。
第 7 个参数 next_queue 是下一个消息队列,所存储的指针。
返回值:
TX_SUCCESS: (0x00)成功获取队列信息。
TX_QUEUE_ERROR:(0x09)无效的消息队列指针。
参数输入TX_NULL(0x00)表示不需要该参数。

相关示例代码在发送消息和接收消息函数中已经涉及。

5.tx_queue_delete
UINT tx_queue_delete(TX_QUEUE *queue_ptr);

删除消息队列:

第 1 个参数 queue_ptr 是消息队列控制块指针。
返回值:
TX_SUCCESS: (0x00)成功删除消息队列。
TX_QUEUE_ERROR:(0x09)无效的消息队列指针。
TX_CALLER_ERROR:(0x13)无效的服务调用者。
所有挂起等待此队列的线程都将恢复,并给出TX_DELETED返回状态。

在线程0中删除消息,可以看到删除成功。

void    thread_0_entry(ULONG thread_input)
	//线程,串口发送数据
{
						CHAR *name;
						ULONG enqueued;
						ULONG available_storage;
						TX_THREAD *first_suspended;
						ULONG suspended_count;
						TX_QUEUE *next_queue;
	
	char message[] = "hello threadx!";
	UINT aa=tx_queue_send(&queue_ptr,&message,TX_NO_WAIT);
	huartsend(aa);
	UINT bb=tx_queue_info_get(&queue_ptr, 
						&name,
						&enqueued, 
						&available_storage,
						&first_suspended, 
						&suspended_count,
						&next_queue);
	huartsend(bb);
	char buffer[256];
	snprintf(buffer,sizeof(buffer),"queue name:%s\nenqueued:%lu\navailable_storage:%lu\nsuspended_count:%lu\n",name,enqueued,available_storage,suspended_count);\
	HAL_UART_Transmit(&huart1,(uint8_t *)buffer,strlen(buffer),HAL_MAX_DELAY);
	
	CHAR buffer1[32];
	
	UINT cc=tx_queue_receive(&queue_ptr,
                      buffer1, 
                      TX_WAIT_FOREVER);
	huartsend(cc);
	HAL_UART_Transmit(&huart1,(uint8_t *)buffer1,strlen(buffer1),HAL_MAX_DELAY);
	UINT dd=tx_queue_info_get(&queue_ptr, 
						&name,
						&enqueued, 
						&available_storage,
						&first_suspended, 
						&suspended_count,
						&next_queue);
	huartsend(dd);
	snprintf(buffer,sizeof(buffer),"queue name:%s\nenqueued:%lu\navailable_storage:%lu\nsuspended_count:%lu\n",name,enqueued,available_storage,suspended_count);\
	HAL_UART_Transmit(&huart1,(uint8_t *)buffer,strlen(buffer),HAL_MAX_DELAY);
	UINT ee= tx_queue_delete(&queue_ptr);
	huartsend(ee);
	
}

6.tx_queue_flush
UINT tx_queue_flush(TX_QUEUE *queue_ptr);
 

清空消息队列:

第 1 个参数 queue_ptr 是消息队列控制块指针。
返回值:
TX_SUCCESS: (0x00)成功刷新消息队列。
TX_QUEUE_ERROR:(0x09)无效的消息队列指针。
如果队列已满,则丢弃所有挂起线程的消息,然后恢复每个挂起的线程,返回状态表明消息发送成功。如果队列为空,则此服务不执行任何操作。

示例代码先清空消息队列,再打印消息队列信息。

void    thread_0_entry(ULONG thread_input)
	//线程,串口发送数据
{
						CHAR *name;
						ULONG enqueued;
						ULONG available_storage;
						TX_THREAD *first_suspended;
						ULONG suspended_count;
						TX_QUEUE *next_queue;
	
	char message[] = "hello threadx!";
	UINT aa=tx_queue_send(&queue_ptr,&message,TX_NO_WAIT);
	//发送
	huartsend(aa);
	UINT bb=tx_queue_info_get(&queue_ptr, 
						&name,
						&enqueued, 
						&available_storage,
						&first_suspended, 
						&suspended_count,
						&next_queue);
	huartsend(bb);
	char buffer[256];
	snprintf(buffer,sizeof(buffer),"queue name:%s\nenqueued:%lu\navailable_storage:%lu\nsuspended_count:%lu\n",name,enqueued,available_storage,suspended_count);\
	HAL_UART_Transmit(&huart1,(uint8_t *)buffer,strlen(buffer),HAL_MAX_DELAY);
	
	UINT cc= tx_queue_flush(&queue_ptr);
	huartsend(cc);
	
	UINT dd=tx_queue_info_get(&queue_ptr, 
						&name,
						&enqueued, 
						&available_storage,
						&first_suspended, 
						&suspended_count,
						&next_queue);
	huartsend(dd);
	snprintf(buffer,sizeof(buffer),"queue name:%s\nenqueued:%lu\navailable_storage:%lu\nsuspended_count:%lu\n",name,enqueued,available_storage,suspended_count);\
	HAL_UART_Transmit(&huart1,(uint8_t *)buffer,strlen(buffer),HAL_MAX_DELAY);
	
	
	
}

7.tx_queue_front_send
UINT tx_queue_front_send(TX_QUEUE *queue_ptr,
                         VOID *source_ptr, 
                         ULONG wait_option);

 发送紧急消息插队到队首:

第 1 个参数 queue_ptr 是消息队列控制块指针。
第 2 个参数 source_ptr 是需发送消息的指针。
第 3 个参数 wait_option 是等待选项。
返回值:
TX_SUCCESS: (0x00)消息发送成功。
TX_DELETED: (0x01)线程挂起时消息队列被删除。
TX_QUEUE_FULL: (0x0B)服务无法发送消息,因为在指定的等待时间内队列已满。
TX_WAIT_ABORTED: (0x1A)挂起被另一个线程、计时器或ISR中止。
TX_QUEUE_ERROR:(0x09)无效的消息队列指针。
TX_PTR_ERROR:(0x03)消息的源指针无效。
TX_WAIT_ERROR: (0x04)在非线程调用时指定了TX_NO_WAIT以外的等待选项。

先发送一个消息,再发送一个插队消息,可以看到,接收到的是插队消息,因此,发送紧急消息插队到队首函数调用成功。

void    thread_0_entry(ULONG thread_input)
	//线程,串口发送数据
{
						CHAR *name;
						ULONG enqueued;
						ULONG available_storage;
						TX_THREAD *first_suspended;
						ULONG suspended_count;
						TX_QUEUE *next_queue;
	
	char message1[] = "hello threadx!1";
	UINT aa=tx_queue_send(&queue_ptr,&message1,TX_NO_WAIT);
	char message3[] = "dddddd\n";
	//UINT ac=tx_queue_send(&queue_ptr,&message3,TX_NO_WAIT);
	UINT fontmsg=tx_queue_front_send(&queue_ptr,&message3,TX_NO_WAIT);
	
	//发送
	huartsend(aa);
	UINT bb=tx_queue_info_get(&queue_ptr, 
						&name,
						&enqueued, 
						&available_storage,
						&first_suspended, 
						&suspended_count,
						&next_queue);
	huartsend(bb);
	char buffer[256];
	snprintf(buffer,sizeof(buffer),"queue name:%s\nenqueued:%lu\navailable_storage:%lu\nsuspended_count:%lu\n",name,enqueued,available_storage,suspended_count);\
	HAL_UART_Transmit(&huart1,(uint8_t *)buffer,strlen(buffer),HAL_MAX_DELAY);
	
	char buffer1[32];
	tx_queue_receive(&queue_ptr,&buffer1,TX_NO_WAIT);
	HAL_UART_Transmit(&huart1,(uint8_t *)buffer1,strlen(buffer1),HAL_MAX_DELAY);
	
	UINT dd=tx_queue_info_get(&queue_ptr, 
						&name,
						&enqueued, 
						&available_storage,
						&first_suspended, 
						&suspended_count,
						&next_queue);
	huartsend(dd);
	snprintf(buffer,sizeof(buffer),"queue name:%s\nenqueued:%lu\navailable_storage:%lu\nsuspended_count:%lu\n",name,enqueued,available_storage,suspended_count);\
	HAL_UART_Transmit(&huart1,(uint8_t *)buffer,strlen(buffer),HAL_MAX_DELAY);
	
	
	
}

8.tx_queue_prioritize
UINT tx_queue_prioritize(TX_QUEUE *queue_ptr);

挂起列表中最高优先级线程提到队首:

第 1 个参数 queue_ptr 是消息队列控制块指针。

返回值:

TX_SUCCESS:(0x00)成功。

TX_QUEUE_ERROR:(0x09)无效的消息队列指针。

在上述示例代码后面写一个挂起列表中最高优先级线程提到队首函数,并打印函数返回值,可以看到,函数返回值是0。

void    thread_0_entry(ULONG thread_input)
	//线程,串口发送数据
{
						CHAR *name;
						ULONG enqueued;
						ULONG available_storage;
						TX_THREAD *first_suspended;
						ULONG suspended_count;
						TX_QUEUE *next_queue;
	
	char message1[] = "hello threadx!1";
	UINT aa=tx_queue_send(&queue_ptr,&message1,TX_NO_WAIT);
	char message3[] = "dddddd\n";
	//UINT ac=tx_queue_send(&queue_ptr,&message3,TX_NO_WAIT);
	UINT fontmsg=tx_queue_front_send(&queue_ptr,&message3,TX_NO_WAIT);
	
	//发送
	huartsend(aa);
	UINT bb=tx_queue_info_get(&queue_ptr, 
						&name,
						&enqueued, 
						&available_storage,
						&first_suspended, 
						&suspended_count,
						&next_queue);
	huartsend(bb);
	char buffer[256];
	snprintf(buffer,sizeof(buffer),"queue name:%s\nenqueued:%lu\navailable_storage:%lu\nsuspended_count:%lu\n",name,enqueued,available_storage,suspended_count);\
	HAL_UART_Transmit(&huart1,(uint8_t *)buffer,strlen(buffer),HAL_MAX_DELAY);
	
	char buffer1[32];
	tx_queue_receive(&queue_ptr,&buffer1,TX_NO_WAIT);
	HAL_UART_Transmit(&huart1,(uint8_t *)buffer1,strlen(buffer1),HAL_MAX_DELAY);
	
	UINT dd=tx_queue_info_get(&queue_ptr, 
						&name,
						&enqueued, 
						&available_storage,
						&first_suspended, 
						&suspended_count,
						&next_queue);
	huartsend(dd);
	snprintf(buffer,sizeof(buffer),"queue name:%s\nenqueued:%lu\navailable_storage:%lu\nsuspended_count:%lu\n",name,enqueued,available_storage,suspended_count);\
	HAL_UART_Transmit(&huart1,(uint8_t *)buffer,strlen(buffer),HAL_MAX_DELAY);
	
	UINT gg= tx_queue_prioritize(&queue_ptr);
	huartsend(gg);
}

 

 9.tx_queue_send_notify
UINT  tx_queue_send_notify( TX_QUEUE *queue_ptr,
        					VOID (*queue_send_notify)(TX_QUEUE *));

发送通知回调:

第 1 个参数 queue_ptr 是消息队列控制块指针。
第 2 个参数 queue_send_notify 是队列发送通知函数的指针。如果该值为TX_NULL,则禁用通知。
返回值:
TX_SUCCESS: (0x00)队列发送通知注册成功。
TX_QUEUE_ERROR:(0x09)无效的队列指针。
TX_FEATURE_NOT_ENABLED: (0xFF)系统编译时禁用了通知功能。
当消息被发送到指定队列时将调用queue_send_notify函数(自定义)。发送通知回调不允许调用任何带有挂起选项的 API。

在tx_application_define写发送通知回调函数,并定义该函数。

void queue_send_notify_function(TX_QUEUE *queue_ptr);

VOID tx_application_define(void  *first_unused_memory)
{
	UINT dd=tx_queue_create(&queue_ptr,"queue 0",16,first_unused_memory,128);
	huartsend(dd);
	UINT ee= tx_queue_send_notify(&queue_ptr, queue_send_notify_function);
  tx_thread_create(&thread_0, "thread 0", thread_0_entry, 0,  
            thread_0_stack, DEMO_STACK_SIZE, 
            1, 1, 10, TX_AUTO_START);
	tx_thread_create(&thread_1, "Thread 1", thread_1_entry, 0,
                     thread_1_stack, DEMO_STACK_SIZE,
                     2, 2, TX_NO_TIME_SLICE, TX_AUTO_START);
}
void queue_send_notify_function(TX_QUEUE *queue_ptr)
{
	UINT aa=888888;
	huartsend(aa);
}

 

  • 13
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
RT-Thread是一个开源嵌入式实时操作系统,它提供了丰富的功能和组件来支持嵌入式应用的开发。其中一个重要的功能是消息队列消息队列是一种数据结构,用于在不同任务或线程之间传递消息。在RT-Thread中,任务可以通过向消息队列发送消息来与其他任务进行通信。消息队列允许任务以非阻塞和异步的方式发送和接收消息,从而提高了系统的并发性和响应性。 消息队列在RT-Thread中的接收过程如下: 1. 创建消息队列:首先,任务需要创建一个消息队列,并指定消息数据的大小和队列的长度。这可以通过调用`rt_mq_create`函数来实现。 2. 接收消息:任务可以使用`rt_mq_recv`函数从消息队列中接收消息。这个函数会从队列中取出最早的一条消息,并将其返回给调用者。如果队列中没有消息可用,调用者可以选择等待或立即返回。 3. 处理接收到的消息:接收到的消息可以被任务用于执行相应的操作。可以根据消息内容来判断接下来需要执行的步骤。 4. 释放消息队列资源:当任务完成了对消息的处理后,可以通过调用`rt_mq_detach`函数来释放消息队列所占用的资源。 需要注意的是,消息队列的发送和接收可以在不同的任务中进行。通过使用消息队列,任务之间可以实现解耦和异步通信,提高系统的可维护性和扩展性。 综上所述,RT-Thread消息队列接收过程包括创建消息队列、接收消息、处理消息和释放资源等步骤,以实现任务之间的通信和协作。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值