当前位置:首页 > 嵌入式系统实训报告
return (OS_PRIO_EXIST); //具有该优先级的任务已经存在 }
#endif
/*$PAGE*/ /*
*************************************************************************************************
* 删除一个指定优先级的任务(DELETE A TASK) *
* 描述: 删除一个指定优先级的任务。任务可以传递自己的优先级给OSTaskDel(),从而删除自身.如果任
* 务不知道自己的优先级,还可以传递参数OS_PRIO_SELF.被删除的任务将回到休眠状态.任务被删
* 除后可以用函数OSTaskCreate()或OSTaskCreateExt()重新建立. *
* 参数: prio 为指定要删除任务的优先级,也可以用参数OS_PRIO_SELF代替,此时,下一个优先级最高
* 的就绪任务将开始运行。 *
* 返回: OS_NO_ERR:函数调用成功;
* OS_TASK_DEL_IDLE:错误操作,试图删除空闲任务(Idle task); * OS_TASK_DEL_ ERR:错误操作,指定要删除的任务不存在;
* OS_PRIO_INVALID:参数指定的优先级大于OS_LOWEST_PRIO; * OS_TASK_DEL_ISR:错误操作,试图在中断处理程序中删除任务. * *
* 注意: 1、OSTaskDel()将判断用户是否试图删除uC/OS中的空闲任务(Idle task);
* 2、在删除占用系统资源的任务时要小心,此时,为安全起见可以用另一个函数OSTaskDelReq().
************************************************************************************************* */
6 H:\\SOURCE中文源代码\\OS_TASK.C /*$PAGE*/
#if OS_TASK_DEL_EN > 0 //允许生成 OSTaskDel()函数 INT8U OSTaskDel (INT8U prio) //删除任务(任务的优先级) {
#if OS_CRITICAL_METHOD == 3 //中断函数被设定为模式3 OS_CPU_SR cpu_sr; #endif
#if OS_EVENT_EN > 0 //消息事件是否 > 0 OS_EVENT *pevent; //定义事件指针 #endif
//版本是否 > 2.51 并且 允许产生事件标志相关代码 并且应用中最多事件标志组的数
目 > 0
#if (OS_VERSION >= 251) && (OS_FLAG_EN > 0) && (OS_MAX_FLAGS > 0) OS_FLAG_NODE *pnode; //定义标志节点 #endif
OS_TCB *ptcb; //定义消息事件的任务控制块指针 if (OSIntNesting > 0) { //当前中断嵌套 > 0时,表示还有中断程序运行
return (OS_TASK_DEL_ISR); //错误操作,试图在中断处理程序中删除任务 }
#if OS_ARG_CHK_EN > 0 //所有参数必须在指定的参数内 if (prio == OS_IDLE_PRIO) { //检查任务优先级是否是空闲任务
return (OS_TASK_DEL_IDLE); //错误操作,试图删除空闲任务(Idle task)
} //当任务 >= 最低优先级 并且 任务不是本身
if (prio >= OS_LOWEST_PRIO && prio != OS_PRIO_SELF) { //检查任务是否是合法的
return (OS_PRIO_INVALID); //参数指定的优先级大于OS_LOWEST_PRIO } #endif
OS_ENTER_CRITICAL(); //关闭中断
if (prio == OS_PRIO_SELF) { //检查的删除者是否是任务(优先级)本身 prio = OSTCBCur->OSTCBPrio; //正在运行的优先级(任务本身的优先级)
} //删除的任务必须存在 if ((ptcb = OSTCBPrioTbl[prio]) != (OS_TCB *)0) { //调用这个任务的优先级的就绪值
if ((OSRdyTbl[ptcb->OSTCBY] &= ~ptcb->OSTCBBitX) == 0x00) { //当就绪=1(即就绪状态)
OSRdyGrp &= ~ptcb->OSTCBBitY; //该任务处于就绪值,从就绪表中去除 }
#if OS_EVENT_EN > 0 //消息事件是否 > 0
pevent = ptcb->OSTCBEventPtr; //拾取该任务的事件控制指针 if (pevent != (OS_EVENT *)0) {
//指向事件控制块的指针是否为Null if ((pevent->OSEventTbl[ptcb->OSTCBY] &= ~ptcb->OSTCBBitX) == 0) { //事件(消息)在等待表中将自己所处的表中删除
pevent->OSEventGrp &= ~ptcb->OSTCBBitY; } } #endif
//版本是否 > 2.51 并且 允许产生事件标志相关代码 并且应用中最多事件标志组的
数目 > 0
#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; //将任务时钟节拍清0,确保重新开中断,中断程序不使该任务就绪
ptcb->OSTCBStat = OS_STAT_RDY; //将任务的状态字处于完毕状态 if (OSLockNesting < 255) { //如果锁定嵌套计数器 < 255,
OSLockNesting++; //锁定嵌套计数器加1,使这个任务处于休眠状态 }
OS_EXIT_CRITICAL(); //打开中断
OS_Dummy(); //增加一个空指令 OS_ENTER_CRITICAL(); //关闭中断 if (OSLockNesting > 0) { //(可以继续执行删除任务的操作了) OSLockNesting--; //重新关闭中断后,可以通过锁定嵌套计数器减1,重新允许任务调度 }
OSTaskDelHook(ptcb); //可在钩子程序中加入自定程序
OSTaskCtr--; //任务计数器减1,ucos管理的任务减少一个
OSTCBPrioTbl[prio] = (OS_TCB *)0; //将被删除的任务控制块OS_TCB指针=Null,
//从任务优先级中把OS_TCB删除 if (ptcb->OSTCBPrev == (OS_TCB *)0) { //任务块双向链接表的前链接是否Null
ptcb->OSTCBNext->OSTCBPrev = (OS_TCB *)0; //删除该任务的任务控制块OS_TCB
OSTCBList = ptcb->OSTCBNext; //链接表指向后一个链接 } else { //否则 ptcb->OSTCBPrev->OSTCBNext = ptcb->OSTCBNext; // ? ptcb->OSTCBNext->OSTCBPrev = ptcb->OSTCBPrev; // ? 7 H:\\SOURCE中文源代码\\OS_TASK.C
} //OSTCBPrev:用于任务块双向链接表的前链接
//OSTCBNext:用于任务块双向链接表的后链接
//OSTCBFreeList:空任务控制块指针 ptcb->OSTCBNext = OSTCBFreeList; //被删除的任务控制块OS_TCB被退回到空闲OS_TCB表中
OSTCBFreeList = ptcb; //以供建立其它任务使用 OS_EXIT_CRITICAL(); //打开中断
OS_Sched(); //任务调度,最高任务优先级运行 return (OS_NO_ERR); //函数调用成功 }
OS_EXIT_CRITICAL(); //打开中断 return (OS_TASK_DEL_ERR); //错误操作,指定要删除的任务不存在 }
#endif
/*$PAGE*/ /*
*************************************************************************************************
* 请求一个任务删除其它任务或自身(REQUEST THAT A TASK DELETE ITSELF) *
* 描述: 请求一个任务删除自身。通常OSTaskDelReq()用于删除一个占有系统资源的任务(例如任务建立
* 了信号量)对于此类任务,在删除任务之前应当先释放任务占用的系统资源。
* 具体的做法是:在需要被删除的任务中调用OSTaskDelReq()检测是否有其他任务的删除请求,如
* 果有,则释放自身占用的资源,然后调用OSTaskDel()删除自身。例如,假设任务5要删除任务10,
* 而任务10占有系统资源,此时任务5不能直接调用OSTaskDel(10)删除任务10,而应该调用
* OSTaskDelReq(10)向任务10发送删除请求.在任务10中调用OSTaskDelReq(OS_PRIO_SELF),并检测
* 返回值。如果返回OS_TASK_DEL_REQ,则表明有来自其他任务的删除请求,此时任务10应该先释放
* 资源,然后调用OSTaskDel(OS_PRIO_SELF)删除自己。任务5可以循环调用OSTaskDelReq(10)并检
* 测返回值,如果返回OS_TASK_NOT_EXIST,表明任务10已经成功删除。 * void Task(void *data) * { * ... * ...
* while (1) {
* OSTimeDly(1);
* if (OSTaskDelReq(OS_PRIO_SELF) == OS_TASK_DEL_REQ) * {
* 释放任务占用的系统资源; * 释放动态分配的内存;
* OSTaskDel(OS_PRIO_SELF); * }
共分享92篇相关文档