📄 emos_task.c
字号:
uint16 id,
EMOS_STK *pbos,
uint32 stk_size,
void *pext,
uint16 opt)
{
void* psp = NULL;
uint8 err;
uint16 i;
EMOS_STK* pfill = NULL;
if (prio > EMOS_LOWEST_PRIO)
{
/* Make sure priority is within allowable range */
return (EMOS_PRIO_INVALID);
}
EMOS_ENTER_CRITICAL();
if (gEmosTCBPrioTbl[prio] == (EMOS_TCB_T *)0)
{
/* Make sure task doesn't already exist at this priority */
gEmosTCBPrioTbl[prio] = (EMOS_TCB_T *)1; /* Reserve the priority to prevent others from doing ... */
/* ... the same thing until task is created. */
EMOS_EXIT_CRITICAL();
if (opt & EMOS_TASK_OPT_STK_CHK)
{
/* See if stack checking has been enabled */
if (opt & EMOS_TASK_OPT_STK_CLR)
{
/* See if stack needs to be cleared */
pfill = pbos; /* Yes, fill the stack with zeros */
for (i = 0; i < stk_size; i++)
{
#if EMOS_STK_GROWTH == 1
*pfill++ = (EMOS_STK)0;
#else
*pfill-- = (EMOS_STK)0;
#endif
}
}
}
/*two important init routine called by TaskCreate*/
psp = (void *)emosTaskStkInit(task, pdata, ptos, opt); /* Initialize the task's stack */
err = emosTCBInit(prio, (EMOS_STK *)psp, (EMOS_STK *)pbos, id, stk_size, pext, opt);
if (err == EMOS_NO_ERR)
{
EMOS_ENTER_CRITICAL();
gEmosTaskCtr++; /* Increment the #tasks counter */
emosTaskCreateHook(gEmosTCBPrioTbl[prio]); /* Call user defined hook */
EMOS_EXIT_CRITICAL();
if (gEmosRunning)
{
/* Find highest priority task if multitasking has started */
emosSched();
}
}
else
{
EMOS_ENTER_CRITICAL();
gEmosTCBPrioTbl[prio] = (EMOS_TCB_T *)0;/* Make this priority available to others */
EMOS_EXIT_CRITICAL();
}
return (err);
}
else
{
EMOS_EXIT_CRITICAL();
return (EMOS_PRIO_EXIST);
}
}
#endif
/*********************************************************************************************************
* DELETE A TASK
*
* Description: This function allows you to delete a task. The calling task can delete itself by
* its own priority number. The deleted task is returned to the dormant state and can be
* re-activated by creating the deleted task again.
* Arguments : prio is the priority of the task to delete. Note that you can explicitely delete
* the current task without knowing its priority level by setting 'prio' to
* EMOS_PRIO_SELF.
* Returns : EMOS_NO_ERR if the call is successful
* EMOS_TASK_DEL_IDLE if you attempted to delete uC/OS-II's idle task
* EMOS_PRIO_INVALID if the priority you specify is higher that the maximum allowed
* (i.e. >= EMOS_LOWEST_PRIO) or, you have not specified EMOS_PRIO_SELF.
* EMOS_TASK_DEL_ERR if the task you want to delete does not exist
* EMOS_TASK_DEL_ISR if you tried to delete a task from an ISR
* Notes : 1) To reduce interrupt latency, OSTaskDel() 'disables' the task:
* a) by making it not ready
* b) by removing it from any wait lists
* c) by preventing OSTimeTick() from making the task ready to run.
* The task can then be 'unlinked' from the miscellaneous structures in uC/OS-II.
* 2) The function OSDummy() is called after EMOS_EXIT_CRITICAL() because, on most processors,
* the next instruction following the enable interrupt instruction is ignored. You can
* replace OSDummy() with a macro that basically executes a NO OP (i.e. EMOS_NOP()). The
* NO OP macro would avoid the execution time of the function call and return.
* 3) An ISR cannot delete a task.
* 4) The lock nesting counter is incremented because, for a brief instant, if the current
* task is being deleted, the current task would not be able to be rescheduled because it
* is removed from the ready list. Incrementing the nesting counter prevents another task
* from being schedule. This means that the ISR would return to the current task which is
* being deleted. The rest of the deletion would thus be able to be completed.
*********************************************************************************************************/
#if EMOS_TASK_DEL_EN
uint8 emosTaskDel (uint8 prio)
{
EMOS_TCB_T* ptcb = NULL;
EMOS_EVENT_T* pevent = NULL;
if (prio == EMOS_IDLE_PRIO)
{
/* Not allowed to delete idle task*/
return (EMOS_TASK_DEL_IDLE);
}
if (prio >= EMOS_LOWEST_PRIO && prio != EMOS_PRIO_SELF)
{
/* Task priority valid ?*/
return (EMOS_PRIO_INVALID);
}
EMOS_ENTER_CRITICAL();
if (gEmosIntNesting > 0)
{
/* See if trying to delete from ISR */
EMOS_EXIT_CRITICAL();
return (EMOS_TASK_DEL_ISR);
}
if (prio == EMOS_PRIO_SELF)
{
/* See if requesting to delete self */
prio = gEmosTCBCur->osTCBPrio; /* Set priority to delete to current */
}
if ((ptcb = gEmosTCBPrioTbl[prio]) != (EMOS_TCB_T *)0)
{
/* Task to delete must exist*/
if ((gEmosRdyTbl[ptcb->osTCBY] &= ~ptcb->osTCBBitX) == 0)
{
/* Make task not ready*/
gEmosRdyGrp &= ~ptcb->osTCBBitY;
}
if ((pevent = ptcb->osTCBEventPtr) != (EMOS_EVENT_T *)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 */
}
}
ptcb->osTCBDly = 0; /* Prevent OSTimeTick() from updating */
ptcb->osTCBStat = EMOS_STAT_RDY; /* Prevent task from being resumed */
gEmosLockNesting++;
EMOS_EXIT_CRITICAL(); /* Enabling INT. ignores next instruc. */
emosDummy(); /* ... Dummy ensures that INTs will be */
EMOS_ENTER_CRITICAL(); /* ... disabled HERE! */
gEmosLockNesting--;
emosTaskDelHook(ptcb); /* Call user defined hook */
gEmosTaskCtr--; /* One less task being managed */
gEmosTCBPrioTbl[prio] = (EMOS_TCB_T *)0; /* Clear old priority entry */
if (ptcb->osTCBPrev == (EMOS_TCB_T *)0)
{
/* Remove from TCB chain*/
ptcb->osTCBNext->osTCBPrev = (EMOS_TCB_T *)0;
gEmosTCBList = ptcb->osTCBNext;
}
else
{
ptcb->osTCBPrev->osTCBNext = ptcb->osTCBNext;
ptcb->osTCBNext->osTCBPrev = ptcb->osTCBPrev;
}
ptcb->osTCBNext = gEmosTCBFreeList; /* Return TCB to free TCB list */
gEmosTCBFreeList = ptcb;
EMOS_EXIT_CRITICAL();
emosSched(); /* Find new highest priority task*/
return (EMOS_NO_ERR);
}
/*deleteing task does not exist*/
else
{
EMOS_EXIT_CRITICAL();
return (EMOS_TASK_DEL_ERR);
}
}
#endif
/**********************************************************************************************************
* 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 EMOS_PRIO_SELF and monitors the returned value. If the return
* value is EMOS_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(EMOS_PRIO_SELF) == EMOS_TASK_DEL_REQ) {
* Release any owned resources;
* De-allocate any dynamic memory;
* OSTaskDel(EMOS_PRIO_SELF);
* }
* }
* }
* Arguments : prio is the priority of the task to request the delete from
* Returns : EMOS_NO_ERR if the task exist and the request has been registered
* EMOS_TASK_NOT_EXIST if the task has been deleted. This allows the caller to know whether
* the request has been executed.
* EMOS_TASK_DEL_IDLE if you requested to delete uC/OS-II's idle task
* EMOS_PRIO_INVALID if the priority you specify is higher that the maximum allowed
* (i.e. >= EMOS_LOWEST_PRIO) or, you have not specified EMOS_PRIO_SELF.
* EMOS_TASK_DEL_REQ if a task (possibly another task) requested that the running task be
* deleted.
**********************************************************************************************************/
#if EMOS_TASK_DEL_EN
uint8 emosTaskDelReq (uint8 prio)
{
bool stat;
uint8 err;
EMOS_TCB_T* ptcb = NULL;
if (prio == EMOS_IDLE_PRIO)
{
/* Not allowed to delete idle task*/
return (EMOS_TASK_DEL_IDLE);
}
if (prio >= EMOS_LOWEST_PRIO && prio != EMOS_PRIO_SELF)
{
/* Task priority valid ? */
return (EMOS_PRIO_INVALID);
}
if (prio == EMOS_PRIO_SELF)
{
/* See if a task is requesting to ... */
EMOS_ENTER_CRITICAL(); /* ... this task to delete itself */
stat = gEmosTCBCur->osTCBDelReq; /* Return request status to caller*/
EMOS_EXIT_CRITICAL();
return (stat);
}
else
{
EMOS_ENTER_CRITICAL();
if ((ptcb = gEmosTCBPrioTbl[prio]) != (EMOS_TCB_T *)0)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -