⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ucos-ii源码分析.c

📁 ucosII源码分析
💻 C
📖 第 1 页 / 共 3 页
字号:
uC/OS-II源码分析
在这里我不想分模块来慢慢分析这个OS的行为,我们从CPU的执行顺序来看吧,这样也许清晰一些,并且我们暂时抛弃那些Event/MailBox、信号量等元素,还是先看看作为一个OS核心的Task Schedule部分内容吧。
首先从main函数开始,下面是uC/OS-II main函数的大致流程:
main(){
 OSInit();
 TaskCreate(...);
 OSStart();
}
首先是调用OSInit进行初始化,然后使用TaskCreate创建几个进程/Task,最后调用OSStart,操作系统就开始运行了。
 
OSInit
 
最先看看OSInit完成哪些初始化:
void  OSInit (void)
{
#if OS_VERSION >= 204
    OSInitHookBegin();                                           /* Call port specific initialization code   */
#endif
    OS_InitMisc();                                               /* Initialize miscellaneous variables       */
    OS_InitRdyList();                                            /* Initialize the Ready List                */
    OS_InitTCBList();                                            /* Initialize the free list of OS_TCBs      */
    OS_InitEventList();                                          /* Initialize the free list of OS_EVENTs    */
#if (OS_VERSION >= 251) && (OS_FLAG_EN > 0) && (OS_MAX_FLAGS > 0)
    OS_FlagInit();                                               /* Initialize the event flag structures     */
#endif
#if (OS_MEM_EN > 0) && (OS_MAX_MEM_PART > 0)
    OS_MemInit();                                                /* Initialize the memory manager            */
#endif
#if (OS_Q_EN > 0) && (OS_MAX_QS > 0)
    OS_QInit();                                                  /* Initialize the message queue structures  */
#endif
    OS_InitTaskIdle();                                           /* Create the Idle Task                     */
#if OS_TASK_STAT_EN > 0
    OS_InitTaskStat();                                           /* Create the Statistic Task                */
#endif
#if OS_VERSION >= 204
    OSInitHookEnd();                                             /* Call port specific init. code            */
#endif
#if OS_VERSION >= 270 && OS_DEBUG_EN > 0
    OSDebugInit();
#endif
}
OS_InitMisc()完成的是一些其其他他的变量的初始化:
    OSIntNesting  = 0;                                     /* Clear the interrupt nesting counter      */
    OSLockNesting = 0;                                     /* Clear the scheduling lock counter        */
    OSTaskCtr     = 0;                                     /* Clear the number of tasks                */
    OSRunning     = FALSE;                                 /* Indicate that multitasking not started   */
    
    OSCtxSwCtr    = 0;                                     /* Clear the context switch counter         */
    OSIdleCtr     = 0L;                                    /* Clear the 32-bit idle counter            */
