您現在的位置是:首頁 > 足球

「FreeRTOS原始碼解析(六)」訊息佇列

  • 由 嵌入式的那點事兒 發表于 足球
  • 2022-07-10
簡介當任務等待的時間超過了指定的阻塞時間,即使佇列中還不允許入隊,任務也會自動從阻塞態轉移為就緒態,此時傳送訊息的任務或者中斷程式會收到一個錯誤碼 errQUEUE_FULL

鏈式佇列入隊修改頭指標嗎

##熱愛記錄、鍾愛分享、酷愛生活

一、前言

甜妻來襲:總裁乖乖就範

期許

現代言情

免費閱讀

本期文章講解FreeRTOS實時作業系統原始碼,主要是原始碼分析,實操很少。上節講了FreeRTOS中斷管理功能,詳細講述了異常和中斷的關係,以及FreeRTOS中的中斷相關約定。本節講解FreeRTOS的訊息佇列。

訊息佇列

用於任務間通訊的資料結構,佇列可以在任務與任務間、中斷和任務間傳遞資訊,實現了任務接收來自其他任務或中斷的不固定長度的訊息,任務能夠從佇列裡面讀取訊息。

建立訊息佇列時 FreeRTOS 會先給訊息佇列分配一塊記憶體空間,這塊記憶體的大小等於

訊息佇列控制塊

大小加上(

單個訊息空間大小與訊息佇列長度的乘積

),接著再初始化訊息佇列,此時訊息佇列為空。每個訊息佇列都與訊息空間在同一段連續的記憶體空間中,在建立成功的時候,這些記憶體就被佔用了,只有刪除了訊息佇列的時候,這段記憶體才會被釋放掉,建立成功的時候就已經分配好每個訊息空間與訊息佇列的容量,無法更改。

訊息佇列有幾大特性如下圖所示:

「FreeRTOS原始碼解析(六)」訊息佇列

二、訊息佇列的應用

媽咪今天又賺錢了呢

暴躁的七哥

現代言情

免費閱讀

訊息佇列可以應用於傳送不定長訊息的場合,包括任務與任務間的訊息交換,佇列是FreeRTOS 主要的任務間通訊方式,可以在任務與任務間、中斷和任務間傳送資訊,送到佇列的訊息是透過複製方式實現的,佇列儲存的資料是原資料,不是原資料的引用。

三、原始碼分析

媽咪,你被顧總套路了

夏星空

現代言情

免費閱讀

「FreeRTOS原始碼解析(六)」訊息佇列

1、建立訊息佇列函式

「FreeRTOS原始碼解析(六)」訊息佇列

xQueueCreate()函式:

原型:

QueueHandle_t xQueueCreate( UBaseType_t uxQueueLength,UBaseType_t uxItemSize );

功能:用於建立一個新的佇列(動態)。

引數:

uxQueueLength :佇列能夠儲存的最大訊息單元數目,即佇列長度。

uxItemSize: 佇列中訊息單元的大小,以位元組為單位。

返回值:如果建立成功則返回一個佇列控制代碼,用於訪問建立的佇列。如果建立不成功則返回NULL,可能原因是建立佇列需要的 RAM 無法分配成功。

xQueueCreateStatic()函式:

原型:QueueHandle_t xQueueCreateStatic(UBaseType_t uxQueueLength,

UBaseType_t uxItemSize,

uint8_t *pucQueueStorageBuffer,

StaticQueue_t *pxQueueBuffer );

功能:用於建立一個新的佇列。

引數:

uxQueueLength: 佇列能夠儲存的最大單元數目,即佇列深度。

uxItemSize: 佇列中資料單元的長度,以位元組為單位。

pucQueueStorageBuffer :指標,指向一個 uint8_t 型別的陣列,陣列的大小至少有uxQueueLength* uxItemSize 個位元組。當 uxItemSize 為 0 時,pucQueueStorageBuffer 可以為 NULL。

pxQueueBuffer: 指標,指向 StaticQueue_t 型別的變數,該變數用於儲存佇列的資料結構。

返回值:如果建立成功則返回一個佇列控制代碼,用於訪問建立的佇列。如果建立不成功則返回NULL,可能原因是建立佇列需要的 RAM 無法分配成功。

2、寫佇列操作

重生之最強劍神

天運老貓

遊戲

免費閱讀

任務或者中斷服務程式可以給訊息佇列傳送訊息。

如果佇列未滿或者允許覆蓋入隊

,FreeRTOS 會將訊息複製到訊息佇列隊尾,

否則

,會根據使用者指定的阻塞超時時間進行阻塞。

阻塞時間中,如果佇列一直不允許入隊,該任務將保持阻塞狀態以等待佇列允許入隊。

當其它任務從其等待的佇列中讀取了資料(佇列變成未滿狀態)

,該任務將自動由阻塞態轉為就緒態。

當任務等待的時間超過了指定的阻塞時間

,即使佇列中還不允許入隊,任務也會自動從阻塞態轉移為就緒態,此時傳送訊息的任務或者中斷程式會收到一個錯誤碼 errQUEUE_FULL。

傳送緊急訊息時,傳送的位置是訊息佇列隊頭而非隊尾,接收者就能夠優先接收到緊急訊息,從而及時進行訊息處理。

「FreeRTOS原始碼解析(六)」訊息佇列

xQueueSend()函式:

原型:

BaseType_t xQueueSend(QueueHandle_t xQueue,

const void * pvItemToQueue,

TickType_t xTicksToWait);

功能:

用於向佇列尾部發送一個佇列訊息。

引數:

xQueue: 佇列控制代碼。

pvItemToQueue :指標,指向要傳送到佇列尾部的佇列訊息。

xTicksToWait :佇列滿時,等待佇列空閒的最大超時時間。如果佇列滿並 且xTicksToWait 被設定成 0,函式立刻返回。超時時間的單位為系統節拍週期,常量 portTICK_PERIOD_MS 用於輔助計算真實的時間,單位為 ms。如果 INCLUDE_vTaskSuspend 設定成 1,並且指定延時為 portMAX_DELAY 將導致任務掛起(沒有超時)。

返回值:訊息傳送成功成功返回 pdTRUE,否則返回 errQUEUE_FULL。

xQueueSendFromISR()函式:

原型:

BaseType_t xQueueSendFromISR(QueueHandle_t xQueue,

const void *pvItemToQueue,

BaseType_t *pxHigherPriorityTaskWoken);

功能:在中斷服務程式中用於向佇列尾部發送一個訊息。

引數:

xQueue: 佇列控制代碼。

pvItemToQueue :指標,指向要傳送到佇列尾部的訊息。

pxHigherPriorityTaskWoken: 如果入隊導致一個任務解鎖,並且解鎖的任務優先順序高於當前被中斷的任務,則將*pxHigherPriorityTaskWoken設定成 pdTRUE,然後在中斷退出前需要進行一次上下文切換, 去 執 行 被 喚醒 的 優 先 級 更高 的 任 務 。

返回值:訊息傳送成功返回 pdTRUE,否則返回 errQUEUE_FULL。

xQueueSendToFront()函式:

原型:

BaseType_t xQueueSendToFront( QueueHandle_t xQueue,

const void * pvItemToQueue,

TickType_t xTicksToWait );

功能:於向佇列隊首發送一個訊息。

引數:

xQueue: 佇列控制代碼。

pvItemToQueue: 指標,指向要傳送到佇列首部的訊息。

xTicksToWait :佇列滿時,等待佇列空閒的最大超時時間。如果佇列滿並 且xTicksToWait 被設定成 0,函式立刻返回。超時時間的單位為系統節拍週期,常量 portTICK_PERIOD_MS 用於輔助計算真實的時間,單位為 ms。如果 INCLUDE_vTaskSuspend 設定成 1,並且指定延時為 portMAX_DELAY 將導致任務無限阻塞(沒有超時)。

返回值:傳送訊息成功返回 pdTRUE,否則返回 errQUEUE_FULL。

xQueueSendToFrontFromISR()函式:

原型:

BaseType_t xQueueSendToFrontFromISR(QueueHandle_t xQueue,

const void *pvItemToQueue,

BaseType_t *pxHigherPriorityTaskWoken);

功能:在中斷服務程式中向訊息佇列隊首發送一個訊息。

引數:

xQueue :佇列控制代碼。

pvItemToQueue :指標,指向要傳送到隊首的訊息。

