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

📄 task.c

📁 基于MDK的LPC1100处理器开发应用例程
💻 C
📖 第 1 页 / 共 3 页
字号:
/**
 *******************************************************************************
 * @file       task.c
 * @version    V1.13    
 * @date       2010.04.26
 * @brief      task 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>

/*---------------------------- Variable Define -------------------------------*/

/*!< Table use to save TCB pointer.              */
OSTCB    TCBTbl[CFG_MAX_USER_TASKS+SYS_TASK_NUM] = {{0}};

/*!< The stack of IDLE task.                     */
OS_STK   idle_stk[CFG_IDLE_STACK_SIZE] = {0};

P_OSTCB  FreeTCB     = NULL;  /*!< pointer to free TCB                        */	
P_OSTCB  TCBRdy      = NULL;  /*!< Pointer to the READY list.                 */
P_OSTCB  TCBNext     = NULL;  /*!< Poniter to task that next scheduled by OS  */
P_OSTCB  TCBRunning  = NULL;  /*!< Pointer to TCB that current running task.  */
U64      OSCheckTime = 0;     /*!< The counter of system tick.                */

#if CFG_ORDER_LIST_SCHEDULE_EN ==0
OS_TID   PriNum;
U8       ActivePri[CFG_MAX_USER_TASKS+SYS_TASK_NUM];
U8       TaskNumPerPri[CFG_MAX_USER_TASKS+SYS_TASK_NUM];
OS_TID   RdyTaskPri[CFG_MAX_USER_TASKS+SYS_TASK_NUM] = {0};	
U32      RdyTaskPriInfo[(CFG_MAX_USER_TASKS+SYS_TASK_NUM+31)/32];
#endif


/**
 *******************************************************************************
 * @brief      Create a TCB list.	  
 * @param[in]  None 	 
 * @param[out] None    
 * @retval     None		 
 *
 * @par Description
 * @details    This function is called by CoOSInit() to initial the empty list	 
 *             of OS_TCBS,supply a pointer to free TCB.
 *******************************************************************************
 */
void CreateTCBList(void)
{	
    U8  i;
    P_OSTCB ptcb1,ptcb2;
    
#if CFG_ORDER_LIST_SCHEDULE_EN ==0
	PriNum = 0;
#endif

	ptcb1 = &TCBTbl[0];	                /* Build the free TCB list            */
    ptcb2 = &TCBTbl[1];  
    for(i=0;i< (CFG_MAX_USER_TASKS+SYS_TASK_NUM-1);i++ )
    {
		ptcb1->taskID    = i;
		ptcb1->state     = TASK_DORMANT;
        ptcb1->TCBnext   = ptcb2;
#if CFG_ORDER_LIST_SCHEDULE_EN ==0
		RdyTaskPri[i]    = INVALID_ID;
		ActivePri[i]	 = INVALID_ID;
#endif
        ptcb1++;
        ptcb2++;	
    }
#if CFG_ORDER_LIST_SCHEDULE_EN ==0
		ActivePri[i]	 = INVALID_ID;
#endif

	ptcb1->taskID    = i;	
    ptcb1->TCBnext   = NULL;
    FreeTCB = &TCBTbl[0];         /* Initialize FreeTCB as head item of list  */			
}



#if CFG_ORDER_LIST_SCHEDULE_EN ==0

/**
 *******************************************************************************
 * @brief      Get sequence number for Assign priority	  
 * @param[in]  pri            Assign priority	 
 * @param[out] SequenceNum    priority number 
 * @retval     TRUE           Assign priority in priority queue.    
 *             FALSE          Assign priority not in priority queue. 		 
 *					
 * @par Description
 * @details    This function is called in Binary-Scheduling Algorithm 
 *             to get sequence number for Assign priority.     
 *******************************************************************************
 */
static BOOL  GetPriSeqNum(U8 pri,OS_TID* SequenceNum)
{
	OS_TID  seqNum;
	OS_TID  num,tmpNum;
	num = 0;
	seqNum = PriNum;
	while(num != seqNum)
	{
		tmpNum = num;
		num = (num+seqNum)/2;
		if(pri == ActivePri[num])
		{
			*SequenceNum = num;
			return TRUE;
		}
		else if (pri < ActivePri[num])
		{
			seqNum = num;
			num = tmpNum;
		}
		else
		{
			num++;
		}
	}
	*SequenceNum = num;
	return FALSE;		
}


