建立任务,OSTaskCreateExt()

用OSTaskCreateExt()函数来建立任务会更加灵活,但会增加一些额外的开销。OSTaskCreateExt()函数的代码如程序清单 L4.3所示。
	我们可以看到OSTaskCreateExt()需要九个参数!前四个参数(task,pdata,ptos和prio)与OSTaskCreate()的四个参数完全相同,连先后顺序都一样。这样做的目的是为了使用户能够更容易地将用户的程序从OSTaskCreate()移植到OSTaskCreateExt()上去。
	id参数为要建立的任务创建一个特殊的标识符。该参数在µC/OS以后的升级版本中可能会用到,但在µC/OS-Ⅱ中还未使用。这个标识符可以扩展µC/OS-Ⅱ功能,使它可以执行的任务数超过目前的64个。但在这里,用户只要简单地将任务的id设置成与任务的优先级一样的值就可以了。
	pbos是指向任务的堆栈栈底的指针,用于堆栈的检验。
	stk_size用于指定堆栈成员数目的容量。也就是说,如果堆栈的入口宽度为4字节宽,那么stk_size为10000是指堆栈有40000个字节。该参数与pbos一样,也用于堆栈的检验。
	pext是指向用户附加的数据域的指针,用来扩展任务的OS_TCB。例如,用户可以为每个任务增加一个名字(参看实例3),或是在任务切换过程中将浮点寄存器的内容储存到这个附加数据域中,等等。
	opt用于设定OSTaskCreateExt()的选项,指定是否允许堆栈检验,是否将堆栈清零,任务是否要进行浮点操作等等。µCOS_Ⅱ.H文件中有一个所有可能选项(OS_TASK_OPT_STK_CHK,OS_TASK_OPT_STK_CLR和OS_TASK_OPT_SAVE_FP)的常数表。每个选项占有opt的一位,并通过该位的置位来选定(用户在使用时只需要将以上OS_TASK_OPT_???选项常数进行位或(OR)操作就可以了)。

