发新帖本帖赏金 50.00元(功能说明)我要提问
返回列表
打印
[资料干货]

ucos中的CPU利用率与实现原理

[复制链接]
282|0
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
forgot|  楼主 | 2023-2-20 15:31 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
IDL, ID, TI, ST, CPU, ucos
本帖最后由 forgot 于 2023-2-20 15:33 编辑

  在PC机上,大家可以通过任务管理器查看自己电脑的性能参数,如CPU利用率、内存占用、硬盘以及以太网吞吐量等,往往开的软件越多,CPU利用率就越高。在单片机上运行嵌入式操作系统之后,也一样可以查看自己的单片机CPU利用率,就是OSCPUUsage。这个CPU利用率同样可以反应程序占用CPU资源的情况,利用率越高时,该值就越大,利用率越低时,该值就越小;而单片机的RAM使用情况反应的就是其内存的占用,如果RAM过高的时候,需要通过优化变量及更改堆栈空间大小来减小内存占用。

  这里只说一下单片机获取CPU占用率OSCPUUsage值的实现原理,以uC/OS-II嵌入式操作系统为例,按照系统任务类型划分,除了用户任务之外还有一个空闲任务和一个统计任务,在OSInit();中有两个函数分别为:OS_InitTaskIdle();与OS_InitTaskStat();空闲任务系统都是会建立的,该任务就是当某段时间内,CPU没有用户任务需要处理的时候,就会执行空闲任务,但是要获得OSCPUUsage值必须还要建立统计任务,如果用户程序打算使用统计任务,那么就必须在主函数当中只建立一开始任务start_task,在开始任务start_task();中调用OSStatInit(),之后建立其他用户自己的任务。

  其中在os_cfg.h中需要使能OS_TASK_STAT_EN,这样在OSInit();中就可以实现统计任务的创建OS_InitTaskStat();,该任务具有倒数第二高的优先级,只比空闲任务优先级高。该任务会通过for (;;){}来实现单位时间内(1/10秒内)空闲任务的计数,并通过OSCPUUsage   = (INT8U)(100uL - OSIdleCtrRun / OSIdleCtrMax);计算得到CPU使用率。其中OSIdleCtrMax是系统最大空闲率,在前面的OSStatInit()中通过计算获取,这就是具体的实现原理。

  获取:OSIdleCtrMax 值
void  OSStatInit (void)
{
#if OS_CRITICAL_METHOD == 3u                     /* Allocate storage for CPU status register           */
    OS_CPU_SR  cpu_sr = 0u;
#endif

    OSTimeDly(2u);                               /* Synchronize with clock tick                        */
    OS_ENTER_CRITICAL();
    OSIdleCtr    = 0uL;                          /* Clear idle counter                                 */
    OS_EXIT_CRITICAL();
    OSTimeDly(OS_TICKS_PER_SEC / 10u);           /* 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();
}

  计算OSCPUUsage :
void  OS_TaskStat (void *p_arg)
{
#if OS_CRITICAL_METHOD == 3u                     /* Allocate storage for CPU status register           */
    OS_CPU_SR  cpu_sr = 0u;
#endif



    p_arg = p_arg;                               /* Prevent compiler warning for not using 'p_arg'     */
    while (OSStatRdy == OS_FALSE) {
        OSTimeDly(2u * OS_TICKS_PER_SEC / 10u);  /* Wait until statistic task is ready                 */
    }
    OSIdleCtrMax /= 100uL;
    if (OSIdleCtrMax == 0uL) {
        OSCPUUsage = 0u;
#if OS_TASK_SUSPEND_EN > 0u
        (void)OSTaskSuspend(OS_PRIO_SELF);
#else
        for (;;) {
            OSTimeDly(OS_TICKS_PER_SEC);
        }
#endif
    }
    for (;;) {
        OS_ENTER_CRITICAL();
        OSIdleCtrRun = OSIdleCtr;                /* Obtain the of the idle counter for the past second */
        OSIdleCtr    = 0uL;                      /* Reset the idle counter for the next second         */
        OS_EXIT_CRITICAL();
        OSCPUUsage   = (INT8U)(100uL - OSIdleCtrRun / OSIdleCtrMax);
        OSTaskStatHook();                        /* Invoke user definable hook                         */
#if (OS_TASK_STAT_STK_CHK_EN > 0u) && (OS_TASK_CREATE_EXT_EN > 0u)
        OS_TaskStatStkChk();                     /* Check the stacks for each task                     */
#endif
        OSTimeDly(OS_TICKS_PER_SEC / 10u);       /* Accumulate OSIdleCtr for the next 1/10 second      */
    }
}

  在MDK中进行系统调试DEBUG的时候。也可以将OSCPUUsage右击添加到watch窗口中进行查看,来实时监测CPU利用率,如果多任务是采用OSTimeDly();延时函数进行就绪,可以按照实际需要通过调节延时值来调整CPU利用率,对于一些不必要一直运行的任务,可以通过等待信号量的方式进行就绪,这样可以降低利用率,让需要的运行的任务可以及时得到运行。

MDK调试watch窗口:

使用特权

评论回复

打赏榜单

21ic小管家 打赏了 50.00 元 2023-03-13
理由:签约作者奖励

相关帖子

发新帖 本帖赏金 50.00元(功能说明)我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

1370

主题

11287

帖子

51

粉丝