📄 os_task.c
字号:
/* Make task not ready */
OSRdyGrp &= ~ptcb->OSTCBBitY;
}
#if OS_EVENT_EN > 0
pevent = ptcb->OSTCBEventPtr;
if (pevent != (OS_EVENT *) 0)
{
/* If task is waiting on event */
if ((pevent->OSEventTbl[ptcb->OSTCBY] &= ~ptcb->OSTCBBitX) == 0)
{
/* ... remove task from */
pevent->OSEventGrp &= ~ptcb->OSTCBBitY; /* ... event ctrl block */
}
}
#endif
#if (OS_VERSION >= 251) && (OS_FLAG_EN > 0) && (OS_MAX_FLAGS > 0)
pnode = ptcb->OSTCBFlagNode;
if (pnode != (OS_FLAG_NODE *) 0)
{
/* If task is waiting on event flag */
OS_FlagUnlink(pnode); /* Remove from wait list */
}
#endif
ptcb->OSTCBDly = 0; /* Prevent OSTimeTick() from updating */
ptcb->OSTCBStat = OS_STAT_RDY; /* Prevent task from being resumed */
if (OSLockNesting < 255)
{
OSLockNesting++;
}
OS_EXIT_CRITICAL(); /* Enabling INT. ignores next instruc. */
OS_Dummy(); /* ... Dummy ensures that INTs will be */
OS_ENTER_CRITICAL(); /* ... disabled HERE! */
if (OSLockNesting > 0)
{
OSLockNesting--;
}
OSTaskDelHook(ptcb); /* Call user defined hook */
OSTaskCtr--; /* One less task being managed */
OSTCBPrioTbl[prio] = (OS_TCB *) 0; /* Clear old priority entry */
if (ptcb->OSTCBPrev == (OS_TCB *) 0)
{
/* Remove from TCB chain */
ptcb->OSTCBNext->OSTCBPrev = (OS_TCB *) 0;
OSTCBList = ptcb->OSTCBNext;
}
else
{
ptcb->OSTCBPrev->OSTCBNext = ptcb->OSTCBNext;
ptcb->OSTCBNext->OSTCBPrev = ptcb->OSTCBPrev;
}
ptcb->OSTCBNext = OSTCBFreeList; /* Return TCB to free TCB list */
OSTCBFreeList = ptcb;
OS_EXIT_CRITICAL();
OS_Sched(); /* Find new highest priority task */
return (OS_NO_ERR);
}
OS_EXIT_CRITICAL();
return (OS_TASK_DEL_ERR);
}
#endif
/*$PAGE*/
/*
*********************************************************************************************************
* REQUEST THAT A TASK DELETE ITSELF
*
* Description: This function is used to:
* a) notify a task to delete itself.
* b) to see if a task requested that the current task delete itself.
* This function is a little tricky to understand. Basically, you have a task that needs
* to be deleted however, this task has resources that it has allocated (memory buffers,
* semaphores, mailboxes, queues etc.). The task cannot be deleted otherwise these
* resources would not be freed. The requesting task calls OSTaskDelReq() to indicate that
* the task needs to be deleted. Deleting of the task is however, deferred to the task to
* be deleted. For example, suppose that task #10 needs to be deleted. The requesting task
* example, task #5, would call OSTaskDelReq(10). When task #10 gets to execute, it calls
* this function by specifying OS_PRIO_SELF and monitors the returned value. If the return
* value is OS_TASK_DEL_REQ, another task requested a task delete. Task #10 would look like
* this:
*
* void Task(void *data)
* {
* .
* .
* while (1) {
* OSTimeDly(1);
* if (OSTaskDelReq(OS_PRIO_SELF) == OS_TASK_DEL_REQ) {
* Release any owned resources;
* De-allocate any dynamic memory;
* OSTaskDel(OS_PRIO_SELF);
* }
* }
* }
*
* Arguments : prio is the priority of the task to request the delete from
*
* Returns : OS_NO_ERR if the task exist and the request has been registered
* OS_TASK_NOT_EXIST if the task has been deleted. This allows the caller to know whether
* the request has been executed.
* OS_TASK_DEL_IDLE if you requested to delete uC/OS-II's idle task
* OS_PRIO_INVALID if the priority you specify is higher that the maximum allowed
* (i.e. >= OS_LOWEST_PRIO) or, you have not specified OS_PRIO_SELF.
* OS_TASK_DEL_REQ if a task (possibly another task) requested that the running task be
* deleted.
*********************************************************************************************************
*/
/*$PAGE*/
#if OS_TASK_DEL_EN > 0
INT8U OSTaskDelReq(INT8U prio)
{
#if OS_CRITICAL_METHOD == 3 /* Allocate storage for CPU status register */
OS_CPU_SR cpu_sr;
#endif
BOOLEAN stat;
INT8U err;
OS_TCB *ptcb;
#if OS_ARG_CHK_EN > 0
if (prio == OS_IDLE_PRIO)
{
/* Not allowed to delete idle task */
return (OS_TASK_DEL_IDLE);
}
if (prio >= OS_LOWEST_PRIO && prio != OS_PRIO_SELF)
{
/* Task priority valid ? */
return (OS_PRIO_INVALID);
}
#endif
if (prio == OS_PRIO_SELF)
{
/* See if a task is requesting to ... */
OS_ENTER_CRITICAL(); /* ... this task to delete itself */
stat = OSTCBCur->OSTCBDelReq; /* Return request status to caller */
OS_EXIT_CRITICAL();
return (stat);
}
OS_ENTER_CRITICAL();
ptcb = OSTCBPrioTbl[prio];
if (ptcb != (OS_TCB *) 0)
{
/* Task to delete must exist */
ptcb->OSTCBDelReq = OS_TASK_DEL_REQ; /* Set flag indicating task to be DEL. */
err = OS_NO_ERR;
}
else
{
err = OS_TASK_NOT_EXIST; /* Task must be deleted */
}
OS_EXIT_CRITICAL();
return (err);
}
#endif
/*$PAGE*/
/*
*********************************************************************************************************
* RESUME A SUSPENDED TASK
*
* Description: This function is called to resume a previously suspended task. This is the only call that
* will remove an explicit task suspension.
*
* Arguments : prio is the priority of the task to resume.
*
* Returns : OS_NO_ERR if the requested task is resumed
* OS_PRIO_INVALID if the priority you specify is higher that the maximum allowed
* (i.e. >= OS_LOWEST_PRIO)
* OS_TASK_RESUME_PRIO if the task to resume does not exist
* OS_TASK_NOT_SUSPENDED if the task to resume has not been suspended
*********************************************************************************************************
*/
#if OS_TASK_SUSPEND_EN > 0
INT8U OSTaskResume(INT8U prio)
{
#if OS_CRITICAL_METHOD == 3 /* Allocate storage for CPU status register */
OS_CPU_SR cpu_sr;
#endif
OS_TCB *ptcb;
#if OS_ARG_CHK_EN > 0
if (prio >= OS_LOWEST_PRIO)
{
/* Make sure task priority is valid */
return (OS_PRIO_INVALID);
}
#endif
OS_ENTER_CRITICAL();
ptcb = OSTCBPrioTbl[prio];
if (ptcb == (OS_TCB *) 0)
{
/* Task to suspend must exist */
OS_EXIT_CRITICAL();
return (OS_TASK_RESUME_PRIO);
}
if ((ptcb->OSTCBStat & OS_STAT_SUSPEND) != OS_STAT_RDY)
{
/* Task must be suspended */
if (((ptcb->OSTCBStat &= ~OS_STAT_SUSPEND) == OS_STAT_RDY) && /* Remove suspension */
(ptcb->OSTCBDly == 0))
{
/* Must not be delayed */
OSRdyGrp |= ptcb->OSTCBBitY; /* Make task ready to run */
OSRdyTbl[ptcb->OSTCBY] |= ptcb->OSTCBBitX;
OS_EXIT_CRITICAL();
OS_Sched();
}
else
{
OS_EXIT_CRITICAL();
}
return (OS_NO_ERR);
}
OS_EXIT_CRITICAL();
return (OS_TASK_NOT_SUSPENDED);
}
#endif
/*$PAGE*/
/*
*********************************************************************************************************
* STACK CHECKING
*
* Description: This function is called to check the amount of free memory left on the specified task's
* stack.
*
* Arguments : prio is the task priority
*
* pdata is a pointer to a data structure of type OS_STK_DATA.
*
* Returns : OS_NO_ERR upon success
* OS_PRIO_INVALID if the priority you specify is higher that the maximum allowed
* (i.e. > OS_LOWEST_PRIO) or, you have not specified OS_PRIO_SELF.
* OS_TASK_NOT_EXIST if the desired task has not been created
* OS_TASK_OPT_ERR if you did NOT specified OS_TASK_OPT_STK_CHK when the task was created
*********************************************************************************************************
*/
#if OS_TASK_CREATE_EXT_EN > 0
INT8U OSTaskStkChk(INT8U prio, OS_STK_DATA *pdata)
{
#if OS_CRITICAL_METHOD == 3 /* Allocate storage for CPU status register */
OS_CPU_SR cpu_sr;
#endif
OS_TCB *ptcb;
OS_STK *pchk;
INT32U free;
INT32U size;
#if OS_ARG_CHK_EN > 0
if (prio > OS_LOWEST_PRIO && prio != OS_PRIO_SELF)
{
/* Make sure task priority is valid */
return (OS_PRIO_INVALID);
}
#endif
pdata->OSFree = 0; /* Assume failure, set to 0 size */
pdata->OSUsed = 0;
OS_ENTER_CRITICAL();
if (prio == OS_PRIO_SELF)
{
/* See if check for SELF */
prio = OSTCBCur->OSTCBPrio;
}
ptcb = OSTCBPrioTbl[prio];
if (ptcb == (OS_TCB *) 0)
{
/* Make sure task exist */
OS_EXIT_CRITICAL();
return (OS_TASK_NOT_EXIST);
}
if ((ptcb->OSTCBOpt & OS_TASK_OPT_STK_CHK) == 0)
{
/* Make sure stack checking option is set */
OS_EXIT_CRITICAL();
return (OS_TASK_OPT_ERR);
}
free = 0;
size = ptcb->OSTCBStkSize;
pchk = ptcb->OSTCBStkBottom;
OS_EXIT_CRITICAL();
#if OS_STK_GROWTH == 1
while (*pchk++ == (OS_STK) 0)
{
/* Compute the number of zero entries on the stk */
free++;
}
#else
while (*pchk-- == (OS_STK) 0)
{
free++;
}
#endif
pdata->OSFree = free * sizeof(OS_STK); /* Compute number of free bytes on the stack */
pdata->OSUsed = (size - free) * sizeof(OS_STK); /* Compute number of bytes used on the stack */
return (OS_NO_ERR);
}
#endif
/*$PAGE*/
/*
*********************************************************************************************************
* SUSPEND A TASK
*
* Description: This function is called to suspend a task. The task can be the calling task if the
* priority passed to OSTaskSuspend() is the priority of the calling task or OS_PRIO_SELF.
*
* Arguments : prio is the priority of the task to suspend. If you specify OS_PRIO_SELF, the
* calling task will suspend itself and rescheduling will occur.
*
* Returns : OS_NO_ERR if the requested task is suspended
* OS_TASK_SUSPEND_IDLE if you attempted to suspend the idle task which is not allowed.
* OS_PRIO_INVALID if the priority you specify is higher that the maximum allowed
* (i.e. >= OS_LOWEST_PRIO) or, you have not specified OS_PRIO_SELF.
* OS_TASK_SUSPEND_PRIO if the task to suspend does not exist
*
* Note : You should use this function with great care. If you suspend a task that is waiting for
* an event (i.e. a message, a semaphore, a queue ...) you will prevent this task from
* running when the event arrives.
*********************************************************************************************************
*/
#if OS_TASK_SUSPEND_EN > 0
INT8U OSTaskSuspend(INT8U prio)
{
#if OS_CRITICAL_METHOD == 3 /* Allocate storage for CPU status register */
OS_CPU_SR cpu_sr;
#endif
BOOLEAN self;
OS_TCB *ptcb;
#if OS_ARG_CHK_EN > 0
if (prio == OS_IDLE_PRIO)
{
/* Not allowed to suspend idle task */
return (OS_TASK_SUSPEND_IDLE);
}
if (prio >= OS_LOWEST_PRIO && prio != OS_PRIO_SELF)
{
/* Task priority valid ? */
return (OS_PRIO_INVALID);
}
#endif
OS_ENTER_CRITICAL();
if (prio == OS_PRIO_SELF)
{
/* See if suspend SELF */
prio = OSTCBCur->OSTCBPrio;
self = TRUE;
}
else if (prio == OSTCBCur->OSTCBPrio)
{
/* See if suspending self */
self = TRUE;
}
else
{
self = FALSE; /* No suspending another task */
}
ptcb = OSTCBPrioTbl[prio];
if (ptcb == (OS_TCB *) 0)
{
/* Task to suspend must exist */
OS_EXIT_CRITICAL();
return (OS_TASK_SUSPEND_PRIO);
}
if ((OSRdyTbl[ptcb->OSTCBY] &= ~ptcb->OSTCBBitX) == 0x00)
{
/* Make task not ready */
OSRdyGrp &= ~ptcb->OSTCBBitY;
}
ptcb->OSTCBStat |= OS_STAT_SUSPEND; /* Status of task is 'SUSPENDED' */
OS_EXIT_CRITICAL();
if (self == TRUE)
{
/* Context switch only if SELF */
OS_Sched();
}
return (OS_NO_ERR);
}
#endif
/*$PAGE*/
/*
*********************************************************************************************************
* QUERY A TASK
*
* Description: This function is called to obtain a copy of the desired task's TCB.
*
* Arguments : prio is the priority of the task to obtain information from.
*
* Returns : OS_NO_ERR if the requested task is suspended
* OS_PRIO_INVALID if the priority you specify is higher that the maximum allowed
* (i.e. > OS_LOWEST_PRIO) or, you have not specified OS_PRIO_SELF.
* OS_PRIO_ERR if the desired task has not been created
*********************************************************************************************************
*/
#if OS_TASK_QUERY_EN > 0
INT8U OSTaskQuery(INT8U prio, OS_TCB *pdata)
{
#if OS_CRITICAL_METHOD == 3 /* Allocate storage for CPU status register */
OS_CPU_SR cpu_sr;
#endif
OS_TCB *ptcb;
#if OS_ARG_CHK_EN > 0
if (prio > OS_LOWEST_PRIO && prio != OS_PRIO_SELF)
{
/* Task priority valid ? */
return (OS_PRIO_INVALID);
}
#endif
OS_ENTER_CRITICAL();
if (prio == OS_PRIO_SELF)
{
/* See if suspend SELF */
prio = OSTCBCur->OSTCBPrio;
}
ptcb = OSTCBPrioTbl[prio];
if (ptcb == (OS_TCB *) 0)
{
/* Task to query must exist */
OS_EXIT_CRITICAL();
return (OS_PRIO_ERR);
}
memcpy(pdata, ptcb, sizeof(OS_TCB)); /* Copy TCB into user storage area */
OS_EXIT_CRITICAL();
return (OS_NO_ERR);
}
#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -