15 - FreeRTOS隊列API

  • FreeRTOS爲操作隊列提供了非常豐富的API函數,包括隊列的創建、刪除,靈活的入隊和出隊方式、帶中斷保護的入隊和出隊等等。下面就來詳細講述這些API函數。

獲取隊列入隊信息數目

函數描述

UBaseType_t uxQueueMessagesWaiting( QueueHandle_t xQueue );

  • 返回隊列中存儲的信息數目。具有中斷保護的版本爲uxQueueMessagesWaitingFromISR(),原型爲:UBaseType_t uxQueueMessagesWaitingFromISR( const QueueHandle_t xQueue )。

參數描述

xQueue:隊列句柄

獲取隊列的空閒數目

函數描述

UBaseType_t uxQueueSpacesAvailable( QueueHandle_t xQueue );

  • 返回隊列的空閒數目。

參數描述

xQueue:隊列句柄

刪除隊列

函數描述

void vQueueDelete( QueueHandle_t xQueue );

  • 刪除隊列並釋放所有分配給隊列的內存。

參數描述

xQueue:隊列句柄

復位隊列

函數描述

BaseType_t xQueueReset( QueueHandle_t xQueue );

  • 將隊列復位到初始狀態。

參數描述

xQueue:隊列句柄

返回值

FreeRTOSV7.2.0以及以後的版本總是返回pdPASS。

創建隊列

函數描述

QueueHandle_t xQueueCreate (UBaseType_t uxQueueLength, UBaseType_t uxItemSize);

  • 創建新隊列。爲新隊列分配指定的存儲空間並返回隊列句柄。

參數描述

  • usQueueLength:隊列項數目
  • uxItemSize:每個隊列項大小,單位是字節。隊列項通過拷貝入隊而不是通過引用入隊,因此需要隊列項的大小。每個隊列項的大小必須相同。

返回值

成功創建隊列返回隊列句柄,否自返回0。

用法舉例

 struct AMessage
 {
     portCHAR ucMessageID;
     portCHAR ucData[ 20 ];
 };
 void vATask( void*pvParameters )
 {
     xQueueHandle xQueue1, xQueue2;
     // 創建一個隊列,隊列能包含10個unsigned long類型的值。
     xQueue1 = xQueueCreate( 10, sizeof( unsigned portLONG ));
     if( xQueue1 ==0 )
     {
         // 隊列創建失敗,不可以使用
     }
     // 創建一個隊列,隊列能包含10個 Amessage結構體指針類型的值。
     // 這樣可以通過傳遞指針變量來包含大量數據。
     xQueue2 =xQueueCreate( 10, sizeof( struct AMessage * ) );
     if( xQueue2 ==0 )
     {
         // 隊列創建失敗,不可以使用
     }
     // ... 任務的其它代碼.
 }

向隊列投遞隊列項

函數描述

BaseType_t xQueueSend(QueueHandle_t xQueue, const void * pvItemToQueue, TickType_t xTicksToWait );

  • 其實是一個宏,真正被調用的函數是xQueueGenericSend()。定義這個宏是爲了向後兼容那些不包含函數xQueueSendToFront()和xQueueSendToBack()宏的FreeRTOS版本。它與xQueueSendToBack()等同。
  • 這個宏向隊列尾部投遞一個隊列項。項目以拷貝的形式入隊,而不是引用形式入隊。絕不可以在中斷服務例程中調用這個宏,使用帶有中斷保護的版本xQueueSendFromISR()來完成相同的功能。

參數描述

  • xQueue:隊列句柄。
  • pvItemToQueue:指針,指向要入隊的項目。要保存到隊列中的項目字節數在隊列創建時就已確定。因此要從指針pvItemToQueue指向的區域拷貝到隊列存儲區域的字節數,也已確定。
  • xTicksToWait:如果隊列滿,任務等待隊列空閒的最大時間。如果隊列滿並且xTicksToWait被設置成0,函數立刻返回。時間單位爲系統節拍時鐘週期,因此宏portTICK_PERIOD_MS可以用來輔助計算真實延時值。如果INCLUDE_vTaskSuspend設置成1,並且指定延時爲portMAX_DELAY將引起任務無限阻塞(沒有超時)。

返回值

隊列項入隊成功返回pdTRUE,否則返回errQUEUE_FULL。

用法舉例

struct AMessage
 {
      portCHAR ucMessageID;
      portCHAR ucData[ 20 ];
 }xMessage;
 unsigned portLONG ulVar = 10UL;
 void vATask( void *pvParameters )
 {
     xQueueHandle xQueue1, xQueue2;
     struct AMessage *pxMessage;
     /*創建一個隊列,隊列能包含10個unsigned long類型的值。*/
     xQueue1 = xQueueCreate( 10, sizeof( unsigned portLONG ) );
     /* 創建一個隊列,隊列能包含10個 Amessage結構體指針類型的值。
       這樣可以通過傳遞指針變量來包含大量數據。*/
     xQueue2 = xQueueCreate( 10, sizeof( struct AMessage * ) );
     // ...
     if( xQueue1 != 0 )
     {
          /*1個unsigned long型數據入隊.如果需要等待隊列空間變的有效,
         會最多等待10個系統節拍週期*/
          if( xQueueSend( xQueue1, ( void * ) &ulVar, ( portTickType ) 10 ) !=pdPASS )
          {
               /*消息入隊失敗*/
          }
    }
    if( xQueue2 != 0 )
    {
         /* 發送一個指向結構體Amessage的對象,如果隊列滿也不等待 */
         pxMessage = & xMessage;
         xQueueSend( xQueue2, ( void * ) &pxMessage, ( portTickType ) 0 );
    }
         //... 任務其餘代碼.
 }

向隊列投遞隊列項(帶中斷保護)

函數描述

BaseType_t xQueueSendFromISR (QueueHandle_t xQueue, const void *pvItemToQueue, BaseType_t *pxHigherPriorityTaskWoken);

  • 其實是一個宏,真正被調用的函數是xQueueGenericSendFromISR()。這個宏是xQueueSend()的中斷保護版本,用於中斷服務程序,等價於xQueueSendToBackFromISR()。
  • 在中斷服務例程中向隊列尾部投遞一個隊列項。

參數描述

  • xQueue:隊列句柄。
  • pvItemToQueue:指針,指向要入隊的項目。要保存到隊列中的項目字節數在隊列創建時就已確定。因此要從指針pvItemToQueue指向的區域拷貝到隊列存儲區域的字節數,也已確定。
  • pxHigherPriorityTaskWoken:如果入隊導致一個任務解鎖,並且解鎖的任務優先級高於當前運行的任務,則該函數將*pxHigherPriorityTaskWoken設置成pdTRUE。如果xQueueSendFromISR()設置這個值爲pdTRUE,則中斷退出前需要一次上下文切換。從FreeRTOS V7.3.0起,pxHigherPriorityTaskWoken稱爲一個可選參數,並可以設置爲NULL。

返回值

列項入隊成功返回pdTRUE,否則返回errQUEUE_FULL。

用法舉例

void vBufferISR( void )
{
    portCHARcIn;
    portBASE_TYPE xHigherPriorityTaskWoken;
 
    /* 初始化,沒有喚醒任務*/
    xHigherPriorityTaskWoken = pdFALSE;
 
    /* 直到緩衝區爲空 */
    do
    {
        /* 從緩衝區獲得一個字節數據 */
        cIn = portINPUT_BYTE( RX_REGISTER_ADDRESS );                                                      
 
        /* 投遞這個數據 */
        xQueueSendFromISR( xRxQueue, &cIn, &xHigherPriorityTaskWoken );
    }while( portINPUT_BYTE( BUFFER_COUNT ) );
 
    /* 這裏緩衝區已空,如果需要進行一個上下文切換*/
    /*根據不同移植平臺,這個函數也不同*/
    portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
}

向隊列尾部投遞隊列項

函數描述

BaseType_t xQueueSendToBack(QueueHandle_t xQueue,
const void * pvItemToQueue, TickType_t xTicksToWait );

  • 其實是一個宏,真正被調用的函數是xQueueGenericSend()。這個宏等價於xQueueSend()。
  • 向隊列尾投遞一個隊列項。絕不可以在中斷中調用這個宏,可以使用帶有中斷保護的版本xQueueSendToBackFromISR ()來完成相同功能。

