FreeRTOS队列与消息传递-1FreeRTOS队列及其结构

任务与任务之间、任务与中断之间经常需要进行一些信息交互和消息传递。FreeRTOS利用队列来实现任务间的通信,队列可以用于在任务与任务之间、任务与中断之间传递消息,所以又被称为消息队列。另外,用于资源共享和访问的二值信号量、计数信号量、互斥信号量和递归互斥信号量也都是通过队列来实现的,这个我们后面在细说。

1 FreeRTOS队列及其结构

队列是一种特殊的数据结构,可以保存有限个具有确定长度的数据单元。队列可以保存的最大单元数目被称为队列的深度,在创建队列时需要设定其深度和每个单元的大小。

2 FreeRTOS队列特性

2.1 存储数据

通常情况下,队列作为FIFO(先进先出)结构使用,即数据从队列尾写入,从队列读出,当然,从队列首写入也是可以的。FreeRTOS向队列写入数据是通过字节复制把据复制存储到队列中的,而不是通过数据引用(只传递数据指针)的方式实现的。从队中读出数据将删除队列中复制的数据。

2.2 多任务访问

队列不属于某个任务,所有任务都可以操作队列,向队列发送消息,或者从队列中获
息,前提是队列要在操作之前创建好。

2.3 读队列时阻塞

当某个任务试图读一个队列时,可以指定一个阻塞超时时间,在这段时间中,如果队列为空,那么该任务将保持阻塞态以等待队列数据有效。如果其他任务或中断服务示例程序向其等待的队列中写入了数据,那么该任务将自动由阻塞态转为就绪态。当等待的时间超过了指定的阻塞超时时间时,即使队列中尚无有效数据,任务也会自动从阻塞态转为就绪态。
由于队列可以被多个任务读取,所以对单个队列而言,也可能有多个任务处于阻塞态以等待队列数据有效。在这种情况下,一旦队列数 据有效,只会有一个任务被解除阻塞态,这个任务就是所有等待任务中优先级最高的任务。如果所有等待任务的优先级相同,那么被解除阻塞态的任务将是等待最久的任务。

2.4 写队列时阻塞

同读队列一样,任务也可以在写队列时指定一个阻塞超时时间,这个时间是当被写队列已满时,任务进入阻塞态以等待队列空间有效的最长时间。
由于队列可以被多个任务写入,所以对单个队列而言,也可能有多个任务处于阻塞态以等待队列空间有效。在这种情况下,一旦队列空间有效,只会有一个任务被解除阻塞态,这个任务就是所有等待任务中优先级最高的任务。如果所有等待任务的优先级相同,那么被解除阻塞态的任务将是等待最久的任务。

2.5 队列读写过程4

创建一个队列Queue用于进行任务1和任务2之间的通信,此队列最多可以保存5个字符。队列在刚创建好时是空的,不包含任务数据单元。

任务1将一个本地变量的值写入队列(入队),由于队列之前是空的,所以写入的值目前是队列中唯一的数据单元,队列尾和队列首同是这个值。

任务1改变本地变量的值并再次写入队列,由于之前队列首已经有数值了,新写入的值被插入队列尾,紧跟在第一个值之后,现在队列中还有3个空的数据单元。

任务2从队列读取(接受)数据到本地变量,读取的值是队列首的数值,即任务1第一次写入的值。

 任务2已经读走了一个数据单元,现在队列中只剩下任务1第二次写入的值,这个值将在任务2下一次读队列时被读走,目前队列中空数据单元变为4个。

 3 队列结构体

FreeRTOS用结构体Queue_t描述队列,在queue.c文件中定义,旧版本类型名为xQUEUE,新版本类项名为Queue_t,省略部分条件编译代码的定义为:

typedef struct QueueDefinition 		/*旧版本使用的队列结构体类型名*/
{
	int8_t *pcHead;					/*指向队列存储区首地址*/
	int8_t *pcWriteTo;				/*指向队列存储区下一个空闲地址*/

	union
	{
		QueuePointers_t xQueue;		/*用作队列时保存队列尾等信息*/
		SemaphoreData_t xSemaphore; /*用作信号量时保存额外数据*/
	} u;

	List_t xTasksWaitingToSend;		/*等待发送任务列表*/
	List_t xTasksWaitingToReceive;	/*等待接收任务列表*/

	volatile UBaseType_t uxMessagesWaiting;/*队列中当前队列项数量*/
	UBaseType_t uxLength;			/*队列长度,即最大队列项数量*/
	UBaseType_t uxItemSize;			/*队列中每个队列项的最大长度,单位为B*/

	volatile int8_t cRxLock;		/*队列上锁后,存储从队列中接收到的队列项数*/
	volatile int8_t cTxLock;		/*队列上锁后,存储发送到队列的队列项数量*/
	#if( ( configSUPPORT_STATIC_ALLOCATION == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) )
		uint8_t ucStaticallyAllocated;	/*< Set to pdTRUE if the memory used by the queue was statically allocated to ensure no attempt is made to free the memory. */
	#endif

	#if ( configUSE_QUEUE_SETS == 1 )
		struct QueueDefinition *pxQueueSetContainer;
	#endif

	#if ( configUSE_TRACE_FACILITY == 1 )
		UBaseType_t uxQueueNumber;
		uint8_t ucQueueType;
	#endif

} xQUEUE;
/*新版本队列类项名*/
typedef xQUEUE Queue_t

队列结构体类型中定义了队列长度,队列项大小,操作队列的指针,以及入队阻塞任务列表和出队阻塞列表等成员。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值