一般说来,任务可在OSStart()启动任务调度之前来创建,也可在任务中创建,但是UC/OS有个规定:在调用OSStart()启动任务调度之前,必须创建了至少一个任务。因此一般习惯上,在OSStart()启动任务调度之前先创建一个任务,并赋予它最高的优先级,从而使它成为起始任务,然后在这个起始任务中再创建其他任务。如果要使用统计任务,则统计任务的初始化函数也必须在这个起始任务中来调用。
注意:
UC/OS不允许在中断服务程序中创建任务。
下面是创建任务的示意性代码:
/******************主函数*****************/ void main(void) { ... ... OSInit(); //对ucos-ii进行初始化 ... ... OSTaskCreate(TaskStart,... ...); //创建起始任务 OSStart(); //开始多任务调度 } /*****************起始任务***************/ void TaskStart(void *pdata) { ... ... //在这个位置安装并启动ucos-ii的时钟 OSStatInit(); //初始化统计任务 ... ... //在这个位置创建其他任务 for(; ;) { /*起始任务TaskStart的代码*/ } }
创建任务函数
任务的创建实质上是创建一个任务控制块,并通过任务控制块把任务代码和任务堆栈关联起来形成一个完整的任务。UC/OS提供两个函数创建任务OSTaskCreate()和OSTaskCreateExt()。一般前者用的多,OSTaskCreate()如下所示:
1 INT8U OSTaskCreate (void (*task)(void *p_arg), void *p_arg, OS_STK *ptos, INT8U prio) 2 { 3 OS_STK *psp; 4 INT8U err; 5 #if OS_CRITICAL_METHOD == 3 6 OS_CPU_SR cpu_sr = 0; 7 #endif 8 #if OS_ARG_CHK_EN > 0 9 if (prio > OS_LOWEST_PRIO) { //检测任务的优先级是否合法 10 return (OS_PRIO_INVALID); 11 } 12 #endif 13 OS_ENTER_CRITICAL(); 14 if (OSIntNesting > 0) { /* Make sure we don\'t create the task from within an ISR */ 15 OS_EXIT_CRITICAL(); 16 return (OS_ERR_TASK_CREATE_ISR); 17 } 18 if (OSTCBPrioTbl[prio] == (OS_TCB *)0) {//确认优先级未被使用 19 OSTCBPrioTbl[prio] = (OS_TCB *)1; //保留优先级 20 21 OS_EXIT_CRITICAL(); 22 psp = OSTaskStkInit(task, p_arg, ptos, 0);//初始化堆栈 23 err = OS_TCBInit(prio, psp, (OS_STK *)0, 0, 0, (void *)0, 0);//初始化任务控制块 24 if (err == OS_NO_ERR) { 25 if (OSRunning == OS_TRUE) { /* Find highest priority task if multitasking has started */ 26 OS_Sched();//任务调度 27 } 28 } else { 29 OS_ENTER_CRITICAL(); 30 OSTCBPrioTbl[prio] = (OS_TCB *)0;//放弃任务 31 OS_EXIT_CRITICAL(); 32 } 33 return (err); 34 } 35 OS_EXIT_CRITICAL(); 36 return (OS_PRIO_EXIST); 37 } 38 #endif
在“启动任务”中完成与系统硬件有关的各种初始化工作,然后创建各个实质任务和所需要的各种通信工具,至此系统才真正完成准备工作,“启动任务”的使命也就结束了,最
后将自己删除。为了保证“启动任务”能够连续运行,必须将“启动任务”的优先级选择为最高。否则,当“启动任务”创建一个优先级高于自己的任务时,刚刚创建的任务就会立即
进入运行状态,而与这个任务关联的其它任务可能还没有创建,它使用的通信工具也还没有创建,系统必然出错。“启动任务”调用的“自我删除”函数会进行任务调度操作,从而使
系统开始运行各个实质任务