μC/OS-II的任務之間的通訊與同步
程序清單L6.11發出一個信號量
INT8UOSSemPost(OS_EVENT*pevent)
{
OS_ENTER_CRITICAL();
if(pevent->OSEventType!=OS_EVENT_TYPE_SEM){(1)
OS_EXIT_CRITICAL();
return(OS_ERR_EVENT_TYPE);
}
if(pevent->OSEventGrp){(2)
OSEventTaskRdy(pevent,(void*)0,OS_STAT_SEM);(3)
OS_EXIT_CRITICAL();
OSSched();(4)
return(OS_NO_ERR);
}else{
if(pevent->OSEventCnt65535){
pevent->OSEventCnt++;(5)
OS_EXIT_CRITICAL();
return(OS_NO_ERR);
}else{
OS_EXIT_CRITICAL();
return(OS_SEM_OVF);
}
}
}
6.6.4 無等待地請求一個信號量,OSSemAccept()
當一個任務請求一個信號量時,如果該信號量暫時無效,也可以讓該任務簡單地返回,而不是進入睡眠等待狀態。這種情況下的操作是由OSSemAccept()函數完成的,其源代碼見程序清單L6.12。該函數在最開始也是檢查參數指針pevent指向的事件控制塊是否是由OSSemCreate()函數建立的[L6.12(1)],接著從該信號量的事件控制塊中取出當前計數值[L6.12(2)],并檢查該信號量是否有效(計數值是否為非0值)[L6.12(3)]。如果有效,則將信號量的計數值減1[L6.12(4)],然后將信號量的原有計數值返回給調用函數[L6.12(5)]。調用函數需要對該返回值進行檢查。如果該值是0,說明該信號量無效。如果該值大于0,說明該信號量有效,同時該值也暗示著該信號量當前可用的資源數。應該注意的是,這些可用資源中,已經被該調用函數自身占用了一個(該計數值已經被減1)。中斷服務子程序要請求信號量時,只能用OSSemAccept()而不能用OSSemPend(),因為中斷服務子程序是不允許等待的。
程序清單L6.12無等待地請求一個信號量
INT16UOSSemAccept(OS_EVENT*pevent)
{
INT16Ucnt;
OS_ENTER_CRITICAL();
if(pevent->OSEventType!=OS_EVENT_TYPE_SEM){(1)
OS_EXIT_CRITICAL();
return(0);
}
cnt=pevent->OSEventCnt;(2)
if(cnt>0){(3)
pevent->OSEventCnt--;(4)
}
OS_EXIT_CRITICAL();
return(cnt);(5)
}
6.6.5 查詢一個信號量的當前狀態,OSSemQuery()
在應用程序中,用戶隨時可以調用函數OSSemQuery()[程序清單L6.13]來查詢一個信號量的當前狀態。該函數有兩個參數:一個是指向信號量對應事件控制塊的指針pevent。該指針是在生產信號量時,由OSSemCreate()函數返回的;另一個是指向用于記錄信號量信息的數據結構OS_SEM_DATA(見uCOS_II.H)的指針pdata。因此,調用該函數前,用戶必須先定義該結構變量,用于存儲信號量的有關信息。在這里,之所以使用一個新的數據結構的原因在于,調用函數應該只關心那些和特定信號量有關的信息, 而不是象OS_EVENT數據結構包含的很全面的信息。
該數據結構只包含信號量計數值.OSCnt和等待任務列表.OSEventTbl[]、.OSEventGrp,而OS_EVENT中還包含了另外的兩個域.OSEventType和.OSEventPtr。
和其它與信號量有關的函數一樣,OSSemQuery()也是先檢查pevent指向的事件控制塊是否是OSSemCreate()產生的[L6.13(1)],然后將等待任務列表[L6.13(2)]和計數值[L6.13(3)]
從OS_EVENT結構拷貝到OS_SEM_DATA結構變量中去。
程序清單L6.13查詢一個信號量的狀態
INT8UOSSemQuery(OS_EVENT*pevent,OS_SEM_DATA*pdata)
{
INT8Ui;
INT8U*psrc;
INT8U*pdest;
OS_ENTER_CRITICAL();
if(pevent->OSEventType!=OS_EVENT_TYPE_SEM){(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++;
}
pdata->OSCnt=pevent->OSEventCnt;(3)
OS_EXIT_CRITICAL();
return(OS_NO_ERR);
}
6.7 郵箱
郵箱是μC/OS-II中另一種通訊機制, 它可以使一個任務或者中斷服務子程序向另一個任務發送一個指針型的變量。該指針指向一個包含了特定“消息”的數據結構。為了在μC/OS-II中使用郵箱,必須將OS_CFG.H中的OS_MBOX_EN常數置為1。
使用郵箱之前,必須先建立該郵箱。該操作可以通過調用OSMboxCreate()函數來完成(見下節),并且要指定指針的初始值。一般情況下,這個初始值是NULL,但也可以初始化一個郵
箱,使其在最開始就包含一條消息。如果使用郵箱的目的是用來通知一個事件的發生(發送一
條消息),那么就要初始化該郵箱為NULL,因為在開始時,事件還沒有發生。如果用戶用郵箱
來共享某些資源,那么就要初始化該郵箱為一個非NULL的指針。在這種情況下,郵箱被當成一
個二值信號量使用。
μC/OS-II提供了5種對郵箱的操作:OSMboxCreate(),OSMboxPend(),OSMboxPost(),
OSMboxAccept()和 OSMboxQuery()函數。圖F6.6描述了任務、中斷服務子程序和郵箱之間的關
系,這里用符號“I”表示郵箱。郵箱包含的內容是一個指向一條消息的指針。一個郵箱只能包
含一個這樣的指針(郵箱為滿時),或者一個指向NULL的指針(郵箱為空時)。從圖F6.6可以看出,任務或者中斷服務子程序可以調用函數OSMboxPost(),但是只有任務可以調用函數OSMboxPend()和OSMboxQuery()。

圖F6.6任務、中斷服務子程序和郵箱之間的關系
6.7.1 建立一個郵箱,OSMboxCreate()
程序清單L6.14是OSMboxCreate()函數的源代碼,基本上和函數OSSemCreate()相似。不同之處在于事件控制塊的類型被設置成OS_EVENT_TYPE_MBOX[L6.14(1)], 以及使用.OSEventPtr域來容納消息指針,而不是使用.OSEventCnt域[L6.14(2)]。












評論