📄 task.c
字号:
/**
*******************************************************************************
* @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>© 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 + -