建立任务,OSTaskCreate()
想让µC/OS-Ⅱ管理用户的任务,用户必须要先建立任务。用户可以通过传递任务地址和其它参数到以下两个函数之一来建立任务:OSTaskCreate() 或 OSTaskCreateExt()。OSTaskCreate()与µC/OS是向下兼容的,OSTaskCreateExt()是OSTaskCreate()的扩展版本,提供了一些附加的功能。用两个函数中的任何一个都可以建立任务。任务可以在多任务调度开始前建立,也可以在其它任务的执行过程中被建立。在开始多任务调度(即调用OSStart())前,用户必须建立至少一个任务。任务不能由中断服务程序(ISR)来建立。
OSTaskCreate()的代码如下程序。从中可以知道,OSTaskCreate()需要四个参数:task是任务代码的指针,pdata是当任务开始执行时传递给任务的参数的指针,ptos是分配给任务的堆栈的栈顶指针,prio是分配给任务的优先级。
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); |
} |
} |
建立任务,OSTaskCreateExt()
用OSTaskCreateExt()函数来建立任务会更加灵活,但会增加一些额外的开销。OSTaskCreateExt()函数的代码如程序。
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。例如,用户可以为每个任务增加一个名字,或是在任务切换过程中将浮点寄存器的内容储存到这个附加数据域中,等等。
opt用于设定OSTaskCreateExt()的选项,指定是否允许堆栈检验,是否将堆栈清零,任务是否要进行浮点操作等等。µCOS_Ⅱ.H文件中有一个所有可能选项(OS_TASK_OPT_STK_CHK,OS_TASK_OPT_STK_CLR和OS_TASK_OPT_SAVE_FP)的常数表。每个选项占有opt的一位,并通过该位的置位来选定(用户在使用时只需要将以上OS_TASK_OPT_???选项常数进行位或(OR)操作就可以了)。
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); |
} |
} |
UCOS_II基础入门:
扫一扫关注微信公众号,获取更多实时的嵌入式资讯,嵌入式学习指导方法,汽车电子最新资讯等。