UCOS-III学习笔记——main函数中的配置与初始化

μC/ OS III Version: v3.03.01

μC/ CPU Version: v1.29.01

μC/ LIB Version: v1.37.00

FOR: NXP LPC1768 CPU

UCOS-III学习笔记——LPC1768移植

首先贴出app.c中的main()函数的代码:

int  main (void)
{
    OS_ERR  err;


    CPU_Init();

    BSP_Init();                                                 /* Initialize BSP functions                             */

    Mem_Init();

    OSInit(&err);                                               /* Initialize "uC/OS-III, The Real-Time Kernel"         */

    OSTaskCreate((OS_TCB     *)&App_TaskStartTCB,               /* Create the start task                                */
                 (CPU_CHAR   *)"App Task Start",
                 (OS_TASK_PTR ) App_TaskStart,
                 (void       *) 0,
                 (OS_PRIO     ) APP_CFG_TASK_START_PRIO,
                 (CPU_STK    *)&App_TaskStartStk[0],
                 (CPU_STK     )(APP_CFG_TASK_START_STK_SIZE / 10u),
                 (CPU_STK_SIZE) APP_CFG_TASK_START_STK_SIZE,
                 (OS_MSG_QTY  ) 0,
                 (OS_TICK     ) 0,
                 (void       *) 0,
                 (OS_OPT      )(OS_OPT_TASK_STK_CHK | OS_OPT_TASK_STK_CLR),
                 (OS_ERR     *)&err);
#if (OS_TASK_NAME_EN > 0u)
    OSTaskNameSet(APP_CFG_TASK_START_PRIO, "Start", &err);
#endif

    OSStart(&err);                                              /* Start multitasking (i.e. give control to uC/OS-III). */

    while(DEF_ON){				                /* Should Never Get Here							    */
    };
}

完成Startup文件的工作后,代码将从main()函数开始,下面将逐一对其中的函数进行讲解。

1.  CPU_Init()

共完成3个工作:

CPU_TS_Init(); /*时间戳初始化*/

CPU_IntDisMeasInit(); /*测试关闭时间功能初始化*/

CPU_NameInit(); /*CPU名字初始化(清零)*/

2.  BSP_Init()

主要做的的硬件相关的板级驱动初始化,例如时钟配置,引脚配置,中断配置等,每块控制板的结构不同,初始化过程也不尽相同,所以做系统移植时改动最多的地方就在这里。

3.  Mem_Init()

Mem_Init()是库文件lib_mem.c中的一个初始化函数,如果程序中使用uC/LIB的话,需要调用初始化函数。其主要做的工作是Initialize heap memory pool和Initialize memory pool table。

4.  OSInit(&err)

初始化OS内核使用到的函数和全局变量,下面给出了未受宏定义限制的部分初始化内容(相对来说比较重要):

首先初始化钩子函数(这个函数我还没使用过):

OSInitHook();                                          

然后初始化各个全局变量:

OSIntNestingCtr                 = (OS_NESTING_CTR)0;    /*清除中断嵌套计数器*/

OSRunning                       =  OS_STATE_OS_STOPPED; /*声明多任务未开始*/

OSSchedLockNestingCtr           = (OS_NESTING_CTR)0;    /*清除调度锁计数器*/

OSTCBCurPtr                     = (OS_TCB *)0;          /*TCB相关的指针初始化*/
OSTCBHighRdyPtr                 = (OS_TCB *)0;          

OSPrioCur                       = (OS_PRIO)0;           /*优先级相关的指针初始化*/
OSPrioHighRdy                   = (OS_PRIO)0;
OSPrioSaved                     = (OS_PRIO)0;

然后是各个函数的初始化:

OS_PrioInit();                                          /*优先级bitmap表初始化*/

OS_RdyListInit();                                       /*就绪列表初始化*/

OS_TaskInit(p_err);                                     /*任务初始化*/

OS_IdleTaskInit(p_err);                                 /*空闲任务初始化*/

