zoukankan      html  css  js  c++  java
  • UCOSII学习笔记【二】

    根据之前用到zigbee的协议栈的时候的学习的经验,对于操作系统(当然zigbee协议栈不是一个操作系统,但是有点类似)的掌握,先应该从整体上有个大的框架上的了解.至少要知道整个系统是怎么运行的,这个时候不需要了解的很深,只需要大概的了解一下流程即可。
      那么整个系统的运行当然是从main函数开始执行的,先看看main函数中的语句:
      void  main (void)
    {
      INT8U err;
      PC_DispClrScr(DISP_FGND_WHITE + DISP_BGND_BLACK);      /* Clear the screen                         */

      OSInit();                                              /* Initialize uC/OS-II                      */

      PC_DOSSaveReturn();                                    /* Save environment to return to DOS        */
      PC_VectSet(uCOS, OSCtxSw);                             /* Install uC/OS-II's context switch vector */

      RandomSem   = OSSemCreate(1);                          /* Random number semaphore                  */

      OSTaskCreate(TaskStart, (void *)0, &TaskStartStk[TASK_STK_SIZE - 1], 0);
      OSTaskNameSet(0,"Task0",&err);
      OSStart();                                             /* Start multitasking                       */
    }

    我们暂时可以讲PC_DispClrScr()函数屏蔽掉,暂时不管他,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
    }
      ucosII发展到目前为止已经有很多的版本,这个初始化函数我是从V2.82版本中复制过来的,因为相比较于比较经典的V2.52的版本,V2.82中的这个版本看起来更让人感觉到清晰明了,从函数中可以看到就是依次对操作系统中的各个部分进行初始化,运用预处理指令的好处是可以实现对操作系统的灵活配置,比如当我们不需要进行内存管理部分时,就可以将OS_MEM_EN变量设置为0,此时由上面的程序中可以看到,在编译器就行编译时就不会对OS_MemInit()函数进行编译,从而在一些资源有限的处理器上减少资源的消耗,能比较方便的实现灵活的移植.对相关功能的配置是在OS_CFG.H头文件中进行的。使用者只要更改其中变量的值就可以实现系统的需求.
      PC_DOSSaveReturn()函数由后面的注释中可以看到是返回到DOS界面,可以不看(包括前面一个PC开头的函数在内,这些函数是因为ucosII的开发是在PC机上完成的,作者给出的例子也是基于PC的,但是不妨碍移植到你所用的处理器上,当然对处理器有一些限制性要求).RandomSem   = OSSemCreate(1); 实现的功能是产生一个信号量,该信号量的功能在今后你将会明白,暂时不管,因为我们主要看的是宏观上的了解.
    OSTaskCreate(TaskStart, (void *)0, &TaskStartStk[TASK_STK_SIZE - 1], 0);
    OSTaskNameSet(0,"Task0",&err);
    由函数的名称中就可以看到上面的第一个函数是产生一个任务,该任务是在main函数中最后一个函数OSStart()之前必须要进行的,因为ucosii要求在系统start之前必须至少有一个任务。OSTaskNameSet(0,"Task0",&err);函数是对任务命名,暂时不问。
    OSStart(); 该函数是main函数中执行的最后一个函数,该函数的运行就标志了整个操作系统运行起来了.


    不过貌似看起来很简单,不就是对其进行初始化,在creat task,再start os 吗?是的。

    那看看在OSStart中操作系统做了什么呢?

    void  OSStart (void)
    {
        INT8U y;
        INT8U x;


        if (OSRunning == FALSE) {
            y             = OSUnMapTbl[OSRdyGrp];        /* Find highest priority's task priority number   */
            x             = OSUnMapTbl[OSRdyTbl[y]];
            OSPrioHighRdy = (INT8U)((y << 3) + x);
            OSPrioCur     = OSPrioHighRdy;
            OSTCBHighRdy  = OSTCBPrioTbl[OSPrioHighRdy]; /* Point to highest priority task ready to run    */
            OSTCBCur      = OSTCBHighRdy;
            OSStartHighRdy();                            /* Execute target specific code to start task     */
        }
    }

    由于ucosII总是根据任务的优先级来选择该执行那个任务的,任务的prio数值越小,则优先级越高,所以最高的优先级是0,最低的优先级根据ucosII的版本不同而不同,V2.52中是63,V2.8中是255,但是无论是哪一个版本,最低的优先级都会被空闲任务占据(MCU总是要有任务执行的嘛!),很容易理解,空闲任务就是不执行任务的任务(当然用户可以在里面添加代码,比如让MCU进入低功耗模式),即空闲任务的prio等于系统允许的最大任务数,此时还有一个任务,就是统计任务,该任务在OS_CFG.h中如果配置为允许的话,就会产生一个优先级比空闲任务第一个的统计任务,该任务功能就是统计CPU的使用情况。在操作系统第一次start之后,就要对现在已经拥有的任务中找到优先级最高的任务就行执行,其实我们已经看到,在OSStart执行之前我们已经新建了一个任务,
    OSTaskCreate(TaskStart, (void *)0, &TaskStartStk[TASK_STK_SIZE - 1], 0); 其中第一个参数就是新建的任务,其实是一个函数的首地址,最后一个参数就是任务的优先级,可以看到TaskStart的优先级prio = 0,即最高优先级。
    而在OSStart()函数中要完成的功能就是找到这个任务,即当前优先级最高的任务。具体有下列的语句实现:
            y             = OSUnMapTbl[OSRdyGrp];        /* Find highest priority's task priority number   */
            x             = OSUnMapTbl[OSRdyTbl[y]];
            OSPrioHighRdy = (INT8U)((y << 3) + x);
            OSPrioCur     = OSPrioHighRdy;
    在后面会陆续讲到这些语句。
    至此,main函数就执行完了。系统开始运行了,可能大家仍然会迷茫究竟是怎么运行的,但是毕竟一嘴吃不了一个胖子,咱们得一步一步好好的理解,从而不会在后面产生混淆的地方,到时候就不好纠正过来了。

    到目前为止,main中还有一个函数没有讲,为了保证完整性,
    void  TaskStart (void *pdata)
    {
    #if OS_CRITICAL_METHOD == 3                                /* Allocate storage for CPU status register */
      OS_CPU_SR  cpu_sr;
    #endif
      char       s[100];
      INT16S     key;
      (void)s;                                               //prevent the warning

      pdata = pdata;                                         /* Prevent compiler warning                 */

      TaskStartDispInit();                                   /* Initialize the display                   */

      OS_ENTER_CRITICAL();
      PC_VectSet(0x08, OSTickISR);                           /* Install uC/OS-II's clock tick ISR        */
      PC_SetTickRate(OS_TICKS_PER_SEC);                      /* Reprogram tick rate                      */
      OS_EXIT_CRITICAL();

      OSStatInit();                                          /* Initialize uC/OS-II's statistics         */
      OSView_Init();

      TaskStartCreateTasks();                                /* Create all the application tasks         */

      for (;;) {
        TaskStartDisp();                                  /* Update the display                       */


        if (PC_GetKey(&key) == OS_TRUE) {                     /* See if key has been pressed              */
        if (key == 0x1B) {                             /* Yes, see if it's the ESCAPE key          */
          PC_DOSReturn();                            /* Return to DOS                            */
        }
        }

        OSCtxSwCtr = 0;                                    /* Clear context switch counter             */
        OSTimeDlyHMSM(0, 0, 1, 0);                         /* Wait one second                          */
      }
    }
    这个函数是用户自己写的,作者给出的是一个例子,主要实现的功能就是中间的一个函数
    TaskStartCreateTasks();  该函数就是生成任务,具体代码不在贴出,因为跟操作系统无关,不然就偏离了主题。

    敬请期待下一节

  • 相关阅读:
    蔚来NIO Pilot 全球首试 终于摘掉半成品帽子
    这个机械手可精准灵活地接住一颗掉落的棉花糖并使其“安然无恙”
    谷歌已经领先 那么苹果的人工智能战略又在哪里
    你见过机器船吗?MIT新版ROBOAT可以自动组装
    谷歌、亚马逊、苹果三大语音助手发展现状 谁被甩在身后了
    Python中的十大图像处理工具
    测试用例设计理论
    Flask+Mysql搭建网站之数据库问题
    Flask+Mysql搭建网站之网页设计
    Flask+Mysql搭建网站之安装Mysql
  • 原文地址:https://www.cnblogs.com/zxqwolf/p/2841704.html
Copyright © 2011-2022 走看看