新聞中心

移植μC/OS-Ⅱ

作者: 時間:2016-10-08 來源:網(wǎng)絡 收藏

8.05.01OSTaskStkInt()

OSTaskCreate()和OSTaskCreateExt()通過調(diào)用OSTaskStkInt()來初始化任務的堆棧結構,因此,堆棧看起來就像剛發(fā)生過中斷并將所有的寄存器保存到堆棧中的情形一樣。圖8.3顯示了OSTaskStkInt()放到正被建立的任務堆棧中的東西。注意,在這里我假定了堆棧是從上往下長的。下面的討論同樣適用于從下往上長的堆棧。

在用戶建立任務的時候,用戶會傳遞任務的地址,pdata指針,任務的堆棧棧頂和任務的優(yōu)先級給OSTaskCreate()和OSTaskCreateExt()。雖然OSTaskCreateExt()還要求有其它的參數(shù),但這些參數(shù)在討論OSTaskStkInt()的時候是無關緊要的。為了正確初始化堆棧結構,OSTaskStkInt()只要求剛才提到的前三個參數(shù)和一個附加的選項,這個選項只能在OSTaskCreateExt()中得到。

圖 8.3 堆棧初始化(pdata通過堆棧傳遞)

回顧一下,在μC/OS-Ⅱ中,無限循環(huán)的任務看起來就像其它的C函數(shù)一樣。當任務開始被μC/OS-Ⅱ執(zhí)行時,任務就會收到一個參數(shù),好像它被其它的任務調(diào)用一樣。

voidMyTask(void*pdata)

{

/* 對'pdata'做某些操作 */

for(;;){

/* 任務代碼 */

}

}

如果我想從其它的函數(shù)中調(diào)用MyTask(),C編譯器就會先將調(diào)用MyTask()的函數(shù)的返回地址保存到堆棧中,再將參數(shù)保存到堆棧中。實際上有些編譯器會將pdata參數(shù)傳至一個或多個寄存器中。在后面我會討論這類情況。假定pdata會被編譯器保存到堆棧中,OSTaskStkInit()就會簡單的模仿編譯器的這種動作,將pdata保存到堆棧中[F8.3(1)]。但是結果表明,與C函數(shù)調(diào)用不一樣,調(diào)用者的返回地址是未知的。用戶所擁有的是任務的開始地址,而不是調(diào)用該函數(shù)(任務)的函數(shù)的返回地址!事實上用戶不必太在意這點,因為任務并不希望返回到其它函數(shù)中。

這時,用戶需要將寄存器保存到堆棧中,當處理器發(fā)現(xiàn)并開始執(zhí)行中斷的時候,它會自動地完成該過程的。一些處理器會將所有的寄存器存入堆棧,而其它一些處理器只將部分寄存器存入堆棧。一般而言,處理器至少得將程序計數(shù)器的值(中斷返回地址)和處理器的狀態(tài)字存入堆棧[F8.3(2)]。很明顯,處理器是按一定的順序?qū)⒓拇嫫鞔嫒攵褩5模脩粼趯⒓拇嫫鞔嫒攵褩5臅r候也就必須依照這一順序。

接著,用戶需要將剩下的處理器寄存器保存到堆棧中[F8.3(3)]。保存的命令依賴于用戶的處理器是否允許用戶保存它們。 有些處理器用一個或多個指令就可以馬上將許多寄存器都保存起來。用戶必須用特定的指令來完成這一過程。例如,Intel80x86使用PUSHA指令將8個寄存器保存到堆棧中。對Motorola68HC11處理器而言,在中斷響應期間,所有的寄存器都會按一定順序自動的保存到堆棧中,所以在用戶將寄存器存入堆棧的時候,也必須依照這一順序。

現(xiàn)在是時候討論這個問題了: 如果用戶的C編譯器將pdata參數(shù)傳遞到寄存器中而不是堆棧中該作些什么?用戶需要從編譯器的文檔中找到pdata儲存在哪個寄存器中。pdata的內(nèi)容就會隨著這個寄存器的儲存被放置在堆棧中。

圖 8.4 堆棧初始化(pdata通過寄存器傳遞)

一旦用戶初始化了堆棧,OSTaskStkInit()就需要返回堆棧指針所指的地址[F8.3(4)]。

OSTaskCreate()和OSTaskCreateExt()會獲得該地址并將它保存到任務控制塊(OS_TCB)中。

處理器文檔會告訴用戶堆棧指針會指向下一個堆??臻e位置, 還是會指向最后存入數(shù)據(jù)的堆棧單元位置。例如,對Intel80x86處理器而言,堆棧指針會指向最后存入數(shù)據(jù)的堆棧單元位置,而對Motorola68HC11處理器而言,堆棧指針會指向下一個空閑的位置。

8.05.02OSTaskCreateHook()

當用OSTaskCreate()或OSTaskCreateExt()建立任務的時候就會調(diào)用OSTaskCreateHook()。該函數(shù)允許用戶或使用用戶的移植實例的用戶擴展μC/OS-Ⅱ的功能。

當μC/OS-Ⅱ設置完了自己的內(nèi)部結構后,會在調(diào)用任務調(diào)度程序之前調(diào)用OSTaskCreateHook()。該函數(shù)被調(diào)用的時候中斷是禁止的。因此用戶應盡量減少該函數(shù)中的代碼以縮短中斷的響應時間。

當OSTaskCreateHook()被調(diào)用的時候,它會收到指向已建立任務的OS_TCB的指針,這樣它就可以訪問所有的結構成員了。當使用OSTaskCreate()建立任務時,OSTaskCreateHook()的功能是有限的。但當用戶使用OSTaskCreateExt()建立任務時,用戶會得到OS_TCB中的擴展指針OSTCBExtPtr),該指針可用來訪問任務的附加數(shù)據(jù),如浮點寄存器,MMU寄存器,任務計數(shù)器的內(nèi)容,以及調(diào)試信息。

只用當OS_CFG.H中的OS_CPU_HOOKS_EN被置為1時才會產(chǎn)生OSTaskCreateHook()的代碼。這樣,使用用戶的移植實例的用戶可以在其它的文件中重新定義hook函數(shù)。

8.05.03OSTaskDelHook()

當任務被刪除的時候就會調(diào)用OSTaskDelHook()。 該函數(shù)在把任務從μC/OS-Ⅱ的內(nèi)部任務鏈表中解開之前被調(diào)用。當OSTaskDelHook()被調(diào)用的時候,它會收到指向正被刪除任務的OS_TCB的指針, 這樣它就可以訪問所有的結構成員了。 OSTaskDelHook()可以用來檢驗TCB擴展是否被建立了(一個非空指針)并進行一些清除操作。OSTaskDelHook()不返回任何值。

只用當OS_CFG.H中的OS_CPU_HOOKS_EN被置為1時才會產(chǎn)生OSTaskDelHook()的代碼。

8.05.04OSTaskSwHook()

當發(fā)生任務切換的時候調(diào)用OSTaskSwHook()。不管任務切換是通過OSCtxSw()還是OSIntCtxSw()來執(zhí)行的都會調(diào)用該函數(shù)。OSTaskSwHook()可以直接訪問OSTCBCur和OSTCBHighRdy,因為它們是全局變量。OSTCBCur指向被切換出去的任務的OS_TCB,而OSTCBHighRdy指向新任務的OS_TCB。 注意在調(diào)用OSTaskSwHook()期間中斷一直是被禁止的。

因為代碼的多少會影響到中斷的響應時間,所以用戶應盡量使代碼簡化。OSTaskSwHook()沒有任何參數(shù),也不返回任何值。



關鍵詞:

評論


相關推薦

技術專區(qū)

關閉