#ucos# #ucos创建任务#
嵌入式初学者入门(2) Ucos II 创建第一个任务之二
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(); //开中断 |
查看评论 回复