📄 flag.c
字号:
/**
*******************************************************************************
* @file flag.c
* @version V1.13
* @date 2010.04.26
* @brief Flag management implementation code of coocox CoOS kernel.
*******************************************************************************
* @copy
*
* INTERNAL FILE,DON'T PUBLIC.
*
* <h2><center>© COPYRIGHT 2009 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,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 != 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 = TRUE;
OsSchedUnlock();
/* The required flag is set and the task is in running state */
curTCB->pnode = 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 == NULL) /* If time-out occurred */
{
return E_TIMEOUT;
}
else /* If flag is set */
{
curTCB->pnode = 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
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -