新聞中心

EEPW首頁 > 嵌入式系統(tǒng) > 設(shè)計應(yīng)用 > μC/OS-II的任務(wù)之間的通訊與同步

μC/OS-II的任務(wù)之間的通訊與同步

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

程序清單L6.26清空消息隊列

INT8UOSQFlush(OS_EVENT*pevent)

{

OS_Q*pq;

OS_ENTER_CRITICAL();

if(pevent->OSEventType!=OS_EVENT_TYPE_Q){(1)

OS_EXIT_CRITICAL();

return(OS_ERR_EVENT_TYPE);

}

pq=pevent->OSEventPtr;

pq->OSQIn=pq->OSQStart;(2)

pq->OSQOut=pq->OSQStart;

pq->OSQEntries=0;

OS_EXIT_CRITICAL();

return(OS_NO_ERR);

}

6.8.7 查詢一個消息隊列的狀態(tài),OSQQuery()

OSQQuery()函數(shù)使用戶可以查詢一個消息隊列的當前狀態(tài)。 程序清單L6.27是該函數(shù)的源代碼。OSQQuery()需要兩個參數(shù):一個是指向消息隊列的指針pevent。它是在建立一個消息隊列時,由OSQCreate()函數(shù)返回的;另一個是指向OS_Q_DATA(見uCOS_II.H)數(shù)據(jù)結(jié)構(gòu)的指針pdata。該結(jié)構(gòu)包含了有關(guān)消息隊列的信息。在調(diào)用OSQQuery()函數(shù)之前,必須先定義該數(shù)據(jù)結(jié)構(gòu)變量。OS_Q_DATA結(jié)構(gòu)包含下面的幾個域:

.OSMsg 如果消息隊列中有消息,它包含指針.OSQOut所指向的隊列單元中的內(nèi)容。如果隊列是空的,.OSMsg包含一個NULL指針。

.OSNMsgs是消息隊列中的消息數(shù)(.OSQEntries的拷貝)。

.OSQSize 是消息隊列的總的容量

.OSEventTbl[]和.OSEventGrp是消息隊列的等待任務(wù)列表。通過它們,OSQQuery()的調(diào)用函數(shù)可以得到等待該消息隊列中的消息的任務(wù)總數(shù)。

OSQQuery()函數(shù)首先檢查pevent指針指向的事件控制塊是一個消息隊列[L6.27(1)],然后復(fù)制等待任務(wù)列表[L6.27(2)]。如果消息隊列中有消息[L6.27(3)],.OSQOut指向的隊列單元中的內(nèi)容被復(fù)制到OS_Q_DATA結(jié)構(gòu)中[L6.27(4)], 否則的話, 就復(fù)制一個NULL指針[L6.27(5)]。

最后,復(fù)制消息隊列中的消息數(shù)和消息隊列的容量大小[L6.27(6)]。

程序清單L6.27程序消息隊列的狀態(tài)

INT8UOSQQuery(OS_EVENT*pevent,OS_Q_DATA*pdata)

{

OS_Q*pq;

INT8Ui;

INT8U*psrc;

INT8U*pdest;

OS_ENTER_CRITICAL();

if(pevent->OSEventType!=OS_EVENT_TYPE_Q){(1)

OS_EXIT_CRITICAL();

return(OS_ERR_EVENT_TYPE);

}

pdata->OSEventGrp=pevent->OSEventGrp;(2)

psrc=pevent->OSEventTbl[0];

pdest=pdata->OSEventTbl[0];

for(i=0;i

*pdest++=*psrc++;

}

pq=(OS_Q*)pevent->OSEventPtr;

if(pq->OSQEntries>0){(3)

pdata->OSMsg=pq->OSQOut;(4)

}else{

pdata->OSMsg=(void*)0;(5)

}

pdata->OSNMsgs=pq->OSQEntries;(6)

pdata->OSQSize=pq->OSQSize;

OS_EXIT_CRITICAL();

return(OS_NO_ERR);

}

6.8.8 使用消息隊列讀取模擬量的值

在控制系統(tǒng)中,經(jīng)常要頻繁地讀取模擬量的值。這時,可以先建立一個定時任務(wù)OSTimeDly()[見5.00節(jié),延時一個任務(wù),OSTimeDly()],并且給出希望的抽樣周期。然后,如圖F6.11所示,讓A/D采樣的任務(wù)從一個消息隊列中等待消息。該程序最長的等待時間就是抽樣周期。當沒有其它任務(wù)向該消息隊列中發(fā)送消息時,A/D采樣任務(wù)因為等待超時而退出等待狀態(tài)并進行執(zhí)行。這就模仿了OSTimeDly()函數(shù)的功能。

也許,讀者會提出疑問,既然OSTimeDly()函數(shù)能完成這項工作,為什么還要使用消息隊列呢?這是因為,借助消息隊列,我們可以讓其它的任務(wù)向消息隊列發(fā)送消息來終止A/D采樣任務(wù)等待消息,使其馬上執(zhí)行一次A/D采樣。此外,我們還可以通過消息隊列來通知A/D采樣程序具體對哪個通道進行采樣,告訴它增加采樣頻率等等,從而使得我們的應(yīng)用更智能化。換句話說,我們可以告訴A/D采樣程序,“現(xiàn)在馬上讀取通道3的輸入值!”之后,該采樣任務(wù)將重新開始在消息隊列中等待消息,準備開始一次新的掃描過程。

圖F6.11讀模擬量輸入——Figure6.11

6.8.9 使用一個消息隊列作為計數(shù)信號量

在消息隊列初始化時,可以將消息隊列中的多個指針設(shè)為非NULL值(如void*1),來實現(xiàn)計數(shù)信號量的功能。這里,初始化為非NULL值的指針數(shù)就是可用的資源數(shù)。系統(tǒng)中的任務(wù)可以通過OSQPend()來請求“信號量”,然后通過調(diào)用OSQPost()來釋放“信號量”,如程序清單L6.28。如果系統(tǒng)中只使用了計數(shù)信號量和消息隊列,使用這種方法可以有效地節(jié)省代碼空間。

這時將OS_SEM_EN設(shè)為0,就可以不使用信號量,而只使用消息隊列。值得注意的是,這種方法

為共享資源引入了大量的指針變量。也就是說,為了節(jié)省代碼空間,犧牲了RAM空間。另外,

對消息隊列的操作要比對信號量的操作慢,因此,當用計數(shù)信號量同步的信號量很多時,這種

方法的效率是非常低的。

程序清單L6.28使用消息隊列作為一個計數(shù)信號量

OS_EVENT*QSem;

void*QMsgTbl[N_RESOURCES]

voidmain(void)

{

OSInit();

.

QSem=OSQCreate(QMsgTbl[0],N_RESOURCES);

for(i=0;i

OSQPost(Qsem,(void*)1);

}

.

.

OSTaskCreate(Task1,..,..,..);

.

.

OSStart();

}

voidTask1(void*pdata)

{

INT8Uerr;

for(;;){

OSQPend(QSem,0,err);/*得到對資源的訪問權(quán)*/

.

./*任務(wù)獲得信號量,對資源進行訪問*/

.

OSMQPost(QSem,(void*)1);/*釋放對資源的訪問權(quán)*/

}

}


上一頁 1 2 3 4 5 6 7 8 9 10 11 下一頁

關(guān)鍵詞:

評論


相關(guān)推薦

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

關(guān)閉