返回列表 发新帖我要提问本帖赏金: 50.00元(功能说明)

[资料干货] ucos中的CPU利用率与实现原理

[复制链接]
926|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 值
  1. void  OSStatInit (void)
  2. {
  3. #if OS_CRITICAL_METHOD == 3u                     /* Allocate storage for CPU status register           */
  4.     OS_CPU_SR  cpu_sr = 0u;
  5. #endif

  6.     OSTimeDly(2u);                               /* Synchronize with clock tick                        */
  7.     OS_ENTER_CRITICAL();
  8.     OSIdleCtr    = 0uL;                          /* Clear idle counter                                 */
  9.     OS_EXIT_CRITICAL();
  10.     OSTimeDly(OS_TICKS_PER_SEC / 10u);           /* Determine MAX. idle counter value for 1/10 second  */
  11.     OS_ENTER_CRITICAL();
  12.     OSIdleCtrMax = OSIdleCtr;                    /* Store maximum idle counter count in 1/10 second    */
  13.     OSStatRdy    = OS_TRUE;
  14.     OS_EXIT_CRITICAL();
  15. }

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



  6.     p_arg = p_arg;                               /* Prevent compiler warning for not using 'p_arg'     */
  7.     while (OSStatRdy == OS_FALSE) {
  8.         OSTimeDly(2u * OS_TICKS_PER_SEC / 10u);  /* Wait until statistic task is ready                 */
  9.     }
  10.     OSIdleCtrMax /= 100uL;
  11.     if (OSIdleCtrMax == 0uL) {
  12.         OSCPUUsage = 0u;
  13. #if OS_TASK_SUSPEND_EN > 0u
  14.         (void)OSTaskSuspend(OS_PRIO_SELF);
  15. #else
  16.         for (;;) {
  17.             OSTimeDly(OS_TICKS_PER_SEC);
  18.         }
  19. #endif
  20.     }
  21.     for (;;) {
  22.         OS_ENTER_CRITICAL();
  23.         OSIdleCtrRun = OSIdleCtr;                /* Obtain the of the idle counter for the past second */
  24.         OSIdleCtr    = 0uL;                      /* Reset the idle counter for the next second         */
  25.         OS_EXIT_CRITICAL();
  26.         OSCPUUsage   = (INT8U)(100uL - OSIdleCtrRun / OSIdleCtrMax);
  27.         OSTaskStatHook();                        /* Invoke user definable hook                         */
  28. #if (OS_TASK_STAT_STK_CHK_EN > 0u) && (OS_TASK_CREATE_EXT_EN > 0u)
  29.         OS_TaskStatStkChk();                     /* Check the stacks for each task                     */
  30. #endif
  31.         OSTimeDly(OS_TICKS_PER_SEC / 10u);       /* Accumulate OSIdleCtr for the next 1/10 second      */
  32.     }
  33. }

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

MDK调试watch窗口:

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?注册

×

打赏榜单

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

您需要登录后才可以回帖 登录 | 注册

本版积分规则

2083

主题

14591

帖子

59

粉丝
快速回复 在线客服 返回列表 返回顶部