新聞中心

        EEPW首頁 > 嵌入式系統 > 設計應用 > μC/OS-II的任務之間的通訊與同步

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

        作者: 時間:2016-10-08 來源:網絡 收藏

        表T6.1OSMapTbl[]

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

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

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

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

        }

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

        這樣,最終就可以得到處于等待該事件狀態的最高優先級任務了。程序清單L6.4是該算法的具體實現代碼。

        程序清單L6.4在等待任務列表中查找最高優先級的任務

        y=OSUnMapTbl[pevent->OSEventGrp];

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

        prio=(y3)+x;

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

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

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

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

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

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

        空閑事件控制塊鏈表中。

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

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

        y 初始化一個事件控制塊

        y 使一個任務進入就緒態

        y 使一個任務進入等待該事件的狀態

        y 因為等待超時而使一個任務進入就緒態

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

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

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

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

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

        制塊的指針pevent。

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

        voidOSEventWaitListInit(OS_EVENT*pevent)

        {

        INT8Ui;

        pevent->OSEventGrp=0x00;

        for(i=0;i

        pevent->OSEventTbl[i]=0x00;

        }

        }

        6.3 使一個任務進入就緒態,OSEventTaskRdy()

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

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

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

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

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

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



        關鍵詞:

        評論


        相關推薦

        技術專區

        關閉
        主站蜘蛛池模板: 富裕县| 临桂县| 朝阳区| 太保市| 德安县| 咸丰县| 宁武县| 南安市| 吴堡县| 社会| 黑龙江省| 玛多县| 西畴县| 略阳县| 台中市| 鄂托克前旗| 巍山| 阿勒泰市| 峨边| 四川省| 昌乐县| 博客| 新津县| 东平县| 无锡市| 通道| 昌乐县| 基隆市| 都昌县| 宜宾县| 陵川县| 峡江县| 龙里县| 凤台县| 达尔| 容城县| 达拉特旗| 潮安县| 沁阳市| 宜君县| 麻栗坡县|