本帖最后由 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窗口:
|