新聞中心

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

        μC/OS-II的內核結構

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

        圖F3.4統計任務的初始化

        TaskStart()負責初始化和啟動時鐘節拍[圖F3.4(5)]。在這里啟動時鐘節拍是必要的,因為用戶不會希望在多任務還沒有開始時就接收到時鐘節拍中斷。接下去TaskStart()調用統計初始化函數OSStatInit()[圖F3.4(6)]。統計初始化函數OSStatInit()決定在沒有其它應用任務運行時,空閑計數器(OSIdleCtr)的計數有多快。奔騰II微處理器以333MHz運行時,加1操作可以使該計數器的值達到每秒15,000,000次。OSIdleCtr的值離32位計數器的溢出極限值4,294,967,296還差得遠。微處理器越來越快,用戶要注意這里可能會是將來的一個潛在問題。

        系統統計初始化任務函數OSStatInit()調用延遲函數OSTimeDly()將自身延時2個時鐘節拍以停止自身的運行[圖F3.4(7)]。這是為了使OSStatInit()與時鐘節拍同步。μC/OS-Ⅱ然后選下一個優先級最高的進入就緒態的任務運行,這恰好是統計任務OSTaskStat()。

        讀者會在后面讀到OSTaskStat()的代碼,但粗看一下,OSTaskStat()所要做的第一件事就是查看統計任務就緒標志是否為“假”,如果是的話,也要延時兩個時鐘節拍[圖F3.4(8)]。一定會是這樣,因為標志OSStatRdy已被OSInit()函數初始化為“假”,所以

        實際上DSTaskStat也將自己推入休眠態(Sleep)兩個時鐘節拍[圖F3.4(9)]。于是任務切換到空閑任務,OSTaskIdle()開始運行,這是唯一一個就緒態任務了。CPU處在空閑任務OSTaskIdle中,直到TaskStart()的延遲兩個時鐘節拍完成[圖3.4(10)]。兩個時鐘節拍之后,TaskStart()恢復運行[圖F3.4(11)]。 在執行OSStartInit()時,空閑計數器OSIdleCtr被清零[圖F3.4(12)]。然后,OSStatInit()將自身延時整整一秒[圖F3.4(13)]。因為沒有其它進入就緒態的任務,OSTaskIdle()又獲得了CPU的控制權[圖F3.4(14)]。一秒鐘以后,TaskStart()繼續運行,還是在OSStatInit()中,空閑計數器將1秒鐘內計數的值存入空閑計數器最大值OSIdleCtrMax中[圖F3.4(15)]。

        OSStarInit()將統計任務就緒標志OSStatRdy設為“真”[圖F3.4(16)],以此來允許兩個時鐘節拍以后OSTaskStat()開始計算CPU的利用率。

        統計任務的初始化函數OSStatInit()的代碼如程序清單L3.13所示。

        程序清單L3.13統計任務的初始化.

        voidOSStatInit(void)

        {

        OSTimeDly(2);

        OS_ENTER_CRITICAL();

        OSIdleCtr=0L;

        OS_EXIT_CRITICAL();

        OSTimeDly(OS_TICKS_PER_SEC);

        OS_ENTER_CRITICAL();

        OSIdleCtrMax=OSIdleCtr;

        OSStatRdy=TRUE;

        OS_EXIT_CRITICAL();

        }

        統計任務OSStat()的代碼程序清單L3.14所示。在前面一段中,已經討論了為什么要等待統計任務就緒標志OSStatRdy[L3.14(1)]。這個任務每秒執行一次,以確定所有應用程序中的任務消耗了多少CPU時間。當用戶的應用程序代碼加入以后,運行空閑任務的CPU時間就少了,OSIdleCtr就不會像原來什么任務都不運行時有那么多計數。要知道,OSIdleCtr的最大計數值是OSStatInit()在初始化時保存在計數器最大值OSIdleCtrMax中的。CPU利用率(表達式[3.1])是保存在變量OSCPUsage[L3.14(2)]中的:

        [3.1]表達式 Needtotypesettheequation.

        一旦上述計算完成,OSTaskStat()調用任務統計外界接入函數OSTaskStatHook()[L3.14(3)],這是一個用戶可定義的函數,這個函數能使統計任務得到擴展。這樣,用戶可以計算并顯示所有任務總的執行時間,每個任務執行時間的百分比以及其它信息(參見1.09節例3)。

        程序清單L3.14統計任務

        voidOSTaskStat(void*pdata)

        {

        INT32Urun;

        INT8Susage;

        pdata=pdata;

        while(OSStatRdy==FALSE){(1)

        OSTimeDly(2*OS_TICKS_PER_SEC);

        }

        for(;;){

        OS_ENTER_CRITICAL();

        OSIdleCtrRun=OSIdleCtr;

        run=OSIdleCtr;

        OSIdleCtr=0L;

        OS_EXIT_CRITICAL();

        if(OSIdleCtrMax>0L){

        usage=(INT8S)(100L-100L*run/OSIdleCtrMax);(2)

        if(usage>100){

        OSCPUUsage=100;

        }elseif(usage0){

        OSCPUUsage=0;

        }else{

        OSCPUUsage=usage;

        }

        }else{

        OSCPUUsage=0;

        }

        OSTaskStatHook();(3)

        OSTimeDly(OS_TICKS_PER_SEC);

        }

        }

        3.9 μC/OS中的中斷處理

        μC/OS中,中斷服務子程序要用匯編語言來寫。然而,如果用戶使用的C語言編譯器支持在線匯編語言的話,用戶可以直接將中斷服務子程序代碼放在C語言的程序文件中。中斷服務子程序的示意碼如程序清單L3.15所示。

        程序清單L3.15μC/OS-II中的中斷服務子程序.

        用戶中斷服務子程序:

        保存全部CPU寄存器;(1)

        調用OSIntEnter或OSIntNesting直接加1; (2)

        執行用戶代碼做中斷服務;(3)

        調用OSIntExit(); (4)

        執行中斷返回指令; (6)

        用戶代碼應該將全部CPU寄存器推入當前任務棧[L3.15(1)]。注意,有些微處理器,例如Motorola68020(及68020以上的微處理器),做中斷服務時使用另外的堆棧。

        μC/OS-Ⅱ可以用在這類微處理器中,當任務切換時,寄存器是保存在被中斷了的那個任務的棧中的。

        μC/OS-Ⅱ需要知道用戶在做中斷服務,故用戶應該調用OSIntEnter(),或者將全程變量OSIntNesting[L3.15(2)]直接加1,如果用戶使用的微處理器有存儲器直接加1的單條指令的話。如果用戶使用的微處理器沒有這樣的指令,必須先將OSIntNesting讀入寄存器,再將寄存器加1,然后再寫回到變量OSIatNesting中去,就不如調用OSIatEnter()。

        OSIntNesting是共享資源。OSIntEnter()把上述三條指令用開中斷、關中斷保護起來,以保證處理OSIntNesting時的排它性。直接給OSIntNesting加1比調用OSIntEnter()快得多,可能時,直接加1更好。要當心的是,在有些情況下,從OSIntEnter()返回時,會把中斷開了。遇到這種情況,在調用OSIntEnter()之前要先清中斷源,否則,中斷將連續反復打入,用戶應用程序就會崩潰!



        關鍵詞:

        評論


        相關推薦

        技術專區

        關閉
        主站蜘蛛池模板: 天气| 大连市| 霍邱县| 南安市| 三河市| 山西省| 普宁市| 张北县| 林口县| 济阳县| 涪陵区| 红桥区| 新闻| 伊通| 富川| 略阳县| 泸西县| 威远县| 夏津县| 周口市| 承德市| 临夏县| 双峰县| 忻州市| 贵定县| 宿州市| 台北县| 芜湖县| 宜君县| 文昌市| 健康| 平度市| 丹寨县| 鄂托克旗| 武冈市| 宣武区| 尚志市| 平遥县| 台州市| 柘荣县| 丹巴县|