新聞中心

EEPW首頁(yè) > 嵌入式系統(tǒng) > 設(shè)計(jì)應(yīng)用 > μC/OS-II的任務(wù)之間的通訊與同步

μC/OS-II的任務(wù)之間的通訊與同步

作者: 時(shí)間:2016-10-08 來(lái)源:網(wǎng)絡(luò) 收藏

{

INT8Uerr;

for(;;){

OSMboxPost(MboxTimeDly,(void*)1);/*取消任務(wù)1的延時(shí)*/

.

.

}

}

6.8 消息隊(duì)列

消息隊(duì)列是μC/OS-II中另一種通訊機(jī)制, 它可以使一個(gè)任務(wù)或者中斷服務(wù)子程序向另一個(gè)任務(wù)發(fā)送以指針方式定義的變量。因具體的應(yīng)用有所不同,每個(gè)指針指向的數(shù)據(jù)結(jié)構(gòu)變量也有所不同。為了使用μC/OS-II的消息隊(duì)列功能,需要在OS_CFG.H文件中,將OS_Q_EN常數(shù)設(shè)置為1,并且通過常數(shù)OS_MAX_QS來(lái)決定μC/OS-II支持的最多消息隊(duì)列數(shù)。

在使用一個(gè)消息隊(duì)列之前, 必須先建立該消息隊(duì)列。 這可以通過調(diào)用OSQCreate()函數(shù) (見

6.07.01節(jié)),并定義消息隊(duì)列中的單元數(shù)(消息數(shù))來(lái)完成。

μC/OS-II提供了7個(gè)對(duì)消息隊(duì)列進(jìn)行操作的函數(shù):OSQCreate(),OSQPend(),OSQPost(),

OSQPostFront(),OSQAccept(),OSQFlush()和OSQQuery()函數(shù)。圖F6.7是任務(wù)、中斷服務(wù)子程序和消息隊(duì)列之間的關(guān)系。其中,消息隊(duì)列的符號(hào)很像多個(gè)郵箱。實(shí)際上,我們可以將消息隊(duì)列看作時(shí)多個(gè)郵箱組成的數(shù)組,只是它們共用一個(gè)等待任務(wù)列表。每個(gè)指針?biāo)赶虻臄?shù)據(jù)結(jié)構(gòu)是由具體的應(yīng)用程序決定的。N代表了消息隊(duì)列中的總單元數(shù)。當(dāng)調(diào)用OSQPend()或者OSQAccept()之前,調(diào)用N次OSQPost()或者OSQPostFront()就會(huì)把消息隊(duì)列填滿。從圖F6.7中可以看出,一個(gè)任務(wù)或者中斷服務(wù)子程序可以調(diào)用OSQPost(),OSQPostFront(),OSQFlush()或者OSQAccept()函數(shù)。但是,只有任務(wù)可以調(diào)用OSQPend()和OSQQuery()函數(shù)。

圖F6.7任務(wù)、中斷服務(wù)子程序和消息隊(duì)列之間的關(guān)系——Figure6.7

圖F6.8是實(shí)現(xiàn)消息隊(duì)列所需要的各種數(shù)據(jù)結(jié)構(gòu)。這里也需要事件控制塊來(lái)記錄等待任務(wù)列表[F6.8(1)],而且,事件控制塊可以使多個(gè)消息隊(duì)列的操作和信號(hào)量操作、郵箱操作相同的代碼。當(dāng)建立了一個(gè)消息隊(duì)列時(shí),一個(gè)隊(duì)列控制塊(OS_Q結(jié)構(gòu),見OS_Q.C文件)也同時(shí)被建立,并通過OS_EVENT中的.OSEventPtr域鏈接到對(duì)應(yīng)的事件控制塊[F6.8(2)]。 在建立一個(gè)消息隊(duì)列之前,必須先定義一個(gè)含有與消息隊(duì)列最大消息數(shù)相同個(gè)數(shù)的指針數(shù)組[F6.8(3)]。數(shù)組的起始地址以及數(shù)組中的元素?cái)?shù)作為參數(shù)傳遞給OSQCreate()函數(shù)。事實(shí)上,如果內(nèi)存占用了連續(xù)的地址空間,也沒有必要非得使用指針數(shù)組結(jié)構(gòu)。

文件OS_CFG.H中的常數(shù)OS_MAX_QS定義了在μC/OS-II中可以使用的最大消息隊(duì)列數(shù),這個(gè)值最小應(yīng)為2。μC/OS-II在初始化時(shí)建立一個(gè)空閑的隊(duì)列控制塊鏈表,如圖F6.9所示。

圖F6.8用于消息隊(duì)列的數(shù)據(jù)結(jié)構(gòu)——Figure6.8

圖F6.9空閑隊(duì)列控制塊鏈表——Figure6.9

隊(duì)列控制塊是一個(gè)用于維護(hù)消息隊(duì)列信息的數(shù)據(jù)結(jié)構(gòu),它包含了以下的一些域。這里,仍然在各個(gè)變量前加入一個(gè)[.]來(lái)表示它們是數(shù)據(jù)結(jié)構(gòu)中的一個(gè)域。

.OSQPtr在空閑隊(duì)列控制塊中鏈接所有的隊(duì)列控制塊。一旦建立了消息隊(duì)列,該域就不再有用了。

