新聞中心

EEPW首頁 > 嵌入式系統(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 來源:網(wǎng)絡(luò) 收藏

程序清單 L3.18Motorola68HC11中的中斷服務(wù)子程序

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

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

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

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

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

3.10 時(shí)鐘節(jié)拍

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

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

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

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

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

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

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

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

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

voidmain(void)

{

.

.

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

.

.

/* 應(yīng)用程序初始化代碼 ...*/

/*... 通過調(diào)用OSTaskCreate()創(chuàng)建至少一個(gè)任務(wù) */

.

.

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

.

.

OSStart();/* 開始多任務(wù)調(diào)度 */

}

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

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

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

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

voidOSTickISR(void)

{

保存處理器寄存器的值;

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

調(diào)用OSTimeTick();

調(diào)用OSIntExit();

恢復(fù)處理器寄存器的值;

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

}

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

程序清單L3.21時(shí)鐘節(jié)拍函數(shù)OSTimtick()的一個(gè)節(jié)拍服務(wù)

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()還通過調(diào)用OSTime()[L3.21(7)]累加從開機(jī)以來的時(shí)間,用的是一個(gè)無符號32位變量。注意,在給OSTime加1之前使用了關(guān)中斷,因?yàn)槎鄶?shù)微處理器給32位數(shù)加1的操作都得使用多條指令。

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

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

voidTickTask(void*pdata)

{

pdata=pdata;

for(;;){

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

OSTimeTick();

}

}

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

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

voidOSTickISR(void)

{

保存處理器寄存器的值;

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

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

調(diào)用OSIntExit();

恢復(fù)處理器寄存器的值;

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

}

3.11 μC/OS-Ⅱ初始化

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

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

圖F3.7表示調(diào)用OSInit()之后,一些μC/OS-Ⅱ變量和數(shù)據(jù)結(jié)構(gòu)之間的關(guān)系。其解釋是基于以下假設(shè)的:



關(guān)鍵詞:

評論


相關(guān)推薦

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

關(guān)閉