牛骨文教育服务平台(让学习变的简单)
博文笔记

uc/os-ii统计任务

创建时间:2015-06-30 投稿人: 浏览次数:722

uC/OS-II定义了两个系统任务,空闲任务与统计任务。

  • 空闲任务OSTaskIdle()是μC/OS-Ⅱ必不可少的系统函数,当没有其它任务进入就绪态时,该任务立即转入运行态。空闲任务的优先级永远设为最低,即OS_LOWEST_PRIO,永远不被挂起,也不能被删除。

  • 空闲任务什么都不做,只是在不停地给一个32位计数器OSIdleCtr加1,统计任务使用这个计数器以确定当前应用程序实际消耗的CPU时间。计数器是一个全局变量,大多数8位或16位CPU对32位变量加1需要多条指令,所以在访问前必须先关中断,然后再开启,以防高优先级任务或中断打入。

void  OS_TaskIdle (void *p_arg)
{
#if OS_CRITICAL_METHOD == 3                      /* Allocate storage for CPU status register           */
    OS_CPU_SR  cpu_sr = 0;
#endif



    (void)p_arg;                                 /* Prevent compiler warning for not using "p_arg"     */
    for (;;) {
        OS_ENTER_CRITICAL();
        OSIdleCtr++;
        OS_EXIT_CRITICAL();
        OSTaskIdleHook();                        /* Call user definable HOOK                           */
    }
}
  • 统计任务OSTaskStat()也是μC/OS-Ⅱ的系统函数之一,其功能是计算当前CPU的利用率,告诉用户应用程序使用了多少CPU时间。一旦将文件OS_CFG.H中的配置常数OS_ TASK_STAT_EN置1,这个任务就自动建立。它每秒钟运行一次,计算结果放在一个有符号的8位整数OSCPUsage中,表示格式是百分数,精确到1%。
void  OS_TaskStat (void *p_arg)
{
#if OS_CRITICAL_METHOD == 3                      /* Allocate storage for CPU status register           */
    OS_CPU_SR  cpu_sr = 0;
#endif



    (void)p_arg;                                 /* Prevent compiler warning for not using "p_arg"     */
    while (OSStatRdy == OS_FALSE) {
        OSTimeDly(2 * OS_TICKS_PER_SEC / 10);    /* Wait until statistic task is ready                 */
    }
    OSIdleCtrMax /= 100L;
    if (OSIdleCtrMax == 0L) {
        OSCPUUsage = 0;
        (void)OSTaskSuspend(OS_PRIO_SELF);
    }
    for (;;) {
        OS_ENTER_CRITICAL();
        OSIdleCtrRun = OSIdleCtr;                /* Obtain the of the idle counter for the past second */
        OSIdleCtr    = 0L;                       /* Reset the idle counter for the next second         */
        OS_EXIT_CRITICAL();
        OSCPUUsage   = (INT8U)(100L - OSIdleCtrRun / OSIdleCtrMax);
        OSTaskStatHook();                        /* Invoke user definable hook                         */
#if (OS_TASK_STAT_STK_CHK_EN > 0) && (OS_TASK_CREATE_EXT_EN > 0)
        OS_TaskStatStkChk();                     /* Check the stacks for each task                     */
#endif
        OSTimeDly(OS_TICKS_PER_SEC / 10);        /* Accumulate OSIdleCtr for the next 1/10 second      */
    }
}
  • 下面重点分析一下如何计算CPU利用率。
    使用统计任务时,初始化时只能建立唯一的一个任务,其它任务的建立只能在多任务启动后建立。值得注意的是:时钟节拍的初始化和启动工作也可以放在OSStart()函数中完成。一般不要在多任务启动之前启动时钟节拍器,因为这样做可能导致任务开始前应用程序就收到时钟节拍中断,以至系统崩溃。
void main (void)
{  
    OSInit();      /*初始化ucosii  */     
    OSTaskCreate(TaskStart,(void *)0,
        &startup_task_stk[STARTUP_TASK_STK_SIZE-1], STARTUP_TASK_PRIO);/*创建唯一任务  */        
    OSStart();       
}
void TaskStart(void *p_arg)
{
    SysTick_init();/*安装并启动始终节拍   */
    OSStatInit(); /*调用系统函数,初始化统计任务  */         
    while(1)
    {
         /*TaskStart代码      */
    }
}
  • 统计任务的使用方法是:首先用户在初始化时建立一个也只能是一个任务,其次在这个唯一的任务中调用OSStatInit()函数。
