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

          新聞中心

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

          μC/OS-II的內核結構

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

          程序清單 L3.18Motorola68HC11中的中斷服務子程序

          本文引用地址:http://www.ex-cimer.com/article/201610/305744.htm

          M68HC11_ISR:/* 快中斷服務程序,必須禁止中斷*/

          所有寄存器被CPU自動保存;

          執(zhí)行用戶代碼以響應中斷;

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

          3.10 時鐘節(jié)拍

          μC/OS需要用戶提供周期性信號源,用于實現(xiàn)時間延時和確認超時。節(jié)拍率應在每秒

          10次到100次之間,或者說10到100Hz。時鐘節(jié)拍率越高,系統(tǒng)的額外負荷就越重。時鐘

          節(jié)拍的實際頻率取決于用戶應用程序的精度。時鐘節(jié)拍源可以是專門的硬件定時器,也可

          以是來自50/60Hz交流電源的信號。

          用戶必須在多任務系統(tǒng)啟動以后再開啟時鐘節(jié)拍器,也就是在調用OSStart()之后。

          換句話說,在調用OSStart()之后做的第一件事是初始化定時器中斷。通常,容易犯的錯

          誤是將允許時鐘節(jié)拍器中斷放在系統(tǒng)初始化函數OSInit()之后,在調啟動多任務系統(tǒng)啟動

          函數OSStart()之前,如程序清單L3.19所示。

          程序清單L3.19啟動時鐘就節(jié)拍器的不正確做法.

          voidmain(void)

          {

          .

          .

          OSInit();/* 初始化uC/OS-II*/

          .

          .

          /* 應用程序初始化代碼 ...*/

          /*... 通過調用OSTaskCreate()創(chuàng)建至少一個任務 */

          .

          .

          允許時鐘節(jié)拍(TICKER)中斷;/* 千萬不要在這里允許時鐘節(jié)拍中斷!!! */

          .

          .

          OSStart();/* 開始多任務調度 */

          }

          這里潛在地危險是,時鐘節(jié)拍中斷有可能在μC/OS-Ⅱ啟動第一個任務之前發(fā)生,此時μC/OS-Ⅱ是處在一種不確定的狀態(tài)之中,用戶應用程序有可能會崩潰。

          μC/OS-Ⅱ中的時鐘節(jié)拍服務是通過在中斷服務子程序中調用OSTimeTick()實現(xiàn)的。

          時鐘節(jié)拍中斷服從所有前面章節(jié)中描述的規(guī)則。時鐘節(jié)拍中斷服務子程序的示意代碼如程序清單L3.20所示。這段代碼必須用匯編語言編寫,因為在C語言里不能直接處理CPU的寄存器。

          程序清單L3.20時鐘節(jié)拍中斷服務子程序的示意代碼

          voidOSTickISR(void)

          {

          保存處理器寄存器的值;

          調用OSIntEnter()或是將OSIntNesting加1;

          調用OSTimeTick();

          調用OSIntExit();

          恢復處理器寄存器的值;

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

          }

          時鐘節(jié)拍函數OSTimeTick()的代碼如程序清單3.21所示。OSTimtick()以調用可由用戶定義的時鐘節(jié)拍外連函數OSTimTickHook()開始,這個外連函數可以將時鐘節(jié)拍函數OSTimtick()予以擴展[L3.2(1)]。筆者決定首先調用OSTimTickHook()是打算在時鐘節(jié)拍中斷服務一開始就給用戶一個可以做點兒什么的機會,因為用戶可能會有一些時間要求苛刻的工作要做。OSTimtick()中量大的工作是給每個用戶任務控制塊OS_TCB中的時間延時項OSTCBDly減1(如果該項不為零的話)。OSTimTick()從OSTCBList開始,沿著OS_TCB鏈表做,一直做到空閑任務[L3.21(3)]。當某任務的任務控制塊中的時間延時項OSTCBDly減到了零,這個任務就進入了就緒態(tài)[L3.21(5)]。而確切被任務掛起的函數OSTaskSuspend()掛起的任務則不會進入就緒態(tài)[L3.21(4)]。OSTimTick()的執(zhí)行時間直接與應用程序中建立了多少個任務成正比。

          程序清單L3.21時鐘節(jié)拍函數OSTimtick()的一個節(jié)拍服務

          voidOSTimeTick(void)

          {

          OS_TCB*ptcb;

          OSTimeTickHook();(1)

          ptcb=OSTCBList;(2)

          while(ptcb->OSTCBPrio!=OS_IDLE_PRIO){(3)

          OS_ENTER_CRITICAL();

          if(ptcb->OSTCBDly!=0){

          if(--ptcb->OSTCBDly==0){

          if(!(ptcb->OSTCBStatOS_STAT_SUSPEND)){(4)

          OSRdyGrp|=ptcb->OSTCBBitY;(5)

          OSRdyTbl[ptcb->OSTCBY]|=ptcb->OSTCBBitX;

          }else{

          ptcb->OSTCBDly=1;

          }

          }

          }

          ptcb=ptcb->OSTCBNext;

          OS_EXIT_CRITICAL();

          }

          OS_ENTER_CRITICAL();(6)

          OSTime++; (7)

          OS_EXIT_CRITICAL();

          }

          OSTimeTick()還通過調用OSTime()[L3.21(7)]累加從開機以來的時間,用的是一個無符號32位變量。注意,在給OSTime加1之前使用了關中斷,因為多數微處理器給32位數加1的操作都得使用多條指令。

          中斷服務子程序似乎就得寫這么長,如果用戶不喜歡將中斷服務程序寫這么長,可以從任務級調用OSTimeTick(),如程序清單L3.22所示。要想這么做,得建立一個高于應用程序中所有其它任務優(yōu)先級的任務。時鐘節(jié)拍中斷服務子程序利用信號量或郵箱發(fā)信號給這個高優(yōu)先級的任務。

          程序清單L3.22時鐘節(jié)拍任務TickTask()作時鐘節(jié)拍服務.

          voidTickTask(void*pdata)

          {

          pdata=pdata;

          for(;;){

          OSMboxPend(...);/* 等待從時鐘節(jié)拍中斷服務程序發(fā)來的信號 */

          OSTimeTick();

          }

          }

          用戶當然需要先建立一個郵箱(初始化成NULL)用于發(fā)信號給上述任何告知時鐘節(jié)拍中斷已經發(fā)生了(程序清單L3.23)。

          程序清單L3.23時鐘節(jié)拍中斷服務函數OSTickISR()做節(jié)拍服務。

          voidOSTickISR(void)

          {

          保存處理器寄存器的值;

          調用OSIntEnter()或是將OSIntNesting加1;

          發(fā)送一個‘空’消息(例如, (void*)1)到時鐘節(jié)拍的郵箱;

          調用OSIntExit();

          恢復處理器寄存器的值;

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

          }

          3.11 μC/OS-Ⅱ初始化

          在調用μC/OS-Ⅱ的任何其它服務之前,μC/OS-Ⅱ要求用戶首先調用系統(tǒng)初始化函數OSIint()。OSIint()初始化μC/OS-Ⅱ所有的變量和數據結構(見OS_CORE.C)。

          OSInit()建立空閑任務idle task,這個任務總是處于就緒態(tài)的??臻e任務OSTaskIdle()的優(yōu)先級總是設成最低,即OS_LOWEST_PRIO。如果統(tǒng)計任務允許OS_TASK_STAT_EN和任務建立擴展允許都設為1,則OSInit()還得建立統(tǒng)計任務OSTaskStat()并且讓其進入就緒態(tài)。OSTaskStat的優(yōu)先級總是設為OS_LOWEST_PRIO-1。

          圖F3.7表示調用OSInit()之后,一些μC/OS-Ⅱ變量和數據結構之間的關系。其解釋是基于以下假設的:



          關鍵詞:

          評論


          相關推薦

          技術專區(qū)

          關閉
          看屁屁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); })();