⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 flag.c

📁 基于MDK的LPC1100处理器开发应用例程
💻 C
📖 第 1 页 / 共 2 页
字号:
 *******************************************************************************
 */
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 + -