<meter id="pryje"><nav id="pryje"><delect id="pryje"></delect></nav></meter>
          <label id="pryje"></label>

          新聞中心

          EEPW首頁(yè) > 嵌入式系統(tǒng) > 設(shè)計(jì)應(yīng)用 > μC/OS-II的內(nèi)核結(jié)構(gòu)

          μC/OS-II的內(nèi)核結(jié)構(gòu)

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

          圖F3.4統(tǒng)計(jì)任務(wù)的初始化

          TaskStart()負(fù)責(zé)初始化和啟動(dòng)時(shí)鐘節(jié)拍[圖F3.4(5)]。在這里啟動(dòng)時(shí)鐘節(jié)拍是必要的,因?yàn)橛脩舨粫?huì)希望在多任務(wù)還沒(méi)有開始時(shí)就接收到時(shí)鐘節(jié)拍中斷。接下去TaskStart()調(diào)用統(tǒng)計(jì)初始化函數(shù)OSStatInit()[圖F3.4(6)]。統(tǒng)計(jì)初始化函數(shù)OSStatInit()決定在沒(méi)有其它應(yīng)用任務(wù)運(yùn)行時(shí),空閑計(jì)數(shù)器(OSIdleCtr)的計(jì)數(shù)有多快。奔騰II微處理器以333MHz運(yùn)行時(shí),加1操作可以使該計(jì)數(shù)器的值達(dá)到每秒15,000,000次。OSIdleCtr的值離32位計(jì)數(shù)器的溢出極限值4,294,967,296還差得遠(yuǎn)。微處理器越來(lái)越快,用戶要注意這里可能會(huì)是將來(lái)的一個(gè)潛在問(wèn)題。

          系統(tǒng)統(tǒng)計(jì)初始化任務(wù)函數(shù)OSStatInit()調(diào)用延遲函數(shù)OSTimeDly()將自身延時(shí)2個(gè)時(shí)鐘節(jié)拍以停止自身的運(yùn)行[圖F3.4(7)]。這是為了使OSStatInit()與時(shí)鐘節(jié)拍同步。μC/OS-Ⅱ然后選下一個(gè)優(yōu)先級(jí)最高的進(jìn)入就緒態(tài)的任務(wù)運(yùn)行,這恰好是統(tǒng)計(jì)任務(wù)OSTaskStat()。

          讀者會(huì)在后面讀到OSTaskStat()的代碼,但粗看一下,OSTaskStat()所要做的第一件事就是查看統(tǒng)計(jì)任務(wù)就緒標(biāo)志是否為“假”,如果是的話,也要延時(shí)兩個(gè)時(shí)鐘節(jié)拍[圖F3.4(8)]。一定會(huì)是這樣,因?yàn)闃?biāo)志OSStatRdy已被OSInit()函數(shù)初始化為“假”,所以

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

          OSStarInit()將統(tǒng)計(jì)任務(wù)就緒標(biāo)志OSStatRdy設(shè)為“真”[圖F3.4(16)],以此來(lái)允許兩個(gè)時(shí)鐘節(jié)拍以后OSTaskStat()開始計(jì)算CPU的利用率。

          統(tǒng)計(jì)任務(wù)的初始化函數(shù)OSStatInit()的代碼如程序清單L3.13所示。

          程序清單L3.13統(tǒng)計(jì)任務(wù)的初始化.

          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();

          }

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

          [3.1]表達(dá)式 Needtotypesettheequation.

          一旦上述計(jì)算完成,OSTaskStat()調(diào)用任務(wù)統(tǒng)計(jì)外界接入函數(shù)OSTaskStatHook()[L3.14(3)],這是一個(gè)用戶可定義的函數(shù),這個(gè)函數(shù)能使統(tǒng)計(jì)任務(wù)得到擴(kuò)展。這樣,用戶可以計(jì)算并顯示所有任務(wù)總的執(zhí)行時(shí)間,每個(gè)任務(wù)執(zhí)行時(shí)間的百分比以及其它信息(參見1.09節(jié)例3)。

          程序清單L3.14統(tǒng)計(jì)任務(wù)

          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中,中斷服務(wù)子程序要用匯編語(yǔ)言來(lái)寫。然而,如果用戶使用的C語(yǔ)言編譯器支持在線匯編語(yǔ)言的話,用戶可以直接將中斷服務(wù)子程序代碼放在C語(yǔ)言的程序文件中。中斷服務(wù)子程序的示意碼如程序清單L3.15所示。

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

          用戶中斷服務(wù)子程序:

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

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

          執(zhí)行用戶代碼做中斷服務(wù);(3)

          調(diào)用OSIntExit(); (4)

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

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

          μC/OS-Ⅱ可以用在這類微處理器中,當(dāng)任務(wù)切換時(shí),寄存器是保存在被中斷了的那個(gè)任務(wù)的棧中的。

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

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



          關(guān)鍵詞:

          評(píng)論


          相關(guān)推薦

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

          關(guān)閉
          看屁屁www成人影院,亚洲人妻成人图片,亚洲精品成人午夜在线,日韩在线 欧美成人 (function(){ var bp = document.createElement('script'); var curProtocol = window.location.protocol.split(':')[0]; if (curProtocol === 'https') { bp.src = 'https://zz.bdstatic.com/linksubmit/push.js'; } else { bp.src = 'http://push.zhanzhang.baidu.com/push.js'; } var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(bp, s); })();