3 算法实现原理分析
操作系统运行时是不断在不同的任务间进行切换, 而驱动这一调度过程是通过系统 tick 来驱动的,即每产生一次系统 tick 则检
查一下当前正在运行的任务的环境判断是否需要切换任务,即调度, 如果需要,则触发 PendSV,通过在 PendSV 中断调用
vTaskSwitchContext()函数来实现任务的调度。 而本文所要讲述的 CPU 使用率算法是通过在一定时间内( 1000 个时间片内) ,
计算空闲任务所占用的时间片总量, 100 减去空闲任务所占百分比则为工作任务所占百分比,即 CPU 使用率。
此函数为空闲任务钩子函数, 每次当切换到空闲任务时就会运行此钩子函数, 它的作用就是记录当前空闲任务的句柄并保存
到全局变量 xIdleHandle。
此函数为操作系统的 tick 钩子函数,即每次产生系统 tick 中断都会进入到此钩子函数。 此钩子函数实际上就是具体计算 CPU
使用率的算法了。 osCPU_TotalIdleTime 是一个全局变量, 表示在 1000 个 tick 时间内空闲任务总共占用的时间片,
CALCULATION_PERIOD 宏的值为 1000, 即每 1000 个 tick 时间内重新计算一次 CPU 的使用率。
下面两个函数就是如何计算 osCPU_TotalIdleTime 的:
void StartIdleMonitor (void)
{
if( xTaskGetCurrentTaskHandle() == xIdleHandle ) //如果是切入到空闲任务
{
osCPU_IdleStartTime = xTaskGetTickCountFromISR();//记录切入到空闲任务的时间点
}
}
void EndIdleMonitor (void)
{
if( xTaskGetCurrentTaskHandle() == xIdleHandle ) //如果是从空闲任务切出
{
/* Store the handle to the idle task. */
osCPU_IdleSpentTime = xTaskGetTickCountFromISR() - osCPU_IdleStartTime; //计算此次空闲
任务花费多长时间
osCPU_TotalIdleTime += osCPU_IdleSpentTime; //空闲任务所占时间进行累加
}
}
这两个函数是调度器钩子函数,在调度器进行任务切进和切出时分别回调, StartIdleMonitor()函数记录切换到空闲任务时的时
间点, EndIdleMonitor()则在推出空闲任务时计算此次空闲任务花费多长时间,并累加到 osCPU_TotalIdleTime, 即空闲任务
总共占用的时间片 。
uint16_t osGetCPUUsage (void)
{
return (uint16_t)osCPU_Usage; //直接返回全局变量 osCPU_Usage, 即 CPU 使用率
}
全局变量 osCPU_Usage 保存的就是 CPU 的使用率,它是在操作系统的 tick 钩子函数中每隔 1000 个 tick 就被重新计算一次。
|