📄 task.c
字号:
ptcb->TCBprev = tcbInsert;
TCBRdy = tcbInsert;
}
return;
}
else
{
ptcb = &TCBTbl[RdyTaskPri[RdyTaskSeqNum]];
}
}
ptcbNext = ptcb->TCBnext;
tcbInsert->TCBnext = ptcbNext; /* Set link for list */
ptcb->TCBnext = tcbInsert;
tcbInsert->TCBprev = ptcb;
if(ptcbNext != NULL)
{
ptcbNext->TCBprev = tcbInsert;
}
#else
ptcb = TCBRdy;
if (ptcb == NULL) /* Is ready list NULL? */
{
TaskSchedReq = TRUE;
TCBRdy = tcbInsert; /* Yse,set tcbInsert as head item of list */
}
else if (prio < ptcb->prio)/* Is PRI of inserted task higher than TCBRdy? */
{
TaskSchedReq = TRUE;
tcbInsert->TCBnext = ptcb; /* Yes,set tcbInsert as head item of list */
ptcb->TCBprev = tcbInsert;
TCBRdy = tcbInsert;
}
else /* No,find correct place */
{
ptcbNext = ptcb->TCBnext; /* Get next item */
while(ptcbNext != NULL) /* Is last item in ready list? */
{ /* No,find correct place */
if(prio < ptcbNext->prio) /* Is correct place? */
break; /* Yes,break circulation */
ptcb = ptcbNext; /* Save current item */
ptcbNext = ptcbNext->TCBnext; /* Get next item */
}
tcbInsert->TCBnext = ptcbNext; /* Set link for list */
ptcb->TCBnext = tcbInsert;
tcbInsert->TCBprev = ptcb;
if(ptcbNext != NULL)
{
ptcbNext->TCBprev = tcbInsert;
}
}
#endif
}
/**
*******************************************************************************
* @brief Remove a task from the READY list
* @param[in] ptcb A pointer to task which be removed.
* @param[out] None
* @retval None
*
* @par Description
* @details This function is called to remove a task from the READY list.
*******************************************************************************
*/
void RemoveFromTCBRdyList(P_OSTCB ptcb)
{
#if CFG_ORDER_LIST_SCHEDULE_EN ==0
U8 prio;
U8 seqNum;
BOOL isChange;
isChange = FALSE;
prio = ptcb->prio;
GetPriSeqNum(prio,&seqNum);
#endif
/* Is there only one item in READY list? */
if((ptcb->TCBnext == NULL) && (ptcb->TCBprev == NULL) )
{
TCBRdy = NULL; /* Yes,set READY list as NULL */
#if CFG_ORDER_LIST_SCHEDULE_EN ==0
isChange = TRUE;
#endif
}
else if(ptcb->TCBprev == NULL) /* Is the first item in READY list? */
{
/* Yes,remove task from the list,and reset the head of READY list */
TCBRdy = ptcb->TCBnext;
ptcb->TCBnext = NULL;
TCBRdy->TCBprev = NULL;
#if CFG_ORDER_LIST_SCHEDULE_EN ==0
if(TCBRdy->prio != prio)
isChange = TRUE;
#endif
}
else if( ptcb->TCBnext == NULL) /* Is the last item in READY list? */
{ /* Yes,remove task from list */
#if CFG_ORDER_LIST_SCHEDULE_EN ==0
if(ptcb->TCBprev->prio != prio)
isChange = TRUE;
else
RdyTaskPri[seqNum] = ptcb->TCBprev->taskID;
#endif
ptcb->TCBprev->TCBnext = NULL;
ptcb->TCBprev = NULL;
}
else /* No, remove task from list */
{
#if CFG_ORDER_LIST_SCHEDULE_EN ==0
if((ptcb->TCBprev->prio != prio) && (ptcb->TCBnext->prio != prio))
isChange = TRUE;
else if((ptcb->TCBprev->prio == prio) && (ptcb->TCBnext->prio != prio))
RdyTaskPri[seqNum] = ptcb->TCBprev->taskID;
#endif
ptcb->TCBprev->TCBnext = ptcb->TCBnext;
ptcb->TCBnext->TCBprev = ptcb->TCBprev;
ptcb->TCBnext = NULL;
ptcb->TCBprev = NULL;
}
#if CFG_ORDER_LIST_SCHEDULE_EN ==0
if(isChange == TRUE)
{
RdyTaskPri[seqNum] = INVALID_ID;
SetPrioSeqNumStatus(seqNum, 0);
}
#endif
}
#if CFG_MUTEX_EN > 0
#define CFG_PRIORITY_SET_EN (1)
#endif
#if CFG_PRIORITY_SET_EN >0
/**
*******************************************************************************
* @brief Change task priority
* @param[in] taskID Specify task id.
* @param[in] priority New priority.
* @param[out] None
* @retval E_OK Change priority successful.
* @retval E_INVALID_ID Invalid id,change priority fail.
* @retval E_PROTECTED_TASK Can't change idle task priority.
*
* @par Description
* @details This function is called to change priority for a specify task.
*******************************************************************************
*/
StatusType CoSetPriority(OS_TID taskID,U8 priority)
{
P_OSTCB ptcb;
#if CFG_MUTEX_EN >0
U8 prio;
P_MUTEX pMutex;
#endif
#if CFG_EVENT_EN >0
P_ECB pecb;
#endif
if(taskID == 0) /* Is idle task? */
{
return E_PROTECTED_TASK; /* Yes,error return */
}
#if CFG_PAR_CHECKOUT_EN >0 /* Check validity of parameter */
if(taskID >= CFG_MAX_USER_TASKS + SYS_TASK_NUM)
{
return E_INVALID_ID;
}
#endif
ptcb = &TCBTbl[taskID]; /* Get TCB of task ID */
#if CFG_PAR_CHECKOUT_EN >0
if(ptcb->state == TASK_DORMANT)
{
return E_INVALID_ID;
}
if(priority > CFG_LOWEST_PRIO)
{
return E_INVALID_ID;
}
#endif
if(ptcb->prio != priority) /* Is PRI equal to original PRI? */
{ /* No */
#if CFG_MUTEX_EN >0
if(ptcb->mutexID != INVALID_ID)
{
pMutex = &MutexTbl[ptcb->mutexID];
if(pMutex->taskID == ptcb->taskID) /* Task hold mutex? */
{
pMutex->originalPrio= priority;/* Yes,change original PRI in mutex*/
if(ptcb->prio < priority) /* Is task priority higher than set?*/
{
return E_OK; /* Yes,do nothing,return OK */
}
}
}
#endif
#if CFG_ORDER_LIST_SCHEDULE_EN ==0
DeleteTaskPri(ptcb->prio);
ActiveTaskPri(priority);
#endif
ptcb->prio = priority; /* Change task PRI */
if(ptcb->state == TASK_READY) /* Is task in READY list? */
{
OsSchedLock(); /* Yes,reorder task in READY list */
RemoveFromTCBRdyList(ptcb);
InsertToTCBRdyList(ptcb);
OsSchedUnlock();
}
else if(ptcb->state == TASK_RUNNING)/* Is task running? */
{
if(ptcb->prio > TCBRdy->prio) /* Yes,Is PRI higher than TCBRdy? */
{
OsSchedLock(); /* Yes,reorder task in READY list */
TaskSchedReq = TRUE;
OsSchedUnlock();
}
}
else
{ /* No,task in WAITING list */
#if CFG_MUTEX_EN >0
if(ptcb->mutexID != INVALID_ID) /* Is task in mutex WAITING list? */
{
/* Yes,reset the highest PRI in the list */
OsSchedLock();
pMutex = &MutexTbl[ptcb->mutexID];
ptcb = pMutex->waittingList;
prio = pMutex->originalPrio;
pMutex->hipriTaskID = pMutex->taskID;
while(ptcb != NULL)
{
if(ptcb->prio < prio)
{
prio = ptcb->prio;
pMutex->hipriTaskID = ptcb->taskID;
}
ptcb = ptcb->TCBnext;
}
OsSchedUnlock();
if(pMutex->originalPrio != prio)
{
CoSetPriority(pMutex->taskID,prio);
}
}
#endif
#if CFG_EVENT_EN >0
ptcb = &TCBTbl[taskID];
if(ptcb->eventID != INVALID_ID) /* Is task in event WAITING list? */
{
pecb = &EventTbl[ptcb->eventID];
/* Yes,is event sort type as preemptive PRI? */
if(pecb->eventSortType == EVENT_SORT_TYPE_PRIO)
{
/* Yes,reorder task in the list */
RemoveEventWaittingList(ptcb);
EventTaskToWait(pecb,ptcb);
}
}
#endif
}
}
return E_OK;
}
#endif
/**
*******************************************************************************
* @brief Schedule function
* @param[in] None
* @param[out] None
* @retval None
*
* @par Description
* @details This function is called by every where need to switch context,
* It is schedule function of OS kernel.
*******************************************************************************
*/
void Schedule(void)
{
U8 RunPrio,RdyPrio;
P_OSTCB pRdyTcb,pCurTcb;
pCurTcb = TCBRunning;
pRdyTcb = TCBRdy;
if((pRdyTcb==NULL) || (pCurTcb != TCBNext) || (OSSchedLock >1) || (OSIntNesting >0))
{
return;
}
TaskSchedReq = FALSE;
RunPrio = pCurTcb->prio;
RdyPrio = pRdyTcb->prio;
/* Is Running task status was changed? */
if(pCurTcb->state != TASK_RUNNING)
{
TCBNext = pRdyTcb; /* Yes,set TCBNext and reorder READY list */
pRdyTcb->state = TASK_RUNNING;
RemoveFromTCBRdyList(pRdyTcb);
}
else if(RdyPrio < RunPrio ) /* Is higher PRI task coming in? */
{
TCBNext = pRdyTcb; /* Yes,set TCBNext and reorder READY list */
InsertToTCBRdyList(pCurTcb);
RemoveFromTCBRdyList(pRdyTcb);
pRdyTcb->state = TASK_RUNNING;
}
#if CFG_ROBIN_EN >0 /* Is time for robinning */
else if((RunPrio == RdyPrio) && (OSCheckTime == OSTickCnt))
{
TCBNext = pRdyTcb; /* Yes,set TCBNext and reorder READY list */
InsertToTCBRdyList(pCurTcb);
RemoveFromTCBRdyList(pRdyTcb);
pRdyTcb->state = TASK_RUNNING;
}
#endif
else
{
return;
}
#if CFG_ROBIN_EN >0
if(TCBNext->prio == TCBRdy->prio) /* Reset OSCheckTime for task robinnig */
OSCheckTime = OSTickCnt + TCBNext->timeSlice;
#endif
#if CFG_STK_CHECKOUT_EN > 0 /* Is stack overflow? */
if((pCurTcb->stkPtr < pCurTcb->stack)||(*(U32*)(pCurTcb->stack) != MAGIC_WORD))
{
CoStkOverflowHook(pCurTcb->taskID); /* Yes,call handler */
}
#endif
SwitchContext(); /* Call task context switch */
}
/**
*******************************************************************************
* @brief Assign a TCB to task being created
* @param[in] None
* @param[out] None
*
* @retval XXXX
*
* @par Description
* @details This function is called to assign a task control block for task
* being created.
*******************************************************************************
*/
static P_OSTCB AssignTCB(void)
{
P_OSTCB ptcb;
OsSchedLock(); /* Lock schedule */
if(FreeTCB == NULL) /* Is there no free TCB */
{
OsSchedUnlock(); /* Yes,unlock schedule */
return NULL; /* Error return */
}
ptcb = FreeTCB; /* Yes,assgin free TCB for this task */
/* Set next item as the head of free TCB list */
FreeTCB = FreeTCB->TCBnext;
OsSchedUnlock();
return ptcb;
}
/**
*******************************************************************************
* @brief Create a task
* @param[in] task Task code entry.
* @param[in] argv The parameter passed to task.
* @param[in] parameter Task priority + stack size + time slice + isWaitting.
* @param[in] stk Pointer to stack top of task.
* @param[out] None
* @retval E_CREATE_FAIL Fail to create a task .
* @retval others Valid task id.
*
* @par Description
* @details This function is called by application to create a task,return a id
* to mark this task.
*******************************************************************************
*/
OS_TID CreateTask(FUNCPtr task,void *argv,U32 parameter,OS_STK *stk)
{
OS_STK* stkTopPtr;
P_OSTCB ptcb;
U8 prio;
#if CFG_ROBIN_EN >0
U16 timeSlice;
#endif
#if CFG_STK_CHECKOUT_EN >0 /* Check validity of parameter */
U16 sktSz;
sktSz = (parameter&0xfff00)>>8;
#endif
prio = parameter&0xff;
#if CFG_PAR_CHECKOUT_EN >0 /* Check validity of parameter */
if(task == NULL)
{
return E_CREATE_FAIL;
}
if(stk == NULL)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -