UCOSIII任务创建
UCOSIII是多任务系统,那么肯定要能创建任务,创建任务就是将任务控制块、任务堆栈、任务代码等联系在一起,并且初始化任务控制块的相应字段。在UCOSIII中我们通过函数OSTaskCreate()来创建任务,OSTaskCreate()函数原型如下(在os_task.c中有定义)。
OSTaskCreate()的函数定义为:
void OSTaskCreate (OS_TCB *p_tcb, //任务控制块
CPU_CHAR *p_name, //任务名称
OS_TASK_PTR p_task, //任务函数
void *p_arg, //传递给任务函数的参数
OS_PRIO prio, //任务优先级
CPU_STK *p_stk_base, //任务堆栈基地址
CPU_STK_SIZE stk_limit, //任务堆栈深度限位
CPU_STK_SIZE stk_size, //任务堆栈大小
OS_MSG_QTY q_size, //任务内部消息队列能够接收的最大消息数目,为0时禁止接收消息
OS_TICK time_quanta, //当使能时间片轮转时的时间片长度,为0时为默认长度
void *p_ext, //用户补充的存储区
OS_OPT opt, //任务选项
OS_ERR *p_err) //存放该函数错误时的返回值
{
... //函数省略
OSSched();
}
对于任务创建函数有几点解释的:
参数*p_arg:传递给任务的参数。这就要求我们在定义任务函数的时候,需要给它赋予任务参数;但是我们一般在创建任务的时候,很少会传递这个参数,一般为0。比如,任务start_task的任务说明:
void start_task(void *p_arg);
参数q_size:UCOSIII中每个任务都有一个可选的内部消息队列,我们要定义宏OS_CFG_TASK_Q_EN>0,这是才会使用这个内部消息队列;
参数opt:包含任务的特定选项,有如下选项可以设置:
UCOSIII任务删除
OSTaskDel()函数用来删除任务,当一个任务不需要运行的话,我们就可以将其删除掉,删除任务不是说删除任务代码,而是UCOSIII不再管理这个任务。
void OSTaskDel (OS_TCB *p_tcb,
OS_ERR *p_err)
{
... //函数省略
OSSched(); /* Find new highest priority task */
}
对于任务删除函数有几点说明的:
调用OSTaskDel()删除一个任务后,这个任务的任务堆栈、OS_TCB所占用的内存并没有释放掉,因此我们可以利用他们用于其他的任务,当然我们也可以使用内存管理的方法给任务堆栈和OS_TCB分配内存,这样当我们删除掉某个任务后我们就可以使用内存释放函数将这个任务的任务堆栈和OS_TCB所占用的内存空间释放掉。
尽管UCOSIII允许在系统运行中删除任务,但是应该尽量避免这种操作,如果这个任务可能占有与其他任务共享的资源,在删除此任务之前这个被占有的资源没有被释放就有可能导致奇怪的结果。
UCOSIII任务挂起
有时候有些任务因为某些原因需要暂停运行,但是以后还要运行,因此我们就不能删除掉任务,这里我们可以使用OSTaskSuspend()函数挂起这个任务,以后再恢复运行,函数OSTaskSuspend()的原型如下:
void OSTaskSuspend (OS_TCB *p_tcb,
OS_ERR *p_err)
{
... //函数省略
OS_TaskSuspend(p_tcb, p_err);
}
我们可以多次调用OSTaskSuspend ()函数来挂起一个任务,因此我们需要调用同样次数的OSTaskResume()函数才可以恢复被挂起的任务,这一点非常重要。
UCOSIII任务恢复
OSTaskResume()函数用来恢复被OSTaskSuspend()函数挂起的任务,OSTaskResume()函数是唯一能恢复被挂起任务的函数。函数OSTaskResume()的原型如下:
void OSTaskSuspend (OS_TCB *p_tcb,
OS_ERR *p_err)
{
... //函数省略
OS_TaskSuspend(p_tcb, p_err);
}
如果被挂起的任务还在等待别的内核对象,比如事件标志组、信号量、互斥信号量、消息队列等,即使使用OSTaskResume()函数恢复了被挂起的任务,该任务也不一定能立即运行,该任务还是要等相应的内核对象,只有等到内核对象后才可以继续运行。