新聞中心

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

        μC/OS-II的內核結構

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

        上述兩步完成以后,用戶可以開始服務于叫中斷的設備了[L3.15(3)]。這一段完全取決于應用。μC/OS-Ⅱ允許中斷嵌套,因為μC/OS-Ⅱ跟蹤嵌套層數OSIntNesting。然而,為允許中斷嵌套,在多數情況下,用戶應在開中斷之前先清中斷源。

        調用脫離中斷函數OSIntExit()[L3.15(4)]標志著中斷服務子程序的終結,OSIntExit()將中斷嵌套層數計數器減1。當嵌套計數器減到零時,所有中斷,包括嵌套的中斷就都完成了,此時μC/OS-Ⅱ要判定有沒有優先級較高的任務被中斷服務子程序(或任一嵌套的中斷)喚醒了。如果有優先級高的任務進入了就緒態,μC/OS-Ⅱ就返回到那個高優先級的任務,OSIntExit()返回到調用點[L3.15(5)]。保存的寄存器的值是在這時恢復的,然后是執行中斷返回指令[L3.16(6)]。注意,如果調度被禁止了(OSIntNesting>0),μC/OS-Ⅱ將被返回到被中斷了的任務。

        以上描述的詳細解釋如圖F3.5所示。中斷來到了[F3.5(1)]但還不能被被CPU識別,也許是因為中斷被μC/OS-Ⅱ或用戶應用程序關了,或者是因為CPU還沒執行完當前指令。一旦CPU響應了這個中斷[F3.5(2)],CPU的中斷向量(至少大多數微處理器是如此)跳轉到中斷服務子程序[F3.5(3)]。如上所述,中斷服務子程序保存CPU寄存器(也叫做CPUcontext)[F3.5(4)],一旦做完,用戶中斷服務子程序通知μC/OS-Ⅱ進入中斷服務子程序了,辦法是調用OSIntEnter()或者給SIntNesting直接加1[F3.5(5)]。然后用戶中斷服務代碼開始執行[F3.5(6)]。用戶中斷服務中做的事要盡可能地少,要把大部分工作留給任務去做。中斷服務子程序通知某任務去做事的手段是調用以下函數之一:OSMboxPost(),OSQPost(),OSQPostFront(),OSSemPost()。中斷發生并由上述函數發出消息時,接收消息的任務可能是,也可能不是掛起在郵箱、隊列或信號量上的任務。用戶中斷服務完成以后,要調用OSIntExit()[F3.5(7)]。從時序圖上可以看出,對被中斷了的任務說來,如果沒有高優先級的任務被中斷服務子程序激活而進入就緒態,OSIntExit()只占用很短的運行

        時間。進而,在這種情況下,CPU寄存器只是簡單地恢復[F3.5(8)]并執行中斷返回指令

        [F3.5(9)]。如果中斷服務子程序使一個高優先級的任務進入了就緒態,則OSIntExit()將占用

        較長的運行時間,因為這時要做任務切換[F3.5(10)]。新任務的寄存器內容要恢復并執行中

        斷返回指令[F3.5(12)]。

        圖 3.5 中斷服務

        進入中斷函數 OSIntEnter()的代碼如程序清單 L3.16 所示,從中斷服務中退出函數

        OSIntExit()的代碼如程序清單 L3.17 所示。如前所述,OSIntEnter()所做的事是非常少的。

        程序清單 L3.16 通知μC/OS-Ⅱ,中斷服務子程序開始了.

        voidOSIntEnter(void)

        {

        OS_ENTER_CRITICAL();

        OSIntNesting++;

        OS_EXIT_CRITICAL();

        }

        恢復所有CPU寄存器; (5)

        程序清單 L3.17 通知μC/OS-Ⅱ,脫離了中斷服務

        voidOSIntExit(void)

        {

        OS_ENTER_CRITICAL();(1)

        if((--OSIntNesting|OSLockNesting)==0){(2)

        OSIntExitY=OSUnMapTbl[OSRdyGrp];(3)

        OSPrioHighRdy=(INT8U)((OSIntExitY3)+

        OSUnMapTbl[OSRdyTbl[OSIntExitY]]);

        if(OSPrioHighRdy!=OSPrioCur){

        OSTCBHighRdy=OSTCBPrioTbl[OSPrioHighRdy];

        OSCtxSwCtr++;

        OSIntCtxSw();(4)

        }

        }

        OS_EXIT_CRITICAL();

        }

        OSIntExit()看起來非常像OSSched()。但有三點不同。第一點,OSIntExit()使中斷

        嵌套層數減1[L3.17(2)]而調度函數OSSched()的調度條件是:中斷嵌套層數計數器和鎖定

        嵌套計數器(OSLockNesting)二者都必須是零。第二個不同點是,OSRdyTbl[]所需的檢索

        值Y是保存在全程變量OSIntExitY中的[L3.17(3)]。這是為了避免在任務棧中安排局部變

        量。這個變量在哪兒和中斷任務切換函數OSIntCtxSw()有關,(見9.04.03節,中斷任務

        切換函數)。最后一點,如果需要做任務切換,OSIntExit()將調用OSIntCtxSw()[L3.17

        (4)]而不是調用OS_TASK_SW(),正像在OSSched()函數中那樣。

        調用中斷切換函數OSIntCtxSw()而不調用任務切換函數 OS_TASK_SW(),有兩個原因,

        首先是,如程序清單中L3.5(1)和圖F3.6(1)所示,一半的工作,即CPU寄存器入棧的工作

        已經做完了。第二個原因是,在中斷服務子程序中調用OSIntExit()時,將返回地址推入

        了堆棧[L3.15(4)和F3.6(2)]。OSIntExit()中的進入臨界段函數OS_ENTER_CRITICAL()或

        許將CPU的狀態字也推入了堆棧L3.7(1)和F3.6(3)。這取決于中斷是怎么被關掉的(見第8

        章移植μC/OS-Ⅱ)。最后,調用OSIntCtxSw()時的返回地址又被推入了堆棧[L3.17(4)和

        F3.1(4)],除了棧中不相關的部分,當任務掛起時,棧結構應該與μC/OS-Ⅱ所規定的完全

        一致。OSIntCtxSw()只需要對棧指針做簡單的調整,如圖F3.6(5)所示。換句話說,調整

        棧結構要保證所有掛起任務的棧結構看起來是一樣的。

        圖3.6中斷中的任務切換函數OSIntCtxSw()調整棧結構

        有的微處理器,像Motorola68HC11中斷發生時CPU寄存器是自動入棧的,且要想允許

        中斷嵌套的話,在中斷服務子程序中要重新開中斷,這可以視作一個優點。確實,如果用

        戶中斷服務子程序執行得非常快,用戶不需要通知任務自身進入了中斷服務,只要不在中

        斷服務期間開中斷,也不需要調用OSIntEnter()或OSIntNesting加1。程序清單L3。18

        中的示意代碼表示這種情況。一個任務和這個中斷服務子程序通訊的唯一方法是通過全程

        變量。



        關鍵詞:

        評論


        相關推薦

        技術專區

        關閉
        主站蜘蛛池模板: 同心县| 达尔| 府谷县| 阿合奇县| 安顺市| 上犹县| 舟曲县| 揭东县| 高碑店市| 林甸县| 田林县| 于田县| 桓台县| 东城区| 吉林省| 永城市| 沁阳市| 藁城市| 桑日县| 中方县| 阳原县| 承德市| 中江县| 临城县| 合肥市| 洛扎县| 满洲里市| 康保县| 抚顺县| 永新县| 南江县| 临洮县| 兴隆县| 康保县| 福海县| 包头市| 涿州市| 靖宇县| 定兴县| 威宁| 施秉县|