.OSQStart是指向消息隊(duì)列的指針數(shù)組的起始地址的指針。用戶應(yīng)用程序在使用消息隊(duì)列之前必須先定義該數(shù)組。

.OSQEnd是指向消息隊(duì)列結(jié)束單元的下一個(gè)地址的指針。該指針使得消息隊(duì)列構(gòu)成一個(gè)循環(huán)的緩沖區(qū)。

.OSQIn 是指向消息隊(duì)列中插入下一條消息的位置的指針。當(dāng).OSQIn和.OSQEnd相等時(shí),.OSQIn被調(diào)整指向消息隊(duì)列的起始單元。

.OSQOut 是指向消息隊(duì)列中下一個(gè)取出消息的位置的指針。當(dāng).OSQOut和.OSQEnd相等時(shí),.OSQOut被調(diào)整指向消息隊(duì)列的起始單元。

.OSQSize 是消息隊(duì)列中總的單元數(shù)。該值是在建立消息隊(duì)列時(shí)由用戶應(yīng)用程序決定的。在μC/OS-II中,該值最大可以是65,535。

.OSQEntries 是消息隊(duì)列中當(dāng)前的消息數(shù)量。當(dāng)消息隊(duì)列是空的時(shí),該值為0。當(dāng)消息隊(duì)列滿了以后,該值和.OSQSize值一樣。在消息隊(duì)列剛剛建立時(shí),該值為0。

消息隊(duì)列最根本的部分是一個(gè)循環(huán)緩沖區(qū),如圖F6.10。其中的每個(gè)單元包含一個(gè)指針。

隊(duì)列未滿時(shí),.OSQIn[F6.10(1)]指向下一個(gè)存放消息的地址單元。如果隊(duì)列已滿(.OSQEntries

與.OSQSize相等),.OSQIn[F6.10(3)]則與.OSQOut指向同一單元。如果在.OSQIn指向的單元

插入新的指向消息的指針,就構(gòu)成 FIFO(First-In-First-Out)隊(duì)列。相反,如果在.OSQOut

指向的單元的下一個(gè)單元插入新的指針,就構(gòu)成LIFO隊(duì)列(Last-In-First-Out)[F6.10(2)]。

當(dāng).OSQEntries和.OSQSize相等時(shí),說明隊(duì)列已滿。消息指針總是從.OSQOut[F6.10(4)]指向

的單元取出。指針.OSQStart和.OSQEnd [F6.10(5)]定義了消息指針數(shù)組的頭尾,以便在.OSQIn

和.OSQOut到達(dá)隊(duì)列的邊緣時(shí),進(jìn)行邊界檢查和必要的指針調(diào)整,實(shí)現(xiàn)循環(huán)功能。

圖F6.10消息隊(duì)列是一個(gè)由指針組成的循環(huán)緩沖區(qū)——Figure6.10

6.8.1 建立一個(gè)消息隊(duì)列,OSQCreate()

程序清單L6.21是OSQCreate()函數(shù)的源代碼。該函數(shù)需要一個(gè)指針數(shù)組來(lái)容納指向各個(gè)消息的指針。該指針數(shù)組必須聲名為void類型。

OSQCreate()首先從空閑事件控制塊鏈表中取得一個(gè)事件控制塊(見圖F6.3)[L6.21(1)],并對(duì)剩下的空閑事件控制塊列表的指針做相應(yīng)的調(diào)整,使它指向下一個(gè)空閑事件控制塊[L6.21(2)]。 接著, OSQCreate()函數(shù)從空閑隊(duì)列控制塊列表中取出一個(gè)隊(duì)列控制塊[L6.21(3)]。

如果有空閑隊(duì)列控制塊是可以的,就對(duì)其進(jìn)行初始化[L6.21(4)]。然后該函數(shù)將事件控制塊的類型設(shè)置為OS_EVENT_TYPE_Q[L6.21(5)],并使其.OSEventPtr指針指向隊(duì)列控制塊[L6.21(6)]。OSQCreate()還要調(diào)用OSEventWaitListInit()函數(shù)對(duì)事件控制塊的等待任務(wù)列表初始化[見6.01節(jié),初始化一個(gè)事件控制塊,OSEventWaitListInit()][L6.21(7)]。因?yàn)榇藭r(shí)消息隊(duì)列正在初始化,顯然它的等待任務(wù)列表是空的。最后,OSQCreate()向它的調(diào)用函數(shù)返回一個(gè)指向事件控制塊的指針[L6.21(9)]。該指針將在調(diào)用OSQPend(),OSQPost(),OSQPostFront(),OSQFlush(),OSQAccept()和OSQQuery()等消息隊(duì)列處理函數(shù)時(shí)使用。因此,該指針可以被看作是對(duì)應(yīng)消息隊(duì)列的句柄。值得注意的是,如果此時(shí)沒有空閑的事件控制塊,OSQCreate()函數(shù)將返回一個(gè)NULL指針。如果沒有隊(duì)列控制塊可以使用,為了不浪費(fèi)事件控制塊資源,OSQCreate()函數(shù)將把剛剛?cè)〉玫氖录刂茐K重新返還給空閑事件控制塊列表[L6.21(8)]。



關(guān)鍵詞:

評(píng)論


相關(guān)推薦

技術(shù)專區(qū)

關(guān)閉