參數描述

同xQueueSend()。

返回值

同xQueueSend()。

用法舉例

同xQueueSend()。

向隊列尾部投遞隊列項(帶中斷保護)

函數描述

BaseType_t xQueueSendToBackFromISR (QueueHandle_t xQueue, const void *pvItemToQueue, BaseType_t *pxHigherPriorityTaskWoken );

  • 其實是一個宏,真正被調用的函數是xQueueGenericSendFromISR()。這個宏是xQueueSendToBack()的中斷保護版本,用於中斷服務程序,等價於xQueueSendFromISR()。
  • 在中斷服務例程中向隊列尾部投遞一個隊列項。

參數描述

同QueueSendFromISR()。

返回值

同QueueSendFromISR()。

用法舉例

同QueueSendFromISR()。

向隊列首部投遞隊列項

函數描述

BaseType_t xQueueSendToFront(QueueHandle_t xQueue, const void * pvItemToQueue,TickType_t xTicksToWait);

  • 其實是一個宏,真正被調用的函數是xQueueGenericSend()。
  • 這個宏向隊列首部投遞一個隊列項。絕不可以在中斷服務例程中調用這個宏,可以使用帶有中斷保護的版本xQueueSendToFrontFromISR ()來完成相同功能。

參數描述

  • xQueue:隊列句柄。
  • pvItemToQueue:指針,指向要入隊的項目。要保存到隊列中的項目字節數在隊列創建時就已確定。因此要從指針pvItemToQueue指向的區域拷貝到隊列存儲區域的字節數,也已確定。
  • xTicksToWait:如果隊列滿,任務等待隊列空閒的最大時間。如果隊列滿並且xTicksToWait被設置成0,函數立刻返回。時間單位爲系統節拍時鐘週期,因此宏portTICK_PERIOD_MS可以用來輔助計算真實延時值。如果INCLUDE_vTaskSuspend設置成1,並且指定延時爲portMAX_DELAY將引起任務無限阻塞(沒有超時)。

返回值

隊列項入隊成功返回pdTRUE,否則返回errQUEUE_FULL。

向隊列首部投遞隊列項(帶中斷保護)

函數描述

BaseType_t xQueueSendToFrontFromISR (QueueHandle_t xQueue, const void *pvItemToQueue,BaseType_t *pxHigherPriorityTaskWoken);

  • 其實是一個宏,真正被調用的函數是xQueueGenericSendFromISR()。這個宏是xQueueSendToFront ()的中斷保護版本,用於中斷服務程序。

參數描述

  • xQueue:隊列句柄。
  • pvItemToQueue:指針,指向要入隊的項目。要保存到隊列中的項目字節數在隊列創建時就已確定。因此要從指針pvItemToQueue指向的區域拷貝到隊列存儲區域的字節數,也已確定。
  • pxHigherPriorityTaskWoken:如果入隊導致一個任務解鎖,並且解鎖的任務優先級高於當前運行的任務,則該函數將*pxHigherPriorityTaskWoken設置成pdTRUE。如果xQueueSendFromISR()設置這個值爲pdTRUE,則中斷退出前需要一次上下文切換。從FreeRTOS V7.3.0起,pxHigherPriorityTaskWoken稱爲一個可選參數,並可以設置爲NULL。

返回值

列項入隊成功返回pdTRUE,否則返回errQUEUE_FULL。

讀取並移除隊列項

函數描述

BaseType_t xQueueReceive(QueueHandle_t xQueue, void *pvBuffer,TickType_t xTicksToWait);

  • 其實是一個宏,真正被調用的函數是xQueueGenericReceive()。
  • 這個宏從隊列中讀取一個隊列項並把該隊列項從隊列中刪除。讀取隊列項是以拷貝的形式完成,而不是以引用的形式,因此必須提供足夠大的緩衝區以便容納隊列項。參數pvBuffer指向這個緩衝區。
  • 絕不可以在中斷服務例程中調用這個宏,可以使用使用帶有中斷保護的版本xQueueReceiveFromISR來完成相同功能。