程序清单 L 4.3	OSTaskCreateExt()
INT8U OSTaskCreateExt (void   (*task)(void *pd),
                       void    *pdata,
                       OS_STK  *ptos,                       INT8U    prio,
                       INT16U   id,
                       OS_STK  *pbos,
                       INT32U   stk_size,
                       void    *pext,
                       INT16U   opt)
{
    void    *psp;
    INT8U    err;
    INT16U   i;
    OS_STK  *pfill;


    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)

        if (opt & OS_TASK_OPT_STK_CHK) {	                              (5)
            if (opt & OS_TASK_OPT_STK_CLR) {
                Pfill = pbos;
                for (i = 0; i < stk_size; i++) {
                    #if OS_STK_GROWTH == 1
                    *pfill++ = (OS_STK)0;
                    #else
                    *pfill-- = (OS_STK)0;
                    #endif
                }
            }
        }
        psp = (void *)OSTaskStkInit(task, pdata, ptos, opt);	          (6)
        err = OSTCBInit(prio, psp, pbos, id, stk_size, pext, opt);	    (7)        if (err == OS_NO_ERR) {	                                       (8)
            OS_ENTER_CRITICAL;
            OSTaskCtr++;	                                              (9)
            OSTaskCreateHook(OSTCBPrioTbl[prio]);	                    (10)
            OS_EXIT_CRITICAL();
            if (OSRunning) {	                                         (11)
                OSSched();	                                           (12)
            }
        } else {
            OS_ENTER_CRITICAL();
            OSTCBPrioTbl[prio] = (OS_TCB *)0;	                        (13)
            OS_EXIT_CRITICAL();
        }
        return (err);
    } else {
        OS_EXIT_CRITICAL();
        return (OS_PRIO_EXIST);
    }
}

	OSTaskCreateExt()一开始先检测分配给任务的优先级是否有效[L4.3(1)]。任务的优先级必须在0到OS_LOWEST_PRIO之间。接着,OSTaskCreateExt()要确保在规定的优先级上还没有建立任务[L4.3(2)]。在使用µC/OS-Ⅱ时,每个任务都有特定的优先级。如果某个优先级是空闲的,µC/OS-Ⅱ通过放置一个非空指针在OSTCBPrioTbl[]中来保留该优先级[L4.3(3)]。这就使得OSTaskCreateExt()在设置任务数据结构的其他部分时能重新允许中断[L4.3(4)]。
	为了对任务的堆栈进行检验[参看4.03,堆栈检验,OSTaskStkChk()],用户必须在opt参数中设置OS_TASK_OPT_STK_CHK标志。堆栈检验还要求在任务建立时堆栈的存储内容都是0(即堆栈已被清零)。为了在任务建立的时候将堆栈清零,需要在opt参数中设置OS_TASK_OPT_STK_CLR。当以上两个标志都被设置好后,OSTaskCreateExt()才能将堆栈清零[L4.3(5)]。
	接着,OSTaskCreateExt()调用OSTaskStkInit()[L4.3(6)],它负责建立任务的堆栈。该函数是与处理器的硬件体系相关的函数,可以在OS_CPU_C.C文件中找到。有关实现OSTaskStkInit()的细节可参看第八章——移植µC/OS-Ⅱ。如果已经有人在你用的处理器上成功地移植了µC/OS-Ⅱ,而你又得到了他的代码,就不必考虑该函数的实现细节了。OSTaskStkInit()函数返回新的堆栈栈顶(psp),并被保存在任务的0S_TCB中。
	µC/OS-Ⅱ支持的处理器的堆栈既可以从上(高地址)往下(低地址)递减也可以从下往上递增(参看4.02,任务堆栈)。用户在调用OSTaskCreateExt()的时候必须知道堆栈是递增的还是递减的(参看用户所用处理器的OS_CPU.H中的OS_STACK_GROWTH),因为用户必须得把堆栈的栈顶传递给OSTaskCreateExt(),而栈顶可能是堆栈的最低地址(当OS_STK_GROWTH为0时),也可能是最高地址(当OS_STK_GROWTH为1时)。
	一旦OSTaskStkInit()函数完成了建立堆栈的任务,OSTaskCreateExt()就调用OSTCBInit() [L4.3(7)],从空闲的OS_TCB缓冲池中获得并初始化一个OS_TCB。OSTCBInit()的代码在OSTaskCreate()中曾描述过(参看4.00节), 从OSTCBInit()返回后,OSTaskCreateExt()要检验返回代码[L4.3(8)],如果成功,就增加OSTaskCtr[L4.3(9)],OSTaskCtr用于保存产生的任务数目。如果OSTCBInit()返回失败,就置OSTCBPrioTbl[prio]的入口为0[L4.3(13)]以放弃对该任务优先级的占用。然后,OSTaskCreateExt()调用OSTaskCreateHook()[L4.3(10)],OSTaskCreateHook()是用户自己定义的函数,用来扩展OSTaskCreateExt()的功能。OSTaskCreateHook()可以在OS_CPU_C.C中定义(如果OS_CPU_HOOKS_EN置1),也可以在其它地方定义(如果OS_CPU_HOOKS_EN置0)。注意,OSTaskCreateExt()在调用OSTaskCreateHook()时,中断是关掉的,所以用户应该使OSTaskCreateHook()函数中的代码尽量简化,因为这将直接影响中断的响应时间。OSTaskCreateHook()被调用时会收到指向任务被建立时的OS_TCB的指针。这意味着该函数可以访问OS_TCB数据结构中的所有成员。
	如果OSTaskCreateExt()函数是在某个任务的执行过程中被调用的(即OSRunning置为True[L4.3(11)]),以任务调度函数会被调用[L4.3(12)]来判断是否新建立的任务比原来的任务有更高的优先级。如果新任务的优先级更高,内核会进行一次从旧任务到新任务的任务切换。如果在多任务调度开始之前(即用户还没有调用OSStart()),新任务就已经建立了,则任务调度函数不会被调用。

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值