OS_FLAG.C(3)
上篇我們介紹了創(chuàng)建和刪除事件標(biāo)志組函數(shù),后來在接著看源代碼的時候,發(fā)現(xiàn)倒著來更有助于理解。所以后面幾篇我會選擇較為合適的方式來不定期更博,方便大家理解。
1.介紹刪除節(jié)點(diǎn)函數(shù)OS_FlagUnlink (OS_FLAG_NODE *pnode):
/*$PAGE*/ /*2018/2/13 ********************************************************************************************************* * UNLINK EVENT FLAG NODE FROM WAITING LIST * 從等待列表中將事件標(biāo)志節(jié)點(diǎn)取消關(guān)聯(lián)(刪除節(jié)點(diǎn)) * Description: This function is internal to uC/OS-II and is used to unlink an event flag node from a * list of tasks waiting for the event flag. *描述:該功能為內(nèi)部函數(shù),用來從等待事件標(biāo)志任務(wù)列表中解除事件標(biāo)志節(jié)點(diǎn) * Arguments : pnode is a pointer to a structure which contains data about the task waiting for * event flag bit(s) to be set. *參數(shù): --pnode:指向結(jié)構(gòu)體的指針。該結(jié)構(gòu)體中包含等待事件標(biāo)志位的任務(wù)的數(shù)據(jù)。 * Returns : none *返回值:無 * Called by : OS_FlagTaskRdy() OS_FLAG.C * OSFlagPend() OS_FLAG.C * OSTaskDel() OS_TASK.C *可以被:OS_FLAG.C文件中的OS_FlagTaskRdy()和OSFlagPend()函數(shù)還有OS_TASK.C文件中的OSTaskDel()函數(shù)調(diào)用。 * Note(s) : 1) This function assumes that interrupts are disabled. * 2) This function is INTERNAL to uC/OS-II and your application should not call it.注釋:1)該功能不可以被中斷。為原子函數(shù)2)該功能為內(nèi)部函數(shù),你的應(yīng)用程序不能調(diào)用。 ********************************************************************************************************* */void OS_FlagUnlink (OS_FLAG_NODE *pnode)/*pnode為要進(jìn)行移除的節(jié)點(diǎn)*/ {#if OS_TASK_DEL_EN > 0uOS_TCB *ptcb;#endifOS_FLAG_GRP *pgrp; /*pgrp指向事件標(biāo)志組*/OS_FLAG_NODE *pnode_prev; /*pnode_prev指向前一個節(jié)點(diǎn)*/OS_FLAG_NODE *pnode_next; /*pnode_next指向后一個節(jié)點(diǎn)*/pnode_prev = (OS_FLAG_NODE *)pnode->OSFlagNodePrev;pnode_next = (OS_FLAG_NODE *)pnode->OSFlagNodeNext;if (pnode_prev == (OS_FLAG_NODE *)0) /*如果前一個節(jié)點(diǎn)為空。那么pnode指向的是等待列表的首節(jié)點(diǎn)(相當(dāng)于刪除首節(jié)點(diǎn))*/{ pgrp= (OS_FLAG_GRP *)pnode->OSFlagNodeFlagGrp; /*pgrp指向要移除節(jié)點(diǎn)所在的組*/pgrp->OSFlagWaitList = (void *)pnode_next; /*將該節(jié)點(diǎn)的下一個作為pgrp指向等待列表的指針*/if (pnode_next != (OS_FLAG_NODE *)0) /*如果下一個節(jié)點(diǎn)不是空*/{pnode_next->OSFlagNodePrev = (OS_FLAG_NODE *)0; /* 將下一個節(jié)點(diǎn)指向前一個節(jié)點(diǎn)的指針設(shè)置為空*/}} else/*如果前一個節(jié)點(diǎn)不為空,不是首節(jié)點(diǎn)(相當(dāng)于從中間刪除)*/{ pnode_prev->OSFlagNodeNext = pnode_next; if (pnode_next != (OS_FLAG_NODE *)0) { pnode_next->OSFlagNodePrev = pnode_prev; }}#if OS_TASK_DEL_EN > 0u /*如果允許刪除任務(wù)*/ptcb = (OS_TCB *)pnode->OSFlagNodeTCB; /*將該節(jié)點(diǎn)指向的TCB節(jié)點(diǎn)賦給ptcb指針*/ptcb->OSTCBFlagNode = (OS_FLAG_NODE *)0;/*將該指針下的TCB標(biāo)志節(jié)點(diǎn)設(shè)為空,表示刪除*/#endif } #endif從這個函數(shù)中不難看出,如果要刪除節(jié)點(diǎn),首先要看刪除的是首節(jié)點(diǎn)還是中間結(jié)點(diǎn)或者尾節(jié)點(diǎn),然后進(jìn)行刪除。
刪除的方式這里也不需要贅述了,比較簡單。可以參考上一篇。
2.介紹 是否可以使任務(wù)變?yōu)榫途w態(tài)(是否可以被調(diào)度)BOOLEAN ?OS_FlagTaskRdy (OS_FLAG_NODE *pnode,OS_FLAGS ?flags_rdy)函數(shù):
/*$PAGE*/ /*2018/2/13 ********************************************************************************************************* * MAKE TASK READY-TO-RUN, EVENT(s) OCCURRED * 是否可以使任務(wù)變?yōu)榫途w態(tài) * Description: This function is internal to uC/OS-II and is used to make a task ready-to-run because the * desired event flag bits have been set. *描述:該功能函數(shù)是內(nèi)部函數(shù)。作用為當(dāng)事件標(biāo)志位被設(shè)置后使任務(wù)變?yōu)榫途w態(tài)。 * Arguments : pnode is a pointer to a structure which contains data about the task waiting for * event flag bit(s) to be set. *參數(shù): --pnode:指向結(jié)構(gòu)體的指針。該結(jié)構(gòu)體包括了等待事件標(biāo)志位被設(shè)置的任務(wù)數(shù)據(jù)。 * flags_rdy contains the bit pattern of the event flags that cause the task to become * ready-to-run. * --flags_rdy:事件標(biāo)志組的位模式 * Returns : OS_TRUE If the task has been placed in the ready list and thus needs scheduling * OS_FALSE The task is still not ready to run and thus scheduling is not necessary *返回值: OS_TRUE:返回真,說明任務(wù)已經(jīng)被放在了就緒列表中,需要調(diào)度;OS_FALSE:返回假,說明該任務(wù)仍處于等待狀態(tài),不需要進(jìn)行調(diào)度。 * Called by : OSFlagsPost() OS_FLAG.C *被OS_FLAG.C文件中的OSFlagsPost()函數(shù)調(diào)用。 * Note(s) : 1) This function assumes that interrupts are disabled. * 2) This function is INTERNAL to uC/OS-II and your application should not call it.注釋:1)該功能不可以被中斷‘2)該功能為內(nèi)部函數(shù),你的應(yīng)用程序不能調(diào)用。 ********************************************************************************************************* */static BOOLEAN OS_FlagTaskRdy (OS_FLAG_NODE *pnode,OS_FLAGS flags_rdy) {OS_TCB *ptcb; /*指向TCB的指針*/BOOLEAN sched; /*是否調(diào)度的標(biāo)志*/ptcb = (OS_TCB *)pnode->OSFlagNodeTCB; /*指向正在等待的任務(wù)的TCB*/ptcb->OSTCBDly = 0u; /*將TCB的延遲時間設(shè)置為0*/ptcb->OSTCBFlagsRdy = flags_rdy; ptcb->OSTCBStat &= (INT8U)~(INT8U)OS_STAT_FLAG;ptcb->OSTCBStatPend = OS_STAT_PEND_OK;if (ptcb->OSTCBStat == OS_STAT_RDY) /*如果此時TCB狀態(tài)為就緒態(tài)*/{ OSRdyGrp |= ptcb->OSTCBBitY; /*將任務(wù)放在就緒隊(duì)列中*/OSRdyTbl[ptcb->OSTCBY] |= ptcb->OSTCBBitX; /*得到位掩碼*/sched = OS_TRUE; /*將調(diào)度標(biāo)志設(shè)置為真*/} else{sched = OS_FALSE; /*將調(diào)度標(biāo)志設(shè)置為假*/}OS_FlagUnlink(pnode); /*調(diào)用刪除節(jié)點(diǎn)函數(shù),將已放在就緒列表中的該節(jié)點(diǎn)從等待列表中刪除*/return (sched); /*返回是否調(diào)度的真假值*/ }該函數(shù)的作用很清楚:判斷任務(wù)是否可以轉(zhuǎn)化為就緒態(tài)。如果可以轉(zhuǎn)化,就將標(biāo)志設(shè)置為真,不可以,就設(shè)置為假,然后返回。
但是這里面有一個問題,我有點(diǎn)疑惑:
OS_FlagUnlink(pnode); /*調(diào)用刪除節(jié)點(diǎn)函數(shù),將已放在就緒列表中的該節(jié)點(diǎn)從等待列表中刪除*/該行語句不在if~else語句中,說明不論是否任務(wù)已經(jīng)準(zhǔn)備好從等待態(tài)轉(zhuǎn)化為就緒態(tài),都從等待列表中刪除。這樣對嗎?或者是我哪里理解錯誤?請高手指點(diǎn)一二。
3.介紹初始化事件標(biāo)志函數(shù)?OS_FlagInit (void):
/*$PAGE*/ /*2018/2/13 ********************************************************************************************************* * INITIALIZE THE EVENT FLAG MODULE * 初始化事件標(biāo)志 * Description: This function is called by uC/OS-II to initialize the event flag module. Your application * MUST NOT call this function. In other words, this function is internal to uC/OS-II. *描述:該功能用來初始化事件標(biāo)志模塊。你的應(yīng)用程序不能調(diào)用該功能。 * Arguments : none *參數(shù):無 * Returns : none *返回值:無 * WARNING : You MUST NOT call this function from your code. This is an INTERNAL function to uC/OS-II. 警告:在你的代碼中不能調(diào)用該功能,這是uc/os的內(nèi)部函數(shù)。 ********************************************************************************************************* */ void OS_FlagInit (void) {#if OS_MAX_FLAGS == 1u /*如果只有一個標(biāo)志*/OSFlagFreeList = (OS_FLAG_GRP *)&OSFlagTbl[0]; /*只有一個事件標(biāo)志組,空閑列表指針指向標(biāo)志表中第0號內(nèi)容*/OSFlagFreeList->OSFlagType = OS_EVENT_TYPE_UNUSED;/*將標(biāo)志類型設(shè)置為未使用類型*/OSFlagFreeList->OSFlagWaitList = (void *)0; /*將等待列表指針置為空*/OSFlagFreeList->OSFlagFlags = (OS_FLAGS)0; /*將標(biāo)志設(shè)為0*/#if OS_FLAG_NAME_EN > 0uOSFlagFreeList->OSFlagName = (INT8U *)"?"; /*將名字設(shè)置為未命名*/#endif#endif#if OS_MAX_FLAGS >= 2u /*如果不止一個標(biāo)志*/INT16U ix;INT16U ix_next; OS_FLAG_GRP *pgrp1; /*第一個指向事件標(biāo)志組的指針*/OS_FLAG_GRP *pgrp2; /*第一個指向事件標(biāo)志組的指針*/OS_MemClr((INT8U *)&OSFlagTbl[0], sizeof(OSFlagTbl)); /* 從內(nèi)存中清除事件標(biāo)志組表*/for (ix = 0u; ix < (OS_MAX_FLAGS - 1u); ix++) /*遍歷該表,初始化所有的事件標(biāo)志*/{ ix_next = ix + 1u;pgrp1 = &OSFlagTbl[ix];pgrp2 = &OSFlagTbl[ix_next];pgrp1->OSFlagType = OS_EVENT_TYPE_UNUSED; /*將標(biāo)志類型設(shè)置為未使用類型*/pgrp1->OSFlagWaitList = (void *)pgrp2; /*將指向下一個標(biāo)志的指針賦給OSFlagWaitList*/#if OS_FLAG_NAME_EN > 0upgrp1->OSFlagName = (INT8U *)(void *)"?"; /*將名稱初始化為未命名*/#endif}pgrp1 = &OSFlagTbl[ix]; /*處理該表的最后一個*/pgrp1->OSFlagType = OS_EVENT_TYPE_UNUSED;pgrp1->OSFlagWaitList = (void *)0; #if OS_FLAG_NAME_EN > 0upgrp1->OSFlagName = (INT8U *)(void *)"?"; #endifOSFlagFreeList = &OSFlagTbl[0]; #endif }初始化函數(shù)我們之前在OS_CORE.C文件中也有過介紹。這個函數(shù)與那些初始化函數(shù)大同小異。此處不贅述。
4.介紹阻塞任務(wù)函數(shù)?void ?OS_FlagBlock (OS_FLAG_GRP ?*pgrp,OS_FLAG_NODE *pnode,OS_FLAGS ?flags,INT8U ? ? ? ? wait_type,?INT32U ?timeout)
/*$PAGE*/ /*2018/2/13 ********************************************************************************************************* * SUSPEND TASK UNTIL EVENT FLAG(s) RECEIVED OR TIMEOUT OCCURS * 將任務(wù)掛起,直到標(biāo)志被接收或者超時 * Description: This function is internal to uC/OS-II and is used to put a task to sleep until the desired * event flag bit(s) are set. *描述:該功能為內(nèi)部函數(shù),用來將任務(wù)處于睡眠狀態(tài),知道事件標(biāo)志位被設(shè)置 * Arguments : pgrp is a pointer to the desired event flag group. *參數(shù): -pgrp:指向事件標(biāo)志組的指針 * pnode is a pointer to a structure which contains data about the task waiting for * event flag bit(s) to be set. * --pnode:指向結(jié)構(gòu)體的指針。 * flags Is a bit pattern indicating which bit(s) (i.e. flags) you wish to check. * The bits you want are specified by setting the corresponding bits in * 'flags'. e.g. if your application wants to wait for bits 0 and 1 then * 'flags' would contain 0x03. * --flags:存放你想檢測的位。 * wait_type specifies whether you want ALL bits to be set/cleared or ANY of the bits * to be set/cleared. * You can specify the following argument: * OS_FLAG_WAIT_CLR_ALL You will check ALL bits in 'mask' to be clear (0) * OS_FLAG_WAIT_CLR_ANY You will check ANY bit in 'mask' to be clear (0) * OS_FLAG_WAIT_SET_ALL You will check ALL bits in 'mask' to be set (1) * OS_FLAG_WAIT_SET_ANY You will check ANY bit in 'mask' to be set (1) * --timeout:設(shè)置等待類型:OS_FLAG_WAIT_CLR_ALLOS_FLAG_WAIT_CLR_ANYOS_FLAG_WAIT_SET_ALLOS_FLAG_WAIT_SET_ANY * timeout is the desired amount of time that the task will wait for the event flag * bit(s) to be set. * Returns : none *返回值:無 * Called by : OSFlagPend() OS_FLAG.C *被OS_FLAG.C文件中的OSFlagPend()調(diào)用。 * Note(s) : This function is INTERNAL to uC/OS-II and your application should not call it.注釋:該功能為內(nèi)部函數(shù),你的應(yīng)用程序不能調(diào)用。 ********************************************************************************************************* */ static void OS_FlagBlock (OS_FLAG_GRP *pgrp,OS_FLAG_NODE *pnode,OS_FLAGS flags,INT8U wait_type,INT32U timeout) {OS_FLAG_NODE *pnode_next; /*指向下一個節(jié)點(diǎn)的指針*/INT8U y;/*設(shè)置當(dāng)前TCB的參數(shù)*/OSTCBCur->OSTCBStat |= OS_STAT_FLAG; OSTCBCur->OSTCBStatPend = OS_STAT_PEND_OK;OSTCBCur->OSTCBDly = timeout; /*TCB延時設(shè)置為timeout*//*以下幾行代碼都是將pnode設(shè)置為鏈表的新的頭節(jié)點(diǎn)*/#if OS_TASK_DEL_EN > 0uOSTCBCur->OSTCBFlagNode = pnode; /* 將TCB與node聯(lián)系起來 */#endifpnode->OSFlagNodeFlags = flags; /* 保存我們需要等待的標(biāo)志*/pnode->OSFlagNodeWaitType = wait_type; /*保存等待類型 */pnode->OSFlagNodeTCB = (void *)OSTCBCur; /*標(biāo)志指向的TCB為當(dāng)前的TCB*/pnode->OSFlagNodeNext = pgrp->OSFlagWaitList; /*將節(jié)點(diǎn)的指針指向節(jié)點(diǎn)鏈表的頭部*/pnode->OSFlagNodePrev = (void *)0;pnode->OSFlagNodeFlagGrp = (void *)pgrp; /*連接事件標(biāo)志組 */pnode_next = (OS_FLAG_NODE *)pgrp->OSFlagWaitList;/*下一個節(jié)點(diǎn)*/if (pnode_next != (void *)0) /*如果為空地址,只有一個節(jié)點(diǎn)(就是本節(jié)點(diǎn)),如果非空,那么將該鏈表的頭節(jié)點(diǎn)改為現(xiàn)在這個節(jié)點(diǎn)*/{ pnode_next->OSFlagNodePrev = pnode; }pgrp->OSFlagWaitList = (void *)pnode;y = OSTCBCur->OSTCBY; /* 將當(dāng)前的任務(wù)掛起(取消該任務(wù)的就緒態(tài))更改就緒表和就緒組的相關(guān)值*/OSRdyTbl[y] &= (OS_PRIO)~OSTCBCur->OSTCBBitX;if (OSRdyTbl[y] == 0x00u) {OSRdyGrp &= (OS_PRIO)~OSTCBCur->OSTCBBitY;} }這個函數(shù)里提示一點(diǎn):
/*以下幾行代碼都是將pnode設(shè)置為鏈表的新的頭節(jié)點(diǎn)*/#if OS_TASK_DEL_EN > 0uOSTCBCur->OSTCBFlagNode = pnode; /* 將TCB與node聯(lián)系起來 */#endifpnode->OSFlagNodeFlags = flags; /* 保存我們需要等待的標(biāo)志*/pnode->OSFlagNodeWaitType = wait_type; /*保存等待類型 */pnode->OSFlagNodeTCB = (void *)OSTCBCur; /*標(biāo)志指向的TCB為當(dāng)前的TCB*/pnode->OSFlagNodeNext = pgrp->OSFlagWaitList; /*將節(jié)點(diǎn)的指針指向節(jié)點(diǎn)鏈表的頭部*/pnode->OSFlagNodePrev = (void *)0;pnode->OSFlagNodeFlagGrp = (void *)pgrp; /*連接事件標(biāo)志組 */pnode_next = (OS_FLAG_NODE *)pgrp->OSFlagWaitList;/*下一個節(jié)點(diǎn)*/注釋里提到了:這幾行就是將當(dāng)前的節(jié)點(diǎn)pnode設(shè)置為等待列表的新的頭節(jié)點(diǎn),取消其就緒狀態(tài),設(shè)置為掛起狀態(tài)。
在這個的基礎(chǔ)上理解上面幾行語句就很簡單了。
5.OSFlagQuery (OS_FLAG_GRP ?*pgrp,INT8U ?*perr)查詢事件標(biāo)志函數(shù):
/*$PAGE*/ /*2018/2/13 ********************************************************************************************************* * QUERY EVENT FLAG * 查詢事件標(biāo)志 * Description: This function is used to check the value of the event flag group. *描述:該功能用來檢測事件標(biāo)志組的值 * Arguments : pgrp is a pointer to the desired event flag group. *參數(shù): --pgrp:指向事件標(biāo)志組的指針 * perr is a pointer to an error code returned to the called: * OS_ERR_NONE The call was successfull * OS_ERR_FLAG_INVALID_PGRP You passed a NULL pointer * OS_ERR_EVENT_TYPE You are not pointing to an event flag group * --perr錯誤碼指針:OS_ERR_NONE:無錯誤;OS_ERR_FLAG_INVALID_PGRP:pgrp為空指針;OS_ERR_EVENT_TYPE:沒有指向事件標(biāo)志組的指針。 * Returns : The current value of the event flag group. *返回值:事件標(biāo)志組的當(dāng)前值 * Called From: Task or ISR 任務(wù)或者中斷調(diào)用。 ********************************************************************************************************* */#if OS_FLAG_QUERY_EN > 0u OS_FLAGS OSFlagQuery (OS_FLAG_GRP *pgrp,INT8U *perr) {OS_FLAGS flags; /*定義一個“當(dāng)前位”狀態(tài)*/#if OS_CRITICAL_METHOD == 3u OS_CPU_SR cpu_sr = 0u;#endif#ifdef OS_SAFETY_CRITICAL /*安全中斷*/if (perr == (INT8U *)0) {OS_SAFETY_CRITICAL_EXCEPTION();}#endif#if OS_ARG_CHK_EN > 0u /*檢查參數(shù)*/if (pgrp == (OS_FLAG_GRP *)0) { *perr = OS_ERR_FLAG_INVALID_PGRP;return ((OS_FLAGS)0);}#endifif (pgrp->OSFlagType != OS_EVENT_TYPE_FLAG) /*有效化事件標(biāo)志塊類型*/{ *perr = OS_ERR_EVENT_TYPE;return ((OS_FLAGS)0);}OS_ENTER_CRITICAL(); /*進(jìn)入中斷*/ flags = pgrp->OSFlagFlags; /*獲取事件標(biāo)志組的當(dāng)前的事件標(biāo)志位值*/OS_EXIT_CRITICAL(); /*關(guān)閉中斷*/*perr = OS_ERR_NONE; /*將錯誤碼指針設(shè)置為成功調(diào)用*/return (flags); /*返回當(dāng)前事件標(biāo)志狀態(tài)*/ } #endif該函數(shù)關(guān)鍵語句就是上面標(biāo)紅的那一行。
6.設(shè)置或清除事件標(biāo)志組OSFlagPost (OS_FLAG_GRP ?*pgrp,OS_FLAGS ?flags,INT8U ?opt,INT8U ?*perr)函數(shù):
/*$PAGE*/ /*2018/2/13 ********************************************************************************************************* * POST EVENT FLAG BIT(S) * 設(shè)置或清除事件標(biāo)志組 * Description: This function is called to set or clear some bits in an event flag group. The bits to * set or clear are specified by a 'bit mask'. *描述:該功能用來設(shè)置或者清除事件標(biāo)志組中的一些位。這些位由位掩碼來指定。 * Arguments : pgrp is a pointer to the desired event flag group. *參數(shù): --pgrp:指向事件標(biāo)志組的指針 * flags If 'opt' (see below) is OS_FLAG_SET, each bit that is set in 'flags' will * set the corresponding bit in the event flag group. e.g. to set bits 0, 4 * and 5 you would set 'flags' to: * 0x31 (note, bit 0 is least significant bit) * --flags:如果opt是OS_FLAG_SET,那么在flags中的每一位將在事件標(biāo)志組中的相應(yīng)位上也進(jìn)行設(shè)置。例如:如果要將事件標(biāo)志組中的位設(shè)置為0,4,5位為1,那么你就得將flags設(shè)置為00110001。(注釋:0位是最低有效位) * If 'opt' (see below) is OS_FLAG_CLR, each bit that is set in 'flags' will * CLEAR the corresponding bit in the event flag group. e.g. to clear bits 0, * 4 and 5 you would specify 'flags' as:0x31 (note, bit 0 is least significant bit) * --如果opt為OS_FLAG_CLR,那么在flags中設(shè)置的每一位對應(yīng)在事件標(biāo)志組中的對應(yīng)位將被清除掉。例如:如果要清除掉事件標(biāo)志組中的第0,4,5位,你的flags就應(yīng)該被指定為00110001(注釋:0是最低有效位) * * opt indicates whether the flags will be: * set (OS_FLAG_SET) or * cleared (OS_FLAG_CLR) * --opt:有以下兩種選擇:set(OS_FLAG_SET)設(shè)置或者 cleared (OS_FLAG_CLR)清除。這兩個不同的選擇對flags有影響。 * perr is a pointer to an error code and can be: * OS_ERR_NONE The call was successfull * OS_ERR_FLAG_INVALID_PGRP You passed a NULL pointer * OS_ERR_EVENT_TYPE You are not pointing to an event flag group * OS_ERR_FLAG_INVALID_OPT You specified an invalid option * --perr:指向錯誤碼的指針,可以為以下值:OS_ERR_NONE:無錯誤;OS_ERR_FLAG_INVALID_PGRP:pgrp為空指針;OS_ERR_EVENT_TYPE:沒有指向事件標(biāo)志組的指針;OS_ERR_FLAG_INVALID_OPT:opt參數(shù)選擇錯誤。 * Returns : the new value of the event flags bits that are still set. *返回值:flags被修改后的值 * Called From: Task or ISR *由任務(wù)或者中斷調(diào)用。 * WARNING(s) : 1) The execution time of this function depends on the number of tasks waiting on the event * flag group. * 2) The amount of time interrupts are DISABLED depends on the number of tasks waiting on * the event flag group.警告:1)該功能的執(zhí)行時間取決于事件標(biāo)志組中的等待任務(wù)數(shù)量;2)時間中斷無效的數(shù)目取決于事件標(biāo)志組中的等待任務(wù)數(shù)。 ********************************************************************************************************* *///置位或清0事件標(biāo)志組中的標(biāo)志位(指針、標(biāo)志位、條件值、錯誤碼) OS_FLAGS OSFlagPost (OS_FLAG_GRP *pgrp,OS_FLAGS flags,INT8U opt,INT8U *perr) {OS_FLAG_NODE *pnode; /*指向標(biāo)志節(jié)點(diǎn)的指針*/BOOLEAN sched; /*是否被調(diào)度變量*/OS_FLAGS flags_cur; /*當(dāng)前的標(biāo)志值(flags)*/OS_FLAGS flags_rdy; /*就緒的標(biāo)志值(flags)*/BOOLEAN rdy; /*是否就緒變量*/#if OS_CRITICAL_METHOD == 3u /*中斷被設(shè)置為類型3*/OS_CPU_SR cpu_sr = 0u;#endif#ifdef OS_SAFETY_CRITICAL /*定義安全中斷*/if (perr == (INT8U *)0) {OS_SAFETY_CRITICAL_EXCEPTION();}#endif#if OS_ARG_CHK_EN > 0u /*檢查參數(shù)*/if (pgrp == (OS_FLAG_GRP *)0) /*有效化pgrp*/{ *perr = OS_ERR_FLAG_INVALID_PGRP;return ((OS_FLAGS)0);}#endifif (pgrp->OSFlagType != OS_EVENT_TYPE_FLAG) /*確定我們指向的是事件標(biāo)志組*/{ *perr = OS_ERR_EVENT_TYPE;return ((OS_FLAGS)0);} /*$PAGE*/OS_ENTER_CRITICAL(); /*進(jìn)入中斷*/switch (opt) {case OS_FLAG_CLR: /*opt為OS_FLAG_CLR*/pgrp->OSFlagFlags &= (OS_FLAGS)~flags; /*清除在事件標(biāo)志組中設(shè)置的位*/break;case OS_FLAG_SET: /*opt為OS_FLAG_SET*/pgrp->OSFlagFlags |= flags; /* 設(shè)置在事件標(biāo)志組中設(shè)置的位*/break;default: /*無效的選擇*/OS_EXIT_CRITICAL(); /*關(guān)中斷*/*perr = OS_ERR_FLAG_INVALID_OPT; /*將中斷碼設(shè)置為OS_ERR_FLAG_INVALID_OPT*/return ((OS_FLAGS)0); /*返回值為0*/}sched = OS_FALSE; /*將調(diào)度標(biāo)志設(shè)置為false,表示不需要調(diào)度*/pnode = (OS_FLAG_NODE *)pgrp->OSFlagWaitList;while (pnode != (OS_FLAG_NODE *)0) /*瀏覽等待事件標(biāo)志的所有任務(wù)*/{ switch (pnode->OSFlagNodeWaitType) /*根據(jù)等待類型不同執(zhí)行不同的代碼*/{case OS_FLAG_WAIT_SET_ALL: /*要求所有的位都被設(shè)置*/flags_rdy = (OS_FLAGS)(pgrp->OSFlagFlags & pnode->OSFlagNodeFlags);if (flags_rdy == pnode->OSFlagNodeFlags) /*所有的位都被設(shè)置*/{rdy = OS_FlagTaskRdy(pnode, flags_rdy); /*得到該節(jié)點(diǎn)對應(yīng)的任務(wù)是否就緒標(biāo)志*/if (rdy == OS_TRUE) /*該節(jié)點(diǎn)對應(yīng)的任務(wù)已經(jīng)就緒*/{sched = OS_TRUE; /*可以進(jìn)行調(diào)度*/}}break;case OS_FLAG_WAIT_SET_ANY: /*任意一位被設(shè)置*/flags_rdy = (OS_FLAGS)(pgrp->OSFlagFlags & pnode->OSFlagNodeFlags);if (flags_rdy != (OS_FLAGS)0) /*有任何一個標(biāo)志位被設(shè)置*/{rdy = OS_FlagTaskRdy(pnode, flags_rdy); /*得到該節(jié)點(diǎn)對應(yīng)的任務(wù)是否就緒標(biāo)志*/if (rdy == OS_TRUE) /*該節(jié)點(diǎn)對應(yīng)的任務(wù)已經(jīng)就緒*/{sched = OS_TRUE; /*可以進(jìn)行調(diào)度*/ }}break;/*下面兩個case參考上文即可*/#if OS_FLAG_WAIT_CLR_EN > 0ucase OS_FLAG_WAIT_CLR_ALL: flags_rdy = (OS_FLAGS)~pgrp->OSFlagFlags & pnode->OSFlagNodeFlags;if (flags_rdy == pnode->OSFlagNodeFlags) {rdy = OS_FlagTaskRdy(pnode, flags_rdy); if (rdy == OS_TRUE) {sched = OS_TRUE; }}break;case OS_FLAG_WAIT_CLR_ANY: flags_rdy = (OS_FLAGS)~pgrp->OSFlagFlags & pnode->OSFlagNodeFlags;if (flags_rdy != (OS_FLAGS)0) {rdy = OS_FlagTaskRdy(pnode, flags_rdy); if (rdy == OS_TRUE) {sched = OS_TRUE; }}break;#endifdefault: /*這四種情況都不是*/OS_EXIT_CRITICAL(); /*退出中斷*/*perr = OS_ERR_FLAG_WAIT_TYPE;/*設(shè)置錯誤碼為OS_ERR_FLAG_WAIT_TYPE*/return ((OS_FLAGS)0); /*返回0*/}pnode = (OS_FLAG_NODE *)pnode->OSFlagNodeNext; /* 指向下一個等待事件標(biāo)志的任務(wù)節(jié)點(diǎn)*/}OS_EXIT_CRITICAL(); /*退出中斷*/if (sched == OS_TRUE) { /*如果可以進(jìn)行任務(wù)調(diào)度*/OS_Sched(); /*調(diào)度任務(wù)*/}OS_ENTER_CRITICAL(); /*進(jìn)入中斷*/flags_cur = pgrp->OSFlagFlags;/*獲取事件標(biāo)志組的事件標(biāo)志位值作為當(dāng)前的標(biāo)志值*/OS_EXIT_CRITICAL(); /*退出中斷*/*perr = OS_ERR_NONE; /*成功調(diào)用*/return (flags_cur); /*返回當(dāng)前的標(biāo)志值*/ }流程圖為:
7.?OSFlagPend (OS_FLAG_GRP ?*pgrp,OS_FLAGS ?flags,?INT8U ? wait_type,INT32U timeout,INT8U *perr)等待事件標(biāo)志組中的事件標(biāo)志函數(shù):
/*$PAGE*/ /*2018/2/12 ********************************************************************************************************* * WAIT ON AN EVENT FLAG GROUP * 等待事件標(biāo)志組中的事件標(biāo)志 * Description: This function is called to wait for a combination of bits to be set in an event flag * group. Your application can wait for ANY bit to be set or ALL bits to be set. *描述:任務(wù)等待事件標(biāo)志組中的事件標(biāo)志,可以是多個事件標(biāo)志的不同組合方式。可以等待任意指定事件標(biāo)志位置位或清0,也可以是全部指定事件標(biāo)志位置位或清0。如果任務(wù)等待的事件標(biāo)志位條件尚不滿足,則任務(wù)會被掛起,直到指定的事件標(biāo)志組合發(fā)生或指定的等待時間超時。 * Arguments : pgrp is a pointer to the desired event flag group. *參數(shù): --pgrp:指向事件標(biāo)志組的指針 * flags Is a bit pattern indicating which bit(s) (i.e. flags) you wish to wait for. * The bits you want are specified by setting the corresponding bits in * 'flags'. e.g. if your application wants to wait for bits 0 and 1 then * 'flags' would contain 0x03. * --flags:指定需要檢查的事件標(biāo)志位。置為1,則檢查對應(yīng)位;置為0,則忽略對應(yīng)位。 * wait_type specifies whether you want ALL bits to be set or ANY of the bits to be set. * You can specify the following argument: * --wait_type:定義等待事件標(biāo)志位的方式。可以定為以下幾種 * OS_FLAG_WAIT_CLR_ALL You will wait for ALL bits in 'mask' to be clear (0) * OS_FLAG_WAIT_SET_ALL You will wait for ALL bits in 'mask' to be set (1) * OS_FLAG_WAIT_CLR_ANY You will wait for ANY bit in 'mask' to be clear (0) * OS_FLAG_WAIT_SET_ANY You will wait for ANY bit in 'mask' to be set (1) * --OS_FLAG_WAIT_CLR_ALL:所有指定事件標(biāo)志位清0 ;OS_FLAG_WAIT_SET_ALL:任意指定事件標(biāo)志位置1 ;OS_FLAG_WAIT_CLR_ANY:所有指定事件標(biāo)志位清0 ;OS_FLAG_WAIT_SET_ANY:任意指定事件標(biāo)志位置1 ; * NOTE: Add OS_FLAG_CONSUME if you want the event flag to be 'consumed' by * the call. Example, to wait for any flag in a group AND then clear * the flags that are present, set 'wait_type' to: * OS_FLAG_WAIT_SET_ANY + OS_FLAG_CONSUME * --注釋:如果你想在調(diào)用之后將事件標(biāo)志組消耗掉,在等待類型后面加一個OS_FLAG_CONSUME。 * timeout is an optional timeout (in clock ticks) that your task will wait for the * desired bit combination. If you specify 0, however, your task will wait * forever at the specified event flag group or, until a message arrives. * --timeout:以時鐘節(jié)拍數(shù)目的等待超時時限。如果在這一時限得不到事件,任務(wù)將恢復(fù)執(zhí)行。timeout的值為0,表示將無限期地等待事件。timeout的最大值是65535個時鐘節(jié)拍。timeout的值并不與時鐘節(jié)拍同步,timeout計(jì)數(shù)器在下一個時鐘節(jié)拍到來時開始遞減。在這里,所謂下一個時鐘節(jié)拍,也就是立刻就到來了。 * perr is a pointer to an error code and can be: * OS_ERR_NONE The desired bits have been set within the specified * 'timeout'. * OS_ERR_PEND_ISR If you tried to PEND from an ISR * OS_ERR_FLAG_INVALID_PGRP If 'pgrp' is a NULL pointer. * OS_ERR_EVENT_TYPE You are not pointing to an event flag group * OS_ERR_TIMEOUT The bit(s) have not been set in the specified * 'timeout'. * OS_ERR_PEND_ABORT The wait on the flag was aborted. * OS_ERR_FLAG_WAIT_TYPE You didn't specify a proper 'wait_type' argument. * --perr:指向錯誤碼的指針。可以為以下幾種值:OS_ERR_NONE:無錯誤類型OS_ERR_PEND_ISR:從中斷中調(diào)入該程序OS_ERR_FLAG_INVALID_PGRP:pgrp為空指針OS_ERR_EVENT_TYPE:沒有指向事件標(biāo)志組的指針OS_ERR_TIMEOUT:等待事件標(biāo)志組的事件標(biāo)志超時;OS_ERR_PEND_ABORT:等待標(biāo)志被取消OS_ERR_FLAG_WAIT_TYPE:'wait_type'不是指定的參數(shù)之一。 * Returns : The flags in the event flag group that made the task ready or, 0 if a timeout or an error * occurred. *返回值: 如果任務(wù)就緒,返回事件標(biāo)志組的標(biāo)志。如果發(fā)生了超時或者其他錯誤,則返回0。 * Called from: Task ONLY *只能由任務(wù)調(diào)用 * Note(s) : 1) IMPORTANT, the behavior of this function has changed from PREVIOUS versions. The * function NOW returns the flags that were ready INSTEAD of the current state of the * event flags.注釋:1)該功能與以前版本的功能有些許差別。該版本下這個函數(shù)的返回值是是否等待就緒的標(biāo)志而不是當(dāng)前事件標(biāo)志的狀態(tài)。 ********************************************************************************************************* *///等待事件標(biāo)志組的事件標(biāo)志位(事件組指針、需要檢查的標(biāo)志位、等待事件標(biāo)志位的方式、允許等待的時鐘節(jié)拍、出錯代碼的時鐘節(jié)拍) OS_FLAGS OSFlagPend (OS_FLAG_GRP *pgrp,OS_FLAGS flags,INT8U wait_type,INT32U timeout,INT8U *perr) {OS_FLAG_NODE node;OS_FLAGS flags_rdy;INT8U result;INT8U pend_stat; /*掛起狀態(tài)*/BOOLEAN consume; /*是否為消耗類型標(biāo)志*/ #if OS_CRITICAL_METHOD == 3u /*中斷類型被設(shè)定為3*/OS_CPU_SR cpu_sr = 0u; #endif#ifdef OS_SAFETY_CRITICAL /*定義安全中斷*/if (perr == (INT8U *)0) {OS_SAFETY_CRITICAL_EXCEPTION();} #endif#if OS_ARG_CHK_EN > 0u /*檢查參數(shù)*/if (pgrp == (OS_FLAG_GRP *)0) { *perr = OS_ERR_FLAG_INVALID_PGRP;return ((OS_FLAGS)0);} #endifif (OSIntNesting > 0u) /*如果從中斷中調(diào)用該函數(shù)*/{ *perr = OS_ERR_PEND_ISR; /*將錯誤碼設(shè)置為OS_ERR_PEND_ISR*/ return ((OS_FLAGS)0); /*返回值為0*/}if (OSLockNesting > 0u) /*如果調(diào)度器被上鎖了*/{ *perr = OS_ERR_PEND_LOCKED; /*無法調(diào)用該函數(shù),將錯誤碼設(shè)置為OS_ERR_PEND_LOCKED*/return ((OS_FLAGS)0); /*返回值為0*/}if (pgrp->OSFlagType != OS_EVENT_TYPE_FLAG) /*有效化事件標(biāo)志類型*/{ *perr = OS_ERR_EVENT_TYPE;return ((OS_FLAGS)0);}result = (INT8U)(wait_type & OS_FLAG_CONSUME); /*將等待類型和OS_FLAG_CONSUME做邏輯與運(yùn)算,結(jié)果存到result中。*/if (result != (INT8U)0) { /* 如果不是0,說明是消耗類型 */wait_type &= (INT8U)~(INT8U)OS_FLAG_CONSUME;consume = OS_TRUE;} else /*如果result是0,說明不是消耗類型*/{consume = OS_FALSE;} /*$PAGE*/OS_ENTER_CRITICAL(); /*進(jìn)入中斷*/switch (wait_type) /*根據(jù)wait_type的狀態(tài)執(zhí)行不同的程序*/{case OS_FLAG_WAIT_SET_ALL: /*如果是OS_FLAG_WAIT_SET_ALL類型*/flags_rdy = (OS_FLAGS)(pgrp->OSFlagFlags & flags); /*提取出我們需要的位 */if (flags_rdy == flags) /*必須匹配到我們需要的所有的位*/{ if (consume == OS_TRUE) /*如果是消耗類型*/{ pgrp->OSFlagFlags &= (OS_FLAGS)~flags_rdy; /*只清理掉我們需要的位 */}OSTCBCur->OSTCBFlagsRdy = flags_rdy; /*將就緒標(biāo)志保存到OSTCBFlagsRdy中*/OS_EXIT_CRITICAL(); /* 退出中斷*/*perr = OS_ERR_NONE; /*將錯誤碼設(shè)置為無錯誤類型*/return (flags_rdy); /*返回flags_rdy*/} else /*阻塞任務(wù)知道有事件發(fā)生或者超時 */{ OS_FlagBlock(pgrp, &node, flags, wait_type, timeout);OS_EXIT_CRITICAL();}break;case OS_FLAG_WAIT_SET_ANY:flags_rdy = (OS_FLAGS)(pgrp->OSFlagFlags & flags); if (flags_rdy != (OS_FLAGS)0) { if (consume == OS_TRUE) { pgrp->OSFlagFlags &= (OS_FLAGS)~flags_rdy; }OSTCBCur->OSTCBFlagsRdy = flags_rdy; OS_EXIT_CRITICAL(); *perr = OS_ERR_NONE;return (flags_rdy);} else{ OS_FlagBlock(pgrp, &node, flags, wait_type, timeout);OS_EXIT_CRITICAL();}break;#if OS_FLAG_WAIT_CLR_EN > 0ucase OS_FLAG_WAIT_CLR_ALL: /* See if all required flags are cleared */flags_rdy = (OS_FLAGS)~pgrp->OSFlagFlags & flags; /* Extract only the bits we want */if (flags_rdy == flags) { /* Must match ALL the bits that we want */if (consume == OS_TRUE) { /* See if we need to consume the flags */pgrp->OSFlagFlags |= flags_rdy; /* Set ONLY the flags that we wanted */}OSTCBCur->OSTCBFlagsRdy = flags_rdy; /* Save flags that were ready */OS_EXIT_CRITICAL(); /* Yes, condition met, return to caller */*perr = OS_ERR_NONE;return (flags_rdy);} else { /* Block task until events occur or timeout */OS_FlagBlock(pgrp, &node, flags, wait_type, timeout);OS_EXIT_CRITICAL();}break;case OS_FLAG_WAIT_CLR_ANY:flags_rdy = (OS_FLAGS)~pgrp->OSFlagFlags & flags; /* Extract only the bits we want */if (flags_rdy != (OS_FLAGS)0) { /* See if any flag cleared */if (consume == OS_TRUE) { /* See if we need to consume the flags */pgrp->OSFlagFlags |= flags_rdy; /* Set ONLY the flags that we got */}OSTCBCur->OSTCBFlagsRdy = flags_rdy; /* Save flags that were ready */OS_EXIT_CRITICAL(); /* Yes, condition met, return to caller */*perr = OS_ERR_NONE;return (flags_rdy);} else { /* Block task until events occur or timeout */OS_FlagBlock(pgrp, &node, flags, wait_type, timeout);OS_EXIT_CRITICAL();}break; #endifdefault:OS_EXIT_CRITICAL();flags_rdy = (OS_FLAGS)0;*perr = OS_ERR_FLAG_WAIT_TYPE;return (flags_rdy);} /*$PAGE*/OS_Sched(); /*進(jìn)行調(diào)度。找需要運(yùn)行的最高優(yōu)先級任務(wù)*/ OS_ENTER_CRITICAL();/*進(jìn)入中斷*/if (OSTCBCur->OSTCBStatPend != OS_STAT_PEND_OK) /*當(dāng)前TCB掛起狀態(tài)為取消或者超時狀態(tài)*/{ pend_stat = OSTCBCur->OSTCBStatPend;OSTCBCur->OSTCBStatPend = OS_STAT_PEND_OK;OS_FlagUnlink(&node);OSTCBCur->OSTCBStat = OS_STAT_RDY; /* Yes, make task ready-to-run */OS_EXIT_CRITICAL();flags_rdy = (OS_FLAGS)0;switch (pend_stat) {case OS_STAT_PEND_ABORT:*perr = OS_ERR_PEND_ABORT; /* Indicate that we aborted waiting */break;case OS_STAT_PEND_TO:default:*perr = OS_ERR_TIMEOUT; /* Indicate that we timed-out waiting */break;}return (flags_rdy);}flags_rdy = OSTCBCur->OSTCBFlagsRdy;if (consume == OS_TRUE) { /* See if we need to consume the flags */switch (wait_type) {case OS_FLAG_WAIT_SET_ALL:case OS_FLAG_WAIT_SET_ANY: /* Clear ONLY the flags we got */pgrp->OSFlagFlags &= (OS_FLAGS)~flags_rdy;break;#if OS_FLAG_WAIT_CLR_EN > 0ucase OS_FLAG_WAIT_CLR_ALL:case OS_FLAG_WAIT_CLR_ANY: /* Set ONLY the flags we got */pgrp->OSFlagFlags |= flags_rdy;break; #endifdefault:OS_EXIT_CRITICAL();*perr = OS_ERR_FLAG_WAIT_TYPE;return ((OS_FLAGS)0);}}OS_EXIT_CRITICAL();*perr = OS_ERR_NONE; /* Event(s) must have occurred */return (flags_rdy); }流程圖如下:
到這里,OS_FLAG.C文件就介紹完了。中間有幾個函數(shù)沒有介紹,設(shè)置名稱、獲得名稱函數(shù)。大家自行看源碼,很簡單。
下篇將會帶著大家理一下整體的思路。
總結(jié)
以上是生活随笔為你收集整理的OS_FLAG.C(3)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: OS_FLAG.C(2)
- 下一篇: os_mutex.c(全)