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

📄 flag.c

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