新聞中心

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

        μC/OS-II的內核結構

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

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

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

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

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

        執行用戶代碼以響應中斷;

        執行中斷返回指令;

        3.10 時鐘節拍

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

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

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

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

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

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

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

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

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

        voidmain(void)

        {

        .

        .

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

        .

        .

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

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

        .

        .

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

        .

        .

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

        }

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

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

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

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

        voidOSTickISR(void)

        {

        保存處理器寄存器的值;

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

        調用OSTimeTick();

        調用OSIntExit();

        恢復處理器寄存器的值;

        執行中斷返回指令;

        }

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

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

        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所示。要想這么做,得建立一個高于應用程序中所有其它任務優先級的任務。時鐘節拍中斷服務子程序利用信號量或郵箱發信號給這個高優先級的任務。

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

        voidTickTask(void*pdata)

        {

        pdata=pdata;

        for(;;){

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

        OSTimeTick();

        }

        }

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

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

        voidOSTickISR(void)

        {

        保存處理器寄存器的值;

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

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

        調用OSIntExit();

        恢復處理器寄存器的值;

        執行中斷返回指令;

        }

        3.11 μC/OS-Ⅱ初始化

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

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

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



        關鍵詞:

        評論


        相關推薦

        技術專區

        關閉
        主站蜘蛛池模板: 准格尔旗| 和平县| 漯河市| 东宁县| 彰武县| 芷江| 潼南县| 大洼县| 柳林县| 长泰县| 成都市| 轮台县| 贺兰县| 温泉县| 那曲县| 丘北县| 从江县| 乡城县| 瑞昌市| 广元市| 贺州市| 城口县| 罗山县| 澜沧| 剑河县| 莱阳市| 大兴区| 临沧市| 苏尼特左旗| 枣庄市| 阜城县| 崇左市| 财经| 淅川县| 独山县| 温宿县| 吉木萨尔县| 凭祥市| 揭西县| 普兰县| 泸定县|