📄 flag.c
字号:
*******************************************************************************
*/
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 = TRUE;
OsSchedUnlock();
curTCB->pnode = 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 == NULL) /* If time-out occurred */
{
*perr = E_TIMEOUT;
return 0;
}
else /* If the required flags are set */
{
curTCB->pnode = 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 != 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,NULL) == 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 == NULL) /* If this is the first NODE to insert? */
{
pnode->nextNode = NULL;
pnode->prevNode = 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 = 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 == NULL) && (pnode->prevNode == NULL))
{
FlagCrl.headNode = NULL;
FlagCrl.tailNode = NULL;
}
else if(pnode->nextNode == NULL) /* If the NODE is tail */
{
FlagCrl.tailNode = pnode->prevNode;
pnode->prevNode->nextNode = NULL;
}
else if(pnode->prevNode == NULL) /* If the NODE is head */
{
FlagCrl.headNode = pnode->nextNode;
pnode->nextNode->prevNode = NULL;
}
else /* The NODE is in the middle */
{
pnode->nextNode->prevNode = pnode->prevNode;
pnode->prevNode->nextNode = pnode->nextNode;
}
pnode->waitTask->pnode = NULL;
}
#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -