FreeRTOS中信号量与互斥琐的底层都是通过队列来实现的,下面对队列的源码进行初步分析:
队列结构的定义如下:
typedef struct QueueDefinition
{
signed portCHAR *pcHead; /*队列 头部指针*/
signed portCHAR *pcTail; /*尾部指针,比长度多一个字节*/
signed portCHAR *pcWriteTo; /*指向下一个可以写入的空闲空间*/
signed portCHAR *pcReadFrom; /*指向队列中最后一个已读的数据 */
xList xTasksWaitingToSend; /*等待发送的任务队列,按优先级排序 */
xList xTasksWaitingToReceive; /*等待读取的任务队列,按优先级排序*/
volatile unsigned portBASE_TYPE uxMessagesWaiting; /*队列中当前的条目数*/
unsigned portBASE_TYPE uxLength; /*队列总的条目个数 */
unsigned portBASE_TYPE uxItemSize; /*每个条目的大小*/
signed portBASE_TYPE xRxLock; /*队列接收锁标志 */
signed portBASE_TYPE xTxLock; /*队列发送锁标志 */
/*这两个标志的值可以为queueUNLOCKED (-1)、queueLOCKED_UNMODIFIED(0)、或正值,当为正直时表示锁的次数*/
} xQUEUE;
队列的创建
队列通过xQueueCreate函数来创建,此函数主要负责申请队列空间,初始化队列的各项的值。
xQueueHandle xQueueCreate( unsigned portBASE_TYPE uxQueueLength, unsigned portBASE_TYPE uxItemSize )
{
xQUEUE *pxNewQueue;
size_t xQueueSizeInBytes;
/* 为队列分配空间*/
if( uxQueueLength > ( unsigned portBASE_TYPE ) 0 )
{
pxNewQueue = ( xQUEUE * ) pvPortMalloc( sizeof( xQUEUE ) );
if( pxNewQueue != NULL )
{
/* Create the list of pointers to queue items. The queue is one byte
longer than asked for to make wrap checking easier/faster. */
xQueueSizeInBytes = ( size_t ) ( uxQueueLength * uxItemSize ) + ( size_t ) 1; /*分配的空间比队列长度多一个字节,方便检测*/
pxNewQueue->pcHead = ( signed portCHAR * ) pvPortMalloc( xQueueSizeInBytes );
if( pxNewQueue->pcHead != NULL )
{
/* Initialise the queue members as described above where the
queue type is defined. */
pxNewQueue->pcTail = pxNewQueue->pcHead + ( uxQueueLength * uxItemSize );
pxNewQueue->uxMessagesWaiting = 0;
pxNewQueue->pcWriteTo = pxNewQueue->pcHead;
pxNewQueue->pcReadFrom = pxNewQueue->pcHead + ( ( uxQueueLength - 1 ) * uxItemSize ); /*指向的是最后一个已读的条目,故初始化为最后一项*/
pxNewQueue->uxLength = uxQueueLength;
pxNewQueue->uxItemSize = uxItemSize;
pxNewQueue->xRxLock = queueUNLOCKED;
pxNewQueue->xTxLock = queueUNLOCKED;
/* Likewise ensure the event queues start with the correct state. */
vListInitialise( &( pxNewQueue->xTasksWaitingToSend ) ); /*初始化两个等待队列*/
vListInitialise( &( pxNewQueue->xTasksWaitingToReceive ) );
traceQUEUE_CREATE( pxNewQueue ); /*用于调试跟踪*/
return pxNewQueue;
}
else
{
traceQUEUE_CREATE_FAILED();
vPortFree( pxNewQueue );
}
}
}
/* Will only reach here if we could not allocate enough memory or no memory
was required. */
return NULL;
}
文章评论(0条评论)
登录后参与讨论