7.FreeRTOS_邮箱

本文内容的基础知识点在博文 “ FreeRTOS_队列基础知识 ”中,博文链接如下:

FreeRTOS_队列基础知识-优快云博客

邮箱概述

邮箱的本质是一个长度为1的队列

当进行写邮箱时,队列中的数据会被覆盖,因此每次写邮箱一定成功,没有阻塞选择。

当进行读邮箱时,队列中的数据不会消失,因此写一次邮箱后,读邮箱就一定成功。

操作邮箱与操作队列的逻辑完全一致。

写邮箱

函数声明如下:

/* 这是一个宏,写邮箱 */
xQueueOverwrite( xQueue, pvItemToQueue )

/* 宏定义 */
#define xQueueOverwrite( xQueue, pvItemToQueue ) \
    xQueueGenericSend( ( xQueue ), ( pvItemToQueue ), 0, queueOVERWRITE )

/* 真实调用的函数 */
BaseType_t xQueueGenericSend( QueueHandle_t xQueue,
                              const void * const pvItemToQueue,
                              TickType_t xTicksToWait,
                              const BaseType_t xCopyPosition )

xQueue:队列的句柄,即:创建队列函数的返回值

pvItemToQueue:原始数据的指针

读邮箱

函数声明如下:

/* 读邮箱 */
BaseType_t xQueuePeek( QueueHandle_t xQueue,
                       void * const pvBuffer,
                       TickType_t xTicksToWait )

xQueue:队列的句柄,即:创建队列函数的返回值

pvItemToQueue:原始数据的指针

xTicksToWait :当队列为满时等待写入的时间。写0表示不等待,portMAX_DELAY表示死等

实验

验证读邮箱不会移除队列数据、写邮箱会覆盖队列内容

具体代码如下:

void Task1Function(void *param){

	int i;
	
	while(1){
		xQueuePeek((QueueHandle_t)param,&i,portMAX_DELAY);/* 读邮箱 */
		printf("%d",i);
	}
	
}

int main( void )
{
#ifdef DEBUG
  debug();
#endif
	
	TaskHandle_t xHandleTask1;
	QueueHandle_t QueueHandle_Test;/* 定义一个队列句柄,这是个指针 */
	int i = 0;
	
	prvSetupHardware();
	SerialPortInit();
	printf("UART TEST\r\n");
	
	QueueHandle_Test = xQueueCreate(1,sizeof(int));/* 创建队列 */
	if(QueueHandle_Test == NULL){
		printf("queue create fail\r\n");
	}
	xQueueOverwrite(QueueHandle_Test,&i);/* 写邮箱 */
	i++;
    xQueueOverwrite(QueueHandle_Test,&i);/* 写邮箱 */

	xTaskCreate(Task1Function,"Task1",100,(void*)QueueHandle_Test,2,&xHandleTask1);

	vTaskStartScheduler();
	
	return 0;
}

运行结果:

可以看到尽管在创建任务后不再邮箱,但Task1不断的输出1,这说明Task1并未因为不断读邮箱而阻塞,因此读邮箱并不清除队列的值。

在任务创建前,第一次写邮箱的值为0,第二次为1,这时Task打印的值为1,说明写邮箱会覆盖队列内容。

### FreeRTOS 邮箱功能概述 FreeRTOS 提供了一种轻量级的消息传递机制,称为队列 (Queue),其中包括邮箱 (Mailbox) 的概念。虽然 FreeRTOS 并未直接提供名为“邮箱”的独立模块,但可以通过队列来模拟邮箱的行为[^1]。具体来说,邮箱可以被看作是一个特殊的队列,它每次只存储一条消息。 #### 创建和初始化邮箱 创建一个用于模拟邮箱的队列时,通常将其长度设置为 1,并指定数据项大小。以下是创建邮箱的代码示例: ```c #include "FreeRTOS.h" #include "queue.h" // 定义邮箱句柄 QueueHandle_t xMailBox; void vCreateMailBox(void) { // 创建一个长度为1、每条消息大小为 sizeof( uint32_t ) 的队列作为邮箱 xMailBox = xQueueCreate(1, sizeof(uint32_t)); if (xMailBlock != NULL) { // 初始化成功处理逻辑 } } ``` 上述代码通过 `xQueueCreate` 函数创建了一个长度为 1 的队列,这实际上就是一个简单的邮箱结构[^2]。 #### 向邮箱发送消息 向邮箱发送消息的操作类似于向队列写入数据。以下是如何将消息放入邮箱中的示例代码: ```c uint32_t ulMessageToSend = 0xABCD1234; BaseType_t xStatus; xStatus = xQueueSend(xMailBox, &ulMessageToSend, portMAX_DELAY); if (xStatus == pdPASS) { // 消息已成功发送至邮箱 } else { // 发送失败处理逻辑 } ``` 在此过程中,如果邮箱已被占用,则调用方可以选择阻塞直到有空间可用,或者立即返回错误状态[^3]。 #### 从邮箱接收消息 从邮箱读取消息的过程也与常规队列操作一致。下面展示了如何从邮箱中获取消息: ```c uint32_t ulReceivedMessage; BaseType_t xStatus; xStatus = xQueueReceive(xMailBox, &ulReceivedMessage, portMAX_DELAY); if (xStatus == pdPASS) { // 成功接收到消息并保存在 ulReceivedMessage 中 } else { // 接收超时或其他异常情况处理 } ``` 当尝试从空闲邮箱读取时,线程可能会进入等待状态直至新消息到达,除非设置了有限的时间延迟参数[^1]。 #### 注意事项 - **同步问题**:由于多个任务可能访问同一个邮箱资源,在实际应用中需注意互斥保护措施。 - **性能考量**:频繁地切换上下文可能导致额外开销,因此应合理规划任务优先级以及时间片分配策略。 问题
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值