/**
 *******************************************************************************
 * @brief      Get the nearest ready priority sequence number for Assign number	  
 * @param[in]  seqNum         Assign sequence number	 
 * @param[out] None
 * @retval     INVALID_ID     Cannot find higher ready priority.   
 *             Others         Nearest ready priority sequence number 		 
 *					
 * @par Description
 * @details    This function is called in Binary-Scheduling Algorithm 
 *             to get the nearest ready priority sequence number.    
 *******************************************************************************
 */
static U8 GetRdyPriSeqNum(U8 seqNum)
{
	U32 tmp;
	U8  i,j,num;
	S8  cnt;
	i = seqNum/32;
	j = seqNum%32;

	do
	{
	  	tmp = RdyTaskPriInfo[i];
		if(tmp != 0)
		{
			num = j/8;
			do
			{
				if((tmp&(0xff<<(num*8))) !=0 )
				{
					if((tmp&(0xf0<<(num*8))) !=0)
					{
						for(cnt=j; cnt >=(num*8+4); cnt--)	
						{
							if( (tmp&(1<<cnt)) !=0)
							{
								return (32*i+cnt);
							}	
						}			
					}

					if((j&0x4)==4)
						j = (j|0x3) -4;
					
					for(cnt=j; cnt >=num*8; cnt--)	
					{
						if( (tmp&(1<<cnt)) !=0)
						{
							return (32*i+cnt);
						}	
					}
				}
				j = num*8 -1;
			}while((num--)!=0);
		}
		j=31;
	}while((i--)!=0);
	return INVALID_ID;											
}


/**
 *******************************************************************************
 * @brief      Remap the ready status of priority queue from Assign sequence number 
 * @param[in]  seqNum         Assign sequence number	 
 * @param[out] None
 * @retval     None    		 
 *					
 * @par Description
 * @details    This function is called in Binary-Scheduling Algorithm 
 *             to Remap the ready status for priority queue.    
 *******************************************************************************
 */
static void PrioRemap(OS_TID  seqNum)
{
	U8 i,j;
	U32 tmp;
	tmp = j = 0;
	j = seqNum/32;
	for(i=0;i<seqNum%32;i++)
	{
		tmp |= 1<<i;
	}
	tmp &= RdyTaskPriInfo[j];
	
	for(i=seqNum; i<PriNum; i++)
	{
		if((i%32==0)&&(i!=seqNum))
		{
			RdyTaskPriInfo[j++] = tmp;
			tmp = 0;
		}
		if(RdyTaskPri[i] != INVALID_ID)
		{
			tmp = tmp | (1<<(i%32));
		}
	}
	RdyTaskPriInfo[j++] = tmp;
}


/**
 *******************************************************************************
 * @brief      Get the ready status for assign sequence number 
 * @param[in]  seqNum      Assign sequence number	 
 * @param[out] None
 * @retval     TRUE        This priority has ready task   
 *             FALSE       This priority doesn't have ready task  		 
 *					
 * @par Description
 * @details    This function is called in Binary-Scheduling Algorithm 
 *             to get the ready status for assign sequence number.    
 *******************************************************************************
 */
static BOOL GetPrioSeqNumStatus(U8 seqNum)
{
	if( (RdyTaskPriInfo[seqNum/32] & (1<<(seqNum%32))) == 0)
	{
		return FALSE;
	}
	return TRUE;
}


/**
 *******************************************************************************
 * @brief      Set the ready status for assign sequence number 
 * @param[in]  seqNum      Assign sequence number
 * @param[in]  isRdy       Ready statues for assign sequence number 	 
 * @param[out] None
 * @retval     None 		 
 *					
 * @par Description
 * @details    This function is called in Binary-Scheduling Algorithm 
 *             to set the ready status for assign sequence number.    
 *******************************************************************************
 */
static void SetPrioSeqNumStatus(U8 seqNum, BOOL isRdy)
{
	U32 tmp;
	tmp = RdyTaskPriInfo[seqNum/32];
	tmp	&= ~(1<<(seqNum%32));
	tmp |= isRdy<<(seqNum%32);
	RdyTaskPriInfo[seqNum/32] = tmp;
}


/**
 *******************************************************************************
 * @brief      Active priority in queue 
 * @param[in]  pri       Task priority
 * @param[in]  None     
 * @param[out] None
 * @retval     None 		 
 *					
 * @par Description
 * @details    This function is called in Binary-Scheduling Algorithm 
 *             to active priority in queue, if this priority had been in activation,
 *             increate the task num for this priority.    
 *******************************************************************************
 */
