本文内容的基础知识点在博文 “ 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,说明写邮箱会覆盖队列内容。