上回说到,创建操作系统空闲任务的函数OS_InitTaskIdle()中,分别有两个函数OSTaskCreate(),和OSTaskCreateExt(),负责任务的创建。
这一节的主角,便是这两个函数。
先上一张表
只有四个函数待认识。
1、OSTaskCreate()
源码:
1 #if OS_TASK_CREATE_EN > 0 2 INT8U OSTaskCreate (void (*task)(void *p_arg), void *p_arg, OS_STK *ptos, INT8U prio) 3 { 4 OS_STK *psp; 5 INT8U err; 6 #if OS_CRITICAL_METHOD == 3 /* Allocate storage for CPU status register */ 7 OS_CPU_SR cpu_sr = 0; 8 #endif 9 10 11 12 #if OS_ARG_CHK_EN > 0 13 if (prio > OS_LOWEST_PRIO) { /* Make sure priority is within allowable range */ 14 return (OS_ERR_PRIO_INVALID); 15 } 16 #endif 17 OS_ENTER_CRITICAL(); 18 if (OSIntNesting > 0) { /* Make sure we don't create the task from within an ISR */ 19 OS_EXIT_CRITICAL(); 20 return (OS_ERR_TASK_CREATE_ISR); 21 } 22 if (OSTCBPrioTbl[prio] == (OS_TCB *)0) { /* Make sure task doesn't already exist at this priority */ 23 OSTCBPrioTbl[prio] = OS_TCB_RESERVED;/* Reserve the priority to prevent others from doing ... */ 24 /* ... the same thing until task is created. */ 25 OS_EXIT_CRITICAL(); 26 psp = OSTaskStkInit(task, p_arg, ptos, 0); /* Initialize the task's stack */ 27 err = OS_TCBInit(prio, psp, (OS_STK *)0, 0, 0, (void *)0, 0); 28 if (err == OS_ERR_NONE) { 29 if (OSRunning == OS_TRUE) { /* Find highest priority task if multitasking has started */ 30 OS_Sched(); 31 } 32 } else { 33 OS_ENTER_CRITICAL(); 34 OSTCBPrioTbl[prio] = (OS_TCB *)0;/* Make this priority available to others */ 35 OS_EXIT_CRITICAL(); 36 } 37 return (err); 38 } 39 OS_EXIT_CRITICAL(); 40 return (OS_ERR_PRIO_EXIST); 41 } 42 #endif
在第26行,看到了任务堆栈初始化函数OSTaskStkInit()。
任务创建流程图流程图:
附,OSTaskStkInit()的源码
1 OS_STK *OSTaskStkInit (void (*task)(void *pd), void *pdata, OS_STK *ptos, INT16U opt) 2 { 3 OS_EMU_STK *stk; 4 5 stk = (OS_EMU_STK *)((char*)ptos-sizeof(OS_EMU_STK)); /* Load stack pointer */ 6 stk->pData = pdata; 7 stk->Opt = opt; 8 stk->Task = task; 9 stk->Handle = NULL; 10 stk->Id = 0; 11 stk->Exit = 0; 12 13 return ((void *)stk); 14 }
2、OSTaskCreateExt()
其实这两个任务创建函数没有太大的区别,只是OSTaskCreateExt()多了一个堆栈检查的功能而已。
源码:
1 #if OS_TASK_CREATE_EXT_EN > 0 2 INT8U OSTaskCreateExt (void (*task)(void *p_arg), 3 void *p_arg, 4 OS_STK *ptos, 5 INT8U prio, 6 INT16U id, 7 OS_STK *pbos, 8 INT32U stk_size, 9 void *pext, 10 INT16U opt) 11 { 12 OS_STK *psp; 13 INT8U err; 14 #if OS_CRITICAL_METHOD == 3 /* Allocate storage for CPU status register */ 15 OS_CPU_SR cpu_sr = 0; 16 #endif 17 18 19 20 #if (OS_TASK_STAT_STK_CHK_EN > 0) && (OS_TASK_CREATE_EXT_EN > 0) 21 void OS_TaskStkClr (OS_STK *pbos, INT32U size, INT16U opt) 22 { 23 if ((opt & OS_TASK_OPT_STK_CHK) != 0x0000) { /* See if stack checking has been enabled */ 24 if ((opt & OS_TASK_OPT_STK_CLR) != 0x0000) { /* See if stack needs to be cleared */ 25 #if OS_STK_GROWTH == 1 26 while (size > 0) { /* Stack grows from HIGH to LOW memory */ 27 size--; 28 *pbos++ = (OS_STK)0; /* Clear from bottom of stack and up! */ 29 } 30 #else 31 while (size > 0) { /* Stack grows from LOW to HIGH memory */ 32 size--; 33 *pbos-- = (OS_STK)0; /* Clear from bottom of stack and down */ 34 } 35 #endif 36 } 37 } 38 }
OSTaskCreateExt()中包含了OS_TaskStkClr()的源码,就是第20行和38行之间
接下来的内容还是在OSTaskCreateExt()内……
1 #if OS_ARG_CHK_EN > 0 2 if (prio > OS_LOWEST_PRIO) { /* Make sure priority is within allowable range */ 3 return (OS_ERR_PRIO_INVALID); 4 } 5 #endif 6 OS_ENTER_CRITICAL(); 7 if (OSIntNesting > 0) { /* Make sure we don't create the task from within an ISR */ 8 OS_EXIT_CRITICAL(); 9 return (OS_ERR_TASK_CREATE_ISR); 10 } 11 if (OSTCBPrioTbl[prio] == (OS_TCB *)0) { /* Make sure task doesn't already exist at this priority */ 12 OSTCBPrioTbl[prio] = OS_TCB_RESERVED;/* Reserve the priority to prevent others from doing ... */ 13 /* ... the same thing until task is created. */ 14 OS_EXIT_CRITICAL(); 15 16 #if (OS_TASK_STAT_STK_CHK_EN > 0) 17 OS_TaskStkClr(pbos, stk_size, opt); /* Clear the task stack (if needed) */ 18 #endif 19 20 psp = OSTaskStkInit(task, p_arg, ptos, opt); /* Initialize the task's stack */ 21 err = OS_TCBInit(prio, psp, pbos, id, stk_size, pext, opt); 22 if (err == OS_ERR_NONE) { 23 if (OSRunning == OS_TRUE) { /* Find HPT if multitasking has started */ 24 OS_Sched(); 25 } 26 } else { 27 OS_ENTER_CRITICAL(); 28 OSTCBPrioTbl[prio] = (OS_TCB *)0; /* Make this priority avail. to others */ 29 OS_EXIT_CRITICAL(); 30 } 31 return (err); 32 } 33 OS_EXIT_CRITICAL(); 34 return (OS_ERR_PRIO_EXIST); 35 } 36 #endif
可以看到,在堆栈初始化之前(第20行),调用了堆栈检查函数(第17行)。
流程图
所谓不同,仅是用蓝框标出来的部分而已。
最后重申三点:
1、OSTaskCreateExt()只是比OSTaskCreate()增加了堆栈清除的功能,其他并无太大区别;
2、堆栈清除函数只是为堆栈检查做准备的;
3、系统默认的任务创建函数是OSTaskCreateExt()。