μC/OS-II的任務之間的通訊與同步
原因掛起了。[見4.07節,掛起一個任務,OSTaskSuspend(),和4.08節,恢復一個任務,
OSTaskResume()]。
另外,.OSEventTaskRdy()函數要在中斷禁止的情況下調用。
程序清單L6.6使一個任務進入就緒狀態
voidOSEventTaskRdy(OS_EVENT*pevent,void*msg,INT8Umsk)
{
OS_TCB*ptcb;
INT8Ux;
INT8Uy;
INT8Ubitx;
INT8Ubity;
INT8Uprio;
y=OSUnMapTbl[pevent->OSEventGrp];(1)
bity=OSMapTbl[y];(2)
x=OSUnMapTbl[pevent->OSEventTbl[y]];(3)
bitx=OSMapTbl[x];(4)
prio=(INT8U)((y3)+x);(5)
if((pevent->OSEventTbl[y]=~bitx)==0){(6)
pevent->OSEventGrp=~bity;
}
ptcb=OSTCBPrioTbl[prio];(7)
ptcb->OSTCBDly=0;(8)
ptcb->OSTCBEventPtr=(OS_EVENT*)0;(9)
#if(OS_Q_EN(OS_MAX_QS>=2))||OS_MBOX_EN
ptcb->OSTCBMsg=msg;(10)
#else
msg=msg;
#endif
ptcb->OSTCBStat=~msk;(11)
if(ptcb->OSTCBStat==OS_STAT_RDY){(12)
OSRdyGrp|=bity;(13)
OSRdyTbl[y]|=bitx;
}
}

圖F6.4使一個任務進入就緒狀態——Figure6.4
6.4 使一個任務進入等待某事件發生狀態,OSEventTaskWait()
程序清單L6.7是OSEventTaskWait()函數的源代碼。當某個任務要等待一個事件的發生時,相應事件的OSSemPend(),OSMboxPend()或者OSQPend()函數會調用該函數將當前任務從就緒任務表中刪除,并放到相應事件的事件控制塊的等待任務表中。
程序清單L6.7使一個任務進入等待狀態
voidOSEventTaskWait(OS_EVENT*pevent)
{
OSTCBCur->OSTCBEventPtr=pevent;(1)
if((OSRdyTbl[OSTCBCur->OSTCBY]=~OSTCBCur->OSTCBBitX)==0){(2)
OSRdyGrp=~OSTCBCur->OSTCBBitY;
}
pevent->OSEventTbl[OSTCBCur->OSTCBY]|=OSTCBCur->OSTCBBitX;(3)
pevent->OSEventGrp|=OSTCBCur->OSTCBBitY;
}
在該函數中,首先將指向事件控制塊的指針放到任務的任務控制塊中[L6.7(1)],接著將任務從就緒任務表中刪除[L6.7(2)],并把該任務放到事件控制塊的等待任務表中[L6.7(3)]。
6.5 由于等待超時而將任務置為就緒態,OSEventTO()
程序清單L6.8是OSEventTO()函數的源代碼。當在預先指定的時間內任務等待的事件沒有發生時,OSTimeTick()函數會因為等待超時而將任務的狀態置為就緒。在這種情況下,事件的OSSemPend(),OSMboxPend()或者OSQPend()函數會調用OSEventTO()來完成這項工作。該函數負責從事件控制塊中的等待任務列表里將任務刪除[L6.8(1)],并把它置成就緒狀態[L6.8(2)]。最后,從任務控制塊中將指向事件控制塊的指針刪除[L6.8(3)]。用戶應當注意,調用OSEventTO()也應當先關中斷。
程序清單L6.8因為等待超時將任務置為就緒狀態
voidOSEventTO(OS_EVENT*pevent)
{
if((pevent->OSEventTbl[OSTCBCur->OSTCBY]=~OSTCBCur->OSTCBBitX) ==0)
{ (1)
pevent->OSEventGrp=~OSTCBCur->OSTCBBitY;
}
OSTCBCur->OSTCBStat=OS_STAT_RDY;(2)
OSTCBCur->OSTCBEventPtr=(OS_EVENT*)0;(3)
}
6.6 信號量
μC/OS-II中的信號量由兩部分組成:一個是信號量的計數值,它是一個16位的無符號整數 (0到65,535之間) ; 另一個是由等待該信號量的任務組成的等待任務表。 用戶要在OS_CFG.H中將OS_SEM_EN開關量常數置成1,這樣μC/OS-II才能支持信號量。
在使用一個信號量之前, 首先要建立該信號量, 也即調用OSSemCreate()函數(見下一節) ,
對信號量的初始計數值賦值。該初始值為0到65,535之間的一個數。如果信號量是用來表示一個或者多個事件的發生, 那么該信號量的初始值應設為0。 如果信號量是用于對共享資源的訪問,那么該信號量的初始值應設為1(例如,把它當作二值信號量使用)。最后,如果該信號量是用來表示允許任務訪問n個相同的資源,那么該初始值顯然應該是n,并把該信號量作為一個可計數的信號量使用。
μC/OS-II提供了5個對信號量進行操作的函數。它們是:OSSemCreate(),OSSemPend(),
OSSemPost(),OSSemAccept()和OSSemQuery()函數。圖F6.5說明了任務、中斷服務子程序和
信號量之間的關系。圖中用鑰匙或者旗幟的符號來表示信號量:如果信號量用于對共享資源的
訪問,那么信號量就用鑰匙符號。符號旁邊的數字N代表可用資源數。對于二值信號量,該值
就是1;如果信號量用于表示某事件的發生,那么就用旗幟符號。這時的數字N代表事件已經發
生的次數。從圖F6.5中可以看出OSSemPost()函數可以由任務或者中斷服務子程序調用,而
OSSemPend()和OSSemQuery()函數只能有任務程序調用。

圖F6.5任務、中斷服務子程序和信號量之間的關系——Figure6.5
6.6.1 建立一個信號量,OSSemCreate()
程序清單L6.9是OSSemCreate()函數的源代碼。首先,它從空閑任務控制塊鏈表中得到一個事件控制塊[L6.9(1)],并對空閑事件控制鏈表的指針進行適當的調整,使它指向下一個空閑的事件控制塊[L6.9(2)]。如果這時有任務控制塊可用[L6.9(3)],就將該任務控制塊的事件類型設置成信號量OS_EVENT_TYPE_SEM[L6.9(4)]。其它的信號量操作函數OSSem???()通過檢查該域來保證所操作的任務控制塊類型的正確。例如,這可以防止調用OSSemPost()函數對一個用作郵箱的任務控制塊進行操作[6.06節,郵箱]。接著,用信號量的初始值對任務控制塊進行初始化[L6.9(5)],并調用 OSEventWaitListInit()函數對事件控制任務控制塊的等待任務列表進行初始化[見6.01節,初始化一個任務控制塊,OSEventWaitListInit()][L6.9(6)]。因為信號量正在被初始化,所以這時沒有任何任務等待該信號量。最后,OSSemCreate()返回給調用函數一個指向任務控制塊的指針。以后對信號量的所有操作,如OSSemPend(),OSSemPost(),OSSemAccept()和OSSemQuery()都是通過該指針完成的。因此,這個指針實際上就是該信號量的句柄。如果系統中沒有可用的任務控制塊,OSSemCreate()將返回一個NULL指針。












評論