pxHigherPriorityTaskWoken :如果入隊導致一個任務解鎖,並且解鎖的任務優先順序高於當前被中斷的任務,則將*pxHigherPriorityTaskWoken設定成 pdTRUE,然後在中斷退出前需要進行一次上下文切換, 去 執 行 被 喚醒 的 優 先 級 更高 的 任 務 。

返回值:佇列項投遞成功返回 pdTRUE,否則返回 errQUEUE_FULL。

3、讀訊息佇列

任務讀佇列中的訊息時,可以指定一個阻塞超時時間,僅當訊息佇列中有訊息的時候,任務才能讀取到訊息。阻塞期間,如果佇列為空,任務將保持阻塞狀態以等待佇列資料有效。當其它任務或中斷服務程式往其等待的佇列中寫入了資料,任務將自動由阻塞態轉為就緒態。當任務等待的時間超過了指定的阻塞時間,即使佇列中尚無有效資料,任務也會自動從阻塞態轉移為就緒態。

「FreeRTOS原始碼解析(六)」訊息佇列

xQueueReceive()函式:

原型:

BaseType_t xQueueReceive(QueueHandle_t xQueue,

void *pvBuffer,

TickType_t xTicksToWait);

功能:用於從一個佇列中接收訊息,並把接收的訊息從佇列中刪除。

引數:

xQueue :佇列控制代碼。

pvBuffer :指標,指向接收到要儲存的資料。

xTicksToWait :佇列空時,阻塞超時的最大時間。如果該引數設定為 0,函式立刻返回。超時時間的單位為系統節拍週期,常量 portTICK_PERIOD_MS 用於輔助計算真實的時間,單位為 ms。如果 INCLUDE_vTaskSuspend 設定成 1,並且指定延時為 portMAX_DELAY 將導致任務無限阻塞(沒有超時)。

返回值:佇列項接收成功返回 pdTRUE,否則返回 pdFALSE。

xQueueReceiveFromISR()函式:

原型:

BaseType_t xQueueReceiveFromISR(QueueHandle_t xQueue,

void *pvBuffer,

BaseType_t *pxHigherPriorityTaskWoken);

功能:在中斷中從一個佇列中接收訊息,並從佇列中刪除該訊息。

引數:

xQueue: 佇列控制代碼。

pvBuffer :指標,指向接收到要儲存的資料。

pxHigherPriorityTaskWoken: 任務在往佇列投遞資訊時,如果佇列滿,則任務將阻塞在該佇列上。如果 xQueueReceiveFromISR()到賬了一個任 務 解 鎖 了 則將 *pxHigherPriorityTaskWoken設定為pdTRUE,否 則*pxHigherPriorityTaskWoken 的 值將不變。

返回值:佇列項接收成功返回 pdTRUE,否則返回 pdFALSE。

xQueuePeekFromISR()函式:

原型:

BaseType_t xQueuePeekFromISR(QueueHandle_t xQueue,

void *pvBuffer);

功能:在中斷中從一個佇列中接收訊息,但並不會把訊息從該佇列中移除。

引數:

xQueue: 佇列控制代碼。

pvBuffer :指標,指向接收到要儲存的資料。

返回值:佇列項接收(peek)成功返回 pdTRUE,否則返回 pdFALSE。

4、刪除訊息佇列

極品花都神醫

莊小賢

都市

免費閱讀

訊息佇列刪除函式是根據訊息佇列控制代碼直接刪除的,刪除之後這個訊息佇列的所有資訊都會被系統回收清空,而且不能再次使用這個訊息隊列了。

「FreeRTOS原始碼解析(六)」訊息佇列

對傳入的訊息佇列控制代碼進行檢查,如果訊息佇列是有效的允許進行刪除操作。將訊息佇列從登錄檔中刪除。用的訊息佇列是動態分配記憶體的,所以需要呼叫 vPortFree()函式來釋放訊息佇列的記憶體。

「FreeRTOS原始碼解析(六)」訊息佇列

想了解更多精彩內容,快來關注嵌入式的那點事兒

「FreeRTOS原始碼解析(一)」連結串列

「FreeRTOS原始碼解析(二)」任務

「FreeRTOS原始碼解析(三)」就緒列表和排程

「FreeRTOS原始碼解析(四)」臨界段的保護

Top