*prdytbl++=0;
}
OSPrioCur=0;
OSPrioHighRdy=0;
OSTCBHighRdy=(OS_TCB*)0;
OSTCBCur=(OS_TCB*)0;
}
首先将OSRdyTbl[]数组中全部初始化0,同时将OSPrioCur/OSTCBCur初始化为0,OSPrioHighRdy/OSTCBHighRdy也初始化为0。
4.OS_InitTCBList(void)在OS_CORE.C中
功能:
初始化TCB列表
static void OS_InitTCBList(void)
{
INT8U i;
OS_TCB *ptcb1;
OS_TCB *ptcb2;
OS_MemClr((INT8U*)&OSTCBTbl[0], sizeof(OSTCBTbl));
OS_MemClr((INT8U*)&OSTCBPrioTbl[0],sizeof(OSTCBPrioTbl));
ptcb1=&OSTCBTbl[0];
ptcb2=&OSTCBTbl[1];
for(i=0;i<(OS_MAX_TASKS+OS_N_SYS_TASKS-1);i++){
ptcb1->OSTCBNext=ptcb2;
#ifOS_TASK_NAME_SIZE>1
ptcb1->OSTCBTaskName[0]='?
';
ptcb1->OSTCBTaskName[1]=OS_ASCII_NUL;
#endif
ptcb1++;
ptcb2++;
}
ptcb1->OSTCBNext=(OS_TCB*)0;
#ifOS_TASK_NAME_SIZE>1
ptcb1->OSTCBTaskName[0]='?
';
ptcb1->OSTCBTaskName[1]=OS_ASCII_NUL;
#endif
OSTCBList =(OS_TCB*)0;
OSTCBFreeList =&OSTCBTbl[0];
}
首先把整个数组使用OSTCBNext指针连接成链表链起来,然后将OSTCBList初始化为0,也就是还没有TCB,因为还没有Task产生,OSTCBFreeList指向OSTCBTbl[]数组的第一个表示所有TCB都处于Free状态。
5.OS_InitEventList()在OS_CORE.C中
功能:
初始化Event列表。
static void OS_InitEventList(void)
{
#ifOS_EVENT_EN&&(OS_MAX_EVENTS>0)
#if(OS_MAX_EVENTS>1)
INT16U i;
OS_EVENT *pevent1;
OS_EVENT *pevent2;
OS_MemClr((INT8U*)&OSEventTbl[0],sizeof(OSEventTbl));
pevent1=&OSEventTbl[0];
pevent2=&OSEventTbl[1];
for(i=0;i<(OS_MAX_EVENTS-1);i++){
pevent1->OSEventType =OS_EVENT_TYPE_UNUSED;
pevent1->OSEventPtr =pevent2;
#ifOS_EVENT_NAME_SIZE>1
pevent1->OSEventName[0]='?
';
pevent1->OSEventName[1]=OS_ASCII_NUL;
#endif
pevent1++;
pevent2++;
}
pevent1->OSEventType =OS_EVENT_TYPE_UNUSED;
pevent1->OSEventPtr =(OS_EVENT*)0;
#ifOS_EVENT_NAME_SIZE>1
pevent1->OSEventName[0] ='?
';
pevent1->OSEventName[1] =OS_ASCII_NUL;
#endif
OSEventFreeList =&OSEventTbl[0];
#else
OSEventFreeList =&OSEventTbl[0];
OSEventFreeList->OSEventType =OS_EVENT_TYPE_UNUSED;
OSEventFreeList->OSEventPtr =(OS_EVENT*)0;
#ifOS_EVENT_NAME_SIZE>1
OSEventFreeList->OSEventName[0]='?
';
OSEventFreeList->OSEventName[1]=OS_ASCII_NUL;
#endif
#endif
#endif
}
将EventTbl[]数组中的OSEventType都初始化为OS_EVENT_TYPE_UNUSED。
OS_InitTaskIdle()
跳过其他的如Mem等的初始化,看看IdleTask的初始化。
(void)OSTaskCreateExt(OS_TaskIdle,
(void*)0,
&OSTaskIdleStk[OS_TASK_IDLE_STK_SIZE-1],
OS_IDLE_PRIO,
OS_TASK_IDLE_ID,
&OSTaskIdleStk[0],
OS_TASK_IDLE_STK_SIZE,
(void*)0,
OS_TASK_OPT_STK_CHK|OS_TASK_OPT_STK_CLR);
IdleTask的初始化是调用OSTaskCrete系列的函数创建一个Task
初始化StateTask也是类似调用OSTaskCreate系列函数创建StatTask。
这里只是创建了该Task的各个结构还没有真正运行该Task,直到OSStart中才依据优先级调度运行。
6.OS_FlagInit()
OS_FlagInit()是uc/os内部函数,应用程序不得调用该函数
7.OS_MemInit()
OS_MemInit()作用是初始化动态内存
(二)
OSTaskCreateExt
OSTaskCreateExt负责创建Task所需的数据结构,该函数原形如下所示:
OSTaskCreateExt((void(*)(void*))App_TaskStart,/*指向任务代码指针*/
(void*)0,/*指向一个传递参数的数据块*/
(OS_STK*)&App_TaskStartStk[APP_CFG_TASK_START_STK_SIZE-1],/*指向堆栈栈顶*/
(INT8U)APP_CFG_TASK_START_PRIO,/*任务优先级*/
(INT16U)APP_CFG_TASK_START_PRIO,/*任务标示(暂时不用的)*/
(OS_STK*)&App_TaskStartStk[0],/*指向栈底*/
(INT32U)APP_CFG_TASK_START_STK_SIZE,/*堆栈大小*/
(void*)0,/*定义数据指针*/
(INT8U)(OS_TASK_OPT_STK_CHK|OS_TASK_OPT_STK_CLR));/*进行任务堆栈检查,清空堆栈*/
OSTaskCreateExt函数的执行流程:
(在OS_TASK.C中)
#ifOS_ARG_CHK_EN>0
if(prio>OS_LOWEST_PRIO){
if(prio>OS_LOWEST_PRIO);
}
#endif
OS_ENTER_CRITICAL();
if(OSIntNesting>0){
OS_EXIT_CRITICAL();
return(OS_ERR_TASK_CREATE_ISR);
}
if(OSTCBPrioTbl[prio]==(OS_TCB*)0){
OSTCBPrioTbl[prio]=(OS_TCB*)1;
OS_EXIT_CRITICAL();
psp=OSTaskStkInit(task,p_arg,ptos,0);
err=OS_TCBInit(prio,psp,(OS_STK*)0,0,0,(void*)0,0);
if(err==OS_ERR_NONE){
if(OSRunning==OS_TRUE){
OS_Sched();
}
}else{
OS_ENTER_CRITICAL();
OSTCBPrioTbl[prio]=(OS_TCB*)0;
OS_EXIT_CRITICAL();
}
return(err);
}
OS_EXIT_CRITICAL();
return(OS_PRIO_EXIST);
OS_LOWEST_PRIO在ucos-ii.h中被定义为63,表示Task的优先级从0到63,共64级。
首先判断prio是否超过最低优先级,如果是,则返回OS_PRIO_INVALID错误。
然后调用OS_ENTER_CRITICAL(),进入临界段,在临界段中的代码执行不允许被中断。
这个宏是自定义的,一般是进行关中断操作。
这个宏和OS_EXIT_CRITICAL()相对应,这个宏表示离开临界段。
OSTaskCreate不允许在中断中调用,因此会判断OSIntNesting是否大于0,如果大于0,表示正在中断嵌套,返回OS_ERR_TASK_CREATE_ISR错误。
接着判断该prio是否已经有Task存在,由于uC/OS-II只支持每一个优先级一个Task,因此如果该prio已经有进程存在,OSTaskCreate会返回OS_PRIO_EXIST错误。
相反,如果该prio先前没有Task存在,则将OSTCBPrioTbl[prio]置1,表示该prio已被占用,然后调用OSTaskStkInit初始化堆栈,调用OS_TCBInit初始化TCB,如果OSRunning为TRUE表示OS正在运行,则调用OS_Sched进行进程调度;否则返回。
关于OSTaskStkInit和OS_TCBInit这两个函数。
OSTaskStkInit是一个用户自定义的函数,因为uC/OS-II在设计时无法知道当前处理器在进行进程调度时需要保存哪些信息,OSTaskStkInit就是初始化堆栈,让Task看起来就好像刚刚进入中断并保存好寄存器的值一样,当OS_Sched调度到该Task时,只需切换到该堆栈中,将寄存器值Pop出来,然后执行一个中断返回指令IRET即可。
OSTaskStkInit的原型如下:
OS_STK*OSTaskStkInit(void(*task)(void*pd),void*pdata,OS_STK*ptos,INT16Uopt)
和OSTaskCreate类似,task是进程入口地址,pdata是参数地址,ptos是堆栈指针,而opt只是作为一个预留的参数Option而保留。
返回的是调整以后的堆栈指针。
在OSTaskStkInit中,一般是将pdata入栈,flag入栈,task入栈,然后将各寄存器依次入栈。
OS_TCBInit初始化TCB数据结构,下面只提取主要部分来看:
INT8U OS_TCBInit(INT8Uprio,OS_STK*ptos,OS_STK*pbos,INT16Uid,INT32Ustk_size,void*pext,INT16Uopt)
{
OS_TCB *ptcb;
#ifOS_CRITICAL_METHOD==3
OS_CPU_SRcpu_sr=0;
#endif
OS_ENTER_CRITICAL();
ptcb=OSTCBFreeList;
if(ptcb!
=(OS_TCB*)0){
OSTCBFreeList =ptcb->OSTCBNext;
OS_EXIT_CRITICAL();
ptcb->OSTCBStkPtr =ptos;
ptcb->OSTCBPrio =prio;
ptcb->OSTCBStat =OS_STAT_RDY;
ptcb->OSTCBStatPend=