void  OSStatInit (void)
{
#if OS_CRITICAL_METHOD == 3                      /* Allocate storage for CPU status register           */
    OS_CPU_SR  cpu_sr = 0;
#endif
    OSTimeDly(2);                                /* Synchronize with clock tick                        */
    OS_ENTER_CRITICAL();
    OSIdleCtr    = 0L;                           /* Clear idle counter                                 */
    OS_EXIT_CRITICAL();
    OSTimeDly(OS_TICKS_PER_SEC / 10);            /* Determine MAX. idle counter value for 1/10 second  */
    OS_ENTER_CRITICAL();
    OSIdleCtrMax = OSIdleCtr;                    /* Store maximum idle counter count in 1/10 second    */
    OSStatRdy    = OS_TRUE;
    OS_EXIT_CRITICAL();
}
  • 进入多任务的条件准备好了以后,调用系统启动函数OSStart()。这个函数将使TaskStart()开始执行,因为TaskStart()是优先级最高的任务。TaskStart()负责初始化和启动时钟节拍。在这里启动时钟节拍是必要的,因为用户不会希望在多任务还没有开始时就接收到时钟节拍中断。接下去TaskStart()调用统计初始化函数OSStatInit()
    统计初始化函数OSStatInit()决定在没有其它应用任务运行时,空闲计数器OSIdleCtr的计数有多快。这里取0.1秒(OS_TICKS_PER_SEC / 10)内OSIdleCtr的计数值OSIdleCtrMax 为计算CPU利用率的基准。

    1. 系统统计初始化任务函数OSStatInit()调用延迟函数OSTimeDly(2)将自身延时2个时钟节拍以停止自身的运行。这是为了使OSStatInit()与时钟节拍同步。
    2. μC/OS-Ⅱ然后选下一个优先级最高的进入就绪态的任务运行,这恰好是统计任务OSTaskStat()OSTaskStat()所要做的第一件事就是查看统计任务就绪标志是否为“假”,如果是的话,要延时0.2秒(2 * OS_TICKS_PER_SEC / 10)。一定会是这样,因为标志OSStatRdy已被OSInit()函数初始化为“假”,所以实际上OSTaskStat也将自己推入休眠态0.2秒。
    3. 于是任务切换到空闲任务,OSTaskIdle()开始运行,这是唯一一个就绪态任务了。CPU处在空闲任务OSTaskIdle中,直到TaskStart()的延迟两个时钟节拍完成。
    4. 两个时钟节拍之后,TaskStart()恢复运行。 在执行OSStartInit()时,空闲计数器OSIdleCtr被清零。然后,OSStatInit()将自身延时0.1秒。
    5. 因为没有其它进入就绪态的任务,OSTaskIdle()又获得了CPU的控制权。0.1秒钟以后,TaskStart()继续运行,还是在OSStatInit()中,空闲计数器将0.1秒钟内计数的值存入空闲计数器最大值OSIdleCtrMax
    6. OSStarInit()将统计任务就绪标志OSStatRdy设为“真”,以此来允许OSTaskStat()开始计算CPU的利用率。
  • 统计任务每0.1秒执行一次,以确定所有应用程序中的任务消耗了多少CPU时间。当用户的应用程序代码加入以后,运行空闲任务的CPU时间就少了,OSIdleCtr就不会像原来什么任务都不运行时有那么多计数。要知道,OSIdleCtr的最大计数值是OSStatInit()在初始化时保存在计数器最大值OSIdleCtrMax中的。CPU利用率是保存在变量OSCPUsage中的,根据公式计算OSIdleCtr=OSIdleCtrMax 时CPU利用率最低为0,OSIdleCtr=0 时CPU利用率最高为100%。
     图1-1
    ===========以上为统计任务的分析===============

  • 关于统计任务运行频率的补充

统计任务执行到最后时是OSTimeDly(OS_TICKS_PER_SEC/10);这样一个函数。表示延迟一分钟。而只有统计任务延时时空闲任务才有可能运行,所以每当统计任务运行时OSIdleCtr的值都是在可能的1s内记的数。因为在统计任务在赋完值之后清零了。所以说,统计任务不是1s运行一次,只不过统计任务运行时用到的变量都是在1s内的数据。

参考:http://gha20028.blog.163.com/blog/static/13481666201363021616344/

声明:该文观点仅代表作者本人,牛骨文系教育信息发布平台,牛骨文仅提供信息存储空间服务。