新聞中心

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

μC/OS-II的內核結構

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

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

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

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

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

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

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

3.10 時鐘節(jié)拍

μC/OS需要用戶提供周期性信號源,用于實現時間延時和確認超時。節(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()實現的。

時鐘節(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)的。空閑任務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ū)

關閉