1.前言
freeRTOS中所有任務的通信和同步機制都是基於隊列來實現。
2.隊列的特點
圖 隊列的讀寫操作
- 隊列的數據存儲
(1)隊列可以保存有限個具有確定長度的數據單元,隊列可以保存的最大單元數目稱為隊列的深度;
(2)隊列創建時需要設定隊列深度和每個單元的大小;
(3)隊列先進先出
- 多任務存取
隊列是內核中具有獨立權限的對象,不屬於任何任務,可以有多個任務進行讀寫
- 讀隊列阻塞
(1)任務讀取隊列數據時可以指定一個阻塞超時時間;
(2)未超過阻塞超時時間,隊列為空,任務將保持阻塞狀態;
(3)隊列中寫入數據,任務將由阻塞態轉為就緒態;或者阻塞時間超過了阻塞超時時間,任務也將由阻塞態轉為就緒態;
(4)可能會有多個任務處於阻塞態等待讀取隊列中的數據;
(5)隊列數據有效,優先級最高的任務會解除阻塞,相同優先級則等待時間最長的任務會解除阻塞
- 寫隊列阻塞
(1)任務寫入隊列數據時可以指定一個阻塞超時時間;
(2)未超過阻塞超時時間,隊列滿,任務將保持阻塞狀態;
(3)隊列有空閑,任務將由阻塞態轉為就緒態;或者阻塞時間超過了阻塞超時時間,任務也將由阻塞態轉為就緒態;
(4)可能會有多個任務處於阻塞態等待向隊列中的寫入數據;
(5)隊列有空閑,優先級最高的任務會解除阻塞,相同優先級則等待時間最長的任務會解除阻塞
3. 使用隊列傳遞復合數據類型
圖 結構體用於隊列傳遞舉例
一般是通過傳遞復合數據類型的指針來實現
4.使用隊列傳遞指針
- 如果隊列存儲的數據單元尺寸較大,那最好是利用隊列來傳遞數據的指針
- 利用隊列傳遞指針時,一定要十分小心地做到以下兩點
(1)指針指向的內存空間的所有權必須明確
不會有任意兩個任務同時修改共享內存中的數據 .原則上,共享內存在其指針發送到隊列之前,其內容只允許被發送任務訪問;
共享內存指針從隊列中被讀出之后,其內容亦只允許被接收任務訪問
(2)指針指向的內存空間必須有效
如果指針指向的內存空間是動態分配的,只應該有一個任務負責對其進行內存釋放。當這段內存空間被釋放之后,就不應該有任何一個任務再訪問這段空間
注:切忌用指針訪問任務棧上分配的空間。因為當棧幀發生改變后,棧上的數據將不再有效
5.隊列操作API
API原型 | 函數說明 | 參數說明 | 返回值 |
xQueueCreate( uxQueueLength, uxItemSize ) | 用於創建一個隊列,並返回一個 xQueueHandle 句柄以便於對其創建的隊列進行引用 。當創建隊列時, FreeRTOS 從堆空間中分配內存空間。分配的空間用於存儲隊列數據結構本身以及隊列中包含的數據單元。如果內存堆中沒有足夠的空間來創建隊列,xQueueCreate()將返回 NULL |
隊列能夠存儲的最大單元數目,即隊列深度。
隊列中數據單元的長度,以字節為單位 |
NULL 表示沒有足夠的堆空間分配給隊列而導致創建失敗。 非 NULL 值表示隊列創建成功。此返回值應當保存下來,以作為 操作此隊列的句柄 |
xQueueSendToBack( xQueue, pvItemToQueue, xTicksToWait ) | xQueueSendToBack()用於將數據發送到隊列尾 |
目標隊列的句柄
發送數據的指針
阻塞超時時間。如果在發送時隊列已滿,這個時間即是任務處於阻塞態等待隊列空間有效的最長等待時間 |
|
xQueueSendToFront( xQueue, pvItemToQueue, xTicksToWait ) | 用於將數據發送到隊列首 |
pdPASS errQUEUE_FULL |
|
xQueueSendToFrontFromISR( xQueue, pvItemToQueue, pxHigherPriorityTaskWoken ) | 用於在中斷服務中實現相同的功能 |
||
xQueueSendToBackFromISR( xQueue, pvItemToQueue, pxHigherPriorityTaskWoken ) | 用於在中斷服務中實現相同的功能 | ||
xQueueReceive xQueuePeek |
用於從隊列中接收(讀取)數據單元。接收到的單元同時會從隊列中刪除 也是從從隊列中接收數據單元,不同的是並不從隊列中刪出接收到的單元 注:切記不要在中斷服務例程中調用 xQueueRceive()和 xQueuePeek() |
||
xQueueReceiveFromISR |
|||
uxQueueMessagesWaiting |
用於查詢隊列中當前有效數據單元個數 切記不要在中斷服務例程中調用 uxQueueMessagesWaiting() |
||
uxQueueMessagesWaitingFromISR |
6. 執行流程舉例
send1和sender2負責寫隊列,receiver負責讀隊列: