嵌入式实时操作系统uC/os-II(七)-任务创建
- 函数OSTaskCreate()创建任务
- 应用程序通过调用函数OSTaskCreate()来创建任务。函数OSTaskCreate()的源码如下:
INT8U OSTaskCreate(
void (* task)(void *pd), //指向任务的指针
void *pdata, //传递给任务的参数
OS_STK *ptos, //指向任务堆栈栈顶的指针
INT8U prio //任务的优先级
)
{
void *psp;
INT8U err;
if(prio > OS_LOWEST_PRIO) //检测任务的优先级是否合法
{
return (OS_PRIO_INVALID);
}
OS_ENTER_CRITICAL();
if(OSTCBPrioTbl[prio] == (OS_TCB *)0) //确认优先级未被使用
{
OSTCBPrioTbl[prio] == (OS_TCB *)1;
OS_EXIT_CRITICAL();
psp =(void *) OSTaskStkInit(
task,
pdata,
ptos,
); //初始化任务堆栈
err = OSTCBInit(
prio,
psp,
(void *)0,0,0,
(void *)0,0
); //获得并初始化任务控制块
if (err == OS_NO_ERR)
{
OS_ENTER_CRITICAL();
OSTaskCtr++; //任务计数器加1
OS_EXIT_CRITICAL();
if (OSRunning) //判断uC/OS-II的内核是否在运行状态
{
OSSched(); //任务调度
}
}else{
OS_ENTER_CRITICAL();
OSTCBPrioTbl[prio] = (OS_TCB)0; //放弃任务
OS_EXIT_CRITICAL();
}
return (err);
}else {
OS_EXIT_CRITICAL();
return (OS_PRIO_EXIST);
}
}
- 任务的挂起和恢复
定义:挂起一个任务,就是停止这个任务的运行。
在uC/OS-II中,用户任务可通过调用系统提供OSTaskSuspend()函数来挂起自身或者除空闲任务之外的其他任务。用OSTaskSuspend ()挂起的任务,只能在其他任务中通过调用恢复函数OSTaskResume()使其恢复为就绪状态。任务挂起和恢复的如图2-13所示。
图2-13 任务的挂起和恢复
-
挂起任务
- 挂起任务函数OSTaskSuspend()的原型如下:
INT8U OSTaskSuspend(INTU8U prio);
函数的参数prio为挂起任务的优先级。如果任务挂起自身,则参数必须为常数OS_PRIO_SELF。函数OSTaskSuspend()的流程图如2-14所示。
图2-14 函数OSTaskSuspend()的流程图
由上图可知,主要是判断待要挂起的任务是否调用这个函数本身。如果是任务本身,则必须删除任务在任务就绪表中的就绪标志,并在任务控制块成员OSTCBStat中做了挂起记录之后,引发一次任务调度,以使CPU去运行就绪的其他任务。如果待挂起的任务不是调用函数的任务本身而是其他任务,那么只要删除任务就绪表中被挂起任务的就绪标志,并在任务控制块成员OSTCBStat中做挂起记录即可。
-
恢复任务
- 恢复任务函数OSTaskResume()的原型如下:
INT8U OSTaskResume(INT8U prio);
函数的参数为待恢复任务的优先级。若函数调用成功,则返回信息OS_NO_ERR;否则,根据出错的具体情况返回OS_PRIO_INVALID,OS_TASK_RESUME_PRIO和OS_TASK_NOT_SUSPEND等。
图2-15函数OSTaskResume()的流程图
从图中所示OSTaskResume()的流程图中可知,函数在判断任务确实是一个已经存在的挂起任务,同时它又不是一个等待任务(任务控制块成员OSTCBDly=0)时,就会消除任务控制块成员OSTCBStat中的挂起记录并使任务就绪,最后调用调度器OSSched()进行任务调度,并返回函数调用成功的信息OS_NO_ERR。
- 任务优先级的修改
INT8U OSTaskChangePrio(
INT8U oldprio, //任务现在的优先级别
INT8U newprio //要修改的优先级别
)
- 任务的删除
所谓删除一个任务,就是把该任务置于睡眠状态。具体作法是,把被删除任务的任务控制块从任务控制链表中删除,并归还给空任务控制块链表,然后在任务就绪表中把该任务的就绪状态位设置为0。
函数OSTaskDel()的原型如下:
INT8U OSTaskDel(
INT8U prio //要删除任务的优先级别
);
如果一个任务调用这个函数是为了删除任务自己,则应在调用函数时令函数的参数prio为OS_PRIO_SELF。
有时,任务占用一些动态分配的内存或信号量之类的资源。当删除一个任务时,一些资源就会没有被释放而丢失。因此,在删除一个占用资源的任务时,一定要谨慎。具体办法是,提出删除任务请求的任务只负责提出删除任务的请求,而删除工作则由被删除任务自己来完成。
- 请求删除任务
函数OSTaskDelReq()原型如下:
INT8U OSTaskDelReq(
INT8U prio //待删除任务的优先级别
);
提出删除任务请求的任务在调用这个函数时,函数的参数应该为被删除任务的优先级别prio,被删除任务在调用这个函数时,函数的参数应该为OS_PRIO_SELF。
函数OSTaskDelReq()的流程图如图2-16所示。
图2-16 函数OSTaskDelReq()的流程图
删除任务请求方要用被删除任务的优先级prio作为参数来调用这个函数。从图2-16中可以看出,删除任务请求方调用这个函数的目的就是要看被删除任务控制块是否还在。如果还在,则把被删除任务方的控制块成员OSTCBDelReq的值为OS_TASK_DEL_REQ。
例如,任务请求删除优先级为44的任务,那么完成这个任务的代码片段如下:
While(OSTaskDelReq(44) != OS_TASK_NOT_EXIST)
{
OSTimeDly(1);
}
被删除方调用函数的代码片段如下:
If(OSTaskDelReq(OS_PRIO_SELF) == OS_TASK_DEL_REQ)
{
//释放资源和动态内存的代码
OSTaskDelReq (OS_PRIO_SELF);
}else{
}
- 查询任务的信息
INT8U OSTaskQuery(
INT8U prio, //待查询任务的优先级
OS_TCB *pdata //存储任务信息的结构
);