參數描述

  • pxQueue:隊列句柄。
  • pvBuffer:指向一個緩衝區,用於拷貝接收到的列表項。
  • xTicksToWait:要接收的項目隊列爲空時,允許任務最大阻塞時間。如果設置該參數爲0,則表示即隊列爲空也立即返回。阻塞時間的單位是系統節拍週期,宏portTICK_RATE_MS可輔助計算真實阻塞時間。如果INCLUDE_vTaskSuspend設置成1,並且阻塞時間設置成portMAX_DELAY,將會引起任務無限阻塞(不會有超時)。

返回值

成功接收到列表項返回pdTRUE,否則返回pdFALSE。

用法舉例

struct AMessage
{
    portCHAR ucMessageID;
    portCHAR ucData[ 20 ];
} xMessage;
 
xQueueHandle xQueue;
 
// 創建一個隊列並投遞一個值
void vATask( void *pvParameters )
{
     struct AMessage *pxMessage;
 
     // 創建一個隊列,隊列能包含10個 Amessage結構體指針類型的值。
     // 這樣可以通過傳遞指針變量來包含大量數據。
     xQueue =xQueueCreate( 10, sizeof( struct AMessage * ) );
     if( xQueue == 0)
     {
          // 創建隊列失敗
    }
    // ...
    // 向隊列發送一個指向結構體對象Amessage的指針,如果隊列滿不等待
    pxMessage = & xMessage;
    xQueueSend(xQueue, ( void * ) &pxMessage, ( portTickType ) 0 );
    // ... 其它代碼
}
 
// 該任務從隊列中接收一個隊列項
voidvADifferentTask( void *pvParameters )
{
    struct AMessage *pxRxedMessage;
 
    if( xQueue != 0)
    {
        // 從創建的隊列中接收一個消息,如果消息無效,最多阻塞10個系統節拍週期
        if(xQueueReceive( xQueue, &( pxRxedMessage ), ( portTickType ) 10 ) )
        {
            // 現在pcRxedMessage 指向由vATask任務投遞進來的結構體Amessage變量
        }
    }
   // ... 其它代碼
 }

讀取並移除隊列項(帶中斷保護)

函數描述

BaseType_t xQueueReceiveFromISR (QueueHandle_t xQueue, void *pvBuffer, BaseType_t *pxHigherPriorityTaskWoken);

  • 從隊列中讀取一個隊列項並把該隊列項從隊列中刪除。功能與xQueueReceive()相同,用於中斷服務函數。

參數描述

  • pxQueue:隊列句柄。
  • pvBuffer:指向一個緩衝區,用於拷貝接收到的列表項。
  • pxHigherPriorityTaskWoken:如果入隊導致一個任務解鎖,並且解鎖的任務優先級高於當前運行的任務,則該函數將*pxHigherPriorityTaskWoken設置成pdTRUE。如果xQueueSendFromISR()設置這個值爲pdTRUE,則中斷退出前需要一次上下文切換。從FreeRTOS V7.3.0起,pxHigherPriorityTaskWoken稱爲一個可選參數,並可以設置爲NULL。

返回值

成功接收到列表項返回pdTRUE,否則返回pdFALSE。

用法舉例

xQueueHandle xQueue;
 
/* 該函數創建一個隊列並投遞一些值 */
voidvAFunction( void *pvParameters )
{
     portCHAR cValueToPost;
     const portTickType xBlockTime = (portTickType )0xff;
 
     /*創建一個隊列,可以容納10個portCHAR型變量 */
     xQueue = xQueueCreate( 10, sizeof( portCHAR ) );
     if( xQueue == 0 )
     {
          /* 隊列創建失敗 */
     }
    /*…... */
    /* 投遞一些字符,在ISR中使用。如果隊列滿,任務將會阻塞xBlockTime 個系統節拍週期 */
    cValueToPost = 'a';
    xQueueSend( xQueue, ( void * ) &cValueToPost, xBlockTime );
    cValueToPost = 'b';
    xQueueSend( xQueue, ( void * ) &cValueToPost, xBlockTime );
    /*... 繼續投遞字符 ... 當隊列滿時,這個任務會阻塞*/
    cValueToPost = 'c';
    xQueueSend( xQueue, ( void * ) &cValueToPost, xBlockTime );
}
 
