ucos II 创建第一个任务之二

来源:互联网 发布:sql注入错误 编辑:程序博客网 时间:2024/06/06 19:39

 Ucos II 创建第一个任务之二

下面具体讲解下任务创建的过程

下图就是创建任务函数的实现程序。

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_CRITICAL();

        return (OS_PRIO_EXIST);

    }

}

 

    1.OSTaskCreate()一开始先检测分配给任务的优先级是否有效[L4.1(1)]。任务的优先级必须在0到OS_LOWSEST_PRIO之间。OS_LOWSEST_PRIO的定义是在os_cfg.h这个文件,定义如下:#define  OS_LOWEST_PRIO   12  。这个地方mcu21就有些搞不懂,为什么不是64,而是12?有明白的可以告知mcu21同学。

2.接着,OSTaskCreate()要确保在规定的优先级上还没有建立任务[L4.1(2)]。在使用μC/OS-Ⅱ时,每个任务都有特定的优先级。如果某个优先级是空闲未使用的,μC/OS-Ⅱ通过放置一个非空指针在OSTCBPrioTbl[]中来保留该优先级[L4.1(3)]。这就使得OSTaskCreate()在设置任务数据结构的其他部分时能重新允许中断[L4.1(4)]。

    3.然后,OSTaskCreate()调用OSTaskStkInit()[L4.1(5)],它负责建立任务的堆栈。没错,就是OSTaskStkInit(),系统移植时候,我们辛辛苦苦在OS_CPU_C.C编写了它,原来是跑到这里耀武扬威来了。OSTaskStkInit()函数返回新的堆栈栈顶(psp),并被保存在任务的0S_TCB中。注意用户必须将传递给OSTaskStkInit()函数的第四个参数opt置0,因为OSTaskCreate()与OSTaskCreateExt()不同,它不支持用户为任务的创建过程设置不同的选项,所以没有任何选项可以通过opt参数传递给OSTaskStkInit()。

    4.一旦OSTaskStkInit()函数完成了建立堆栈的任务,OSTaskCreate()就调用OSTCBInit()[L4.1(6)],这也是任务创建的核心,从空闲的OS_TCB池中获得并初始化一个OS_TCB。OSTCBInit()函数首先从OS_TCB缓冲池中获得一个OS_TCB,如果OS_TCB池中有空闲的OS_TCB,它就被初始化。注意一旦OS_TCB被分配,该任务的创建者就已经完全拥有它了,即使这时内核又创建了其它的任务,这些新任务也不可能对已分配的OS_TCB作任何操作,所以OSTCBInit()在这时就可以允许中断,并继续初始化OS_TCB的数据单元。

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

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

   7. 如果OSTaskCreate()函数是在某个任务的执行过程中被调用(即OSRunning置为True[L4.1(10)]),则任务调度函数会被调用[L4.1(11)]来判断是否新建立的任务比原来的任务有更高的优先级。如果新任务的优先级更高,内核会进行一次从旧任务到新任务的任务切换。如果在多任务调度开始之前(即用户还没有调用OSStart()),新任务就已经建立了,则任务调度函数OS_Sched()不会被调用。

   经过以上7步,一个任务大致就创建好了。

   上面程序中多次使用了这两句程序,非常重要,多次使用。

            OS_ENTER_CRITICAL();    //关中断

 

            OS_EXIT_CRITICAL();   //开中断


0 0
原创粉丝点击