FreeRTOS从入门到摔倒-Queue

Day 5 :队列

队列的作用:用于任务与任务,任务与中断之间的通信,在认识队列之前首先确认一些基本常识:

  • 队列中存储的数据,即任务之间交流的数据,成为队列项目
  • 队列长度是队列所能保存的最大数据项目数量;
  • 数据的存储方式有两种:FIFO(先进先出)和LIFO(后进先出),字面意思,很好理解;
  • 队列不属于任何一个任务,仅用于传递消息和数据;
  • FreeRTOS有关于队列的代码都放在queue.c中;

1. 队列结构

typedef struct QueueDefinition
{
   
	int8_t *pcHead;							//指向队列开始地址
	int8_t *pcTail;							//指向队列存储区最后一个字节
	int8_t *pcWriteTo;						//指向存储区下一个空闲区域

	union							
	{
   
		int8_t *pcReadFrom;					//指向最后一个出对的队列项首地址
		UBaseType_t uxRecursiveCallCount;	//用来记录地柜互斥量杯调用的次数
	} u;

	List_t xTasksWaitingToSend;				//等待发送任务列表,队满阻塞
	List_t xTasksWaitingToReceive;			//等待接受任务列表,队空阻塞

	volatile UBaseType_t uxMessagesWaiting;	//队列当前队列项数目
	UBaseType_t uxLength;					//队列长度
	UBaseType_t uxItemSize;					//单个队列项最大长度,单位字节

	volatile int8_t cRxLock;				//队列上锁后出队队列项数目
	volatile int8_t cTxLock;				//队列上锁后入队队列项数目

	//静态存储
	#if( ( configSUPPORT_STATIC_ALLOCATION == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) )
		uint8_t ucStaticallyAllocated;	
	#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;

2.队列创建

和任务一样,创建方式有两种:动态和静态,分别是xQueueCreate( )和xQueueCreateStatic( );动态意味着内存由系统分配,静态意味着内存由用户分配。
xQueueCreate()和xQueueCreateStatic()本质是宏定义,真正的函数是 xQueueGenericCreate( )和xQueueGenericCreateStatic( );具体代码如下:

QueueHandle_t xQueueGenericCreate( 
									const UBaseType_t 	uxQueueLength,    //队列长度
									const UBaseType_t 	uxItemSize, 	  //队列项长度,单位字节
									const uint8_t 	  	ucQueueType       //队列类型
									)
{
   
	Queue_t 	*pxNewQueue;					
	size_t 		xQueueSizeInBytes;
	uint8_t 	*pucQueueStorage;

	//队列长度必须大于0,断言,用于调试,若断言失败,则会卡在死循环里
	configASSERT( uxQueueLength > ( UBaseType_t ) 0 );

	if( uxItemSize == ( UBaseType_t ) 0 )
	{
   
		//队列项大小为0,不需要存储区
		xQueueSizeInBytes = ( size_t ) 0;
	}
	else
	{
   
		//分配足够的存储区
		xQueueSizeInBytes = ( size_t ) ( uxQueueLength * uxItemSize ); 
	}

    //分配内存,大小是队列结构体+消息存储区
	pxNewQueue = ( Queue_t * ) pvPortMalloc( sizeof( Queue_t ) + xQueueSizeInBytes );

	if( pxNewQueue != NULL )		//分配成功
	{
   
		//计算出消息存储区的首地址,队列结构体在前,存储区紧跟其后
		pucQueueStorage = ( ( uint8_t * ) pxNewQueue ) + sizeof( Queue_t );

		#if( configSUPPORT_STATIC_ALLOCATION == 1 )
		{
   
			//动态创建方式需要标记队列字段
			pxNewQueue->ucStaticallyAllocated = pdFALSE;
		}
		#endif

		//初始化队列
		prvInitialiseNewQueue( uxQueueLength, uxItemSize, pucQueueStorage, ucQueueType, pxNewQueue );
	}

	return pxNewQueue;				//返回队列句柄
}

当队列创建成功时,返回队列句柄,否则返回其他值;

QueueHandle_t xQueueGenericCreateStatic( 
										const UBaseType_t uxQueueLength, 	//队列长度
										const UBaseType_t uxItemSize, 		//队列项长度,单位字节
										uint8_t *pucQueueStorage, 			//指向队列存储区
										StaticQueue_t *pxStaticQueue, 		//指向队列结构体
										const uint8_t ucQueueType 			//队列类型
										)
{
   
	Queue_t *pxNewQueue;
	
	//队列长度必须大于0、结构体必须存在等等
	configASSERT( uxQueueLength > ( UBaseType_t ) 0 );
	configASSERT( pxStaticQueue != NULL );
	configASSERT( !( ( pucQueueStorage != NULL ) && ( uxItemSize == 0 ) ) );
	configASSERT( !( ( pucQueueStorage == NULL ) && ( uxItemSize != 0 ) ) );

	#if( configASSERT_DEFINED == 1 )
	{
   
		//没弄懂,猜测是确保静态创建的结构体大小等于实际队列结构体+信号量的大小
		
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值