久久ER99热精品一区二区-久久精品99国产精品日本-久久精品免费一区二区三区-久久综合九色综合欧美狠狠

新聞中心

EEPW首頁 > 嵌入式系統 > 設計應用 > μC/OS-II的任務之間的通訊與同步

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

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

制塊的.OSEventGrp域為非0值時,說明該消息隊列的等待任務列表中有任務。這時,調用

OSEventTaskRdy()函數[見6.02節,使一個任務進入就緒狀態,OSEventTaskRdy()]從列表中取出最高優先級的任務[L6.23(3)], 并將它置于就緒狀態。 然后調用函數OSSched()[L6.23(4)]進行任務的調度。如果上面取出的任務的優先級在整個系統就緒的任務里也是最高的,而且OSQPost()函數不是中斷服務子程序調用的,就執行任務切換,該最高優先級任務被執行。否則的話,OSSched()函數直接返回,調用 OSQPost()函數的任務繼續執行。

程序清單L6.23向消息隊列發送一條消息

INT8UOSQPost(OS_EVENT*pevent,void*msg)

{

OS_Q*pq;

OS_ENTER_CRITICAL();

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

OS_EXIT_CRITICAL();

return(OS_ERR_EVENT_TYPE);

}

if(pevent->OSEventGrp){(2)

OSEventTaskRdy(pevent,msg,OS_STAT_Q);(3)

OS_EXIT_CRITICAL();

OSSched();

(4)

return(OS_NO_ERR);

}else{

pq=pevent->OSEventPtr;

if(pq->OSQEntries>=pq->OSQSize){(5)

OS_EXIT_CRITICAL();

return(OS_Q_FULL);

}else{

*pq->OSQIn++=msg;(6)

pq->OSQEntries++;

if(pq->OSQIn==pq->OSQEnd){

pq->OSQIn=pq->OSQStart;

}

OS_EXIT_CRITICAL();

}

return(OS_NO_ERR);

}

}

如果沒有任務等待該消息隊列中的消息,而且此時消息隊列未滿[L6.23(5)],指向該消息的指針被插入到消息隊列中[L6.23(6)]。這樣,下一個調用OSQPend()函數的任務就可以馬上得到該消息。注意,如果此時消息隊列已滿,那么該消息將由于不能插入到消息隊列中而丟失。

此外,如果OSQPost()函數是由中斷服務子程序調用的,那么即使產生了更高優先級的任務,也不會在調用OSSched()函數時發生任務切換。這個動作一直要等到中斷嵌套的最外層中斷服務子程序調用OSIntExit()函數時才能進行(見3.09節,μC/OS-II中的中斷)。

6.8.4 向消息隊列發送一個消息(后進先出LIFO),OSQPostFront()

OSQPostFront()函數和OSQPost()基本上是一樣的, 只是在插入新的消息到消息隊列中時,使用.OSQOut作為指向下一個插入消息的單元的指針,而不是.OSQIn。程序清單L6.24是它的源代碼。值得注意的是,.OSQOut指針指向的是已經插入了消息指針的單元,所以再插入新的消

息指針前,必須先將.OSQOut指針在消息隊列中前移一個單元。如果.OSQOut指針指向的當前單

元是隊列中的第一個單元[L6.24(1)],這時再前移就會發生越界,需要特別地將該指針指向隊

列的末尾[L6.24(2)]。由于.OSQEnd指向的是消息隊列中最后一個單元的下一個單元,因此.OSQOut必須被調整到指向隊列的有效范圍內[L6.24(3)]。因為QSQPend()函數取出的消息是

由OSQPend()函數剛剛插入的,因此OSQPostFront()函數實現了一個LIFO隊列。

程序清單L6.24向消息隊列發送一條消息(LIFO)

INT8UOSQPostFront(OS_EVENT*pevent,void*msg)

{

OS_Q*pq;

OS_ENTER_CRITICAL();

if(pevent->OSEventType!=OS_EVENT_TYPE_Q){

OS_EXIT_CRITICAL();

return(OS_ERR_EVENT_TYPE);

}

if(pevent->OSEventGrp){

OSEventTaskRdy(pevent,msg,OS_STAT_Q);

OS_EXIT_CRITICAL();

OSSched();

return(OS_NO_ERR);

}else{

pq=pevent->OSEventPtr;

if(pq->OSQEntries>=pq->OSQSize){

OS_EXIT_CRITICAL();

return(OS_Q_FULL);

}else{

if(pq->OSQOut==pq->OSQStart){(1)

pq->OSQOut=pq->OSQEnd;(2)

}

pq->OSQOut--;(3)

*pq->OSQOut=msg;

pq->OSQEntries++;

OS_EXIT_CRITICAL();

}

return(OS_NO_ERR);

}

}

6.8.5 無等待地從一個消息隊列中取得消息,OSQAccept()

如果試圖從消息隊列中取出一條消息,而此時消息隊列又為空時,也可以不讓調用任務等待而直接返回調用函數。這個操作可以調用OSQAccept()函數來完成。程序清單L6.25是該函數的源代碼。 OSQAccept()函數首先查看pevent指向的事件控制塊是否是由OSQCreate()函數建立的[L6.25(1)],然后它檢查當前消息隊列中是否有消息[L6.25(2)]。如果消息隊列中有至少一條消息,那么就從.OSQOut指向的單元中取出消息[L6.25(3)]。OSQAccept()函數的調用函數需要對OSQAccept()返回的指針進行檢查。如果該指針是NULL值,說明消息隊列是空的,其中沒有消息可以[L6.25(4)]。否則的話,說明已經從消息隊列中成功地取得了一條消息。當中斷服務子程序要從消息隊列中取消息時, 必須使用OSQAccept()函數, 而不能使用OSQPend()函數。

程序清單L6.25無等待地從消息隊列中取一條消息

void*OSQAccept(OS_EVENT*pevent)

{

void*msg;

OS_Q*pq;

OS_ENTER_CRITICAL();

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

OS_EXIT_CRITICAL();

return((void*)0);

}

pq=pevent->OSEventPtr;

if(pq->OSQEntries!=0){(2)

msg=*pq->OSQOut++;(3)

pq->OSQEntries--;

if(pq->OSQOut==pq->OSQEnd){

pq->OSQOut=pq->OSQStart;

}

}else{

msg=(void*)0;(4)

}

OS_EXIT_CRITICAL();

return(msg);

}

6.8.6 清空一個消息隊列,OSQFlush()

OSQFlush()函數允許用戶刪除一個消息隊列中的所有消息,重新開始使用。程序清單L6.26是該函數的源代碼。和前面的其它函數一樣,該函數首先檢查pevent指針是否是執行一個消息隊列[L6.26(1)],然后將隊列的插入指針和取出指針復位,使它們都指向隊列起始單元,同時,將隊列中的消息數設為0[L6.26(2)]。這里,沒有檢查該消息隊列的等待任務列表是否為空,因為只要該等待任務列表不空,.OSQEntries就一定是0。唯一不同的是,指針.OSQIn和.OSQOut此時可以指向消息隊列中的任何單元,不一定是起始單元。



關鍵詞:

評論


相關推薦

技術專區

關閉