📄 os_task.c
字号:
#if OS_CFG_ISR_POST_DEFERRED_EN > 0u
if (prio == (OS_PRIO)0) {
if (p_tcb != &OSIntQTaskTCB) {
*p_err = OS_ERR_PRIO_INVALID; /* Not allowed to use priority 0 */
return;
}
}
#endif
if (prio == (OS_CFG_PRIO_MAX - 1u)) {
if (p_tcb != &OSIdleTaskTCB) {
*p_err = OS_ERR_PRIO_INVALID; /* Not allowed to use same priority as idle task */
return;
}
}
OS_TaskInitTCB(p_tcb); /* Initialize the TCB to default values */
*p_err = OS_ERR_NONE;
/* --------------- CLEAR THE TASK'S STACK --------------- */
if ((opt & OS_OPT_TASK_STK_CHK) != (OS_OPT)0) { /* See if stack checking has been enabled */
if ((opt & OS_OPT_TASK_STK_CLR) != (OS_OPT)0) { /* See if stack needs to be cleared */
p_sp = p_stk_base;
for (i = 0u; i < stk_size; i++) { /* Stack grows from HIGH to LOW memory */
*p_sp = (CPU_STK)0; /* Clear from bottom of stack and up! */
p_sp++;
}
}
}
/* ------- INITIALIZE THE STACK FRAME OF THE TASK ------- */
#if (CPU_CFG_STK_GROWTH == CPU_STK_GROWTH_HI_TO_LO)
p_stk_limit = p_stk_base + stk_limit;
#else
p_stk_limit = p_stk_base + (stk_size - 1u) - stk_limit;
#endif
p_sp = OSTaskStkInit(p_task,
p_arg,
p_stk_base,
p_stk_limit,
stk_size,
opt);
/* -------------- INITIALIZE THE TCB FIELDS ------------- */
p_tcb->TaskEntryAddr = p_task; /* Save task entry point address */
p_tcb->TaskEntryArg = p_arg; /* Save task entry argument */
p_tcb->NamePtr = p_name; /* Save task name */
p_tcb->Prio = prio; /* Save the task's priority */
p_tcb->StkPtr = p_sp; /* Save the new top-of-stack pointer */
p_tcb->StkLimitPtr = p_stk_limit; /* Save the stack limit pointer */
p_tcb->TimeQuanta = time_quanta; /* Save the #ticks for time slice (0 means not sliced) */
#if OS_CFG_SCHED_ROUND_ROBIN_EN > 0u
if (time_quanta == (OS_TICK)0) {
p_tcb->TimeQuantaCtr = OSSchedRoundRobinDfltTimeQuanta;
} else {
p_tcb->TimeQuantaCtr = time_quanta;
}
#endif
p_tcb->ExtPtr = p_ext; /* Save pointer to TCB extension */
p_tcb->StkBasePtr = p_stk_base; /* Save pointer to the base address of the stack */
p_tcb->StkSize = stk_size; /* Save the stack size (in number of CPU_STK elements) */
p_tcb->Opt = opt; /* Save task options */
#if OS_CFG_TASK_REG_TBL_SIZE > 0u
for (reg_nbr = 0u; reg_nbr < OS_CFG_TASK_REG_TBL_SIZE; reg_nbr++) {
p_tcb->RegTbl[reg_nbr] = (OS_REG)0;
}
#endif
#if OS_CFG_TASK_Q_EN > 0u
OS_MsgQInit(&p_tcb->MsgQ, /* Initialize the task's message queue */
q_size);
#endif
OSTaskCreateHook(p_tcb); /* Call user defined hook */
/* --------------- ADD TASK TO READY LIST --------------- */
OS_CRITICAL_ENTER();
OS_PrioInsert(p_tcb->Prio);
OS_RdyListInsertTail(p_tcb);
#if OS_CFG_DBG_EN > 0u
OS_TaskDbgListAdd(p_tcb);
#endif
OSTaskQty++; /* Increment the #tasks counter */
if (OSRunning != OS_STATE_OS_RUNNING) { /* Return if multitasking has not started */
OS_CRITICAL_EXIT();
return;
}
OS_CRITICAL_EXIT_NO_SCHED();
OSSched();
}
/*$PAGE*/
/*
************************************************************************************************************************
* DELETE A TASK
*
* Description: This function allows you to delete a task. The calling task can delete itself by specifying a NULL
* pointer for 'p_tcb'. The deleted task is returned to the dormant state and can be re-activated by
* creating the deleted task again.
*
* Arguments : p_tcb is the TCB of the tack to delete
*
* p_err is a pointer to an error code returned by this function:
*
* OS_ERR_NONE if the call is successful
* OS_ERR_STATE_INVALID if the state of the task is invalid
* OS_ERR_TASK_DEL_IDLE if you attempted to delete uC/OS-III's idle task
* OS_ERR_TASK_DEL_INVALID if you attempted to delete uC/OS-III's ISR handler task
* OS_ERR_TASK_DEL_ISR if you tried to delete a task from an ISR
************************************************************************************************************************
*/
#if OS_CFG_TASK_DEL_EN > 0u
void OSTaskDel (OS_TCB *p_tcb,
OS_ERR *p_err)
{
CPU_SR_ALLOC();
#ifdef OS_SAFETY_CRITICAL
if (p_err == (OS_ERR *)0) {
OS_SAFETY_CRITICAL_EXCEPTION();
return;
}
#endif
#if OS_CFG_CALLED_FROM_ISR_CHK_EN > 0u
if (OSIntNestingCtr > (OS_NESTING_CTR)0) { /* See if trying to delete from ISR */
*p_err = OS_ERR_TASK_DEL_ISR;
return;
}
#endif
if (p_tcb == &OSIdleTaskTCB) { /* Not allowed to delete the idle task */
*p_err = OS_ERR_TASK_DEL_IDLE;
return;
}
#if OS_CFG_ISR_POST_DEFERRED_EN > 0u
if (p_tcb == &OSIntQTaskTCB) { /* Cannot delete the ISR handler task */
*p_err = OS_ERR_TASK_DEL_INVALID;
return;
}
#endif
if (p_tcb == (OS_TCB *)0) { /* Delete 'Self'? */
CPU_CRITICAL_ENTER();
p_tcb = OSTCBCurPtr; /* Yes. */
CPU_CRITICAL_EXIT();
}
OS_CRITICAL_ENTER();
switch (p_tcb->TaskState) {
case OS_TASK_STATE_RDY:
OS_RdyListRemove(p_tcb);
break;
case OS_TASK_STATE_SUSPENDED:
break;
case OS_TASK_STATE_DLY: /* Task is only delayed, not on any wait list */
case OS_TASK_STATE_DLY_SUSPENDED:
OS_TickListRemove(p_tcb);
break;
case OS_TASK_STATE_PEND:
case OS_TASK_STATE_PEND_SUSPENDED:
case OS_TASK_STATE_PEND_TIMEOUT:
case OS_TASK_STATE_PEND_TIMEOUT_SUSPENDED:
OS_TickListRemove(p_tcb);
switch (p_tcb->PendOn) { /* See what we are pending on */
case OS_TASK_PEND_ON_NOTHING:
case OS_TASK_PEND_ON_TASK_Q: /* There is no wait list for these two */
case OS_TASK_PEND_ON_TASK_SEM:
break;
case OS_TASK_PEND_ON_FLAG: /* Remove from wait list */
case OS_TASK_PEND_ON_MULTI:
case OS_TASK_PEND_ON_MUTEX:
case OS_TASK_PEND_ON_Q:
case OS_TASK_PEND_ON_SEM:
OS_PendListRemove(p_tcb);
break;
default:
break;
}
break;
default:
OS_CRITICAL_EXIT();
*p_err = OS_ERR_STATE_INVALID;
return;
}
#if OS_CFG_TASK_Q_EN > 0u
(void)OS_MsgQFreeAll(&p_tcb->MsgQ); /* Free task's message queue messages */
#endif
OSTaskDelHook(p_tcb); /* Call user defined hook */
#if OS_CFG_DBG_EN > 0u
OS_TaskDbgListRemove(p_tcb);
#endif
OSTaskQty--; /* One less task being managed */
OS_TaskInitTCB(p_tcb); /* Initialize the TCB to default values */
p_tcb->TaskState = (OS_STATE)OS_TASK_STATE_DEL; /* Indicate that the task was deleted */
OS_CRITICAL_EXIT_NO_SCHED();
OSSched(); /* Find new highest priority task */
*p_err = OS_ERR_NONE;
}
#endif
/*$PAGE*/
/*
************************************************************************************************************************
* FLUSH TASK's QUEUE
*
* Description: This function is used to flush the task's internal message queue.
*
* Arguments : p_tcb is a pointer to the task's OS_TCB. Specifying a NULL pointer indicates that you wish to
* flush the message queue of the calling task.
*
* p_err is a pointer to a variable that will contain an error code returned by this function.
*
* OS_ERR_NONE upon success
* OS_ERR_FLUSH_ISR if you called this function from an ISR
*
* Returns : The number of entries freed from the queue
*
* Note(s) : 1) You should use this function with great care because, when to flush the queue, you LOOSE the
* references to what the queue entries are pointing to and thus, you could cause 'memory leaks'. In
* other words, the data you are pointing to that's being referenced by the queue entries should, most
* likely, need to be de-allocated (i.e. freed).
************************************************************************************************************************
*/
#if OS_CFG_TASK_Q_EN > 0u
OS_MSG_QTY OSTaskQFlush (OS_TCB *p_tcb,
OS_ERR *p_err)
{
OS_MSG_QTY entries;
CPU_SR_ALLOC();
#ifdef OS_SAFETY_CRITICAL
if (p_err == (OS_ERR *)0) {
OS_SAFETY_CRITICAL_EXCEPTION();
return ((OS_MSG_QTY)0);
}
#endif
#if OS_CFG_CALLED_FROM_ISR_CHK_EN > 0u
if (OSIntNestingCtr > (OS_NESTING_CTR)0) { /* Can't flush a message queue from an ISR */
*p_err = OS_ERR_FLUSH_ISR;
return ((OS_MSG_QTY)0);
}
#endif
if (p_tcb == (OS_TCB *)0) { /* Flush message queue of calling task? */
CPU_CRITICAL_ENTER();
p_tcb = OSTCBCurPtr;
CPU_CRITICAL_EXIT();
}
OS_CRITICAL_ENTER();
entries = OS_MsgQFreeAll(&p_tcb->MsgQ); /* Return all OS_MSGs to the OS_MSG pool */
OS_CRITICAL_EXIT();
*p_err = OS_ERR_NONE;
return (entries);
}
#endif
/*$PAGE*/
/*
************************************************************************************************************************
* WAIT FOR A MESSAGE
*
* Description: This function causes the current task to wait for a message to be posted to it.
*
* Arguments : timeout is an optional timeout period (in clock ticks). If non-zero, your task will wait for a
* message to arrive up to the amount of time specified by this argument.
* If you specify 0, however, your task will wait forever or, until a message arrives.
*
* opt determines whether the user wants to block if the task's queue is empty or not:
*
* OS_OPT_PEND_BLOCKING
* OS_OPT_PEND_NON_BLOCKING
*
* p_msg_size is a pointer to a variable that will receive the size of the message
*
* p_ts is a pointer to a variable that will receive the timestamp of when the message was
* received. If you pass a NULL pointer (i.e. (CPU_TS *)0) then you will not get the
* timestamp. In other words, passing a NULL pointer is valid and indicates that you don't
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -