736 lines
24 KiB
C
736 lines
24 KiB
C
/**
|
|
*******************************************************************************
|
|
* @file flag.c
|
|
* @version V1.1.6
|
|
* @date 2014.05.23
|
|
* @brief Flag management implementation code of coocox CoOS kernel.
|
|
*******************************************************************************
|
|
* @copy
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without
|
|
* modification, are permitted provided that the following conditions
|
|
* are met:
|
|
*
|
|
* * Redistributions of source code must retain the above copyright
|
|
* notice, this list of conditions and the following disclaimer.
|
|
* * Redistributions in binary form must reproduce the above copyright
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
* documentation and/or other materials provided with the distribution.
|
|
* * Neither the name of the <ORGANIZATION> nor the names of its
|
|
* contributors may be used to endorse or promote products derived
|
|
* from this software without specific prior written permission.
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
|
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
|
* THE POSSIBILITY OF SUCH DAMAGE.
|
|
*
|
|
* <h2><center>© COPYRIGHT 2014 CooCox </center></h2>
|
|
*******************************************************************************
|
|
*/
|
|
|
|
|
|
|
|
/*---------------------------- Include ---------------------------------------*/
|
|
#include <coocox.h>
|
|
|
|
#if CFG_FLAG_EN > 0
|
|
/*---------------------------- Variable Define -------------------------------*/
|
|
#define FLAG_MAX_NUM 32 /*!< Define max flag number. */
|
|
FCB FlagCrl = {0}; /*!< Flags list struct */
|
|
|
|
|
|
/*---------------------------- Function Declare ------------------------------*/
|
|
static void FlagBlock(P_FLAG_NODE pnode,U32 flags,U8 waitType);
|
|
static P_FLAG_NODE RemoveFromLink(P_FLAG_NODE pnode);
|
|
|
|
/**
|
|
*******************************************************************************
|
|
* @brief Create a flag
|
|
* @param[in] bAutoReset Reset mode,Co_TRUE(Auto Reset) FLASE(Manual Reset).
|
|
* @param[in] bInitialState Initial state.
|
|
* @param[out] None
|
|
* @retval E_CREATE_FAIL Create flag fail.
|
|
* @retval others Create flag successful.
|
|
*
|
|
* @par Description
|
|
* @details This function use to create a event flag.
|
|
* @note
|
|
*******************************************************************************
|
|
*/
|
|
OS_FlagID CoCreateFlag(BOOL bAutoReset,BOOL bInitialState)
|
|
{
|
|
U8 i;
|
|
OsSchedLock();
|
|
|
|
for(i=0;i<FLAG_MAX_NUM;i++)
|
|
{
|
|
/* Assign a free flag control block */
|
|
if((FlagCrl.flagActive&(1<<i)) == 0 )
|
|
{
|
|
FlagCrl.flagActive |= (1<<i); /* Initialize active flag */
|
|
FlagCrl.flagRdy |= (bInitialState<<i);/* Initialize ready flag */
|
|
FlagCrl.resetOpt |= (bAutoReset<<i);/* Initialize reset option */
|
|
OsSchedUnlock();
|
|
return i ; /* Return Flag ID */
|
|
}
|
|
}
|
|
OsSchedUnlock();
|
|
|
|
return E_CREATE_FAIL; /* There is no free flag control block*/
|
|
}
|
|
|
|
|
|
/**
|
|
*******************************************************************************
|
|
* @brief Delete a flag
|
|
* @param[in] id Flag ID.
|
|
* @param[in] opt Delete option.
|
|
* @param[out] None
|
|
* @retval E_CALL Error call in ISR.
|
|
* @retval E_INVALID_ID Invalid event ID.
|
|
* @retval E_TASK_WAITTING Tasks waitting for the event,delete fail.
|
|
* @retval E_OK Event deleted successful.
|
|
*
|
|
* @par Description
|
|
* @details This function is called to delete a event flag.
|
|
* @note
|
|
*******************************************************************************
|
|
*/
|
|
StatusType CoDelFlag(OS_FlagID id,U8 opt)
|
|
{
|
|
P_FLAG_NODE pnode;
|
|
P_FCB pfcb;
|
|
pfcb = &FlagCrl;
|
|
if(OSIntNesting > 0) /* If be called from ISR */
|
|
{
|
|
return E_CALL;
|
|
}
|
|
#if CFG_PAR_CHECKOUT_EN >0
|
|
if((pfcb->flagActive&(1<<id)) == 0) /* Flag is valid or not */
|
|
{
|
|
return E_INVALID_ID;
|
|
}
|
|
#endif
|
|
OsSchedLock();
|
|
pnode = pfcb->headNode;
|
|
|
|
while(pnode != Co_NULL) /* Ready all tasks waiting for flags */
|
|
{
|
|
if((pnode->waitFlags&(1<<id)) != 0) /* If no task is waiting on flags */
|
|
{
|
|
if(opt == OPT_DEL_NO_PEND) /* Delete flag if no task waiting */
|
|
{
|
|
OsSchedUnlock();
|
|
return E_TASK_WAITING;
|
|
}
|
|
else if (opt == OPT_DEL_ANYWAY) /* Always delete the flag */
|
|
{
|
|
if(pnode->waitType == OPT_WAIT_ALL)
|
|
{
|
|
/* If the flag is only required by NODE */
|
|
if( pnode->waitFlags == (1<<id) )
|
|
{
|
|
/* Remove the NODE from waiting list */
|
|
pnode = RemoveFromLink(pnode);
|
|
continue;
|
|
}
|
|
else
|
|
{
|
|
pnode->waitFlags &= ~(1<<id); /* Update waitflags */
|
|
}
|
|
}
|
|
else
|
|
{
|
|
pnode = RemoveFromLink(pnode);
|
|
continue;
|
|
}
|
|
}
|
|
}
|
|
pnode = pnode->nextNode;
|
|
}
|
|
|
|
/* Remove the flag from the flags list */
|
|
pfcb->flagActive &= ~(1<<id);
|
|
pfcb->flagRdy &= ~(1<<id);
|
|
pfcb->resetOpt &= ~(1<<id);
|
|
OsSchedUnlock();
|
|
return E_OK;
|
|
}
|
|
|
|
|
|
/**
|
|
*******************************************************************************
|
|
* @brief AcceptSingleFlag
|
|
* @param[in] id Flag ID.
|
|
* @param[out] None
|
|
* @retval E_INVALID_ID Invalid event ID.
|
|
* @retval E_FLAG_NOT_READY Flag is not in ready state.
|
|
* @retval E_OK The call was successful and your task owns the Flag.
|
|
*
|
|
* @par Description
|
|
* @details This fucntion is called to accept single flag
|
|
* @note
|
|
*******************************************************************************
|
|
*/
|
|
StatusType CoAcceptSingleFlag(OS_FlagID id)
|
|
{
|
|
P_FCB pfcb;
|
|
pfcb = &FlagCrl;
|
|
#if CFG_PAR_CHECKOUT_EN >0
|
|
if(id >= FLAG_MAX_NUM)
|
|
{
|
|
return E_INVALID_ID; /* Invalid 'id',return error */
|
|
}
|
|
if((pfcb->flagActive&(1<<id)) == 0)
|
|
{
|
|
return E_INVALID_ID; /* Flag is deactive,return error */
|
|
}
|
|
#endif
|
|
if((pfcb->flagRdy&(1<<id)) != 0) /* If the required flag is set */
|
|
{
|
|
OsSchedLock()
|
|
pfcb->flagRdy &= ~((FlagCrl.resetOpt)&(1<<id)); /* Clear the flag */
|
|
OsSchedUnlock();
|
|
return E_OK;
|
|
}
|
|
else /* If the required flag is not set */
|
|
{
|
|
return E_FLAG_NOT_READY;
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
*******************************************************************************
|
|
* @brief AcceptMultipleFlags
|
|
* @param[in] flags Flags that waiting to active task.
|
|
* @param[in] waitType Flags wait type.
|
|
* @param[out] perr A pointer to error code.
|
|
* @retval 0
|
|
* @retval springFlag
|
|
*
|
|
* @par Description
|
|
* @details This fucntion is called to accept multiple flags.
|
|
* @note
|
|
*******************************************************************************
|
|
*/
|
|
U32 CoAcceptMultipleFlags(U32 flags,U8 waitType,StatusType *perr)
|
|
{
|
|
U32 springFlag;
|
|
P_FCB pfcb;
|
|
pfcb = &FlagCrl;
|
|
|
|
#if CFG_PAR_CHECKOUT_EN >0
|
|
if((flags&pfcb->flagActive) != flags ) /* Judge flag is active or not? */
|
|
{
|
|
*perr = E_INVALID_PARAMETER; /* Invalid flags */
|
|
return 0;
|
|
}
|
|
#endif
|
|
|
|
springFlag = flags & pfcb->flagRdy;
|
|
|
|
OsSchedLock();
|
|
/* If any required flags are set */
|
|
if( (springFlag != 0) && (waitType == OPT_WAIT_ANY) )
|
|
{
|
|
|
|
pfcb->flagRdy &= ~(springFlag & pfcb->resetOpt); /* Clear the flags */
|
|
OsSchedUnlock();
|
|
*perr = E_OK;
|
|
return springFlag;
|
|
}
|
|
|
|
/* If all required flags are set */
|
|
if((springFlag == flags) && (waitType == OPT_WAIT_ALL))
|
|
{
|
|
pfcb->flagRdy &= ~(springFlag&pfcb->resetOpt); /* Clear the flags */
|
|
OsSchedUnlock();
|
|
*perr = E_OK;
|
|
return springFlag;
|
|
}
|
|
OsSchedUnlock();
|
|
*perr = E_FLAG_NOT_READY;
|
|
return 0;
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
*******************************************************************************
|
|
* @brief WaitForSingleFlag
|
|
* @param[in] id Flag ID.
|
|
* @param[in] timeout The longest time for writting flag.
|
|
* @param[out] None
|
|
* @retval E_CALL Error call in ISR.
|
|
* @retval E_INVALID_ID Invalid event ID.
|
|
* @retval E_TIMEOUT Flag wasn't received within 'timeout' time.
|
|
* @retval E_OK The call was successful and your task owns the Flag,
|
|
* or the event you are waiting for occurred.
|
|
*
|
|
* @par Description
|
|
* @details This function is called to wait for only one flag,
|
|
* (1) if parameter "timeout" == 0,waiting until flag be set;
|
|
* (2) when "timeout" != 0,if flag was set or wasn't set but timeout
|
|
* occured,the task will exit the waiting list,convert to READY
|
|
* or RUNNING state.
|
|
* @note
|
|
*******************************************************************************
|
|
*/
|
|
StatusType CoWaitForSingleFlag(OS_FlagID id,U32 timeout)
|
|
{
|
|
FLAG_NODE flagNode;
|
|
P_FCB pfcb;
|
|
P_OSTCB curTCB;
|
|
|
|
if(OSIntNesting > 0) /* See if the caller is ISR */
|
|
{
|
|
return E_CALL;
|
|
}
|
|
if(OSSchedLock != 0) /* Schedule is lock? */
|
|
{
|
|
return E_OS_IN_LOCK; /* Yes,error return */
|
|
}
|
|
|
|
#if CFG_PAR_CHECKOUT_EN >0
|
|
if(id >= FLAG_MAX_NUM) /* Judge id is valid or not? */
|
|
{
|
|
return E_INVALID_ID; /* Invalid 'id' */
|
|
}
|
|
if((FlagCrl.flagActive&(1<<id)) == 0 )/* Judge flag is active or not? */
|
|
{
|
|
return E_INVALID_ID; /* Flag is deactive ,return error */
|
|
}
|
|
#endif
|
|
|
|
OsSchedLock();
|
|
pfcb = &FlagCrl;
|
|
/* See if the required flag is set */
|
|
if((pfcb->flagRdy&(1<<id)) != 0) /* If the required flag is set */
|
|
{
|
|
pfcb->flagRdy &= ~((pfcb->resetOpt&(1<<id))); /* Clear the flag */
|
|
OsSchedUnlock();
|
|
}
|
|
else /* If the required flag is not set */
|
|
{
|
|
curTCB = TCBRunning;
|
|
if(timeout == 0) /* If time-out is not configured */
|
|
{
|
|
/* Block task until the required flag is set */
|
|
FlagBlock (&flagNode,(1<<id),OPT_WAIT_ONE);
|
|
curTCB->state = TASK_WAITING;
|
|
TaskSchedReq = Co_TRUE;
|
|
OsSchedUnlock();
|
|
|
|
/* The required flag is set and the task is in running state */
|
|
curTCB->pnode = Co_NULL;
|
|
OsSchedLock();
|
|
|
|
/* Clear the required flag or not */
|
|
pfcb->flagRdy &= ~((1<<id)&(pfcb->resetOpt));
|
|
OsSchedUnlock();
|
|
}
|
|
else /* If time-out is configured */
|
|
{
|
|
/* Block task until the required flag is set or time-out occurs */
|
|
FlagBlock(&flagNode,(1<<id),OPT_WAIT_ONE);
|
|
InsertDelayList(curTCB,timeout);
|
|
|
|
OsSchedUnlock();
|
|
if(curTCB->pnode == Co_NULL) /* If time-out occurred */
|
|
{
|
|
return E_TIMEOUT;
|
|
}
|
|
else /* If flag is set */
|
|
{
|
|
curTCB->pnode = Co_NULL;
|
|
OsSchedLock();
|
|
|
|
/* Clear the required flag or not */
|
|
pfcb->flagRdy &= ~((1<<id)&(pfcb->resetOpt));
|
|
OsSchedUnlock();
|
|
}
|
|
}
|
|
}
|
|
return E_OK;
|
|
}
|
|
|
|
|
|
/**
|
|
*******************************************************************************
|
|
* @brief WaitForMultipleFlags
|
|
* @param[in] flags Flags that waiting to active task.
|
|
* @param[in] waitType Flags wait type.
|
|
* @param[in] timeout The longest time for writting flag.
|
|
* @param[out] perr A pointer to error code.
|
|
* @retval 0
|
|
* @retval springFlag
|
|
*
|
|
* @par Description
|
|
* @details This function is called to pend a task for waitting multiple flag.
|
|
* @note
|
|
*******************************************************************************
|
|
*/
|
|
U32 CoWaitForMultipleFlags(U32 flags,U8 waitType,U32 timeout,StatusType *perr)
|
|
{
|
|
U32 springFlag;
|
|
P_FCB pfcb;
|
|
FLAG_NODE flagNode;
|
|
P_OSTCB curTCB;
|
|
|
|
|
|
if(OSIntNesting > 0) /* If the caller is ISR */
|
|
{
|
|
*perr = E_CALL;
|
|
return 0;
|
|
}
|
|
if(OSSchedLock != 0) /* Schedule is lock? */
|
|
{
|
|
*perr = E_OS_IN_LOCK;
|
|
return 0; /* Yes,error return */
|
|
}
|
|
#if CFG_PAR_CHECKOUT_EN >0
|
|
if( (flags&FlagCrl.flagActive) != flags )
|
|
{
|
|
*perr = E_INVALID_PARAMETER; /* Invalid 'flags' */
|
|
return 0;
|
|
}
|
|
#endif
|
|
OsSchedLock();
|
|
pfcb = &FlagCrl;
|
|
springFlag = flags & pfcb->flagRdy;
|
|
|
|
/* If any required flags are set */
|
|
if((springFlag != 0) && (waitType == OPT_WAIT_ANY))
|
|
{
|
|
pfcb->flagRdy &= ~(springFlag & pfcb->resetOpt); /* Clear the flag */
|
|
OsSchedUnlock();
|
|
*perr = E_OK;
|
|
return springFlag;
|
|
}
|
|
|
|
/* If all required flags are set */
|
|
if( (springFlag == flags) && (waitType == OPT_WAIT_ALL) )
|
|
{
|
|
pfcb->flagRdy &= ~(springFlag & pfcb->resetOpt); /* Clear the flags */
|
|
OsSchedUnlock();
|
|
*perr = E_OK;
|
|
return springFlag;
|
|
}
|
|
|
|
curTCB = TCBRunning;
|
|
if(timeout == 0) /* If time-out is not configured */
|
|
{
|
|
/* Block task until the required flag are set */
|
|
FlagBlock(&flagNode,flags,waitType);
|
|
curTCB->state = TASK_WAITING;
|
|
TaskSchedReq = Co_TRUE;
|
|
OsSchedUnlock();
|
|
|
|
curTCB->pnode = Co_NULL;
|
|
OsSchedLock();
|
|
springFlag = flags & pfcb->flagRdy;
|
|
pfcb->flagRdy &= ~(springFlag & pfcb->resetOpt);/* Clear the flags */
|
|
OsSchedUnlock();
|
|
*perr = E_OK;
|
|
return springFlag;
|
|
}
|
|
else /* If time-out is configured */
|
|
{
|
|
/* Block task until the required flag are set or time-out occurred */
|
|
FlagBlock(&flagNode,flags,waitType);
|
|
InsertDelayList(curTCB,timeout);
|
|
|
|
OsSchedUnlock();
|
|
if(curTCB->pnode == Co_NULL) /* If time-out occurred */
|
|
{
|
|
*perr = E_TIMEOUT;
|
|
return 0;
|
|
}
|
|
else /* If the required flags are set */
|
|
{
|
|
curTCB->pnode = Co_NULL;
|
|
OsSchedLock();
|
|
springFlag = flags & FlagCrl.flagRdy;
|
|
|
|
/* Clear the required ready flags or not */
|
|
pfcb->flagRdy &= ~(springFlag & pfcb->resetOpt);
|
|
OsSchedUnlock();
|
|
*perr = E_OK;
|
|
return springFlag;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
*******************************************************************************
|
|
* @brief Clear a Flag
|
|
* @param[in] id Flag ID.
|
|
* @param[out] None
|
|
* @retval E_OK Event deleted successful.
|
|
* @retval E_INVALID_ID Invalid event ID.
|
|
*
|
|
* @par Description
|
|
* @details This function is called to clear a flag.
|
|
*
|
|
* @note
|
|
*******************************************************************************
|
|
*/
|
|
StatusType CoClearFlag(OS_FlagID id)
|
|
{
|
|
P_FCB pfcb;
|
|
pfcb = &FlagCrl;
|
|
#if CFG_PAR_CHECKOUT_EN >0
|
|
if(id >= FLAG_MAX_NUM)
|
|
{
|
|
return E_INVALID_ID; /* Invalid id */
|
|
}
|
|
if((pfcb->flagActive&(1<<id)) == 0)
|
|
{
|
|
return E_INVALID_ID; /* Invalid flag */
|
|
}
|
|
#endif
|
|
|
|
pfcb->flagRdy &= ~(1<<id); /* Clear the flag */
|
|
return E_OK;
|
|
}
|
|
|
|
|
|
/**
|
|
*******************************************************************************
|
|
* @brief Set a flag
|
|
* @param[in] id Flag ID.
|
|
* @param[out] None
|
|
* @retval E_INVALID_ID Invalid event ID.
|
|
* @retval E_OK Event deleted successful.
|
|
*
|
|
* @par Description
|
|
* @details This function is called to set a flag.
|
|
* @note
|
|
*******************************************************************************
|
|
*/
|
|
StatusType CoSetFlag(OS_FlagID id)
|
|
{
|
|
P_FLAG_NODE pnode;
|
|
P_FCB pfcb;
|
|
pfcb = &FlagCrl;
|
|
|
|
#if CFG_PAR_CHECKOUT_EN >0
|
|
if(id >= FLAG_MAX_NUM) /* Flag is valid or not */
|
|
{
|
|
return E_INVALID_ID; /* Invalid flag id */
|
|
}
|
|
if((pfcb->flagActive&(1<<id)) == 0)
|
|
{
|
|
return E_INVALID_ID; /* Flag is not exist */
|
|
}
|
|
#endif
|
|
|
|
if((pfcb->flagRdy&(1<<id)) != 0) /* Flag had already been set */
|
|
{
|
|
return E_OK;
|
|
}
|
|
|
|
pfcb->flagRdy |= (1<<id); /* Update the flags ready list */
|
|
|
|
OsSchedLock();
|
|
pnode = pfcb->headNode;
|
|
while(pnode != Co_NULL)
|
|
{
|
|
if(pnode->waitType == OPT_WAIT_ALL) /* Extract all the bits we want */
|
|
{
|
|
if((pnode->waitFlags&pfcb->flagRdy) == pnode->waitFlags)
|
|
{
|
|
/* Remove the flag node from the wait list */
|
|
pnode = RemoveFromLink(pnode);
|
|
if((pfcb->resetOpt&(1<<id)) != 0)/* If the flags is auto-reset*/
|
|
{
|
|
break;
|
|
}
|
|
continue;
|
|
}
|
|
}
|
|
else /* Extract only the bits we want */
|
|
{
|
|
if( (pnode->waitFlags & pfcb->flagRdy) != 0)
|
|
{
|
|
/* Remove the flag node from the wait list */
|
|
pnode = RemoveFromLink(pnode);
|
|
if((pfcb->resetOpt&(1<<id)) != 0)
|
|
{
|
|
break; /* The flags is auto-reset */
|
|
}
|
|
continue;
|
|
}
|
|
}
|
|
pnode = pnode->nextNode;
|
|
}
|
|
OsSchedUnlock();
|
|
return E_OK;
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
*******************************************************************************
|
|
* @brief Set a flag in ISR
|
|
* @param[in] id Flag ID.
|
|
* @param[out] None
|
|
* @retval E_INVALID_ID Invalid event ID.
|
|
* @retval E_OK Event deleted successful.
|
|
*
|
|
* @par Description
|
|
* @details This function is called in ISR to set a flag.
|
|
* @note
|
|
*******************************************************************************
|
|
*/
|
|
#if CFG_MAX_SERVICE_REQUEST > 0
|
|
StatusType isr_SetFlag(OS_FlagID id)
|
|
{
|
|
if(OSSchedLock > 0) /* If scheduler is locked,(the caller is ISR) */
|
|
{
|
|
/* Insert the request into service request queue */
|
|
if(InsertInSRQ(FLAG_REQ,id,Co_NULL) == Co_FALSE)
|
|
{
|
|
return E_SEV_REQ_FULL; /* The service requst queue is full */
|
|
}
|
|
else
|
|
{
|
|
return E_OK;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
return(CoSetFlag(id)); /* The caller is not ISR, set the flag*/
|
|
}
|
|
}
|
|
#endif
|
|
|
|
/**
|
|
*******************************************************************************
|
|
* @brief Block a task to wait a flag event
|
|
* @param[in] pnode A node that will link into flag waiting list.
|
|
* @param[in] flags Flag(s) that the node waiting for.
|
|
* @param[in] waitType Waiting type of the node.
|
|
* @param[out] None
|
|
* @retval None
|
|
*
|
|
* @par Description
|
|
* @details This function is called to block a task to wait a flag event.
|
|
* @note
|
|
*******************************************************************************
|
|
*/
|
|
static void FlagBlock(P_FLAG_NODE pnode,U32 flags,U8 waitType)
|
|
{
|
|
P_FCB pfcb;
|
|
pfcb = &FlagCrl;
|
|
|
|
TCBRunning->pnode = pnode;
|
|
pnode->waitTask = TCBRunning;
|
|
pnode->waitFlags = flags; /* Save the flags that we need to wait for*/
|
|
pnode->waitType = waitType; /* Save the type of wait */
|
|
|
|
if(pfcb->tailNode == Co_NULL) /* If this is the first NODE to insert? */
|
|
{
|
|
pnode->nextNode = Co_NULL;
|
|
pnode->prevNode = Co_NULL;
|
|
pfcb->headNode = pnode; /* Insert the NODE to the head */
|
|
}
|
|
else /* If it is not the first NODE to insert? */
|
|
{
|
|
pfcb->tailNode->nextNode = pnode; /* Insert the NODE to the tail */
|
|
pnode->prevNode = pfcb->tailNode;
|
|
pnode->nextNode = Co_NULL;
|
|
}
|
|
pfcb->tailNode = pnode;
|
|
}
|
|
|
|
|
|
/**
|
|
*******************************************************************************
|
|
* @brief Remove a flag node from list
|
|
* @param[in] pnode A node that will remove from flag waiting list.
|
|
* @param[out] None
|
|
* @retval pnode Next node of the node that have removed out.
|
|
*
|
|
* @par Description
|
|
* @details This function is called to remove a flag node from the wait list.
|
|
* @note
|
|
*******************************************************************************
|
|
*/
|
|
static P_FLAG_NODE RemoveFromLink(P_FLAG_NODE pnode)
|
|
{
|
|
P_OSTCB ptcb;
|
|
|
|
RemoveLinkNode(pnode); /* Remove the flag node from wait list. */
|
|
ptcb = pnode->waitTask;
|
|
|
|
/* The task in the delay list */
|
|
if(ptcb->delayTick != INVALID_VALUE)/* If the task is in tick delay list */
|
|
{
|
|
RemoveDelayList(ptcb); /* Remove the task from tick delay list */
|
|
}
|
|
|
|
ptcb->pnode = (void*)0xffffffff;
|
|
|
|
if(ptcb == TCBRunning)
|
|
{
|
|
ptcb->state = TASK_RUNNING;
|
|
}
|
|
else
|
|
{
|
|
InsertToTCBRdyList(ptcb); /* Insert the task to ready list */
|
|
}
|
|
return (pnode->nextNode);
|
|
}
|
|
|
|
/**
|
|
*******************************************************************************
|
|
* @brief Remove a flag node from list
|
|
* @param[in] pnode A node that will remove from flag waiting list.
|
|
* @param[out] None
|
|
* @retval None
|
|
*
|
|
* @par Description
|
|
* @details This function is called to remove a flag node from the wait list.
|
|
* @note
|
|
*******************************************************************************
|
|
*/
|
|
void RemoveLinkNode(P_FLAG_NODE pnode)
|
|
{
|
|
/* If only one NODE in the list*/
|
|
if((pnode->nextNode == Co_NULL) && (pnode->prevNode == Co_NULL))
|
|
{
|
|
FlagCrl.headNode = Co_NULL;
|
|
FlagCrl.tailNode = Co_NULL;
|
|
}
|
|
else if(pnode->nextNode == Co_NULL) /* If the NODE is tail */
|
|
{
|
|
FlagCrl.tailNode = pnode->prevNode;
|
|
pnode->prevNode->nextNode = Co_NULL;
|
|
}
|
|
else if(pnode->prevNode == Co_NULL) /* If the NODE is head */
|
|
{
|
|
FlagCrl.headNode = pnode->nextNode;
|
|
pnode->nextNode->prevNode = Co_NULL;
|
|
}
|
|
else /* The NODE is in the middle */
|
|
{
|
|
pnode->nextNode->prevNode = pnode->prevNode;
|
|
pnode->prevNode->nextNode = pnode->nextNode;
|
|
}
|
|
pnode->waitTask->pnode = Co_NULL;
|
|
}
|
|
|
|
#endif
|