μC/OS-II的內(nèi)存管理
圖F7.5是一個演示如何使用μC/OS-II中的動態(tài)分配內(nèi)存功能,以及利用它進行消息傳遞[見第6章]的例子。程序清單L7.8是這個例子中兩個任務的示意代碼,其中一些重要代碼的標號和圖F7.5中括號內(nèi)用數(shù)字標識的動作是相對應的。
第一個任務讀取并檢查模擬輸入量的值(如氣壓、溫度、電壓等),如果其超過了一定的閾值,就向第二個任務發(fā)送一個消息。該消息中含有時間信息、出錯的通道號和錯誤代碼等可以想象的任何可能的信息。
錯誤處理程序是該例子的中心。任何任務、中斷服務子程序都可以向該任務發(fā)送出錯消息。錯誤處理程序則負責在顯示設備上顯示出錯信息,在磁盤上登記出錯記錄,或者啟動另一個任務對錯誤進行糾正等。

圖F7.5使用動態(tài)內(nèi)存分配——Figure7.5
程序清單L7.8內(nèi)存分配的例子——掃描模擬量的輸入和報告出錯
AnalogInputTask()
{
for(;;){
for(所有的模擬量都有輸入){
讀入模擬量輸入值;(1)
if(模擬量超過閾值){
得到一個內(nèi)存塊;(2)
得到當前系統(tǒng)時間(以時鐘節(jié)拍為單位);(3)
將下列各項存入內(nèi)存塊:(4)
系統(tǒng)時間(時間戳);
超過閾值的通道號;
錯誤代碼;
錯誤等級;
等.
向錯誤隊列發(fā)送錯誤消息;(5)
(一個指向包含上述各項的內(nèi)存塊的指針)
}
}
延時任務,直到要再次對模擬量進行采樣時為止;
}
}
ErrorHandlerTask()
{
for(;;){
等待錯誤隊列的消息;(6)
(得到指向包含有關(guān)錯誤數(shù)據(jù)的內(nèi)存塊的指針)
讀入消息,并根據(jù)消息的內(nèi)容執(zhí)行相應的操作;(7)
將內(nèi)存塊放回到相應的內(nèi)存分區(qū)中;(8)
}
}
等待一個內(nèi)存塊
有時候,在內(nèi)存分區(qū)暫時沒有可用的空閑內(nèi)存塊的情況下,讓一個申請內(nèi)存塊的任務等待也是有用的。但是,μC/OS-II本身在內(nèi)存管理上并不支持這項功能。如果確實需要,則可以通過為特定內(nèi)存分區(qū)增加信號量的方法,實現(xiàn)這種功能(見6.05節(jié),信號量)。應用程序為了申請分配內(nèi)存塊,首先要得到一個相應的信號量,然后才能調(diào)用OSMemGet()函數(shù)。整個過程見程序清單L7.9。
程序代碼首先定義了程序中使用到的各個變量[L7.9(1)]。該例中,直接使用數(shù)字定義了各個變量的大小,實際應用中,建議將這些數(shù)字定義成常數(shù)。在系統(tǒng)復位時,μC/OS-II調(diào)用OSInit()進行系統(tǒng)初始化[L7.9(2)],然后用內(nèi)存分區(qū)中總的內(nèi)存塊數(shù)來初始化一個信號量[L7.9(3)],緊接著建立內(nèi)存分區(qū)[L7.9(4)]和相應的要訪問該分區(qū)的任務[L7.9(5)]。當然,到此為止,我們對如何增加其它的任務也已經(jīng)很清楚了。顯然,如果系統(tǒng)中只有一個任務使用動態(tài)內(nèi)存塊,就沒有必要使用信號量了。這種情況不需要保證內(nèi)存資源的互斥。事實上,除非我們要實現(xiàn)多任務共享內(nèi)存,否則連內(nèi)存分區(qū)都不需要。多任務執(zhí)行從OSStart()開始[L7.9(6)]。當一個任務運行時,只有在信號量有效時[L7.9(7)],才有可能得到內(nèi)存塊[L7.9(8)]。一旦信號量有效了,就可以申請內(nèi)存塊并使用它,而沒有必要對OSSemPend()返回
的錯誤代碼進行檢查。因為在這里,只有當一個內(nèi)存塊被其它任務釋放并放回到內(nèi)存分區(qū)后,
μC/OS-II才會返回到該任務去執(zhí)行。同理,對OSMemGet()返回的錯誤代碼也無需做進一步的檢查(一個任務能得以繼續(xù)執(zhí)行,則內(nèi)存分區(qū)中至少有一個內(nèi)存塊是可用的)。當一個任務不再使用某內(nèi)存塊時,只需簡單地將它釋放并返還到內(nèi)存分區(qū)[L7.9(9)],并發(fā)送該信號量[L7.9(10)]。
程序清單L7.9等待從一個內(nèi)存分區(qū)中分配內(nèi)存塊
OS_EVENT*SemaphorePtr;(1)
OS_MEM*PartitionPtr;
INT8UPartition[100][32];
OS_STKTaskStk[1000];
voidmain(void)
{
INT8Uerr;
OSInit();(2)
.
.
SemaphorePtr=OSSemCreate(100);(3)
PartitionPtr=OSMemCreate(Partition,100,32,err);(4)
.
OSTaskCreate(Task,(void*)0,TaskStk[999],err);(5)
.
OSStart();(6)
}
voidTask(void*pdata)
{
INT8Uerr;
INT8U*pblock;
for(;;){
OSSemPend(SemaphorePtr,0,err);(7)
pblock=OSMemGet(PartitionPtr,err);(8)
.
./*使用內(nèi)存塊*/
.
OSMemPut(PartitionPtr,pblock);(9)
OSSemPost(SemaphorePtr);(10)
}
}
評論