OS_TickTaskInit(p_err);                                 /*Tick任务初始化*/

OSCfg_Init();                                           /*系统配置初始化*/
  • OS_PrioInit():初始化了优先级表,代码如下:
    for (i = 0u; i < OS_PRIO_TBL_SIZE; i++) {
         OSPrioTbl[i] = (CPU_DATA)0;
    }

    优先级表是一个数组,在32位的环境下,每一个bit对应一个优先级,所以一个数组成员即可表示32个优先级,此时OS_PRIO_TBL_SIZE定义为1;如果需要支持64个优先级,只需要两个数组成员,OS_PRIO_TBL_SIZE定义为2即可。

  • OS_RdyListInit():初始化OSRdyList[]数组,代码如下:
    for (i = 0u; i < OS_CFG_PRIO_MAX; i++) {  
            p_rdy_list = &OSRdyList[i];
            p_rdy_list->NbrEntries = (OS_OBJ_QTY)0;
            p_rdy_list->HeadPtr    = (OS_TCB   *)0;
            p_rdy_list->TailPtr    = (OS_TCB   *)0;
        }

    数组的大小由宏OS_CFG_PRIO_MAX决定,从OSRdyList[0]到OSRdyList[OS_CFG_PRIO_MAX-1],每一个成员数记录不同优先级的任务,数组的成员为OS_RDY_LIST类型的结构体,每个结构体包含有NbrEntries(个数),HeadPtr(头指针),TailPtr(尾指针)。当有多个同一优先级任务时,结构体中NbrEntries记录任务数量,每个相同优先级的任务以双向链表的方式连接。

  • OS_TaskInit():

        OSTaskQty        = (OS_OBJ_QTY   )0;                    /*任务数量初始化*/
        OSTaskCtxSwCtr   = (OS_CTX_SW_CTR)0;                    /*上下文转换计数器初始化*/

    对任务相关的全局变量进行初始化。

  • OS_IdleTaskInit(p_err):

    OSIdleTaskCtr = (OS_IDLE_CTR)0;
    
    OSTaskCreate((OS_TCB     *)&OSIdleTaskTCB,
                 (CPU_CHAR   *)((void *)"uC/OS-III Idle Task"),
                 (OS_TASK_PTR)OS_IdleTask,
                 (void       *)0,
                 (OS_PRIO     )(OS_CFG_PRIO_MAX - 1u),
                 (CPU_STK    *)OSCfg_IdleTaskStkBasePtr,
                 (CPU_STK_SIZE)OSCfg_IdleTaskStkLimit,
                 (CPU_STK_SIZE)OSCfg_IdleTaskStkSize,
                 (OS_MSG_QTY  )0u,
                 (OS_TICK     )0u,
                 (void       *)0,
                 (OS_OPT      )(OS_OPT_TASK_STK_CHK | OS_OPT_TASK_STK_CLR | OS_OPT_TASK_NO_TLS),
                 (OS_ERR     *)p_err);

    对空闲任务计数器初始化,并创建空闲任务,其任务优先级为最低。所有进入延时(DLY)状态的任务都将转向执行空闲任务,在空闲任务执行时可进行相应的低功耗处理。

  • OS_TickTaskInit(p_err):

    OSTickCtr         = (OS_TICK)0u;                        /*Tick计数器初始化*/
    
    OSTickTaskTimeMax = (CPU_TS)0u;                         /*最大Tick任务时间初始化*/
    
    OS_TickListInit();                                      /*初始化Tick列表(时基列表)*/
    
    OSTaskCreate((OS_TCB     *)&OSTickTaskTCB,
                 (CPU_CHAR   *)((void *)"uC/OS-III Tick Task"),
                 (OS_TASK_PTR )OS_TickTask,
                 (void       *)0,
                 (OS_PRIO     )OSCfg_TickTaskPrio,
                 (CPU_STK    *)OSCfg_TickTaskStkBasePtr,
                 (CPU_STK_SIZE)OSCfg_TickTaskStkLimit,
                 (CPU_STK_SIZE)OSCfg_TickTaskStkSize,
                 (OS_MSG_QTY  )0u,
                 (OS_TICK     )0u,
                 (void       *)0,
                 (OS_OPT      )(OS_OPT_TASK_STK_CHK | OS_OPT_TASK_STK_CLR | OS_OPT_TASK_NO_TLS),
                 (OS_ERR     *)p_err);

    Tick任务初始化时定义初始化了一个Tick列表(时基列表)

    for (i = 0u; i < OSCfg_TickWheelSize; i++) {
        p_spoke                = (OS_TICK_SPOKE *)&OSCfg_TickWheel[i];
        p_spoke->FirstPtr      = (OS_TCB        *)0;
        p_spoke->NbrEntries    = (OS_OBJ_QTY     )0u;
        p_spoke->NbrEntriesMax = (OS_OBJ_QTY     )0u;
    }

    处于延时任务和等待时间有超时限制的任务都会从就绪列表中移除,然后插入时基列表中;后面创建的"uC/OS-III Tick Task"任务的优先级为2,Tick任务在每次的systick系统时钟中断都会进入到OS_TickTsak函数,记录tick的全局变量都会更新,插入在时基列表中的任务TCB记录的tick同样会更新,如果任务的延时时间结束或者超时到期,就会从时基列表移除,插入就绪列表。

  • OSCfg_Init():这个函数没有什么功能,只是用于确保未优化应用程序中未使用的调试变量,不做过多赘述。

