ucos 任务创建

来源:互联网 发布:恶搞锁屏软件生成器 编辑:程序博客网 时间:2024/06/06 18:23

任务是什么?有一句话,CPU不同的时刻总是在执行着优先级最高的任务,所以CPU总是在不同的任务间切换,任务好比linux中近程

在ucos世界里,任务就是一个大箩筐,框中一个或多个函数,CPU像个美女,总是从一个大箩筐跳到一个大箩筐,CPU这么跳来跳去都是找大帅哥

我们知道,CPU总是不断在各个任务间切换,为了下次跳回来,CPU在跳的同时,要保护好现场,这时我们需要用的堆栈了,

所以每当我们创建一个任务,我们都需要给这个任务分配一个堆栈

1.下面就是项目总给其中一个任务设定堆栈大小的程序

#define TASK_STK_SIZE     256

2.设定了堆栈的大小之后,接着就可以创建任务了,创建任务我们需要使用OSTaskCreate()或OSTaskCreateExt()函数,这两个函数减没有很大的区别,只是后者比前者

多了写扩展功能,

OSTaskCreate(void(*task)(void*pd),void *pdata,OS_STK *ptos,INT8U prio)

创建一个任务,OSTaskCreate()需要四个参数:task是任务代码的指针,pdata是当任务开始执行时传递给任务的参数

指针,ptos是分配给任务的堆栈指针,prio是分配给任务的优先级

OSTaskCreate(TaskUartSend,(void*)0,&TaskUartSendStk[TASK_STK_SIZE-1],5);

TaskUartSend就是这个任务执行时间调用的函数名称

&TaskUartSendStk[TASK_STK_SIZE-1]是定义的任务堆栈的栈顶地址

5:表示该任务的优先级5

这样,一个任务就基本创建完毕,接着就可以编写任务的实现函数TaskUartSend了。

创建任务函数的实现程序

INT8U OSTaskCreate(void (*task)(void*pd),void *pdata,OS_STK *ptos,INT8U prio)

{

     void *psp;

     INT8U err;

    if(prio>OS_LOWEST_PRIO)     (1)

   {

             return(OS_PRIO_INVALID);

   }

   OS_ENTER_CRITICAL();

   if(OSTCBPrioTbl[prio]==(OS_TCB*)0)      (2)

   {

        OSTCBPrioTbl[prio]=(OS_TCB*)1;        (3)

       OS_EXIT_CRITICAL();                               (4)

       psp=(void*)OSTaskStkInit(task,pdata,ptos,0);  (5)

       err=OSTCBInit(prio,psp,(void*)0,0,0,(void*)0,0);  (6)

       if(err==OS_NO_ERR)          (7)

      {

                 OS_ENTER_CRITICAL();  

                OSTaskCtr++;          (8)

               OSTaskCreateHook(OSTCBPrioTbl[prio]);     (9)

               OS_EXIT_CRITICAL();

               if(OSRunning)       (10)

                    OSSched();        (11)

     }

     else

      {

                OS_ENTER_CRITICAL();

                OSTCBPrioTbl[prio]=(OS_TCB*)0;          (12)

               OS_EXIT_CRITICAL();

        }

          return(err);

 }

else

{

       OS_EXIT_CRITCAL();

        return(OS_PRIO_EXIST);

}

}

 

  1.OSTaskCreate()一开始先检测分配给任务的优先级是否有效(1);任务的优先级必须在0到OS_LOWEST_PRIO之间,OS_LOWEST_PRIO的定义是在

os_cfg.h这个文件 定义如下:#define OS_LOWEST_PRIO  12

2.接着,OSTaskCreate要确保在规定的优先级上还没建立任务(2),在使用ucos时,每个任务都有特定的优先级,如果某个优先级是空闲未使用,ucos通过

放置一个非空指在OSTCBPrioTbl[]中,来保留该优先级3,这使得OSTaskCreate在设置任务数据结构的其它部分时能重新允许中断(4);

3.然后OSTaskCreate()调用OSTaskStkInit(5),它负责建立任务的堆栈,每次,就是OSTaskStkInit(),系统移植的时候,我们辛辛苦在OS_CPU_C.C编写了它,原来跑到这耀武扬威,OSTaskInit函数返回新的堆栈栈顶(psp),并被保存在任务的OS_TCB中,注意用户必须将传递给OSTaskStkInit函数的第四个参数opt置为0,因为OSTaskCreate与

OSTaskCreateExt不同,它不支持用户为任务的创建过程设置不同的选项,所以没有任务选项可以通过opt参数传递给OSTaskStkInit()

4.一旦OSTaskStkInit函数完成建立了堆栈的任务,OSTaskCreate()就调用OSTCBInit()(6),这也是任务创建的核心,从空闲的OS_TCB池中获得一个OS_TCB,OSTCBInit()函数首先从OS_TCB缓冲池中获得一个OS_TCB,如果OS_TCB池中有空闲的OS_TCB,它就被初始化,注意一旦OS_TCB被分配,该任务的创建者就已经完全拥有它了,即使这时

内核又创建其它的任务,这些新任务也不可能对已分配的OS_TCB作任务操作,所以OSTCBInit在这是可以允许中断,并继续初始化OS_TCB的数据单元。

5.从OSTCBInit返回后,OSTaskCreate要检查返回代码(7),如果成功,就增加OSTaskCtr(8),OSTaskCtr用于保存产生的任务数目。如果OSTCBInit返回失败,就置OSTCBPrioTbl[prio]的入口为0,以放弃该任务优先级。

6.然后,OSTaskCreate()调用OSTaskCreateHook(9),OSTaskCreateHook()是用户自己定义的函数,用来扩展OSTaskCreate()的功能,这一步可以有可以无,移植的时候是没有编写OSTaskCreateHook的,所以也没有调用这一函数。

7.如果OSTaskCreate()函数是在某个任务的指向过程中被调用,则任务调度函数会被调用(4)来判断是否新建立的任务比原来的人更高的优先级,如果新任务的优先级更高,内核会进行一次从旧任务到新任务的任务切换,如果在多任务调度开始之前,新任务就已经建立了,则任务调度函数OS_Sched()不会被调用。

经过以上7步,一个任务大致就创建好了,上面的程序中多次使用了这两句,非常重要,多次使用。OS_ENTER_CRITICAL();  //关中断  OS_EXIT_CRITICAL;//关中断

0 0