今天涂涂画画的时候发现我没有把一些重要的数据结构先做个说明,挺伤的。
等这章写完后一定补上。
好了,还是先上流程图。
嗯,可以看到OSInit()里调用了很多函数,这里只分析打绿色背景的函数;
至于其他的,像 OS_InitEventList(), OS_FlagInit(), OS_MemInit(), OS_QInit(),会在相关章节进行讨论。
首先,我们看OSInit( )在哪里出现。
1 #include "includes.h" 2 3 OS_STK AppStartTaskStk[APP_OS_CFG_START_TASK_STK_SIZE]; 4 5 static void App_TaskStart (void *p_arg); 6 7 8 int main (void) 9 { 10 INT8U err; 11 12 13 OSInit(); /* Initialize OS. */ 14 15 /* Create start task. */ 16 OSTaskCreateExt((void (*)(void *)) App_TaskStart, 17 (void * ) 0, 18 (OS_STK * )&AppStartTaskStk[APP_OS_CFG_START_TASK_STK_SIZE-1], 19 (INT8U ) APP_OS_CFG_START_TASK_PRIO, 20 (INT16U ) APP_OS_CFG_START_TASK_PRIO, 21 (OS_STK * )&AppStartTaskStk[0], 22 (INT32U ) APP_OS_CFG_START_TASK_STK_SIZE, 23 (void * ) 0, 24 (INT16U )(OS_TASK_OPT_STK_CHK | OS_TASK_OPT_STK_CLR)); 25 26 /* Give a name to tasks. */ 27 #if (OS_TASK_NAME_SIZE >= 6) 28 OSTaskNameSet(APP_OS_CFG_START_TASK_PRIO, "Start", &err); 29 #endif 30 #if (OS_TASK_NAME_SIZE >= 5) 31 OSTaskNameSet(OS_TASK_IDLE_PRIO, "Idle", &err); 32 #endif 33 #if ((OS_TASK_NAME_SIZE >= 5) && \ 34 (OS_TASK_STAT_EN > 0)) 35 OSTaskNameSet(OS_TASK_STAT_PRIO, "Stat", &err); 36 #endif 37 38 OSStart(); /* Start OS. */ 39 }
嗯,是在main()内出现,来对整个系统进行初始化,挺重要的。
接下来就开始肢解OSInit()了……
1、 OS_InitMisc()
这个函数的作用是实现对全局变量的初始化;Misc是miscellaneous的简写,杂项的意思。
这里都是些赋值语句。
注意一下line 7那个OSIntNesting,我在后面的中断中经常看到这货= =
1 static void OS_InitMisc (void) 2 { 3 #if OS_TIME_GET_SET_EN > 0 4 OSTime = 0L; /* Clear the 32-bit system clock */ 5 #endif 6 7 OSIntNesting = 0; /* Clear the interrupt nesting counter */ 8 OSLockNesting = 0; /* Clear the scheduling lock counter */ 9 10 OSTaskCtr = 0; /* Clear the number of tasks */ 11 12 OSRunning = OS_FALSE; /* Indicate that multitasking not started */ 13 14 OSCtxSwCtr = 0; /* Clear the context switch counter */ 15 OSIdleCtr = 0L; /* Clear the 32-bit idle counter */ 16 17 #if OS_TASK_STAT_EN > 0 18 OSIdleCtrRun = 0L; 19 OSIdleCtrMax = 0L; 20 OSStatRdy = OS_FALSE; /* Statistic task is not ready */ 21 #endif 22 }
2、OS_InitRdyList()
这个函数的作用是对就绪表进行初始化的工作 (ps: 这篇其实在2_0节之前写的,写到这儿突然觉得自己没把数据结构交代清楚,于是折回写数据结构,写了一星期- -。。)
该函数首先对就绪表和就绪组全部清零,然后初始化相关全局变量。
1 static void OS_InitRdyList (void) 2 { 3 INT8U i; 4 #if OS_LOWEST_PRIO <= 63 5 INT8U *prdytbl; 6 #else 7 INT16U *prdytbl; 8 #endif 9 10 11 OSRdyGrp = 0; /* Clear the ready list */ 12 prdytbl = &OSRdyTbl[0]; 13 for (i = 0; i < OS_RDY_TBL_SIZE; i++) { 14 *prdytbl++ = 0; 15 } 16 17 OSPrioCur = 0; 18 OSPrioHighRdy = 0; 19 20 OSTCBHighRdy = (OS_TCB *)0; 21 OSTCBCur = (OS_TCB *)0; 22 }
3、OS_InitTCBList()
该函数的任务就是初始化控制块链表。这个函数其实在2.0任务管理数据结构中提到过。
在有用户任务运行之前,因为没有用户任务就绪,就绪链表应该是个空链表。而空闲链表这时候应该是最长的,他的长度是操作系统能容纳的任务数。
ps:不知道你们会不会把空闲链表和空闲任务弄混T T,OSInit()里有初始化控制块链表的函数OS_InitTCBList(),也有创建空闲任务的函数OS_InitTaskIdle ( )
源码:
1 static void OS_InitTCBList (void) 2 { 3 INT8U i; 4 OS_TCB *ptcb1; 5 OS_TCB *ptcb2; 6 7 8 OS_MemClr((INT8U *)&OSTCBTbl[0], sizeof(OSTCBTbl)); /* Clear all the TCBs */ 9 OS_MemClr((INT8U *)&OSTCBPrioTbl[0], sizeof(OSTCBPrioTbl)); /* Clear the priority table */ 10 ptcb1 = &OSTCBTbl[0]; 11 ptcb2 = &OSTCBTbl[1]; 12 for (i = 0; i < (OS_MAX_TASKS + OS_N_SYS_TASKS - 1); i++) { /* Init. list of free TCBs */ 13 ptcb1->OSTCBNext = ptcb2; 14 #if OS_TASK_NAME_SIZE > 1 15 ptcb1->OSTCBTaskName[0] = '?'; /* Unknown name */ 16 ptcb1->OSTCBTaskName[1] = OS_ASCII_NUL; 17 #endif 18 ptcb1++; 19 ptcb2++; 20 } 21 ptcb1->OSTCBNext = (OS_TCB *)0; /* Last OS_TCB */ 22 #if OS_TASK_NAME_SIZE > 1 23 ptcb1->OSTCBTaskName[0] = '?'; /* Unknown name */ 24 ptcb1->OSTCBTaskName[1] = OS_ASCII_NUL; 25 #endif 26 OSTCBList = (OS_TCB *)0; /* TCB lists initializations */ 27 OSTCBFreeList = &OSTCBTbl[0]; 28 }
现在的我认识里面很多变量了,嘿嘿。
4、之后在#if/#end if的夹击中有很多函数,比如OS_InitEvenList()、OS_FlagInit()、OS_MemInit()、OS_QInit()这些,将会在接下来的相关章节中进行讨论。
5、 OS_InitTaskIdle ()
最后这个,是我曾经与控制块链表初始化函数OS_InitTCBList()搞混的函数。
为什么在这里要提到这个函数呢,因为它将创建和初始化整个系统的第一个任务——空闲任务。而在下一节,我们将分析一般的任务创建(将认识OSTaskCreate()和OSTaskCreateExt())。
上源码(OS_InitTaskIdle ()的):
1 static void OS_InitTaskIdle (void) 2 { 3 #if OS_TASK_NAME_SIZE > 7 4 INT8U err; 5 #endif 6 7 8 #if OS_TASK_CREATE_EXT_EN > 0 9 #if OS_STK_GROWTH == 1 10 (void)OSTaskCreateExt(OS_TaskIdle, 11 (void *)0, /* No arguments passed to OS_TaskIdle() */ 12 &OSTaskIdleStk[OS_TASK_IDLE_STK_SIZE - 1], /* Set Top-Of-Stack */ 13 OS_TASK_IDLE_PRIO, /* Lowest priority level */ 14 OS_TASK_IDLE_ID, 15 &OSTaskIdleStk[0], /* Set Bottom-Of-Stack */ 16 OS_TASK_IDLE_STK_SIZE, 17 (void *)0, /* No TCB extension */ 18 OS_TASK_OPT_STK_CHK | OS_TASK_OPT_STK_CLR);/* Enable stack checking + clear stack */ 19 #else 20 (void)OSTaskCreateExt(OS_TaskIdle, 21 (void *)0, /* No arguments passed to OS_TaskIdle() */ 22 &OSTaskIdleStk[0], /* Set Top-Of-Stack */ 23 OS_TASK_IDLE_PRIO, /* Lowest priority level */ 24 OS_TASK_IDLE_ID, 25 &OSTaskIdleStk[OS_TASK_IDLE_STK_SIZE - 1], /* Set Bottom-Of-Stack */ 26 OS_TASK_IDLE_STK_SIZE, 27 (void *)0, /* No TCB extension */ 28 OS_TASK_OPT_STK_CHK | OS_TASK_OPT_STK_CLR);/* Enable stack checking + clear stack */ 29 #endif 30 #else 31 #if OS_STK_GROWTH == 1 32 (void)OSTaskCreate(OS_TaskIdle, 33 (void *)0, 34 &OSTaskIdleStk[OS_TASK_IDLE_STK_SIZE - 1], 35 OS_TASK_IDLE_PRIO); 36 #else 37 (void)OSTaskCreate(OS_TaskIdle, 38 (void *)0, 39 &OSTaskIdleStk[0], 40 OS_TASK_IDLE_PRIO); 41 #endif 42 #endif 43 44 #if OS_TASK_NAME_SIZE > 14 45 OSTaskNameSet(OS_TASK_IDLE_PRIO, (INT8U *)"uC/OS-II Idle", &err); 46 #else 47 #if OS_TASK_NAME_SIZE > 7 48 OSTaskNameSet(OS_TASK_IDLE_PRIO, (INT8U *)"OS-Idle", &err); 49 #endif 50 #endif 51 }
我们可以看到,line10、20、32、37,有我们提到过的OSTaskCreate()和OSTaskCreateExt(),算先混个脸熟吧,哈哈。