FreeRTOS實時操作系統(tǒng)隊列基礎
前言
本文介紹隊列的基本知識,詳細源碼分析見FreeRTOS進階之隊列示例分析
1.FreeRTOS隊列
隊列是主要的任務間通訊方式。可以在任務與任務間、中斷和任務間傳送信息。大多數(shù)情況下,隊列用于具有線程保護的FIFO(先進先出)緩沖區(qū):新數(shù)據(jù)放在隊列的后面。當然,數(shù)據(jù)也可以放在隊列的前面,在下一篇講隊列API函數(shù)時,會涉及到數(shù)據(jù)的存放位置。
圖1-1:讀寫隊列
圖1-1所示的隊列中,最多能保存5個項目,并且假設隊列永遠不會滿。任務A使用API函數(shù)xQueueSendToBack()向隊列發(fā)送數(shù)據(jù),每次發(fā)送一個數(shù)據(jù),新入隊的數(shù)據(jù)置于上一次入隊數(shù)據(jù)的后面。任務B使用API函數(shù)xQueueReceive()將數(shù)據(jù)從隊列取出,先入隊的數(shù)據(jù)先出隊。
2.使用模型:最簡單、最靈活
通常情況下,魚和熊掌是不可兼得的,但FreeRTOS的隊列用戶模型管理卻兼顧簡單和靈活。發(fā)送到隊列的消息是通過拷貝實現(xiàn)的,這意味著隊列存儲的數(shù)據(jù)是原數(shù)據(jù),而不是原數(shù)據(jù)的引用。FreeRTOS隊列具有以下特性:
C變量(整形、簡單結(jié)構(gòu)體等等)中的簡單信息可以直接傳送到隊列。這樣就不需要為信息分配緩存也不需要再進行什么拷貝工作。同樣的,信息可以直接從隊列讀取到C變量中。用直接拷貝的方法入隊,可以允許任務立即覆寫已經(jīng)入隊的變量或者緩存,實際上隊列中已經(jīng)保存了這些變量或緩沖區(qū)攜帶的信息。因為變量中的數(shù)據(jù)內(nèi)容是以拷貝的方式入隊的,所以變量自身是允許重復使用的。發(fā)送信息的任務和接收信息的任務并不需要就哪個任務擁有信息、哪個任務釋放信息(當信息不再使用時)而達成一致。
隊列是通過拷貝傳遞數(shù)據(jù)的,但這并不妨礙隊列通過引用來傳遞數(shù)據(jù)。當信息的大小到達一個臨界點后,逐字節(jié)拷貝整個信息是不實際的,可以定義一個指針隊列,只拷貝指向消息的指針來代替整個信息拷貝。FreeRTOS+UDP IP棧例程正是使用這種方法向FreeRTOS協(xié)議棧傳遞大量網(wǎng)絡數(shù)據(jù)的。
隊列內(nèi)存區(qū)域分配由內(nèi)核完成。
變長消息可以通過定義保存一個結(jié)構(gòu)體變量的隊列實現(xiàn),結(jié)構(gòu)體一個成員指向要入隊的緩存,另一個成員保存緩存數(shù)據(jù)的大小。
單個隊列可以接收不同類型信息,并且信息可以來自不同的位置。通過定義保存一個結(jié)構(gòu)體變量的隊列來實現(xiàn),結(jié)構(gòu)體的一個成員保存信息類型,另一個成員保存信息數(shù)據(jù)(或者指向信息數(shù)據(jù)的指針)。數(shù)據(jù)如何解讀取決于信息類型。管理FreeRTOS+UDP IP棧的任務正是使用單個隊列接收ARP定時器時間通知、以太網(wǎng)硬件傳送來的數(shù)據(jù)包、從應用層傳送來的數(shù)據(jù)包、網(wǎng)絡關閉事件等等。
天生適用于那些內(nèi)存保護(MPU)場合。一個具有內(nèi)存區(qū)域保護的任務可以向另一個具有內(nèi)存區(qū)域保護的任務傳遞數(shù)據(jù),因為調(diào)用隊列發(fā)送函數(shù)會引起RTOS提升微控制器特權級別。只有RTOS(具有所有特權)才可以訪問隊列存儲區(qū)域。
在中斷函數(shù)中使用獨立的API。將RTOS任務API和中斷服務例程API分來實現(xiàn)意味著可以避免執(zhí)行時的上下文調(diào)用檢查開銷,還意味著在大多數(shù)情況下,與其它RTOS產(chǎn)品相比,用戶創(chuàng)建中斷服務例程會更簡單。
API函數(shù)很簡單。
3.隊列阻塞
API函數(shù)允許指定阻塞時間。
每當任務企圖從一個空的隊列讀取數(shù)據(jù)時,任務會進入阻塞狀態(tài)(這樣任務不會消耗任何CPU時間并且另一個任務可以運行)直到隊列中出現(xiàn)有效數(shù)據(jù)或者阻塞時間到期。
每當任務企圖向一個滿的隊列寫數(shù)據(jù)時,任務會進入阻塞狀態(tài),直到隊列中出現(xiàn)有效空間或者阻塞時間到期。
如果多個任務阻塞在一個隊列上,那么最高優(yōu)先級別的任務會第一個解除阻塞。
注:中斷程序中必須使用“FromISR”結(jié)尾的API函數(shù)!
總結(jié)一下隊列的基本用法:
定義一個隊列句柄變量,用于保存創(chuàng)建的隊列:xQueueHandle xQueue1;
使用API函數(shù)xQueueCreate()創(chuàng)建一個隊列。
如果希望使用先進先出隊列,使用API函數(shù)xQueueSend()或xQueueSendToBack()向隊列投遞隊列項。如果希望使用后進先出隊列,使用API函數(shù)xQueueSendToFront()向隊列投遞隊列項。如果在中斷服務程序中,切記使用它們的帶中斷保護版本。
使用API函數(shù)xQueueReceive()從隊列讀取隊列項,如果在中斷服務程序中,切記使用它們的帶中斷保護版本。
以上使用的API函數(shù)將在下一篇文章中介紹,更多關于FreeRTOS隊列基礎的資料請關注腳本之家其它相關文章!
相關文章
FreeRTOS實時操作系統(tǒng)的任務創(chuàng)建與任務切換
這篇文章主要為大家介紹了FreeRTOS實時操作系統(tǒng)的任務創(chuàng)建與任務切換,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步早日升職加薪2022-04-04FreeRTOS進階系統(tǒng)節(jié)拍時鐘示例的完全解析
這篇文章主要為大家介紹了FreeRTOS進階系統(tǒng)節(jié)拍時鐘示例的完全解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步早日升職加薪2022-04-04FreeRTOS實時操作系統(tǒng)之可視化追蹤調(diào)試
這篇文章主要為大家介紹了FreeRTOS實時操作系統(tǒng)之可視化追蹤調(diào)試的示例解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步早日升職加薪2022-04-04FreeRTOS動態(tài)內(nèi)存分配管理heap_2示例
這篇文章主要介紹了FreeRTOS動態(tài)內(nèi)存分配管理heap_2示例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步早日升職加薪2022-04-04FreeRTOS實時操作系統(tǒng)的內(nèi)存管理分析
這篇文章主要為大家介紹了FreeRTOS實時操作系統(tǒng)的內(nèi)存管理的示例分析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步早日升職加薪2022-04-04