/* ISR:輸出從隊列接收到的所有字符 */
voidvISR_Routine( void )
{
     portBASE_TYPE xTaskWokenByReceive = pdFALSE;
     portCHAR cRxedChar;
 
     while( xQueueReceiveFromISR( xQueue, ( void *) &cRxedChar, &xTaskWokenByReceive) )
    {
       /* 接收到一個字符串,輸出.*/
       vOutputCharacter( cRxedChar );
       /* 如果從隊列移除一個字符串後喚醒了向此隊列投遞字符的任務,那麼參數xTaskWokenByReceive將會設置成pdTRUE,這個循環無論重複多少次,僅會
          有一個任務被喚醒。*/
    }
    /*這裏緩衝區已空,如果需要進行一個上下文切換根據不同移植平臺,這個函數也不同 */
    portYIELD_FROM_ISR(xTaskWokenByReceive);
}

讀取但不移除隊列項

函數描述

BaseType_t xQueuePeek(QueueHandle_t xQueue, void *pvBuffer, TickType_t xTicksToWait);

  • 其實是一個宏,真正被調用的函數是xQueueGenericReceive()。
  • 這個宏從隊列中讀取一個隊列項,但不會把該隊列項從隊列中移除。這個宏絕不可以用在中斷服務例程中,可以使用使用帶有中斷保護的版本xQueuePeekFromIS()來完成相同功能。

參數描述

同xQueueReceive()。

返回值

同xQueueReceive()。

用法舉例

同xQueueReceive()。

讀取但不移除隊列項(帶中斷保護)

函數描述

BaseType_t xQueuePeekFromISR(QueueHandle_t xQueue, void *pvBuffer,);

  • 功能與xQueuePeek()相同,用於中斷服務程序。

參數描述

  • pxQueue:隊列句柄。
  • pvBuffer:指向一個緩衝區,用於拷貝接收到的列表項。

返回值

成功接收到列表項返回pdTRUE,否則返回pdFALSE。

隊列註冊

函數描述

void vQueueAddToRegistry(QueueHandle_t xQueue, char *pcQueueName,);

  • 爲隊列分配名字並進行註冊。

參數描述

  • xQueue:隊列句柄
  • pcQueueName:分配給隊列的名字。這僅是一個有助於調試的字符串。隊列註冊僅存儲指向隊列名字符串的指針,因此這個字符串必須是靜態的(全局變量活着存儲在ROM/Flash中),不可以定義到堆棧中。
  • 隊列註冊有兩個目的,這兩個目的都是爲了調試RTOS內核:
  1. 它允許隊列具有一個相關的文本名字,在GUI調試中可以容易的標識隊列;
  2. 包含調試器用於定位每一個已經註冊的隊列和信號量時所需的信息。
  • 隊列註冊僅用於調試器。
  • 宏configQUEUE_REGISTRY_SIZE定義了可以註冊的隊列和信號量的最大數量。僅當你想使用可視化調試內核時,才進行隊列和信號量註冊。

用法舉例

void vAFunction( void )
{
    xQueueHandle xQueue;
 
   /*創建一個隊列,可以容納10個char類型數值 */
   xQueue = xQueueCreate( 10, sizeof( portCHAR ) );
 
   /* 我們想可視化調試,所以註冊它*/
   vQueueAddToRegistry( xQueue, "AMeaningfulName" );
}

解除註冊

函數描述

void vQueueUnregisterQueue(QueueHandle_t xQueue);

  • 從隊列註冊表中移除指定的隊列。

參數描述

xQueue:隊列句柄

查詢隊列是否爲空(僅用於中斷服務程序)

函數描述

BaseType_t xQueueIsQueueEmptyFromISR( const QueueHandle_t xQueue );

  • 查詢隊列是否爲空。這個函數僅用於ISR。

參數描述

xQueue:隊列句柄

返回值

隊列非空返回pdFALSE,其它值表示隊列爲空。

查詢隊列是否滿(僅用於中斷服務程序)

函數描述

BaseType_t xQueueIsQueueFullFromISR( const QueueHandle_t xQueue );

  • 查詢隊列是否滿,僅用於ISR。

參數描述

xQueue:隊列句柄

返回值

隊列沒有滿返回pdFALSE,其它值表示隊列滿。

向隊列尾部覆蓋式投遞隊列項

函數描述

BaseType_t xQueueOverwrite(QueueHandle_t xQueue, const void * pvItemToQueue);

  • 其實是個宏,真正被調用的函數是xQueueGenericSend()。這個宏是xQueueSendToBack()的另一個版本,向隊列尾投遞一個隊列項,如果隊列已滿,則覆蓋之前的隊列項。一般用於只有一個隊列項的隊列中,如果隊列的隊列項超過1個,使用這個宏會觸發一個斷言(已經正確定義configASSERT()的情況下)。這個宏絕不可以在中斷服務程序中調用,可以使用使用帶有中斷保護的版本xQueueOverwriteFromISR()來完成相同功能。

參數描述

  • xQueue:隊列句柄。
  • pvItemToQueue:指針,指向要入隊的項目。要保存到隊列中的項目字節數在隊列創建時就已確定。因此要從指針pvItemToQueue指向的區域拷貝到隊列存儲區域的字節數,也已確定。

返回值

總是返回pdPASS。

用法舉例

void vFunction( void *pvParameters )
{
    QueueHandle_t xQueue;
    unsigned long ulVarToSend, ulValReceived;
 
    /*創建隊列,保存一個unsignedlong值。如果一個隊列的隊列項超過1個,強烈建議不要使用xQueueOverwrite(),如果使用xQueueOverwrite()會觸發一個斷言(已經正確定義configASSERT()的情況下)。*/
    xQueue = xQueueCreate( 1, sizeof( unsigned long ) );
 
    /*使用 xQueueOverwrite().向隊列寫入10*/
    ulVarToSend = 10;
    xQueueOverwrite( xQueue, &ulVarToSend );
 
    /*從隊列讀取值,但是不把這個值從隊列中刪除。*/
    ulValReceived = 0;
    xQueuePeek( xQueue, &ulValReceived, 0 );
 
    if( ulValReceived != 10 )
     {
          /* 處理錯誤*/
     }
 
     /*到這裏隊列仍是滿的。使用xQueueOverwrite()覆寫隊列,寫入值100 */
     ulVarToSend = 100;
     xQueueOverwrite( xQueue, &ulVarToSend );
 
     /* 從隊列中讀取值*/
     xQueueReceive( xQueue, &ulValReceived, 0 );
 
     if( ulValReceived != 100 )
     {
          /*處理錯誤 */
     }
 
      /* ... */
}

向隊列尾部覆蓋式投遞隊列項(帶中斷保護)

函數描述

BaseType_t xQueueOverwriteFromISR (QueueHandle_t xQueue, const void * pvItemToQueue,
BaseType_t *pxHigherPriorityTaskWoken);

  • 其實是個宏,真正被調用的函數是xQueueGenericSendFromISR()。這個宏的功能與xQueueOverwrite()相同,用在中斷服務程序中。

參數描述

  • xQueue:隊列句柄。
  • pvItemToQueue:指針,指向要入隊的項目。要保存到隊列中的項目字節數在隊列創建時就已確定。因此要從指針pvItemToQueue指向的區域拷貝到隊列存儲區域的字節數,也已確定。
  • pxHigherPriorityTaskWoken:如果入隊導致一個任務解鎖,並且解鎖的任務優先級高於當前運行的任務,則該函數將*pxHigherPriorityTaskWoken設置成pdTRUE。如果xQueueSendFromISR()設置這個值爲pdTRUE,則中斷退出前需要一次上下文切換。從FreeRTOS V7.3.0起,pxHigherPriorityTaskWoken稱爲一個可選參數,並可以設置爲NULL。

返回值

總是返回pdPASS。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章