您現在的位置是:首頁 > 足球
「FreeRTOS原始碼解析(六)」訊息佇列
- 由 嵌入式的那點事兒 發表于 足球
- 2022-07-10
鏈式佇列入隊修改頭指標嗎
##熱愛記錄、鍾愛分享、酷愛生活
一、前言
甜妻來襲:總裁乖乖就範
期許
現代言情
免費閱讀
本期文章講解FreeRTOS實時作業系統原始碼,主要是原始碼分析,實操很少。上節講了FreeRTOS中斷管理功能,詳細講述了異常和中斷的關係,以及FreeRTOS中的中斷相關約定。本節講解FreeRTOS的訊息佇列。
訊息佇列
是
用於任務間通訊的資料結構,佇列可以在任務與任務間、中斷和任務間傳遞資訊,實現了任務接收來自其他任務或中斷的不固定長度的訊息,任務能夠從佇列裡面讀取訊息。
建立訊息佇列時 FreeRTOS 會先給訊息佇列分配一塊記憶體空間,這塊記憶體的大小等於
訊息佇列控制塊
大小加上(
單個訊息空間大小與訊息佇列長度的乘積
),接著再初始化訊息佇列,此時訊息佇列為空。每個訊息佇列都與訊息空間在同一段連續的記憶體空間中,在建立成功的時候,這些記憶體就被佔用了,只有刪除了訊息佇列的時候,這段記憶體才會被釋放掉,建立成功的時候就已經分配好每個訊息空間與訊息佇列的容量,無法更改。
訊息佇列有幾大特性如下圖所示:
二、訊息佇列的應用
媽咪今天又賺錢了呢
暴躁的七哥
現代言情
免費閱讀
訊息佇列可以應用於傳送不定長訊息的場合,包括任務與任務間的訊息交換,佇列是FreeRTOS 主要的任務間通訊方式,可以在任務與任務間、中斷和任務間傳送資訊,送到佇列的訊息是透過複製方式實現的,佇列儲存的資料是原資料,不是原資料的引用。
三、原始碼分析
媽咪,你被顧總套路了
夏星空
現代言情
免費閱讀
1、建立訊息佇列函式
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。
傳送緊急訊息時,傳送的位置是訊息佇列隊頭而非隊尾,接收者就能夠優先接收到緊急訊息,從而及時進行訊息處理。
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、讀訊息佇列
任務讀佇列中的訊息時,可以指定一個阻塞超時時間,僅當訊息佇列中有訊息的時候,任務才能讀取到訊息。阻塞期間,如果佇列為空,任務將保持阻塞狀態以等待佇列資料有效。當其它任務或中斷服務程式往其等待的佇列中寫入了資料,任務將自動由阻塞態轉為就緒態。當任務等待的時間超過了指定的阻塞時間,即使佇列中尚無有效資料,任務也會自動從阻塞態轉移為就緒態。
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、刪除訊息佇列
極品花都神醫
莊小賢
都市
免費閱讀
訊息佇列刪除函式是根據訊息佇列控制代碼直接刪除的,刪除之後這個訊息佇列的所有資訊都會被系統回收清空,而且不能再次使用這個訊息隊列了。
對傳入的訊息佇列控制代碼進行檢查,如果訊息佇列是有效的允許進行刪除操作。將訊息佇列從登錄檔中刪除。用的訊息佇列是動態分配記憶體的,所以需要呼叫 vPortFree()函式來釋放訊息佇列的記憶體。
想了解更多精彩內容,快來關注嵌入式的那點事兒
「FreeRTOS原始碼解析(一)」連結串列
「FreeRTOS原始碼解析(二)」任務
「FreeRTOS原始碼解析(三)」就緒列表和排程
「FreeRTOS原始碼解析(四)」臨界段的保護