5.  OSTaskCreate(&App_TaskStartTCB,...)

创建在启动OS开始时需要执行的第一个任务"App Task Start",其任务优先级与空闲任务相同为2。

在后面执行任务时所做的工作首先对systick系统时钟进行初始化,并创建用户需要执行的任务,代码如下:

static  void  App_TaskStart (void *p_arg)
{
     OS_ERR  os_err;

    (void)p_arg;                                                /* See Note #1                                          */


    BSP_Start();                                                /* Start BSP and tick initialization                    */

#if (OS_TASK_STAT_EN > 0)
    OSStatInit();                                               /* Determine CPU capacity                               */
#endif

    App_ObjCreate();                                            /* Create Applicaiton kernel objects                    */

    App_TaskCreate();                                           /* Create Application tasks                             */


    while (DEF_TRUE) {                                          /* Task body, always written as an infinite loop.       */
        LED_TOGGLE();
        OSTimeDly(1000, OS_OPT_TIME_DLY, &os_err);
    }
}

创建用户任务完成后可将此任务删除。

6.  OSStart(&err)

OSStart()函数中,主要做了以下工作:

if (OSRunning == OS_STATE_OS_STOPPED) {
    OSPrioHighRdy   = OS_PrioGetHighest();              /*找到已经就绪的最高的优先级*/
    OSPrioCur       = OSPrioHighRdy;                    /*当前优先级等于最高的优先级*/
    OSTCBHighRdyPtr = OSRdyList[OSPrioHighRdy].HeadPtr; 
    OSTCBCurPtr     = OSTCBHighRdyPtr;                  /*将当前TCB指针指向最高优先级的任务TCB*/
    OSRunning       = OS_STATE_OS_RUNNING;
    OSStartHighRdy();                                   /*执行目标特定代码以启动任务*/
    *p_err           = OS_ERR_FATAL_RETURN;             /*OSStart()不会返回*/
    }

函数首先寻找到当前就绪任务的最高优先级,然后将当前的TCB指针指向任务,准备执行。

至此,OS准备工作结束,在执行OSStartHighRdy()后,OS将获得CPU的控制权,启动实时系统和多任务处理。

参考:http://www.firebbs.cn/forum.php?mod=viewthread&tid=23554&highlight=%A1%B6%B4%D30%B5%BD1%BD%CC%C4%E3%D0%B4uC%2FOS-III%A1%B7

QQ:956599264

欢迎交流

猜你喜欢

转载自blog.csdn.net/sinat_27066063/article/details/83993163