其中包括:中断嵌套标志OSIntNesting,调度锁定标志OSLockNesting,OS标志OSRunning等。OSRunning在这里设置为FALSE,在后面OSStartHighRdy中会被设置为TRUE表示OS开始工作。
OS_InitRdyList()初始化就绪Task列表:
static  void  OS_InitRdyList (void)
{
    INT8U    i;
    INT8U   *prdytbl;

    OSRdyGrp      = 0x00;                                  /* Clear the ready list                     */
    prdytbl       = &OSRdyTbl[0];
    for (i = 0; i < OS_RDY_TBL_SIZE; i++) {
        *prdytbl++ = 0x00;
    }
    OSPrioCur     = 0;
    OSPrioHighRdy = 0;
    OSTCBHighRdy  = (OS_TCB *)0;                                 
    OSTCBCur      = (OS_TCB *)0;
}
首先将OSRdyTbl[]数组中全部初始化0,同时将OSPrioCur/OSTCBCur初始化为0,OSPrioHighRdy/OSTCBHighRdy也初始化为0,这几个变量将在第一个OSSchedule中被赋予正确的值。
OS_InitTCBList()这个函数看名称我们就知道是初始化TCB列表。
static  void  OS_InitTCBList (void)
{
    INT8U    i;
    OS_TCB  *ptcb1;
    OS_TCB  *ptcb2;

    OS_MemClr((INT8U *)&OSTCBTbl[0],     sizeof(OSTCBTbl));      /* Clear all the TCBs                 */
    OS_MemClr((INT8U *)&OSTCBPrioTbl[0], sizeof(OSTCBPrioTbl));  /* Clear the priority table           */
    ptcb1 = &OSTCBTbl[0];
    ptcb2 = &OSTCBTbl[1];
    for (i = 0; i < (OS_MAX_TASKS + OS_N_SYS_TASKS - 1); i++) {  /* Init. list of free TCBs            */
        ptcb1->OSTCBNext = ptcb2;
#if OS_TASK_NAME_SIZE > 1
        ptcb1->OSTCBTaskName[0] = '?';                           /* Unknown name                       */
        ptcb1->OSTCBTaskName[1] = OS_ASCII_NUL;
#endif
        ptcb1++;
        ptcb2++;
    }
    ptcb1->OSTCBNext = (OS_TCB *)0;                              /* Last OS_TCB                        */
#if OS_TASK_NAME_SIZE > 1
    ptcb1->OSTCBTaskName[0] = '?';                               /* Unknown name                       */
    ptcb1->OSTCBTaskName[1] = OS_ASCII_NUL;
#endif
    OSTCBList               = (OS_TCB *)0;                       /* TCB lists initializations          */
    OSTCBFreeList           = &OSTCBTbl[0];
}
这里完成的工作很简单,首先把整个数组使用OSTCBNext指针连接成链表链起来,然后将OSTCBList初始化为0,也就是还没有TCB,因为还没有Task产生,OSTCBFreeList指向OSTCBTbl[]数组的第一个表示所有TCB都处于Free状态。
OS_InitEventList()初始化Event列表。
static  void  OS_InitEventList (void)
{
#if OS_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)); /* Clear the event table                   */
    pevent1 = &OSEventTbl[0];
    pevent2 = &OSEventTbl[1];
    for (i = 0; i < (OS_MAX_EVENTS - 1); i++) {             /* Init. list of free EVENT control blocks */
        pevent1->OSEventType    = OS_EVENT_TYPE_UNUSED;
        pevent1->OSEventPtr     = pevent2;
#if OS_EVENT_NAME_SIZE > 1
        pevent1->OSEventName[0] = '?';                      /* Unknown name                            */
        pevent1->OSEventName[1] = OS_ASCII_NUL;
#endif
        pevent1++;
        pevent2++;
    }
    pevent1->OSEventType            = OS_EVENT_TYPE_UNUSED;
    pevent1->OSEventPtr             = (OS_EVENT *)0;
#if OS_EVENT_NAME_SIZE > 1
    pevent1->OSEventName[0]         = '?';                  
    pevent1->OSEventName[1]         = OS_ASCII_NUL;
#endif
    OSEventFreeList                 = &OSEventTbl[0];
#else
    OSEventFreeList                 = &OSEventTbl[0];       /* Only have ONE event control block       */
    OSEventFreeList->OSEventType    = OS_EVENT_TYPE_UNUSED;
    OSEventFreeList->OSEventPtr     = (OS_EVENT *)0;
#if OS_EVENT_NAME_SIZE > 1
    OSEventFreeList->OSEventName[0] = '?';                  /* Unknown name                            */
    OSEventFreeList->OSEventName[1] = OS_ASCII_NUL;
#endif
#endif
#endif
}
同样将EventTbl[]数组中的OSEventType都初始化为OS_EVENT_TYPE_UNUSED。
OS_InitTaskIdle(),中间我们跳过其他的如Mem等的初始化,看看Idle Task的初始化。
    (void)OSTaskCreateExt(OS_TaskIdle,
                          (void *)0,                                 /* No arguments passed to OS_TaskIdle() */
                          &OSTaskIdleStk[OS_TASK_IDLE_STK_SIZE - 1], /* Set Top-Of-Stack                     */
                          OS_IDLE_PRIO,                              /* Lowest priority level                */
                          OS_TASK_IDLE_ID,
                          &OSTaskIdleStk[0],                         /* Set Bottom-Of-Stack                  */
                          OS_TASK_IDLE_STK_SIZE,
                          (void *)0,                                 /* No TCB extension                     */
                          OS_TASK_OPT_STK_CHK | OS_TASK_OPT_STK_CLR);/* Enable stack checking + clear stack  */
其实Idle Task的初始化很简单就是调用OSTaskCrete系列的函数创建一个Task, OSTaskCreate我们后面再做进一步分析。
初始化State Task也是类似调用OSTaskCreate系列函数创建Stat Task。这里只是创建了该Task的各个结构还没有真正运行该Task,直到OSStart中才依据优先级调度运行。

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -