首页 | 新闻 | 新品 | 文库 | 方案 | 视频 | 下载 | 商城 | 开发板 | 数据中心 | 座谈新版 | 培训 | 工具 | 博客 | 论坛 | 百科 | GEC | 活动 | 主题月 | 电子展
返回列表 回复 发帖

ucos在s3c2410上运行过程整体剖析-从main函数到UCOS初始化完毕(3)

ucos在s3c2410上运行过程整体剖析-从main函数到UCOS初始化完毕(3)

struct os_tcb   *OSTCBNext;  /* Pointer to next     TCB in the TCB list*/                     

    struct os_tcb   *OSTCBPrev;  /* Pointer to previous TCB in the TCB list*/                     

//这两个是任务控制块指针,最后这些任务的控制块是链接成双向链表的,以便于查找和修改任务控制块。

#if OS_EVENT_EN

    OS_EVENT        *OSTCBEventPtr;    /* Pointer to event control block*/                              

#endif


#if ((OS_Q_EN > 0) && (OS_MAX_QS > 0)) || (OS_MBOX_EN > 0)

    void            *OSTCBMsg; /* Message received from OSMboxPost() or OSQPost()*/            

#endif


#if (OS_VERSION >= 251) && (OS_FLAG_EN > 0) && (OS_MAX_FLAGS > 0)

#if OS_TASK_DEL_EN > 0

    OS_FLAG_NODE    *OSTCBFlagNode;    /* Pointer to event flag node*/                                 

#endif   

    OS_FLAGS         OSTCBFlagsRdy;    /* Event flags that made task ready to run*/                     

#endif


INT16U           OSTCBDly;  /* Nbr ticks to delay task or, timeout waiting for event*/

//这个是延时的ticks数量,ticks是每秒定时器产生的中断数量,一般是每秒1000个ticks。也就是每秒产生1000个定时器中断。这个变量是用来记忆一个任务延时的ticks的,比如一个任务自己想延时1s钟,那这个变量就要赋值1000.

INT8U            OSTCBStat;        /* Task status */   

//任务的状态,用于记忆任务是运行态,就绪态,还是……                                             

    BOOLEAN    OSTCBPendTO; /* Flag indicating PEND timed out (TRUE == timed out)*/

INT8U            OSTCBPrio;        /* Task priority (0 == highest, 63 == lowest) */

//这个是任务优先级,这个ucos是根据优先级进行调度的,优先级是我们创建任务时赋给任务的一个优先顺序值,在ucos中这个数值越小,优先级越高,比如优先级为3的任务和优先级为8的任务都就绪,那ucos首先运行任务3.  关于ucos高效的任务调度算法我们将在以下文章中详细讲解。            

    INT8U         OSTCBX; /* Bit position in group  corresponding to task priority (0..7) */

    INT8U            OSTCBY;/* Index into ready table corresponding to task priority */     

    INT8U            OSTCBBitX;      /* Bit mask to access bit position in ready table */  

    INT8U            OSTCBBitY;/* Bit mask to access bit position in ready group*/

//上述四个变量是和高效率调度任务有关的。

#if OS_TASK_DEL_EN > 0

    INT8U            OSTCBDelReq;/* Indicates whether a task needs to delete itself*/

#endif


#if OS_TASK_PROFILE_EN > 0

    INT32U       OSTCBCtxSwCtr;    /* Number of time the task was switched in */      

    INT32U  OSTCBCyclesTot;   /* Total number of clock cycles the task has been running*/   

    INT32U   OSTCBCyclesStart; /* Snapshot of cycle counter at start of task resumption*/      

    OS_STK  *OSTCBStkBase;     /* Pointer to the beginning of the task stack */         

    INT32U    OSTCBStkUsed;     /* Number of bytes used from the stack */

#endif

#if OS_TASK_NAME_SIZE > 1

    char             OSTCBTaskName[OS_TASK_NAME_SIZE];

#endif

} OS_TCB;

关于这个任务控制块,这里只是做一下简单的说明,如果有什么不理解的地方没有关系,只要知道定义这个TCB结构体的目的就行。我们会在下面的程序分析中详细地说明的。
前面老是说任务切换和任务调度,我说一下这两个概念的区别,任务调度就是决定要执行那个任务。比如现在有优先级为2,15,34的任务就绪,那任务调度要找出优先级最高的任务,即任务2,这个任务将要运行。而任务切换就是在合适的时间里将当前正在运行的任务保存进度,转而去执行调度程序得到的最高优先级的任务2。这也就是切换的真正含义。

下面我们到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    */

……………………
  OS_InitTaskIdle();  

看代码就知道这个文件实现了对全局杂项变量的初始化,就绪表的初始化,任务控制块的初始化,初始化空闲任务等工作,当然还有其他的初始化操作,这些和我们的操作系统核心内容关系就不是很多了,我们尽量精简这个ucos,只展现其核心内容,让大家明白ucos操作系统是怎么实现对处理机调度的。即多任务实时操作系统到底是怎么实现的。

所谓ucos的初始化就是对那些核心的全局变量进行清零工作,使其处于可知的状态。
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     */
//这个变量用于标志ucos的运行状态的
OSCtxSwCtr    = 0;       /* Clear the context switch counter         */
//这个变量用于记录系统进行任务切换的次数的
OSIdleCtr     = 0L;       /* Clear the 32-bit idle counter            */
//这个是空闲任务用于计数的变量。空闲任务是这样一种任务,在没有任何可执行的用户任务的时候,就要执行空闲任务,它什么也不干,只是让OSIdleCtr这个变量加一。因为cpu在加电后就不能停止执行指令,即是用户没有需要执行的任务,那也要执行一个空闲任务,只要cpu是按照我们的意愿去执行程序,那什么就都在我们的掌握之中,是吧。
下面开始初始化就绪表的相关变量。

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;
//当前优先级的任务控制块
}
继承事业,薪火相传
返回列表