一。 事件控制塊ECB數(shù)據(jù)結(jié)構(gòu):
typedef struct
{
INT8U OSEventType; //事件類型
INT8U OSEventGrp; //等待任務(wù)所在的組
INT16U OSEventCnt; //當(dāng)事件是信號量時(shí)的計(jì)數(shù)器
void *OSEventPtr; //指向消息或消息隊(duì)列的指針
INT8U OSEventTbl[OS_EVENT_TBL_SIZE]; //等待任務(wù)列表
} OS_EVENT;
二.關(guān)鍵算法:
1、將一個(gè)任務(wù)插入到等待事件的任務(wù)列表中:
當(dāng)調(diào)用函數(shù)OS_EventTaskWait( )使一個(gè)任務(wù)進(jìn)入等待某事件發(fā)生時(shí),需要此算法,從而將任務(wù)插入到等待事件的任務(wù)列表中。
pevent -》 OSEventGrp |= OSMapTbl[prio 》》 3];
pevent -》 OSEventTbl[prio》》3] = OSMapTbl[prio & 0x07];
2、從等待事件的任務(wù)列表中使任務(wù)脫離等待狀態(tài):
當(dāng)調(diào)用函數(shù)OS_EventTaskRdy( )使一個(gè)任務(wù)進(jìn)入就緒態(tài)時(shí),需要調(diào)用此算法,從而使等待的任務(wù)脫離等待狀態(tài)進(jìn)入就緒。
if ((pevent -》 OSEventTbl[prio 》》3] &= ~OSMapTbl[prio & 0x07]) == 0)
{
pevent -》 OSEventGrp &= ~OSMapTbl[prio 》》3];
}
3、在等待事件的任務(wù)列表中查找優(yōu)先級最高的任務(wù):
當(dāng)調(diào)用函數(shù)OS_EventTaskRdy( )使一個(gè)任務(wù)進(jìn)入就緒態(tài)時(shí),需要調(diào)用此算法,從而首先找出在等待事件任務(wù)列表中最高優(yōu)先級的任務(wù)進(jìn)入就緒狀態(tài)。
y = OSUnMapTbl[pevent -》 OSEventGrp];
x = OSUnMapTbl[pevent -》 OSEventTbl[y];
prio = (y 《《 3) + x;
三.對事件控制塊ECB的基本操作
1、初始化一個(gè)事件控制塊:
函數(shù)OSSemCreate( ),OSMutexCreate( ),OSMboxCreate( ),OSQCreate( )建立時(shí),必須調(diào)用此函數(shù)進(jìn)行初始化,初始化一個(gè)空的等待列表,表中沒有任何等待事件的任務(wù)。
OS_EventWaitListInit( );
2、使一個(gè)任務(wù)進(jìn)入就緒態(tài):
當(dāng)某個(gè)事件發(fā)生了時(shí),要將事件等待任務(wù)列表中最高優(yōu)先級的任務(wù)進(jìn)入就緒態(tài),函數(shù)OSSemPost,OSMutexPost( ),OSMboxPost( ),OSQPost( )必將調(diào)用此函數(shù)從而使一個(gè)任務(wù)進(jìn)入就緒態(tài)。
OS_EventTaskRdy( );
3、使一個(gè)任務(wù)進(jìn)入等待某事件發(fā)生:
當(dāng)某個(gè)任務(wù)須等待一個(gè)事件的發(fā)生時(shí),信號量、互斥型信號量、郵箱、消息隊(duì)列會(huì)通過相應(yīng)的PEND函數(shù)來調(diào)用這個(gè)函數(shù)。
OS_EventTaskWait( );
4、由于等待超時(shí)而將任務(wù)置為就緒態(tài):
如果在預(yù)先指定的等待時(shí)間內(nèi)任務(wù)等待的事件沒有發(fā)生,那么PNED類型函數(shù)將會(huì)調(diào)用此函數(shù)從而將等待超時(shí)的任務(wù)進(jìn)入就緒態(tài)。
OS_EventTo( );
四.事件控制塊ECB基本操作代碼的分析。
1、OS_EventWaitListInit( );
void OS_EventWaitListInit(OS_EVENT *pevent)
{
INT8U *ptbl; //定義指針變量ptbl
pevent -》 OSEventGrp = 0x00; //清除任務(wù)所在的組
OS_EVENT_TBL_SIZE在UCOS_ II.H中定義大小
ptbl = &pevent -》 OSEventTbl[0];
#if OS_EVENT_TBL_SIZE 》 0
*ptbl++ = 0x00; //清除等待任務(wù)列表,在這里沒有使用for循環(huán)是為了節(jié)省系統(tǒng)開銷
#endif
#if OS_EVENT_TBL_SIZE 》 1
*ptbl++ = 0x00;
#endif
#if OS_EVENT_TBL_SIZE 》 2
*ptbl++ = 0x00;
#endif
#if OS_EVENT_TBL_SIZE 》 3
*ptbl++ = 0x00;
#endif
#if OS_EVENT_TBL_SIZE 》 4
*ptbl++ = 0x00;
#endif
#if OS_EVENT_TBL_SIZE 》 5
*ptbl++ = 0x00;
#endif
#if OS_EVENT_TBL_SIZE 》 6
*ptbl++ = 0x00;
#endif
#if OS_EVENT_TBL_SIZE 》 7
*ptbl++ = 0x00;
#endif
}
2、OS_EventTaskRdy( );
INT8U OS_EventTaskRdy(OS_EVENT *pevent, void *msg,INT8U msk)
{
OS_TCB *ptcb;
INT8U x;
INT8U y;
按照關(guān)鍵算法3,在等待事件的任務(wù)列表中找到優(yōu)先級最高的任務(wù),并確定其優(yōu)先級。
INT8U bitx;
INT8U bity;
INT8U prio;
y = OSUnMapTbl[pevent -》 OSEventGrp];
bity = OSMapTbl[y];
x = OSUnMapTbl[pevent -》 OSEventTbl[y]];
利用算法2,從等待任務(wù)列表中刪除此優(yōu)先級最高的任務(wù)。
bitx = OSMapTbl[x];
prio = (INT8U)(( y 《《 3) + x);
if ((pevent -》 OSEventTbl[y] &= ~bitx) == 0x00)
{ pevent -》 OSEventGrp &= ~bity;}
ptcb = OSTCBPrioTbl[prio]; //知道了任務(wù)優(yōu)先級,從而找到任務(wù)控制塊的指針
ptcb -》 OSTCBDly = 0; //由于此任務(wù)已經(jīng)不再等待事件的發(fā)生,因此直接清0
ptcb -》 OSTCBEventPtr = (OS_EVENT *)0;//由于不再等待事件的發(fā)生,使指向事件控制塊的指針指向NULL
#if ((OS_Q_EN 》 0) && (OS_MAX_QS 》 0)) || (OS_MBOX_EN 》 0)
ptcb -》 OSTCBMsg = msg;//如果此函數(shù)是郵箱或隊(duì)列POST函數(shù)調(diào)用的,則需要將傳遞來的參數(shù)放到它的任務(wù)控制塊中
#else
msg = msg;
#endif
ptcb -》 OSTCBStat &= ~msk;
if (ptcb -》 OSTCBStat == OS_STAT_RDY)]
{
OSRdyGrp |= bity; ---最高優(yōu)先級的任務(wù)插入到就緒任務(wù)列表,由后續(xù)POST函數(shù)中的
OSRdyTbl[y] |= bitx; ---OSSched( )函數(shù)進(jìn)行調(diào)度使任務(wù)進(jìn)入就緒,請參考第三章之就緒表
}
return (prio);
}
3、OS_EventTaskWait( );
void OS_EventTaskWait(OS_EVENT *pevent)
{
OSTCBCur -》 OSTCBEventPtr = pevent;
if (( OSRdyTbl[OSTCBCur -》 OSTCBY] &= ~OSTCBCur-》OSTCBBitx) == 0x00)
{ OSRdyGrp &= ~OSTCBCur -》 OSTCBBity; } //如果在PEND函數(shù)中沒有收到有效的信號量,
//那么將調(diào)用此函數(shù)進(jìn)入睡眠態(tài),在這里將任務(wù)在任務(wù)就緒列表中刪除
pevent -》 OSEventTbl[OSTCBCur -》 OSTCBY] |= OSTCBCur -》 OSTCBBitx;
pevent -》 OSEventGrp |= OSTCBCur -》 OSTCBBity;//把此任務(wù)放到ECB的等待事件的任務(wù)列表中去
}
4、OS_EventTo( );
void OS_EventTO (OS_EVENT *pevent)
{
if (( pevent -》 OSEventTbl[OSTCBCur -》 OSTCBY] &= ~OSTCBCur -》 OSTCBBitx) ==0x00)
{ pevent -》 OSEventGrp &= ~OSTCBCur -》 OSTCBBitY; }//將超時(shí)的任務(wù)在等待任務(wù)列表中刪除
OSTCBCur -》 OSTCBStat = OS_STAT_RDY; //任務(wù)置為就緒態(tài)
OSTCBCur -》 OSTCBEventPtr = (OS_EVENT *)0;
}
(審核編輯: 智匯小新)