📄 os_task.c
字号:
OS_STK *pbos,
INT32U stk_size,
void *pext,
INT16U opt)
{
#if OS_CRITICAL_METHOD == 3 /* 为CPU状态寄存器分配存储变量 */
OS_CPU_SR cpu_sr;
#endif
OS_STK *psp;
INT8U err;
#if OS_ARG_CHK_EN > 0
if (prio > OS_LOWEST_PRIO)
{ /* 确认优先级在许可范围之内 */
return (OS_PRIO_INVALID);
}
#endif
OS_ENTER_CRITICAL();
if (OSTCBPrioTbl[prio] == (OS_TCB *)0)
{ /* 确认优先级未被其他任务占用 */
OSTCBPrioTbl[prio] = (OS_TCB *)1; /* 保留该优先级避免其他处理 ... */
/* ... 直到任务建立. */
OS_EXIT_CRITICAL();
if (((opt & OS_TASK_OPT_STK_CHK) != 0x0000) || /* 如果使能堆栈检验 */
((opt & OS_TASK_OPT_STK_CLR) != 0x0000))
{ /* 如果堆栈需要清零 */
#if OS_STK_GROWTH == 1
(void)memset(pbos, 0, stk_size * sizeof(OS_STK));
#else
(void)memset(ptos, 0, stk_size * sizeof(OS_STK));
#endif
}
psp = (OS_STK *)OSTaskStkInit(task, pdata, ptos, opt); /* 初始化任务堆栈 */
err = OS_TCBInit(prio, psp, pbos, id, stk_size, pext, opt);
if (err == OS_NO_ERR)
{
OS_ENTER_CRITICAL();
OSTaskCtr++; /* 增加任务计数器 */
OS_EXIT_CRITICAL();
if (OSRunning == TRUE)
{ /* 如果多任务启动寻找最高优先级任务 */
OS_Sched();
}
}
else
{
OS_ENTER_CRITICAL();
OSTCBPrioTbl[prio] = (OS_TCB *)0; /* 放弃该优先级 */
OS_EXIT_CRITICAL();
}
return (err);
}
OS_EXIT_CRITICAL();
return (OS_PRIO_EXIST);
}
#endif
/*$PAGE*/
/*
*********************************************************************************************************
* 删除任务
*
* 函数描述: 该函数为删除任务。调用的任务通过设定自身的优先级别可以删除自身。被删除的任务返回到睡眠状态,并
* 通过再次创建删除掉的任务来重新激活。
*
* 输入参数: prio 待删除任务的优先级。注意,如果不知当前任务的优先级可通过设定为OS_PRIO_SELF来删除当前任务。
*
*
* 返回值 : OS_NO_ERR 调用成功
* OS_TASK_DEL_IDLE 想删除 uC/OS-II 的空闲任务
* OS_PRIO_INVALID 指定的优先级高于允许的最大值
* (例如. >= OS_LOWEST_PRIO)或没有指定 OS_PRIO_SELF.
* OS_TASK_DEL_ERR 想删除的任务不存在
* OS_TASK_DEL_ISR 想从中断服务程序中删除任务
*
* 注释 : 1)为减少中断隐患, OSTaskDel() 将关闭该任务:
* a) 通过脱离就绪
* b) 通过从等待列表中移除
* c) 通过避免 OSTimeTick() 使任务就绪待运行。
* 该任务能从 uC/OS-II 中的杂项结构中脱离。
* 2) OS_EXIT_CRITICAL() 后调用 OS_Dummy()的意义是因为在大多数处理器中,紧跟开中断指令的下
* 一条指令常被忽略。
* 3) 中断服务程序不能删除任务
* 4) 如果当前任务正在被删除,由于它已从就绪列表中移出,所以,它将不能被调度,上锁嵌套计数器增加
* 增加嵌套计数器是避免其他任务被调度。也就是一个中断服务程序将返回到当前正被删除的任务。
* 删除剩余部分将完成。
*********************************************************************************************************
*/
/*$PAGE*/
#if OS_TASK_DEL_EN > 0
INT8U OSTaskDel (INT8U prio)
{
#if OS_CRITICAL_METHOD == 3 /* 为CPU状态寄存器分配存储变量 */
OS_CPU_SR cpu_sr;
#endif
#if OS_EVENT_EN > 0
OS_EVENT *pevent;
#endif
#if (OS_VERSION >= 251) && (OS_FLAG_EN > 0) && (OS_MAX_FLAGS > 0)
OS_FLAG_NODE *pnode;
#endif
OS_TCB *ptcb;
BOOLEAN self;
self = self; // 预防编译警告
if (OSIntNesting > 0)
{ /* 确保不是在ISR中删除一个程序 */
return (OS_TASK_DEL_ISR);
}
#if OS_ARG_CHK_EN > 0
if (prio == OS_IDLE_PRIO)
{ /* 不允许删除空闲任务 */
return (OS_TASK_DEL_IDLE);
}
if (prio >= OS_LOWEST_PRIO && prio != OS_PRIO_SELF)
{ /* 任务优先级是否有效? */
return (OS_PRIO_INVALID);
}
#endif
OS_ENTER_CRITICAL();
if (prio == OS_PRIO_SELF)
{ /* 是否请求删除自身? */
prio = OSTCBCur->OSTCBPrio; /* 设定删除当前任务的优先级 */
}
ptcb = OSTCBPrioTbl[prio];
if (ptcb != (OS_TCB *)0) /* 要删除的任务是否存在? */
{
if ((OSRdyTbl[ptcb->OSTCBY] &= ~ptcb->OSTCBBitX) == 0x00)
{ /* 使任务脱离就绪 */
OSRdyGrp &= ~ptcb->OSTCBBitY;
}
#if OS_EVENT_EN > 0
pevent = ptcb->OSTCBEventPtr; /* 任务是否正在等待事件? */
if (pevent != (OS_EVENT *)0)
{
if ((pevent->OSEventTbl[ptcb->OSTCBY] &= ~ptcb->OSTCBBitX) == 0)
{ /* ... 移除任务 */
pevent->OSEventGrp &= ~ptcb->OSTCBBitY; /* ... 从事件控制块 */
}
}
#endif
#if (OS_VERSION >= 251) && (OS_FLAG_EN > 0) && (OS_MAX_FLAGS > 0)
pnode = ptcb->OSTCBFlagNode;
if (pnode != (OS_FLAG_NODE *)0)
{ /* 任务是否在等事件标志? */
OS_FlagUnlink(pnode); /* 从等待列表中移除 */
}
#endif
ptcb->OSTCBDly = 0; /* 避免 OSTimeTick() 更新 */
ptcb->OSTCBStat = OS_STAT_RDY; /* 防止任务重新开始 */
if (OSLockNesting < 255)
{
OSLockNesting++;
}
OS_EXIT_CRITICAL(); /* 打开中断忽略下一指令 */
OS_Dummy(); /* ... 哑函数确保中断关闭 */
OS_ENTER_CRITICAL(); /* ... 此处关闭中断 */
if (OSLockNesting > 0)
{
OSLockNesting--;
}
OSTaskDelHook(ptcb); /* 调用户定义的钩子函数 */
OSTaskCtr--; /* 任务数减一 */
OSTCBPrioTbl[prio] = (OS_TCB *)0; /* 旧优先级任务清零 */
if (ptcb->OSTCBPrev == (OS_TCB *)0)
{ /* 从任务控制块链上移除 */
ptcb->OSTCBNext->OSTCBPrev = (OS_TCB *)0;
OSTCBList = ptcb->OSTCBNext;
}
else
{
ptcb->OSTCBPrev->OSTCBNext = ptcb->OSTCBNext;
ptcb->OSTCBNext->OSTCBPrev = ptcb->OSTCBPrev;
}
ptcb->OSTCBNext = OSTCBFreeList; /* 把任务控制块返回到空余任务控制块 */
OSTCBFreeList = ptcb;
OS_EXIT_CRITICAL();
OS_Sched(); /* 寻找新的最高优先级任务 */
return (OS_NO_ERR);
}
OS_EXIT_CRITICAL();
return (OS_TASK_DEL_ERR);
}
#endif
/*$PAGE*/
/*
*********************************************************************************************************
* 请求删除自身
*
* 函数描述: 该函数用于:
* a) 通知任务删除自身
* b) 其他任务请求当前任务删除自身
* 首先,试图删除一个任务,但是该任务却占用着一些内存缓冲区、信号量、邮箱、队列等资源。
* 因为一些资源还未释放,任务不该被删。正在请求的任务调用 OSTaskDelReq() 来显示需要删除的任务。
* 例如,10号任务需被删除。请求删除的任务例如,5号,将调用 OSTaskDelReq(10)。当10号任务执行时,
* 它将调用 OSTaskDelReq(OS_PRIO_SELF),并检测函数的返回值。如果返回值是OS_TASK_DEL_REQ,则5号请
* 求删除10号任务。10号任务将如下:
*
* 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);
* }
* }
* }
*
* 输入参数 : prio 被删除的任务的优先级
*
* Returns : OS_NO_ERR 如果任务存在,请求许可注册
* OS_TASK_NOT_EXIST 是否任务已被删除。允许调用函数知道请求是否执行。
* OS_TASK_DEL_IDLE 请求删除的任务是否是 uC/OS-II的空闲任务
* OS_PRIO_INVALID 指定的优先级是否高于允许的最大值。
* (例如 >= OS_LOWEST_PRIO) 或没有指定为 OS_PRIO_SELF.
* OS_TASK_DEL_REQ 一个任务(可能是其他任务) 是否请求删除正在运行的任务
*********************************************************************************************************
*/
/*$PAGE*/
#if OS_TASK_DEL_EN > 0
INT8U OSTaskDelReq (INT8U prio)
{
#if OS_CRITICAL_METHOD == 3 /* 为CPU状态寄存器分配存储变量 */
OS_CPU_SR cpu_sr;
#endif
BOOLEAN stat;
INT8U err;
OS_TCB *ptcb;
#if OS_ARG_CHK_EN > 0
if (prio == OS_IDLE_PRIO)
{ /* 不允许删除空闲任务 */
return (OS_TASK_DEL_IDLE);
}
if (prio >= OS_LOWEST_PRIO && prio != OS_PRIO_SELF)
{ /* 任务优先级是否有效 ? */
return (OS_PRIO_INVALID);
}
#endif
if (prio == OS_PRIO_SELF)
{ /* 是否一个任务正在请求 ... */
OS_ENTER_CRITICAL(); /* ... 这个任务要删除自身 */
stat = OSTCBCur->OSTCBDelReq; /* 返回给调用函数的请求状态 */
OS_EXIT_CRITICAL();
return (stat);
}
OS_ENTER_CRITICAL();
ptcb = OSTCBPrioTbl[prio];
if (ptcb != (OS_TCB *)0)
{ /* 要删除的任务必须存在 */
ptcb->OSTCBDelReq = OS_TASK_DEL_REQ; /* 设定标志显示任务被删除 */
err = OS_NO_ERR;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -