Free RTOS学习笔记 - 队列,信号量,互斥量,事件组,任务通知

本文介绍了FreeRTOS中的队列、信号量、互斥量、事件组和任务通知。队列采用先进先出操作,有创建、读写等操作;信号量只传递状态;互斥量解决优先级继承问题;事件组用整数位表示事件;任务通知有简化版和专业版,各有特点和函数原型。

一、队列

1、队列的特点

        数据的操作采用先进先出的方法(FIFO),写数据时放到尾部,读数据时从头部开始读取。

        也可以强制写队列头部,但不会覆盖头部数据。

        队列中每个数据的大小时固定的。

        创建队列时要指定长度,数据大小。

2、队列的使用

在创建队列时,会创建两个链表,分别存放等待数据的任务和等待向队列中写的数据,buf中存放队列的数据。

1)创建队列

#define xQueueCreate( uxQueueLength, uxItemSize )    xQueueGenericCreate( ( uxQueueLength ), ( uxItemSize ), ( queueQUEUE_TYPE_BASE ) )
//uxQueueLength 队列长度
//uxItemSize 每个项大小

可以看到xQueueXCreat()最后调用的是xQueueGenericCreate()。

创建队列时,会创建几个指针,pcHead始终指向头部,不会移动;pcWriteto在初始化时指向头部,后面指向要写入的下一个位置;pcReadFrom指向上一次读的位置,使用前要指向这一次读的位置。

2)向队列中写入数据

//向队列中写数据
#define xQueueSend( xQueue, pvItemToQueue, xTicksToWait ) \
    xQueueGenericSend( ( xQueue ), ( pvItemToQueue ), ( xTicksToWait ), queueSEND_TO_BACK )
//向队列尾部写数据
#define xQueueSendToBack( xQueue, pvItemToQueue, xTicksToWait ) \
    xQueueGenericSend( ( xQueue ), ( pvItemToQueue ), ( xTicksToWait ), queueSEND_TO_BACK )
//向队列首部写数据
#define xQueueSendToFront( xQueue, pvItemToQueue, xTicksToWait ) \
    xQueueGenericSend( ( xQueue ), ( pvItemToQueue ), ( xTicksToWait ), queueSEND_TO_FRONT )
//向队列尾部写数据,可以在中断函数中使用,不可阻塞
#define xQueueSendToBackFromISR( xQueue, pvItemToQueue, pxHigherPriorityTaskWoken ) \
    xQueueGenericSendFromISR( ( xQueue ), ( pvItemToQueue ), ( pxHigherPriorityTaskWoken ), queueSEND_TO_BACK )
//向队列头部写数据,可以在中断函数中使用,不可阻塞
#define xQueueSendToFrontFromISR( xQueue, pvItemToQueue, pxHigherPriorityTaskWoken ) \
    xQueueGenericSendFromISR( ( xQueue ), ( pvItemToQueue ), ( pxHigherPriorityTaskWoken ), queueSEND_TO_FRONT )

向队列中写数据,默认就是向队列尾部写数据;向队列头部写数据实际上是队列其他数据不变,然后写到pcReadFrom的位置,pcReadFrom向后移动一个位置,这样就写到了头部,下一次读取的就是这个数据。

3)从队列中读数据

BaseType_t xQueueReceive( QueueHandle_t xQueue,
                          void * const pvBuffer,
                          TickType_t xTicksToWait )
BaseType_t xQueueReceiveFromISR( QueueHandle_t xQueue,
                                 void * const pvBuffer,
                                 BaseType_t * const pxHigherPriorityTaskWoken )

4)查询

查询队列中有多少个数据,有多少剩余空间。

//返回队列中可用数据的个数
UBaseType_t uxQueueMessagesWaiting( const QueueHandle_t xQueue )
//返回队列中可用空间的个数
UBaseType_t uxQueueSpacesAvailable( const QueueHandle_t xQueue )

5)覆盖/偷看

当队列长度为1时,可以使用xQueueOverwrite()或xQueueOverwriteFromISR()来覆盖数据。队列长度必须为1,当队列满时,这些函数会覆盖里面的数据,这也意味着这些函数不会被阻塞。

#define xQueueOverwrite( xQueue, pvItemToQueue ) \
    xQueueGenericSend( ( xQueue ), ( pvItemToQueue ), 0, queueOVERWRITE )

#define xQueueOverwriteFromISR( xQueue, pvItemToQueue, pxHigherPriorityTaskWoken ) \
    xQueueGenericSendFromISR( ( xQueue ), ( pvItemToQueue ), ( pxHigherPriorityTaskWoken ), queueOVERWRITE )

偷看时不会移除数据,这些函数会从队列中复制出数据。这样意味着如果队列中没有数据,这些函数将会一直阻塞,一旦队列中有数据,每次偷看都会成功。

BaseType_t xQueuePeek( QueueHandle_t xQueue,
                       void * const pvBuffer,
                       TickType_t xTicksToWait )

BaseType_t xQueuePeekFromISR( QueueHandle_t xQueue,
                              void * const pvBuffer )

3、队列集

顾名思义,队列集就是队列的集合,当接收程序想从多个队列中读取数据的时候,如果采用轮训的方式会导致效率低下,可以假设要从mouse,key,touch,三个队列中读取数据,当三个队列中某个队列由数据写入的时候,就会将其句柄放入到Queue_Set中,当从队列集中读取数据的时候,只需获取到其句柄,然后从其对应的队列中读取数据即可。

使用队列集的步骤如下:

	//1.创建队列集
	xQueueSet  = xQueueCreateSet(4);
	//2.添加联系
	xQueueAddToSet(xQueueHandle1,xQueueSet);
	xQueueAddTo
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值