新聞中心

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

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

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

表T6.1OSMapTbl[]

從等待任務(wù)列表中刪除一個任務(wù)的算法則正好相反,如程序清單L6.3所示。

程序清單L6.3從等待任務(wù)列表中刪除一個任務(wù)

if((pevent->OSEventTbl[prio>>3]=~OSMapTbl[prio0x07])==0){

pevent->OSEventGrp=~OSMapTbl[prio>>3];

}

該代碼清除了任務(wù)在.OSEventTbl[]中的相應(yīng)位,并且,如果其所在的組中不再有處于等待該事件的任務(wù)時(即.OSEventTbl[prio>>3]為0),將.OSEventGrp中的相應(yīng)位也清除了。和上面的由任務(wù)優(yōu)先級確定該任務(wù)在等待表中的位置的算法類似,從等待任務(wù)列表中查找處于等待狀態(tài)的最高優(yōu)先級任務(wù)的算法,也不是從.OSEventTbl[0]開始逐個查詢,而是采用了查找另一個表OSUnMapTbl[256](見文件OS_CORE.C)。這里,用于索引的8位分別代表對應(yīng)的8組中有任務(wù)處于等待狀態(tài),其中的最低位具有最高的優(yōu)先級。用這個值索引,首先得到最高優(yōu)先級任務(wù)所在的組的位置(0~7之間的一個數(shù))。然后利用.OSEventTbl[]中對應(yīng)字節(jié)再在OSUnMapTbl[]中查找,就可以得到最高優(yōu)先級任務(wù)在組中的位置(也是0~7之間的一個數(shù))。

這樣,最終就可以得到處于等待該事件狀態(tài)的最高優(yōu)先級任務(wù)了。程序清單L6.4是該算法的具體實現(xiàn)代碼。

程序清單L6.4在等待任務(wù)列表中查找最高優(yōu)先級的任務(wù)

y=OSUnMapTbl[pevent->OSEventGrp];

x=OSUnMapTbl[pevent->OSEventTbl[y]];

prio=(y3)+x;

舉例來說,如果.OSEventGrp的值是01101000(二進制),而對應(yīng)的OSUnMapTbl[.OSEventGrp]值為3,說明最高優(yōu)先級任務(wù)所在的組是3。類似地,如果.OSEventTbl[3]的值是11100100(二進制),OSUnMapTbl[.OSEventTbl[3]]的值為2,則處于等待狀態(tài)的任務(wù)的最高優(yōu)先級是3×8+2=26。

在μC/OS-II中,事件控制塊的總數(shù)由用戶所需要的信號量、郵箱和消息隊列的總數(shù)決定。

該值由OS_CFG.H中的#defineOS_MAX_EVENTS定義。 在調(diào)用OSInit()時 (見3.11節(jié), μC/OS-II

的初始化),所有事件控制塊被鏈接成一個單向鏈表——空閑事件控制塊鏈表(圖F6.3)。每

當建立一個信號量、郵箱或者消息隊列時,就從該鏈表中取出一個空閑事件控制塊,并對它進

行初始化。因為信號量、郵箱和消息隊列一旦建立就不能刪除,所以事件控制塊也不能放回到

空閑事件控制塊鏈表中。

圖F6.3空閑事件控制塊鏈表——Figure6.3

對于事件控制塊進行的一些通用操作包括:

y 初始化一個事件控制塊

y 使一個任務(wù)進入就緒態(tài)

y 使一個任務(wù)進入等待該事件的狀態(tài)

y 因為等待超時而使一個任務(wù)進入就緒態(tài)

為了避免代碼重復(fù)和減短程代碼長度,μC/OS-II將上面的操作用4個系統(tǒng)函數(shù)實現(xiàn),它們是:OSEventWaitListInit(),OSEventTaskRdy(),OSEventWait()和OSEventTO()。

6.2 初始化一個事件控制塊,OSEventWaitListInit()

程序清單L6.5是函數(shù)OSEventWaitListInit()的源代碼。當建立一個信號量、郵箱或者消息隊列時,相應(yīng)的建立函數(shù)OSSemInit(),OSMboxCreate(),或者OSQCreate()通過調(diào)用

