FreeRTOS-queue.c
FreeRTOS-queue.c文件分析
/*队列尾数据指针*/
typedef struct QueuePointers
{
int8_t * pcTail; /*< 队列尾指针,指向队列中数据存储位置的末尾*/
int8_t * pcReadFrom; /*< 队列读指针,指向队列读位置*/
} QueuePointers_t;
/*信号量数据*/
typedef struct SemaphoreData
{
TaskHandle_t xMutexHolder; /*< 互斥量持有者 ,是个任务句柄*/
UBaseType_t uxRecursiveCallCount; /*< 互斥量被递归调用次数*/
} SemaphoreData_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; /*< 条目大小 */
volatile int8_t cRxLock; /*< 队列读锁 */
volatile int8_t cTxLock; /*< 队列写锁 */
} xQUEUE;
BaseType_t xQueueGenericReset( QueueHandle_t xQueue, BaseType_t xNewQueue )
功能:重置队列
参数:
- xQueue 队列指针
- xNewQueue 重置类型:true 表示队列创建,初始化队列;false 表示队列已经被使用过,初始化部分元素。
返回值:成功返回1,否则返回0
QueueHandle_t xQueueGenericCreate( const UBaseType_t uxQueueLength, const UBaseType_t uxItemSize,
const uint8_t ucQueueType )
功能:创建队列
参数:
- uxQueueLength 队列长度,队列包含的条目数量
- uxItemSize 条目大小
- ucQueueType 队列类型
返回值:队列句柄
static void prvInitialiseNewQueue( const UBaseType_t uxQueueLength,
const UBaseType_t uxItemSize,
uint8_t * pucQueueStorage,
const uint8_t ucQueueType,
Queue_t * pxNewQueue )
功能:初始化新队列
参数:
- uxQueueLength 队列中包含的条目数量
- uxItemSize 条目大小
- pucQueueStorage 队列存储区指针
- ucQueueType 队列类型,队列、信号量、互斥量等
- pxNewQueue 队列指针
QueueHandle_t xQueueCreateMutex( const uint8_t ucQueueType )
功能:创建互斥量
参数:
- ucQueueType 类型
返回值: 队列指针,指向创建的互斥量
BaseType_t xQueueGiveMutexRecursive( QueueHandle_t xMutex )
功能:释放互斥量,用于递归调用互斥量的情形
参数:
- xMutex 互斥量指针
返回值:成功返回true,否则返回false
BaseType_t xQueueTakeMutexRecursive( QueueHandle_t xMutex,
TickType_t xTicksToWait )
功能:获取互斥量,用于递归调用互斥量的情形
参数:
- xMutex 互斥量指针
- xTicksToWait 超时等待时间
返回值:
QueueHandle_t xQueueCreateCountingSemaphore( const UBaseType_t uxMaxCount,
const UBaseType_t uxInitialCount )
功能:创建数值信号量
参数:
- uxMaxCount 信号量计数最大值
- uxInitialCount 信号量计数初始值
返回值:队列指针,指向创建的信号量
BaseType_t xQueueGenericSend( QueueHandle_t xQueue,
const void * const pvItemToQueue,
TickType_t xTicksToWait,
const BaseType_t xCopyPosition )
功能:向队列中发送条目
参数:
- xQueue 队列指针
- pvItemToQueue 待发送条目指针
- xTicksToWait 超时等待时间
- xCopyPosition 条目在队列中存放的位置
返回值:成功时返回1,否则返回0
BaseType_t xQueueGenericSendFromISR( QueueHandle_t xQueue,
const void * const pvItemToQueue,
BaseType_t * const pxHigherPriorityTaskWoken,
const BaseType_t xCopyPosition )
功能: 在中断上下文向队列中发送条目
参数:
- xQueue 队列指针
- pvItemToQueue 待发送条目指针
- pxHigherPriorityTaskWoken 输出型参数,指示是否有更高优先级的任务就绪
- xCopyPosition 条目在队列中存放的位置
返回值:成功时返回1,否则返回0
BaseType_t xQueueGiveFromISR( QueueHandle_t xQueue,
BaseType_t * const pxHigherPriorityTaskWoken )
功能:在中断上下文给出信号量(信号量值加1)
参数:
- xQueue 队列指针
- pxHigherPriorityTaskWoken 输出型参数,指示是否有更高优先级的任务就绪
返回值:成功时返回1,否则返回0
BaseType_t xQueueReceive( QueueHandle_t xQueue,
void * const pvBuffer,
TickType_t xTicksToWait )
功能:从队列中读取条目
参数:
- xQueue 队列指针
- pvBuffer 输出型参数,用来接收读出的条目
- xTicksToWait 超时等待时间
返回值:成功时返回1,否则返回0
BaseType_t xQueueSemaphoreTake( QueueHandle_t xQueue,
TickType_t xTicksToWait )
功能:获取信号量(信号量值减1)
参数:
- xQueue 队列指针
- xTicksToWait 超时等待时间
返回值:成功时返回1,否则返回0
BaseType_t xQueuePeek( QueueHandle_t xQueue,
void * const pvBuffer,
TickType_t xTicksToWait )
功能:获取队列中的条目,但是不改变队列读指针
参数:
- xQueue 队列指针
- pvBuffer 输出型参数 保存读取的条目
- xTicksToWait 超时等待时间
返回值:成功时返回1,否则返回0
BaseType_t xQueueReceiveFromISR( QueueHandle_t xQueue,
void * const pvBuffer,
BaseType_t * const pxHigherPriorityTaskWoken )
功能:中断上下文中从队列中读取条目
参数:
- xQueue 队列指针
- pvBuffer 输出型参数 保存读取的条目
- pxHigherPriorityTaskWoken 输出型参数 指示是否有更高优先级的任务就绪
返回值:成功时返回1,否则返回0
BaseType_t xQueuePeekFromISR( QueueHandle_t xQueue,
void * const pvBuffer )
功能:中断上下文从队列中读取条目,但是不改变队列中的读指针
参数:
- xQueue 队列指针
- pvBuffer 输出型参数 保存读取的条目
返回值:成功时返回1,否则返回0
UBaseType_t uxQueueMessagesWaiting( const QueueHandle_t xQueue )
功能:队列中的有效条目数量
参数:
- xQueue 队列指针
返回值:队列中的有效条目数量
UBaseType_t uxQueueSpacesAvailable( const QueueHandle_t xQueue )
功能:队列中还能存多少条目
参数:
- xQueue 队列指针
返回值:队列中还能存多少条目
UBaseType_t uxQueueMessagesWaitingFromISR( const QueueHandle_t xQueue )
功能:中断上下文获取队列中有效的条目数量
参数:
- xQueue 队列指针
返回值:队列中的有效条目数量
void vQueueDelete( QueueHandle_t xQueue )
功能:删除队列,释放队列所占的存储空间
参数:
- xQueue 队列指针
static UBaseType_t prvGetDisinheritPriorityAfterTimeout( const Queue_t * const pxQueue )
功能:获取互斥量继承的优先级
参数:
- pxQueue 队列指针
返回值:互斥量继承的优先级
BaseType_t xQueueIsQueueEmptyFromISR( const QueueHandle_t xQueue )
功能:中断上下文判断队列是否为空
参数:
- xQueue 队列指针
返回值:队列空返回true,否则返回false
BaseType_t xQueueIsQueueFullFromISR( const QueueHandle_t xQueue )
功能:中断上下文判断队列是否满
参数:
- xQueue 队列指针
返回值:队列满返回true,否则返回false
void vQueueWaitForMessageRestricted( QueueHandle_t xQueue,
TickType_t xTicksToWait,
const BaseType_t xWaitIndefinitely )
功能:等待消息,用于定时器timer.c
参数:
- xQueue 队列指针
- xTicksToWait 等待超时时间
- xWaitIndefinitely 是否允许无限期等待
重点函数分析
QueueHandle_t xQueueGenericCreate( const UBaseType_t uxQueueLength,
const UBaseType_t uxItemSize,
const uint8_t ucQueueType )
{
Queue_t * pxNewQueue;
size_t xQueueSizeInBytes;
uint8_t * pucQueueStorage;
configASSERT( uxQueueLength > ( UBaseType_t ) 0 );
/*队列所有元素占用的空间大小*/
xQueueSizeInBytes = ( size_t ) ( uxQueueLength * uxItemSize );
configASSERT( ( uxItemSize == 0 ) || ( uxQueueLength == ( xQueueSizeInBytes / uxItemSize ) ) );
/* 申请队列占用的存储空间,队列本身大小加上队列所有元素的大小*/
pxNewQueue = ( Queue_t * ) pvPortMalloc( sizeof( Queue_t ) + xQueueSizeInBytes ); /*lint !e9087 !e9079 see comment above. */
if( pxNewQueue != NULL )
{
pucQueueStorage = ( uint8_t * ) pxNewQueue;
pucQueueStorage += sizeof( Queue_t ); /*lint !e9016 Pointer arithmetic allowed on char types, especially when it assists conveying intent. */
/*初始化队列*/
prvInitialiseNewQueue( uxQueueLength, uxItemSize, pucQueueStorage, ucQueueType, pxNewQueue );
}
else
{
traceQUEUE_CREATE_FAILED( ucQueueType );
mtCOVERAGE_TEST_MARKER();
}
return pxNewQueue;
}
static void prvInitialiseNewQueue( const UBaseType_t uxQueueLength,
const UBaseType_t uxItemSize,
uint8_t * pucQueueStorage,
const uint8_t ucQueueType,
Queue_t * pxNewQueue )
{
( void ) ucQueueType;
if( uxItemSize == ( UBaseType_t ) 0 )
{
/* 如果条目大小是0,则队列头指向队列本身*/
pxNewQueue->pcHead = ( int8_t * ) pxNewQueue;
}
else
{
/* 否则指向申请的队列元素存储空间 */
pxNewQueue->pcHead = ( int8_t * ) pucQueueStorage;
}
pxNewQueue->uxLength = uxQueueLength;
pxNewQueue->uxItemSize = uxItemSize;
( void ) xQueueGenericReset( pxNewQueue, pdTRUE );
traceQUEUE_CREATE( pxNewQueue );
}
初始化互斥量
static void prvInitialiseMutex( Queue_t * pxNewQueue )
{
if( pxNewQueue != NULL )
{
/* 互斥量持有者设置为空,队列类型为互斥量*/
pxNewQueue->u.xSemaphore.xMutexHolder = NULL;
pxNewQueue->uxQueueType = queueQUEUE_IS_MUTEX;
/* 互斥量递归次数为0*/
pxNewQueue->u.xSemaphore.uxRecursiveCallCount = 0;
traceCREATE_MUTEX( pxNewQueue );
/* 向队列中发送一个条目*/
( void ) xQueueGenericSend( pxNewQueue, NULL, ( TickType_t ) 0U, queueSEND_TO_BACK );
}
else
{
traceCREATE_MUTEX_FAILED();
}
}
创建互斥量
QueueHandle_t xQueueCreateMutex( const uint8_t ucQueueType )
{
QueueHandle_t xNewQueue;
const UBaseType_t uxMutexLength = ( UBaseType_t ) 1, uxMutexSize = ( UBaseType_t ) 0;
/*队列长度是1,元素大小是0。*/
xNewQueue = xQueueGenericCreate( uxMutexLength, uxMutexSize, ucQueueType );
prvInitialiseMutex( ( Queue_t * ) xNewQueue );
return xNewQueue;
}
释放互斥量
BaseType_t xQueueGiveMutexRecursive( QueueHandle_t xMutex )
{
BaseType_t xReturn;
Queue_t * const pxMutex = ( Queue_t * ) xMutex;
configASSERT( pxMutex );
/*如果互斥量的持有者是当前任务则递归数减1,如果递归数是0则释放互斥量,否则不释放互斥量。*/
if( pxMutex->u.xSemaphore.xMutexHolder == xTaskGetCurrentTaskHandle() )
{
traceGIVE_MUTEX_RECURSIVE( pxMutex );
( pxMutex->u.xSemaphore.uxRecursiveCallCount )--;
if( pxMutex->u.xSemaphore.uxRecursiveCallCount == ( UBaseType_t ) 0 )
{
( void ) xQueueGenericSend( pxMutex, NULL, queueMUTEX_GIVE_BLOCK_TIME, queueSEND_TO_BACK );
}
else
{
mtCOVERAGE_TEST_MARKER();
}
xReturn = pdPASS;
}
else
{
xReturn = pdFAIL;
traceGIVE_MUTEX_RECURSIVE_FAILED( pxMutex );
}
return xReturn;
}
获取互斥量
BaseType_t xQueueTakeMutexRecursive( QueueHandle_t xMutex,
TickType_t xTicksToWait )
{
BaseType_t xReturn;
Queue_t * const pxMutex = ( Queue_t * ) xMutex;
configASSERT( pxMutex );
traceTAKE_MUTEX_RECURSIVE( pxMutex );
/*如果互斥量持有者是当前任务,则递归数加1,否则获取信号量,获取成功递归数
加1,否则返回失败。*/
if( pxMutex->u.xSemaphore.xMutexHolder == xTaskGetCurrentTaskHandle() )
{
( pxMutex->u.xSemaphore.uxRecursiveCallCount )++;
xReturn = pdPASS;
}
else
{
xReturn = xQueueSemaphoreTake( pxMutex, xTicksToWait );
if( xReturn != pdFAIL )
{
( pxMutex->u.xSemaphore.uxRecursiveCallCount )++;
}
else
{
traceTAKE_MUTEX_RECURSIVE_FAILED( pxMutex );
}
}
return xReturn;
}
创建数值型信号量
QueueHandle_t xQueueCreateCountingSemaphore( const UBaseType_t uxMaxCount,
const UBaseType_t uxInitialCount )
{
QueueHandle_t xHandle;
configASSERT( uxMaxCount != 0 );
configASSERT( uxInitialCount <= uxMaxCount );
xHandle = xQueueGenericCreate( uxMaxCount, queueSEMAPHORE_QUEUE_ITEM_LENGTH, queueQUEUE_TYPE_COUNTING_SEMAPHORE );
if( xHandle != NULL )
{
( ( Queue_t * ) xHandle )->uxMessagesWaiting = uxInitialCount;
traceCREATE_COUNTING_SEMAPHORE();
}
else
{
traceCREATE_COUNTING_SEMAPHORE_FAILED();
}
return xHandle;
}
向队列中发送一个条目
BaseType_t xQueueGenericSend( QueueHandle_t xQueue,
const void * const pvItemToQueue,
TickType_t xTicksToWait,
const BaseType_t xCopyPosition )
{
BaseType_t xEntryTimeSet = pdFALSE, xYieldRequired;
TimeOut_t xTimeOut;
Queue_t * const pxQueue = xQueue;
configASSERT( pxQueue );
configASSERT( !( ( pvItemToQueue == NULL ) && ( pxQueue->uxItemSize != ( UBaseType_t ) 0U ) ) );
configASSERT( !( ( xCopyPosition == queueOVERWRITE ) && ( pxQueue->uxLength != 1 ) ) );
#if ( ( INCLUDE_xTaskGetSchedulerState == 1 ) || ( configUSE_TIMERS == 1 ) )
{
configASSERT( !( ( xTaskGetSchedulerState() == taskSCHEDULER_SUSPENDED ) && ( xTicksToWait != 0 ) ) );
}
#endif
for( ; ; )
{
taskENTER_CRITICAL();
{
/* 如果队列中还有空间或者是覆盖式发送,那就把数据发送到队列,并检查是否有等待接收的任务,
如果有就进行一次任务调度。返回成功*/
if( ( pxQueue->uxMessagesWaiting < pxQueue->uxLength ) || ( xCopyPosition == queueOVERWRITE ) )
{
traceQUEUE_SEND( pxQueue );
{
xYieldRequired = prvCopyDataToQueue( pxQueue, pvItemToQueue, xCopyPosition );
if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )
{
if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE )
{
queueYIELD_IF_USING_PREEMPTION();
}
else
{
mtCOVERAGE_TEST_MARKER();
}
}
else if( xYieldRequired != pdFALSE )
{
queueYIELD_IF_USING_PREEMPTION();
}
else
{
mtCOVERAGE_TEST_MARKER();
}
}
taskEXIT_CRITICAL();
return pdPASS;
}
else
{
/*如果不等待就直接返回失败*/
if( xTicksToWait == ( TickType_t ) 0 )
{
taskEXIT_CRITICAL();
traceQUEUE_SEND_FAILED( pxQueue );
return errQUEUE_FULL;
} /*记录进入的时间和超时时间*/
else if( xEntryTimeSet == pdFALSE )
{
vTaskInternalSetTimeOutState( &xTimeOut );
xEntryTimeSet = pdTRUE;
}
else
{
mtCOVERAGE_TEST_MARKER();
}
}
}
taskEXIT_CRITICAL();
vTaskSuspendAll();
prvLockQueue( pxQueue );
/* 检查是否超时,如果没超时且队列没有空间就把任务放到等待发送链表。并进行一次任务调度。*/
if( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdFALSE )
{
if( prvIsQueueFull( pxQueue ) != pdFALSE )
{
traceBLOCKING_ON_QUEUE_SEND( pxQueue );
vTaskPlaceOnEventList( &( pxQueue->xTasksWaitingToSend ), xTicksToWait );
prvUnlockQueue( pxQueue );
if( xTaskResumeAll() == pdFALSE )
{
portYIELD_WITHIN_API();
}
}
else
{
prvUnlockQueue( pxQueue );
( void ) xTaskResumeAll();
}
}
else /*如果超时就返回发送失败*/
{
prvUnlockQueue( pxQueue );
( void ) xTaskResumeAll();
traceQUEUE_SEND_FAILED( pxQueue );
return errQUEUE_FULL;
}
}
}

在中断上下文向队列发送数据
BaseType_t xQueueGenericSendFromISR( QueueHandle_t xQueue,
const void * const pvItemToQueue,
BaseType_t * const pxHigherPriorityTaskWoken,
const BaseType_t xCopyPosition )
{
BaseType_t xReturn;
UBaseType_t uxSavedInterruptStatus;
Queue_t * const pxQueue = xQueue;
configASSERT( pxQueue );
configASSERT( !( ( pvItemToQueue == NULL ) && ( pxQueue->uxItemSize != ( UBaseType_t ) 0U ) ) );
configASSERT( !( ( xCopyPosition == queueOVERWRITE ) && ( pxQueue->uxLength != 1 ) ) );
portASSERT_IF_INTERRUPT_PRIORITY_INVALID();
/* 如果队列中有空间或者是覆盖式发送,就把数据发送到队列,并从接收链表取出等待任务,允许调度。否则失败。*/
uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();
{
if( ( pxQueue->uxMessagesWaiting < pxQueue->uxLength ) || ( xCopyPosition == queueOVERWRITE ) )
{
const int8_t cTxLock = pxQueue->cTxLock;
const UBaseType_t uxPreviousMessagesWaiting = pxQueue->uxMessagesWaiting;
traceQUEUE_SEND_FROM_ISR( pxQueue );
( void ) prvCopyDataToQueue( pxQueue, pvItemToQueue, xCopyPosition );
if( cTxLock == queueUNLOCKED )
{
{
if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )
{
if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE )
{
if( pxHigherPriorityTaskWoken != NULL )
{
*pxHigherPriorityTaskWoken = pdTRUE;
}
else
{
mtCOVERAGE_TEST_MARKER();
}
}
else
{
mtCOVERAGE_TEST_MARKER();
}
}
else
{
mtCOVERAGE_TEST_MARKER();
}
( void ) uxPreviousMessagesWaiting;
}
}
else
{
configASSERT( cTxLock != queueINT8_MAX );
pxQueue->cTxLock = ( int8_t ) ( cTxLock + 1 );
}
xReturn = pdPASS;
}
else
{
traceQUEUE_SEND_FROM_ISR_FAILED( pxQueue );
xReturn = errQUEUE_FULL;
}
}
portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus );
return xReturn;
}
在中断上下文释放一个信号量
BaseType_t xQueueGiveFromISR( QueueHandle_t xQueue,
BaseType_t * const pxHigherPriorityTaskWoken )
{
BaseType_t xReturn;
UBaseType_t uxSavedInterruptStatus;
Queue_t * const pxQueue = xQueue;
configASSERT( pxQueue );
configASSERT( pxQueue->uxItemSize == 0 );
configASSERT( !( ( pxQueue->uxQueueType == queueQUEUE_IS_MUTEX ) && ( pxQueue->u.xSemaphore.xMutexHolder != NULL ) ) );
portASSERT_IF_INTERRUPT_PRIORITY_INVALID();
uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();
{
const UBaseType_t uxMessagesWaiting = pxQueue->uxMessagesWaiting;
/* 如果还允许增加,就信号量数值加1,并从等待接收队列中取出任务,允许调度。否则失败。*/
if( uxMessagesWaiting < pxQueue->uxLength )
{
const int8_t cTxLock = pxQueue->cTxLock;
traceQUEUE_SEND_FROM_ISR( pxQueue );
pxQueue->uxMessagesWaiting = uxMessagesWaiting + ( UBaseType_t ) 1;
if( cTxLock == queueUNLOCKED )
{
if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )
{
if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE )
{
if( pxHigherPriorityTaskWoken != NULL )
{
*pxHigherPriorityTaskWoken = pdTRUE;
}
else
{
mtCOVERAGE_TEST_MARKER();
}
}
else
{
mtCOVERAGE_TEST_MARKER();
}
}
else
{
mtCOVERAGE_TEST_MARKER();
}
}
else
{
configASSERT( cTxLock != queueINT8_MAX );
pxQueue->cTxLock = ( int8_t ) ( cTxLock + 1 );
}
xReturn = pdPASS;
}
else
{
traceQUEUE_SEND_FROM_ISR_FAILED( pxQueue );
xReturn = errQUEUE_FULL;
}
}
portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus );
return xReturn;
}
从队列接收数据
BaseType_t xQueueReceive( QueueHandle_t xQueue,
void * const pvBuffer,
TickType_t xTicksToWait )
{
BaseType_t xEntryTimeSet = pdFALSE;
TimeOut_t xTimeOut;
Queue_t * const pxQueue = xQueue;
configASSERT( ( pxQueue ) );
configASSERT( !( ( ( pvBuffer ) == NULL ) && ( ( pxQueue )->uxItemSize != ( UBaseType_t ) 0U ) ) );
#if ( ( INCLUDE_xTaskGetSchedulerState == 1 ) || ( configUSE_TIMERS == 1 ) )
{
configASSERT( !( ( xTaskGetSchedulerState() == taskSCHEDULER_SUSPENDED ) && ( xTicksToWait != 0 ) ) );
}
#endif
for( ; ; )
{
taskENTER_CRITICAL();
{
const UBaseType_t uxMessagesWaiting = pxQueue->uxMessagesWaiting;
/* 如果队列中有数据就从队列中读取数据,并从等待发送链表里取出一个任务,进行一次任务调度。*/
if( uxMessagesWaiting > ( UBaseType_t ) 0 )
{
prvCopyDataFromQueue( pxQueue, pvBuffer );
traceQUEUE_RECEIVE( pxQueue );
pxQueue->uxMessagesWaiting = uxMessagesWaiting - ( UBaseType_t ) 1;
if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE )
{
if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) != pdFALSE )
{
queueYIELD_IF_USING_PREEMPTION();
}
else
{
mtCOVERAGE_TEST_MARKER();
}
}
else
{
mtCOVERAGE_TEST_MARKER();
}
taskEXIT_CRITICAL();
return pdPASS;
}
else /*如果队列中没有数据*/
{
/*如果不等待直接返回失败*/
if( xTicksToWait == ( TickType_t ) 0 )
{
taskEXIT_CRITICAL();
traceQUEUE_RECEIVE_FAILED( pxQueue );
return errQUEUE_EMPTY;
} /*如果等待就设置当前进入的时间和超时时间。*/
else if( xEntryTimeSet == pdFALSE )
{
vTaskInternalSetTimeOutState( &xTimeOut );
xEntryTimeSet = pdTRUE;
}
else
{
mtCOVERAGE_TEST_MARKER();
}
}
}
taskEXIT_CRITICAL();
vTaskSuspendAll();
prvLockQueue( pxQueue );
if( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdFALSE )
{
/* 如果没有超时且队列为空就把当前任务放入等待接收队列,进行一次任务调度。超时或者队列中有数据时会被唤醒。*/
if( prvIsQueueEmpty( pxQueue ) != pdFALSE )
{
traceBLOCKING_ON_QUEUE_RECEIVE( pxQueue );
vTaskPlaceOnEventList( &( pxQueue->xTasksWaitingToReceive ), xTicksToWait );
prvUnlockQueue( pxQueue );
if( xTaskResumeAll() == pdFALSE )
{
portYIELD_WITHIN_API();
}
else
{
mtCOVERAGE_TEST_MARKER();
}
}
else
{
prvUnlockQueue( pxQueue );
( void ) xTaskResumeAll();
}
}
else /*等待超时就返回失败*/
{
prvUnlockQueue( pxQueue );
( void ) xTaskResumeAll();
if( prvIsQueueEmpty( pxQueue ) != pdFALSE )
{
traceQUEUE_RECEIVE_FAILED( pxQueue );
return errQUEUE_EMPTY;
}
else
{
mtCOVERAGE_TEST_MARKER();
}
}
} /*lint -restore */
}
/*获取信号量或者互斥量。如果是获取互斥量,当有更高的优先级任务等待互斥量时,持有互斥量的任务会继承更高的优先级。*/
BaseType_t xQueueSemaphoreTake( QueueHandle_t xQueue,
TickType_t xTicksToWait )
{
BaseType_t xEntryTimeSet = pdFALSE;
TimeOut_t xTimeOut;
Queue_t * const pxQueue = xQueue;
#if ( configUSE_MUTEXES == 1 )
BaseType_t xInheritanceOccurred = pdFALSE;
#endif
configASSERT( ( pxQueue ) );
configASSERT( pxQueue->uxItemSize == 0 );
#if ( ( INCLUDE_xTaskGetSchedulerState == 1 ) || ( configUSE_TIMERS == 1 ) )
{
configASSERT( !( ( xTaskGetSchedulerState() == taskSCHEDULER_SUSPENDED ) && ( xTicksToWait != 0 ) ) );
}
#endif
for( ; ; )
{
taskENTER_CRITICAL();
{
const UBaseType_t uxSemaphoreCount = pxQueue->uxMessagesWaiting;
/* 如果信号量值大于0,则信号量值减1,从等待发送队列中取出任务,并进行一次任务调度,返回成功。*/
if( uxSemaphoreCount > ( UBaseType_t ) 0 )
{
traceQUEUE_RECEIVE( pxQueue );
pxQueue->uxMessagesWaiting = uxSemaphoreCount - ( UBaseType_t ) 1;
#if ( configUSE_MUTEXES == 1 )
{
if( pxQueue->uxQueueType == queueQUEUE_IS_MUTEX )
{
pxQueue->u.xSemaphore.xMutexHolder = pvTaskIncrementMutexHeldCount();
}
else
{
mtCOVERAGE_TEST_MARKER();
}
}
#endif /* configUSE_MUTEXES */
if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE )
{
if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) != pdFALSE )
{
queueYIELD_IF_USING_PREEMPTION();
}
else
{
mtCOVERAGE_TEST_MARKER();
}
}
else
{
mtCOVERAGE_TEST_MARKER();
}
taskEXIT_CRITICAL();
return pdPASS;
}
else /*如果超时*/
{ /*如果不等待超时则返回失败*/
if( xTicksToWait == ( TickType_t ) 0 )
{
#if ( configUSE_MUTEXES == 1 )
{
configASSERT( xInheritanceOccurred == pdFALSE );
}
#endif /* configUSE_MUTEXES */
taskEXIT_CRITICAL();
traceQUEUE_RECEIVE_FAILED( pxQueue );
return errQUEUE_EMPTY;
} /*如果等待超时,则设置进入的时间和超时时间。*/
else if( xEntryTimeSet == pdFALSE )
{
vTaskInternalSetTimeOutState( &xTimeOut );
xEntryTimeSet = pdTRUE;
}
else
{
mtCOVERAGE_TEST_MARKER();
}
}
}
taskEXIT_CRITICAL();
vTaskSuspendAll();
prvLockQueue( pxQueue );
/* 如果没有超时且队列中没有数据,则把当前任务放到等待接收队列进行一次任务调度,等待超时或者有数据。如果是
互斥量还会发送优先级继承。*/
if( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdFALSE )
{
if( prvIsQueueEmpty( pxQueue ) != pdFALSE )
{
traceBLOCKING_ON_QUEUE_RECEIVE( pxQueue );
#if ( configUSE_MUTEXES == 1 )
{
if( pxQueue->uxQueueType == queueQUEUE_IS_MUTEX )
{
taskENTER_CRITICAL();
{
xInheritanceOccurred = xTaskPriorityInherit( pxQueue->u.xSemaphore.xMutexHolder );
}
taskEXIT_CRITICAL();
}
else
{
mtCOVERAGE_TEST_MARKER();
}
}
#endif /* if ( configUSE_MUTEXES == 1 ) */
vTaskPlaceOnEventList( &( pxQueue->xTasksWaitingToReceive ), xTicksToWait );
prvUnlockQueue( pxQueue );
if( xTaskResumeAll() == pdFALSE )
{
portYIELD_WITHIN_API();
}
else
{
mtCOVERAGE_TEST_MARKER();
}
}
else
{
prvUnlockQueue( pxQueue );
( void ) xTaskResumeAll();
}
}
else /*如果超时则返回失败,如果是互斥量会把继承的优先级还原回来。*/
{
prvUnlockQueue( pxQueue );
( void ) xTaskResumeAll();
if( prvIsQueueEmpty( pxQueue ) != pdFALSE )
{
#if ( configUSE_MUTEXES == 1 )
{
if( xInheritanceOccurred != pdFALSE )
{
taskENTER_CRITICAL();
{
UBaseType_t uxHighestWaitingPriority;
uxHighestWaitingPriority = prvGetDisinheritPriorityAfterTimeout( pxQueue );
vTaskPriorityDisinheritAfterTimeout( pxQueue->u.xSemaphore.xMutexHolder, uxHighestWaitingPriority );
}
taskEXIT_CRITICAL();
}
}
#endif /* configUSE_MUTEXES */
traceQUEUE_RECEIVE_FAILED( pxQueue );
return errQUEUE_EMPTY;
}
else
{
mtCOVERAGE_TEST_MARKER();
}
}
} /*lint -restore */
}
浙公网安备 33010602011771号