新聞中心

        EEPW首頁 > 嵌入式系統 > 設計應用 > μC/OS-II的內核結構

        μC/OS-II的內核結構

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

        讀者可以看出,任務優先級的低三位用于確定任務在總就緒表OSRdyTbl[]中的所在位。接下去的三位用于確定是在OSRdyTbl[]數組的第幾個元素。OSMapTbl[]是在ROM中的(見文件OS_CORE.C)屏蔽字,用于限制OSRdyTbl[]數組的元素下標在0到7之間,見表3.1

        本文引用地址:http://www.104case.com/article/201610/305744.htm

        圖3.3μC/OS-Ⅱ就緒表

        如果一個任務被刪除了,則用程序清單3.6中的代碼做求反處理。

        程序清單L3.6從就緒表中刪除一個任務

        if((OSRdyTbl[prio>>3]=~OSMapTbl[prio0x07])==0)

        OSRdyGrp=~OSMapTbl[prio>>3];

        以上代碼將就緒任務表數組OSRdyTbl[]中相應元素的相應位清零,而對于OSRdyGrp,

        只有當被刪除任務所在任務組中全組任務一個都沒有進入就緒態時,才將相應位清零。也

        就是說OSRdyTbl[prio>>3]所有的位都是零時,OSRdyGrp的相應位才清零。為了找到那個

        進入就緒態的優先級最高的任務,并不需要從OSRdyTbl[0]開始掃描整個就緒任務表,只

        需要查另外一張表,即優先級判定表OSUnMapTbl([256])(見文件 OS_CORE.C)。OSRdyTbl[]

        中每個字節的8位代表這一組的8個任務哪些進入就緒態了,低位的優先級高于高位。利用

        這個字節為下標來查OSUnMapTbl這張表,返回的字節就是該組任務中就緒態任務中優先級

        最高的那個任務所在的位置。這個返回值在0到7之間。確定進入就緒態的優先級最高的任

        務是用以下代碼完成的,如程序清單L3.7所示。

        程序清單 L3.7 找出進入就緒態的優先級最高的任務

        y=OSUnMapTbl[OSRdyGrp];

        x=OSUnMapTbl[OSRdyTbl[y]];

        prio=(y3)+x;

        例如,如果OSRdyGrp的值為二進制01101000,查OSUnMapTbl[OSRdyGrp]得到的值是

        3,它相應于OSRdyGrp中的第3位bit3,這里假設最右邊的一位是第0位bit0。類似地,

        如果OSRdyTbl[3]的值是二進制11100100,則OSUnMapTbl[OSRdyTbc[3]]的值是2,即第2

        位。于是任務的優先級Prio就等于26(3*8+2)。利用這個優先級的值。查任務控制塊優

        先級表OSTCBPrioTbl[],得到指向相應任務的任務控制塊OS_TCB的工作就完成了。

        3.5 任務調度(TaskScheduling)

        μC/OS-Ⅱ總是運行進入就緒態任務中優先級最高的那一個。確定哪個任務優先級最

        高,下面該哪個任務運行了的工作是由調度器(Scheduler)完成的。任務級的調度是由函

        數OSSched()完成的。中斷級的調度是由另一個函數OSIntExt()完成的,這個函數將在以

        后描述。OSSched()的代碼如程序清單L3.8所示。

        程序清單L3.8任務調度器(theTaskScheduler)

        voidOSSched(void)

        {

        INT8Uy;

        OS_ENTER_CRITICAL();

        if((OSLockNesting|OSIntNesting)==0){(1)

        y=OSUnMapTbl[OSRdyGrp];(2)

        OSPrioHighRdy=(INT8U)((y3)+OSUnMapTbl[OSRdyTbl[y]]);(2)

        if(OSPrioHighRdy!=OSPrioCur){(3)

        OSTCBHighRdy=OSTCBPrioTbl[OSPrioHighRdy];(4)

        OSCtxSwCtr++;(5)

        OS_TASK_SW();(6)

        }

        }

        OS_EXIT_CRITICAL();

        }

        μC/OS-Ⅱ任務調度所花的時間是常數,與應用程序中建立的任務數無關。如程序清單

        中[L3.8(1)]條件語句的條件不滿足,任務調度函數OSSched()將退出,不做任務調度。這

        個條件是:如果在中斷服務子程序中調用OSSched(),此時中斷嵌套層數

        OSIntNesting>0,或者由于用戶至少調用了一次給任務調度上鎖函數OSSchedLock(),使

        OSLockNesting>0。如果不是在中斷服務子程序調用OSSched(),并且任務調度是允許的,

        即沒有上鎖,則任務調度函數將找出那個進入就緒態且優先級最高的任務[L3.8(2)],進入

        就緒態的任務在就緒任務表中有相應的位置位。一旦找到那個優先級最高的任務,

        OSSched()檢驗這個優先級最高的任務是不是當前正在運行的任務,以此來避免不必要的任

        務調度[L3.8(3)]。注意,在μC/OS中曾經是先得到OSTCBHighRdy然后和OSTCBCur做比

        較。因為這個比較是兩個指針型變量的比較,在8位和一些16位微處理器中這種比較相對

        較慢。而在μC/OS-Ⅱ中是兩個整數的比較。并且,除非用戶實際需要做任務切換,在查任

        務控制塊優先級表OSTCBPrioTbl[]時,不需要用指針變量來查OSTCBHighRdy。綜合這兩項

        改進,即用整數比較代替指針的比較和當需要任務切換時再查表,使得μC/OS-Ⅱ比μC/OS

        在8位和一些16位微處理器上要更快一些。

        為實現任務切換,OSTCBHighRdy必須指向優先級最高的那個任務控制塊OS_TCB,這是

        通過將以OSPrioHighRdy為下標的OSTCBPrioTbl[]數組中的那個元素賦給OSTCBHighRdy來

        實現的[L3.8(4)]。接著,統計計數器OSCtxSwCtr加1,以跟蹤任務切換次數[L3.8(5)]。

        最后宏調用OS_TASK_SW()來完成實際上的任務切換[L3.8(6)]。

        任務切換很簡單,由以下兩步完成,將被掛起任務的微處理器寄存器推入堆棧,然后

        將較高優先級的任務的寄存器值從棧中恢復到寄存器中。在μC/OS-Ⅱ中,就緒任務的棧結

        構總是看起來跟剛剛發生過中斷一樣,所有微處理器的寄存器都保存在棧中。換句話說,

        μC/OS-Ⅱ運行就緒態的任務所要做的一切,只是恢復所有的CPU寄存器并運行中斷返回指

        令。為了做任務切換,運行OS_TASK_SW(),人為模仿了一次中斷。多數微處理器有軟中斷

        指令或者陷阱指令TRAP來實現上述操作。中斷服務子程序或陷阱處理(Traphardler),

        也稱作事故處理(exceptionhandler),必須提供中斷向量給匯編語言函數OSCtxSw()。

        OSCtxSw()除了需要OS_TCBHighRdy指向即將被掛起的任務,還需要讓當前任務控制塊

        OSTCBCur指向即將被掛起的任務,參見第8章,移植μC/OS-Ⅱ,有關于OSCtxSw()的更詳



        關鍵詞:

        評論


        相關推薦

        技術專區

        關閉
        主站蜘蛛池模板: 宁国市| 延庆县| 徐州市| 昌平区| 沭阳县| 若羌县| 高安市| 扎兰屯市| 徐汇区| 甘孜县| 邢台市| 荆门市| 广东省| 新郑市| 武宣县| 兰考县| 怀集县| 抚顺县| 晋中市| 文山县| 绩溪县| 吉林省| 天等县| 临西县| 芦山县| 呼和浩特市| 巴中市| 肇源县| 蓬溪县| 辽阳市| 济源市| 彩票| 伊春市| 南澳县| 惠东县| 邢台市| 缙云县| 闸北区| 平湖市| 嘉祥县| 博爱县|