void ActiveTaskPri(U8 pri)
{
	OS_TID  seqNum,num;
	if(GetPriSeqNum(pri,&seqNum) == FALSE)
	{
		for(num=PriNum;num>seqNum;num--)
		{
			ActivePri[num]     = ActivePri[num-1];
			TaskNumPerPri[num] = TaskNumPerPri[num-1];
			RdyTaskPri[num]    = RdyTaskPri[num-1];
		}
		ActivePri[seqNum]     = pri;
		TaskNumPerPri[seqNum] = 1;
		RdyTaskPri[seqNum]    = INVALID_ID;
		PriNum++;
		PrioRemap(seqNum);
	}
	else
	{
		 TaskNumPerPri[seqNum]++;
	}
}



/**
 *******************************************************************************
 * @brief      Delete priority in queue 
 * @param[in]  pri       Task priority
 * @param[in]  None     
 * @param[out] None
 * @retval     None 		 
 *					
 * @par Description
 * @details    This function is called in Binary-Scheduling Algorithm 
 *             to decrease the task num for this priority, if the num goto 0,
 *             remove the priority for queue.
 *******************************************************************************
 */
void DeleteTaskPri(U8 pri)
{
	OS_TID  seqNum,num;

	GetPriSeqNum(pri,&seqNum);
	TaskNumPerPri[seqNum]--;
	if(TaskNumPerPri[seqNum]==0)
	{
		for(num=seqNum; num<(PriNum-1); num++)
		{
			ActivePri[num]     = ActivePri[num+1];
			TaskNumPerPri[num] = TaskNumPerPri[num+1];
			RdyTaskPri[num]    = RdyTaskPri[num+1];
		}
		PriNum--;
		PrioRemap(seqNum);
	}
}

#endif


/**
 *******************************************************************************
 * @brief      Insert a task to the ready list	   
 * @param[in]  tcbInsert    A pointer to task will be inserted.
 * @param[out] None  
 * @retval     None	 
 *
 * @par Description
 * @details   This function is called to insert a task to the READY list. 
 *******************************************************************************
 */
void InsertToTCBRdyList(P_OSTCB tcbInsert)
{
    P_OSTCB ptcbNext,ptcb;
    U8  prio;
#if CFG_ORDER_LIST_SCHEDULE_EN ==0
	U8  seqNum;
	U8  RdyTaskSeqNum;
#endif
    
    prio = tcbInsert->prio;             /* Get PRI of inserted task           */
    tcbInsert->state     = TASK_READY;  /* Set task as TASK_READY             */

#if CFG_ROBIN_EN >0
	ptcb = TCBRunning;
    /* Set schedule time for the same PRI task as TCBRunning.                 */
    if(prio == ptcb->prio)  /* Is PRI of inserted task equal to running task? */
    {
        if(ptcb != tcbInsert) /* Yes,is inserted task equal to running task?  */
        {
            if(ptcb != NULL)            /* No,TCBRunning == NULL?             */
            {                           /* N0,OSCheckTime < OSTickCnt?        */
                if(OSCheckTime < OSTickCnt)	 
                {                       /* Yes,set OSCheckTime for task robin */
                    OSCheckTime = OSTickCnt + ptcb->timeSlice;	
                }			
            }			
        }
    }
#endif


#if CFG_ORDER_LIST_SCHEDULE_EN ==0
	GetPriSeqNum(prio,&seqNum);
	if(GetPrioSeqNumStatus(seqNum) == TRUE)
	{
		ptcb = &TCBTbl[RdyTaskPri[seqNum]];
		RdyTaskPri[seqNum] = tcbInsert->taskID;
	}
	else
	{
		RdyTaskPri[seqNum] = tcbInsert->taskID;
		RdyTaskSeqNum = GetRdyPriSeqNum(seqNum);
		SetPrioSeqNumStatus(seqNum, 1);
		if(RdyTaskSeqNum == INVALID_ID)
		{
		    ptcb = TCBRdy;
		    TaskSchedReq = TRUE;
			if(ptcb == NULL)
			{
				TCBRdy   = tcbInsert;	
			}
			else
			{
				tcbInsert->TCBnext = ptcb;  /* Yes,set tcbInsert as head item of list */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -