void *OSMboxPend (OS_EVENT *pevent, INT16U timeout, INT8U *err)
{
#if OS_CRITICAL_METHOD == 3 /* Allocate storage for CPU status register */
OS_CPU_SR cpu_sr;
#endif
void *msg;
if (OSIntNesting > 0) { /* See if called from ISR ... */
*err = OS_ERR_PEND_ISR; /* ... can't PEND from an ISR */
return ((void *)0);
}
#if OS_ARG_CHK_EN > 0
if (pevent == (OS_EVENT *)0) { /* Validate 'pevent' */
*err = OS_ERR_PEVENT_NULL;
return ((void *)0);
}
#endif
if (pevent->OSEventType != OS_EVENT_TYPE_MBOX) { /* Validate event block type */
*err = OS_ERR_EVENT_TYPE;
return ((void *)0);
}
OS_ENTER_CRITICAL();
msg = pevent->OSEventPtr; ;首先將消息郵箱的指針成員(數據緩衝區指針)賦值給局部變量msg
if (msg != (void *)0) { ; 檢測是否爲空指針,如果不是空指針,就將消息郵箱的指針賦給msg,並
pevent->OSEventPtr = (void *)0; ;將err指針指向的值賦於常數OS_NO_ERR,然後把msg即消息郵
OS_EXIT_CRITICAL(); ;箱裏的指針返回。
*err = OS_NO_ERR;
return (msg);
}
OSTCBCur->OSTCBStat |= OS_STAT_MBOX; ;如果消息郵箱的指針不可用,就將當前任務控制塊的
OSTCBCur->OSTCBDly = timeout; ;表徵當前任務狀態的成員賦值表示任務由於等待消息郵
OS_EventTaskWait(pevent); ;箱而處於掛起狀態,任務等待的時限爲timeout
OS_EXIT_CRITICAL();
OS_Sched(); ;該任務已經掛起,使用調度器進行任務調度。如果中斷程序都結束、調度器沒有鎖定、就緒表中優先級別最高的任務不是當前任務,那麼進行任務調度,切換程序;否則,從調度其中返回,不做任務diaod
OS_ENTER_CRITICAL();
msg = OSTCBCur->OSTCBMsg; ;將當前任務控制塊指向消息郵箱的指針又給了局部變量msg
if (msg != (void *)0) { ;如果msg指針有效,則改變任務控制塊相應的成員變量,給err指針返回
OSTCBCur->OSTCBMsg = (void *)0; ;無錯信息,並返回msg指針,即返回消息郵箱的指針。
OSTCBCur->OSTCBStat = OS_STAT_RDY;
OSTCBCur->OSTCBEventPtr = (OS_EVENT *)0; /* No longer waiting for event */
OS_EXIT_CRITICAL();
*err = OS_NO_ERR;
return (msg); /* Return the message received */
}
OS_EventTO(pevent); ;任務等待該消息郵箱的時限到
OS_EXIT_CRITICAL();
*err = OS_TIMEOUT; ;返回超時標誌到err指針
return ((void *)0); /* Return a NULL message */
}
請求消息郵箱的工作主要有:第一, 檢查是在中斷服務程序中調用請求消息郵箱,如果是則給err指針返回常數OS_ERR_PEND_ISR,程序返回一個空指針;第二,檢查所請求的郵箱是否有效,如果無效,則給err指針返回常數OS_ERR_PEVENT_NULL,程序返回一個空指針;第三,檢查所請求的消息郵箱的類型是否爲郵箱類型,如果不是,則給err指針返回OS_ERR_EVENT_TYPE,程序返回一個空指針;第四,獲得所請求的郵箱指針,若果該指針有效,將消息郵箱中的指針清空(表示已經被獲得),然後給err指針返回常數OS_NO_ERR,然後程序返回郵箱的指針;第五,如果獲得的郵箱指針無效,就將任務控制塊的狀態設爲等待狀態,並告訴任務控制塊要等待的時限,然後調用OS_EventTaskWait ,刪除掉任務在就緒表中的相應位置,置位任務在事件等待列表中的相應位置;第六,調用OS_Sched()進行任務調度,如果調度成功,則進行任務切換,如果調度條件不滿足,又返回到該程序;第七,將任務控塊成員OSTCBCur->OSTCBMsg指針值(即郵箱的指針)給了msg指針,如果這個指針不空,將OSTCBCur->OSTCBMsg 清零,任務未就緒狀態,給err 指針返回常數OS_NO_ERR,程序返回郵箱指針msg;第八,調用OS_EventTO(pevent);等待時限到,給err指針返回常數OS_TIMEOUT,程序返回一個空指針,程序結束。
void OS_EventTaskWait (OS_EVENT *pevent)
{
INT8U y;
OSTCBCur->OSTCBEventPtr = pevent; ;把事件控制塊的指針保存在任務控制塊成員OSTCBEventPtr裏
y = OSTCBCur->OSTCBY; ;把當前任務從任務就緒表中刪除
OSRdyTbl[y] &= ~OSTCBCur->OSTCBBitX;
if (OSRdyTbl[y] == 0x00) {
OSRdyGrp &= ~OSTCBCur->OSTCBBitY; /* Clear event grp bit if this was only task pending */
}
pevent->OSEventTbl[OSTCBCur->OSTCBY] |= OSTCBCur->OSTCBBitX; ;把當前任務在事件控制塊的
pevent->OSEventGrp |= OSTCBCur->OSTCBBitY; ;列表中的相應位置位。
}該函數主要完成的工作:第一,把事件控制塊的指針保存在等待該事件的任務的任務控制塊的成員OSTCBEventPtr 裏面;第二,把該任務在任務就緒表中的相應位刪除,即該任務處於掛起等待狀態,等待消息郵箱的狀態;第三,把該任務要等待的事件的事件控制塊裏的等待任務列表的相應位置位,表示這個任務要等到這個事件的發生。
void OS_Sched (void)
{
#if OS_CRITICAL_METHOD == 3 /* Allocate storage for CPU status register */
OS_CPU_SR cpu_sr;
#endif
INT8U y;
OS_ENTER_CRITICAL();
if (OSIntNesting == 0) { ;所有的中斷服務程序結束並且調度器沒有鎖定,才進行調度
if (OSLockNesting == 0) {
y = OSUnMapTbl[OSRdyGrp]; ;找出任務就緒表中優先級別最高的就緒任務
OSPrioHighRdy = (INT8U)((y << 3) + OSUnMapTbl[OSRdyTbl[y]]);
if (OSPrioHighRdy != OSPrioCur) { ;如果就緒表中的優先級別最高的任務不是當前任務就進行調度
OSTCBHighRdy = OSTCBPrioTbl[OSPrioHighRdy];
#if OS_TASK_PROFILE_EN > 0
OSTCBHighRdy->OSTCBCtxSwCtr++; /* Inc. # of context switches to this task */
#endif
OSCtxSwCtr++; /* Increment context switch counter */
OS_TASK_SW(); /* Perform a context switch */
}
} ;如果就緒表中優先級最高的任務就是當前的任務,就不再進行任務調度,從
} ;調度器返回。
OS_EXIT_CRITICAL();
}調度器完成的主要工作有:第一,在所有中斷服務結束並且調度器沒有被鎖定時才進行任務調度;第二,找出任務就緒表中優先級別最高的就緒任務;第三,如果優先級別最高的就緒任務不再是當前任務,就進行任務調度,轉去執行優先級別最高的任務,如果就緒表中優先級別最高的任務還是當前任務,那麼不進行任務調度,調度其返回到調用它的程序裏面。
void OS_EventTO (OS_EVENT *pevent)
{
INT8U y;
y = OSTCBCur->OSTCBY;
pevent->OSEventTbl[y] &= ~OSTCBCur->OSTCBBitX;
if (pevent->OSEventTbl[y] == 0x00) {
pevent->OSEventGrp &= ~OSTCBCur->OSTCBBitY;
}
OSTCBCur->OSTCBStat = OS_STAT_RDY; /* Set status to ready */
OSTCBCur->OSTCBEventPtr = (OS_EVENT *)0; /* No longer waiting for event */
};任務等待事件的時限到,刪除事件控制塊等待任務列表中該任務的相應位,是任務的狀態處於就緒狀態。