μC/OS-II的初始化和启动过程

初始化和启动都在main函数里实现。

int main(void)
{   
    system_init();  //各种硬件外设功能的初始化
    OSInit();   //系统初始化
    ...
    .../*在这里创建任务*/ 
    OSStart();   //系统启动                             
}

1、初始化
为了完成自身的工作,μC/OS-II定义了大量的全局数据结构,要让系统跑起来,需要先初始化各种需要的全局变量。

void  OSInit (void)
{
    OSInitHookBegin();                                           /* Call port specific initialization code   */

    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_FLAG_EN > 0u) && (OS_MAX_FLAGS > 0u)
    OS_FlagInit();                                               /* Initialize the event flag structures     */
#endif

#if (OS_MEM_EN > 0u) && (OS_MAX_MEM_PART > 0u)
    OS_MemInit();                                                /* Initialize the memory manager            */
#endif

#if (OS_Q_EN > 0u) && (OS_MAX_QS > 0u)
    OS_QInit();                                                  /* Initialize the message queue structures  */
#endif

    OS_InitTaskIdle();                                           /* Create the Idle Task                     */
#if OS_TASK_STAT_EN > 0u
    OS_InitTaskStat();                                           /* Create the Statistic Task                */
#endif

#if OS_TMR_EN > 0u
    OSTmr_Init();                                                /* Initialize the Timer Manager             */
#endif

    OSInitHookEnd();                                             /* Call port specific init. code            */

#if OS_DEBUG_EN > 0u
    OSDebugInit();
#endif
}
  1. OS首先Initialize了任务控制块、事件控制表,还有一些条件编译的初始化(也就是说这些可以不要,改变一下宏定义就好了,这就是μC/OS-II的剪裁性,具体宏定义全都在os_cfg.h文件里。)
  2. 初始化之后,创建了一个空闲任务,这个必须要有,而且是最低优先级的,这样如果没有任务运行可以让系统有事可干(一直待机)。

2、创建任务
使用OSTaskCreate 创建任务,函数原型为

INT8U  OSTaskCreate (void   (*task)(void *p_arg),void *p_arg,OS_STK  *ptos,INT8U    prio)

创建任务代码示例:

int main(void)
{   
    ...
    OSInit();   
    ...
    OSTaskCreate(start_task,......);//创建起始任务
    OSStart();                              
}
void start_task(void *pdata)
{
  ... ...//在这里启动系统时钟       
    OSStatInit();   //初始化统计任务   

    OS_ENTER_CRITICAL(); //进入临界区
    ... ...//创建任务
    OSTaskCreate(main_task, ... , ... , ...);//创建任务                        
    OS_EXIT_CRITICAL(); //退出临界区
} 

这里只讲创建任务函数和进/退出临界区函数

  1. OS_ENTER_CRITICAL()和OS_EXIT_CRITICAL():
    概念扫盲的时候知道,任何系统都是由中断驱动工作的,对于一些重要的操作,操作系统不希望被打断,于是会先关中断,完成操作后再把中断打开,进入临界区函数和退出实际上就是关开总中断。

  2. OSTaskCreate(main_task, … , … , …)函数原型

    INT8U OSTaskCreate (
    void (*task)(void *p_arg), //指向任务的指针
    void *p_arg,//传递给任务的参数
    OS_STK *ptos,//指向任务堆栈栈顶的指针
    INT8U prio//任务的优先级
    )

3、μC/OS-II的启动
μC/OS-II启动前,是需要先创建至少一个任务的,这个任务在初始化函数里就帮你创建好了,就是空闲函数。不过空闲函数属于系统级任务,是不能在里面添加用户代码的,只进行简单的计数功能,如果执行了OSStart(),而前面并没有创建用户任务,那么这系统除了待机并没啥用了(叫别人干活首先要让别人知道自己要干什么活吧,不然就空闲呗),所以一般创建一个任务,然后用这个任务再创建其它的任务(当然也可以把所有任务一股脑全在这里创建,只不过不好看而已),创建完把这个任务挂起(回收资源)就OK了。
上面有个错误,空闲函数是可以添加用户代码的,不过需要通过os提供的钩子函数,在钩子函数内进行用户操作,并且需要修改相应的宏使能钩子函数。(参考正点原子的UCOS开发手册发现)

void  OSStart (void)
{
    if (OSRunning == OS_FALSE) {
        OS_SchedNew();                               /* Find highest priority's task priority number   */
        OSPrioCur     = OSPrioHighRdy;
        OSTCBHighRdy  = OSTCBPrioTbl[OSPrioHighRdy]; /* Point to highest priority task ready to run    */
        OSTCBCur      = OSTCBHighRdy;
        OSStartHighRdy();                            /* Execute target specific code to start task     */
    }
}

OS_SchedNew()函数源码如下

static  void  OS_SchedNew (void)
{
#if OS_LOWEST_PRIO <= 63u                        /* See if we support up to 64 tasks                   */
    INT8U   y;


    y             = OSUnMapTbl[OSRdyGrp];
    OSPrioHighRdy = (INT8U)((y << 3u) + OSUnMapTbl[OSRdyTbl[y]]);//找到最高优先级任务
#else                                            /* We support up to 256 tasks                         */
    INT8U     y;
    OS_PRIO  *ptbl;


    if ((OSRdyGrp & 0xFFu) != 0u) {
        y = OSUnMapTbl[OSRdyGrp & 0xFFu];
    } else {
        y = OSUnMapTbl[(OS_PRIO)(OSRdyGrp >> 8u) & 0xFFu] + 8u;
    }
    ptbl = &OSRdyTbl[y];
    if ((*ptbl & 0xFFu) != 0u) {
        OSPrioHighRdy = (INT8U)((y << 4u) + OSUnMapTbl[(*ptbl & 0xFFu)]);
    } else {
        OSPrioHighRdy = (INT8U)((y << 4u) + OSUnMapTbl[(OS_PRIO)(*ptbl >> 8u) & 0xFFu] + 8u);
    }
#endif
}

OSStart ()主要任务就是,找到最高优先级的用户任务,标志相应任务控制块,然后执行。

关于如何找到最高优先级任务,在任务调度表一章,OS_SchedNew是对任务就绪表进行的操作,得到就绪任务表里优先级最高的任务。

关于可以支持256个任务,百度了一下,原来是版本升级了。。。

总结一下:
μC/OS-II的初始化和启动涉及的知识有
1、第4章,任务的基本概念,任务的状态、优先级、控制块及其链表结构、任务堆栈,临界区的概念。
2、第5章,任务的管理,包括任务的创建、挂起,并没有涉及任务优先级别的修改、删除、恢复及查询功能。
3、第6章,任务的调度,这里并没有详细描写,只用了一个OS_SchedNew ()函数得到就绪表中的最高优先级,OS_Sched()有在创建任务的时候使用,不过这里没描述。
3、第7章,就是这里的内容了,囊括了书前面写大部分的内容,这本书写的真好,不愧是畅销书

你可能感兴趣的:(uC/OS-II,函数,源码,管理,硬件)