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 )

功能:重置队列

参数:

  1. xQueue 队列指针
  2. xNewQueue  重置类型:true 表示队列创建,初始化队列;false 表示队列已经被使用过,初始化部分元素。

 返回值:成功返回1,否则返回0

 

QueueHandle_t xQueueGenericCreate( const UBaseType_t uxQueueLength, const UBaseType_t uxItemSize,

                                       const uint8_t ucQueueType )

功能:创建队列

参数:

  1. uxQueueLength  队列长度,队列包含的条目数量
  2. uxItemSize   条目大小
  3. ucQueueType 队列类型

返回值:队列句柄

 

static void prvInitialiseNewQueue( const UBaseType_t uxQueueLength,

                                   const UBaseType_t uxItemSize,

                                   uint8_t * pucQueueStorage,

                                   const uint8_t ucQueueType,

                                   Queue_t * pxNewQueue )

功能:初始化新队列

参数:

  1. uxQueueLength 队列中包含的条目数量
  2. uxItemSize 条目大小
  3. pucQueueStorage 队列存储区指针
  4. ucQueueType 队列类型,队列、信号量、互斥量等
  5. pxNewQueue  队列指针

 

QueueHandle_t xQueueCreateMutex( const uint8_t ucQueueType )

功能:创建互斥量

参数:

  1. ucQueueType 类型

返回值: 队列指针,指向创建的互斥量

 

BaseType_t xQueueGiveMutexRecursive( QueueHandle_t xMutex )

功能:释放互斥量,用于递归调用互斥量的情形

参数:

  1. xMutex 互斥量指针

返回值:成功返回true,否则返回false

 

BaseType_t xQueueTakeMutexRecursive( QueueHandle_t xMutex,

                                         TickType_t xTicksToWait )

功能:获取互斥量,用于递归调用互斥量的情形

参数:

  1. xMutex 互斥量指针
  2. xTicksToWait 超时等待时间

返回值:

 

QueueHandle_t xQueueCreateCountingSemaphore( const UBaseType_t uxMaxCount,

                                                 const UBaseType_t uxInitialCount )

功能:创建数值信号量

参数:

  1. uxMaxCount 信号量计数最大值
  2. uxInitialCount 信号量计数初始值

返回值:队列指针,指向创建的信号量

 

BaseType_t xQueueGenericSend( QueueHandle_t xQueue,

                              const void * const pvItemToQueue,

                              TickType_t xTicksToWait,

                              const BaseType_t xCopyPosition )

功能:向队列中发送条目

参数:

  1. xQueue 队列指针
  2. pvItemToQueue 待发送条目指针
  3. xTicksToWait 超时等待时间
  4. xCopyPosition  条目在队列中存放的位置

返回值:成功时返回1,否则返回0

 

BaseType_t xQueueGenericSendFromISR( QueueHandle_t xQueue,

                                     const void * const pvItemToQueue,

                                     BaseType_t * const pxHigherPriorityTaskWoken,

                                     const BaseType_t xCopyPosition )

功能: 在中断上下文向队列中发送条目

参数:

  1. xQueue 队列指针
  2. pvItemToQueue 待发送条目指针
  3. pxHigherPriorityTaskWoken 输出型参数,指示是否有更高优先级的任务就绪
  4. xCopyPosition  条目在队列中存放的位置

返回值:成功时返回1,否则返回0

 

BaseType_t xQueueGiveFromISR( QueueHandle_t xQueue,

                              BaseType_t * const pxHigherPriorityTaskWoken )

功能:在中断上下文给出信号量(信号量值加1)

参数:

  1. xQueue 队列指针
  2. pxHigherPriorityTaskWoken 输出型参数,指示是否有更高优先级的任务就绪

返回值:成功时返回1,否则返回0

 

BaseType_t xQueueReceive( QueueHandle_t xQueue,

                          void * const pvBuffer,

                          TickType_t xTicksToWait )

功能:从队列中读取条目

参数:

  1. xQueue 队列指针
  2. pvBuffer 输出型参数,用来接收读出的条目
  3. xTicksToWait 超时等待时间

返回值:成功时返回1,否则返回0

 

BaseType_t xQueueSemaphoreTake( QueueHandle_t xQueue,

                                TickType_t xTicksToWait )

功能:获取信号量(信号量值减1)

参数:

  1. xQueue 队列指针
  2. xTicksToWait  超时等待时间

返回值:成功时返回1,否则返回0

 

BaseType_t xQueuePeek( QueueHandle_t xQueue,

                       void * const pvBuffer,

                       TickType_t xTicksToWait )

功能:获取队列中的条目,但是不改变队列读指针

参数:

  1. xQueue 队列指针
  2. pvBuffer 输出型参数 保存读取的条目
  3. xTicksToWait 超时等待时间

返回值:成功时返回1,否则返回0

 

BaseType_t xQueueReceiveFromISR( QueueHandle_t xQueue,

                                 void * const pvBuffer,

                                 BaseType_t * const pxHigherPriorityTaskWoken )

功能:中断上下文中从队列中读取条目

参数:

  1. xQueue 队列指针
  2. pvBuffer 输出型参数 保存读取的条目
  3. pxHigherPriorityTaskWoken  输出型参数 指示是否有更高优先级的任务就绪

返回值:成功时返回1,否则返回0

 

BaseType_t xQueuePeekFromISR( QueueHandle_t xQueue,

                              void * const pvBuffer )

功能:中断上下文从队列中读取条目,但是不改变队列中的读指针

参数:

  1. xQueue 队列指针
  2. pvBuffer 输出型参数 保存读取的条目

返回值:成功时返回1,否则返回0

 

UBaseType_t uxQueueMessagesWaiting( const QueueHandle_t xQueue )

功能:队列中的有效条目数量

参数:

  1. xQueue 队列指针

返回值:队列中的有效条目数量

 

UBaseType_t uxQueueSpacesAvailable( const QueueHandle_t xQueue )

功能:队列中还能存多少条目

参数:

  1. xQueue 队列指针

返回值:队列中还能存多少条目

 

UBaseType_t uxQueueMessagesWaitingFromISR( const QueueHandle_t xQueue )

功能:中断上下文获取队列中有效的条目数量

参数:

  1. xQueue 队列指针

返回值:队列中的有效条目数量

 

void vQueueDelete( QueueHandle_t xQueue )

功能:删除队列,释放队列所占的存储空间

参数:

  1. xQueue  队列指针

 

static UBaseType_t prvGetDisinheritPriorityAfterTimeout( const Queue_t * const pxQueue )

功能:获取互斥量继承的优先级

参数:

  1. pxQueue 队列指针

返回值:互斥量继承的优先级

 

BaseType_t xQueueIsQueueEmptyFromISR( const QueueHandle_t xQueue )

功能:中断上下文判断队列是否为空

参数:

  1. xQueue 队列指针

返回值:队列空返回true,否则返回false

 

BaseType_t xQueueIsQueueFullFromISR( const QueueHandle_t xQueue )

功能:中断上下文判断队列是否满

参数:

  1. xQueue 队列指针

返回值:队列满返回true,否则返回false

 

void vQueueWaitForMessageRestricted( QueueHandle_t xQueue,

                                         TickType_t xTicksToWait,

                                         const BaseType_t xWaitIndefinitely )

功能:等待消息,用于定时器timer.c

参数:

  1. xQueue 队列指针
  2. xTicksToWait 等待超时时间
  3. 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 */

}

posted @ 2022-08-08 20:45  明er  阅读(83)  评论(0)    收藏  举报