OSEventWaitListInit()對事件控制塊中的等待任務(wù)列表進行初始化。該函數(shù)初始化一個空的等

待任務(wù)列表,其中沒有任何任務(wù)。該函數(shù)的調(diào)用參數(shù)只有一個,就是指向需要初始化的事件控

制塊的指針pevent。

程序清單L6.5初始化ECB塊的等待任務(wù)列表

voidOSEventWaitListInit(OS_EVENT*pevent)

{

INT8Ui;

pevent->OSEventGrp=0x00;

for(i=0;i

pevent->OSEventTbl[i]=0x00;

}

}

6.3 使一個任務(wù)進入就緒態(tài),OSEventTaskRdy()

程序清單L6.6是函數(shù)OSEventTaskRdy()的源代碼。當發(fā)生了某個事件,該事件等待任務(wù)列表中的最高優(yōu)先級任務(wù)(HighestPriorityTask–HPT)要置于就緒態(tài)時,該事件對應(yīng)的OSSemPost(),OSMboxPost(),OSQPost(),和OSQPostFront()函數(shù)調(diào)用OSEventTaskRdy()實現(xiàn)該操作。換句話說,該函數(shù)從等待任務(wù)隊列中刪除HPT任務(wù)(HighestPriorityTask),并把該任務(wù)置于就緒態(tài)。圖F6.4給出了OSEventTaskRdy()函數(shù)最開始的4個動作。

該函數(shù)首先計算HPT任務(wù)在.OSEventTbl[]中的字節(jié)索引[L6.6/F6.4(1)],其結(jié)果是一個從0到OS_LOWEST_PRIO/8+1之間的數(shù),并利用該索引得到該優(yōu)先級任務(wù)在.OSEventGrp中的位屏蔽碼[L6.6/F6.4(2)](從表T6.1可以得到該值)。然后,OSEventTaskRdy()函數(shù)判斷HPT任務(wù)在.OSEventTbl[]中相應(yīng)位的位置[L6.6/F6.4(3)], 其結(jié)果是一個從0到OS_LOWEST_PRIO/8+1

之間的數(shù),以及相應(yīng)的位屏蔽碼[L6.6/F6.4(4)]。根據(jù)以上結(jié)果,OSEventTaskRdy()函數(shù)計算

出HPT任務(wù)的優(yōu)先級[L6.6(5)],然后就可以從等待任務(wù)列表中刪除該任務(wù)了[L6.6(6)]。

任務(wù)的任務(wù)控制塊中包含有需要改變的信息。知道了HPT任務(wù)的優(yōu)先級,就可以得到指向該任務(wù)的任務(wù)控制塊的指針[L6.6(7)]。因為最高優(yōu)先級任務(wù)運行條件已經(jīng)得到滿足,必須停止OSTimeTick()函數(shù)對.OSTCBDly域的遞減操作,所以O(shè)SEventTaskRdy()直接將該域清澈0[L6.6(8)]。因為該任務(wù)不再等待該事件的發(fā)生,所以O(shè)SEventTaskRdy()函數(shù)將其任務(wù)控制塊中指向事件控制塊的指針指向NULL[L6.6(9)]。如果OSEventTaskRdy()是由OSMboxPost()或者OSQPost()調(diào)用的,該函數(shù)還要將相應(yīng)的消息傳遞給HPT,放在它的任務(wù)控制塊中[L6.6(10)]。

另外,當OSEventTaskRdy()被調(diào)用時,位屏蔽碼msk作為參數(shù)傳遞給它。該參數(shù)是用于對任務(wù)控制塊中的位清零的位屏蔽碼,和所發(fā)生事件的類型相對應(yīng)[L6.6(11)]。最后,根據(jù).OSTCBStat判斷該任務(wù)是否已處于就緒狀態(tài)[L6.6(12)]。如果是,則將HPT插入到μC/OS-II的就緒任務(wù)列表中[L6.6(13)]。注意,HPT任務(wù)得到該事件后不一定進入就緒狀態(tài),也許該任務(wù)已經(jīng)由于其它



關(guān)鍵詞:

評論


相關(guān)推薦

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

關(guān)閉