平均负载表示了对CPU 资源的需求,通过汇总正在运行的线程数(使用率)和正在排队等待运行的线程数(饱和度)计算得出。计算平均负载的一个新方法是把使用率加上线程调度器延时得出,而不是去取样队列长度,从而提高精度。
这个值的意义为,平均负载大于CPU 数量表示CPU 不足以服务线程,有些线程在等待。如果平均负载小于CPU 数量,这(很可能)代表还有一些余量,线程可以在它们想要的时候在CPU 上运行。
平均负载是指单位时间内,系统处于可运行状态和不可中断状态的平均进程数,也就是平均活跃进程数,它和 CPU 使用率并没有直接关系。
可运行状态的进程:是指正在使用 CPU 或者正在等待 CPU 的进程,也就是我们常用 ps 命令看到的,处于 R 状态(Running 或 Runnable)的进程。
不可中断状态的进程:是正处于内核态关键流程中的进程,并且这些流程是不可打断的,比如最常见的是等待硬件设备的 I/O 响应,也就是我们在 ps 命令中看到的 D 状态(Uninterruptible Sleep,也称为 Disk Sleep)的进程。
STM32CubeMX软件中找到FREERTOS。选择Config parameters项,找到[USE_IDLE_HOOK][USE_TICK_HOOK]并使能。
选择Include parameters项,找到[vTaskDelayUntil]并使能。
在FreeOS_Config.h中定义以下宏定义: 注意!!!是在用户代码区定义,否则会被清除。!!!
#define traceTASK_SWITCHED_IN() extern void StartIdleMonitor(void);StartIdleMonitor()
#define traceTASK_SWITCHED_OUT() extern void EndIdleMonitor(void);EndIdleMonitor()
STM32CubeMX软件中找到ADCX(可能是ADC1/ADC2等等),在Mode项,找到Temperature Sensor Channel(温度传感器),并勾选。
选择Parameter Settings项,ADC_Settings–>Continuous Conversion Mode(连续转换模式),使能连续转换。
选择Parameter Settings项,Rank–>Sampling Time,设置为[239.5 Cycles],如果有更大,选更大。
选择Parameter Settings项,ADC Injected Conversion Mode–>Injected Conversion Mode(连续转换模式),选择Auto Injected Mode(自动采集模式)
选择DMA Settings项,Mode设置为Cirular(循环模式),Data Width设置为Word。
通过这个[CPU_TEMP_EN]宏定义来控制,查询CPU温度的代码是否编译。
[使用方法]:用于存储采集到CPU温度的两个变量本文件已定义,使用时,加入 #include “cpu_utils.h” 即可。
HAL_ADC_Start_DMA(&hadc1, &CPU_Temp_AD, 1); //在RTOS任务的循环外调用该采集函数
CPU_TEMP = osGetCPUTemp(&hadc1);//得到真正温度,需要读取温度时调用
/**
******************************************************************************
* @file cpu_utils.c
* @author MCD Application Team
* @version V1.1.0
* @date 20-November-2014
* @brief Utilities for CPU Load calculation
******************************************************************************
* @attention
*
* <h2><center>© COPYRIGHT(c) 2014 STMicroelectronics</center></h2>
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of STMicroelectronics nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
******************************************************************************
*/
/********************** NOTES **********************************************
一、【查询CPU使用率】 要使用此功能,应遵循以下步骤:
1、STM32CubeMX软件中找到FREERTOS。选择Config parameters项,找到[USE_IDLE_HOOK][USE_TICK_HOOK]并使能。
选择Include parameters项,找到[vTaskDelayUntil]并使能。
2、在FreeOS_Config.h中定义以下宏定义: 注意!!!是在用户代码区定义,否则会被清除。!!!
#define traceTASK_SWITCHED_IN() extern void StartIdleMonitor(void);StartIdleMonitor()
#define traceTASK_SWITCHED_OUT() extern void EndIdleMonitor(void);EndIdleMonitor()
3、[获取CPU使用率] usage = osGetCPUUsage();
二、【查询CPU温度】 要使用此功能,应遵循以下步骤:
1、STM32CubeMX软件中找到ADCX(可能是ADC1/ADC2等等),在Mode项,找到Temperature Sensor Channel(温度传感器),并勾选。
选择Parameter Settings项,ADC_Settings-->Continuous Conversion Mode(连续转换模式),使能连续转换。
选择Parameter Settings项,Rank-->Sampling Time,设置为[239.5 Cycles],如果有更大,选更大。
选择Parameter Settings项,ADC Injected Conversion Mode-->Injected Conversion Mode(连续转换模式),选择Auto Injected Mode(自动采集模式)
选择DMA Settings项,Mode设置为Cirular(循环模式),Data Width设置为Word。
2、通过这个[CPU_TEMP_EN]宏定义来控制,查询CPU温度的代码是否编译。
3、[使用方法]:用于存储采集到CPU温度的两个变量本文件已定义,使用时,加入 #include "cpu_utils.h" 即可。
HAL_ADC_Start_DMA(&hadc1, &CPU_Temp_AD, 1); //在RTOS任务的循环外调用该采集函数
CPU_TEMP = osGetCPUTemp(&hadc1);//得到真正温度,需要读取温度时调用
*******************************************************************************/
/* Includes ------------------------------------------------------------------*/
#include "cpu_utils.h"
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
#define CPU_TEMP_EN 1 //0不启用,1启动
/* Private macro -------------------------------------------------------------*/
/* Private function prototypes -----------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
xTaskHandle xIdleHandle = NULL;
__IO uint32_t osCPU_Usage = 0;
uint32_t osCPU_IdleStartTime = 0;
uint32_t osCPU_IdleSpentTime = 0;
uint32_t osCPU_TotalIdleTime = 0;
volatile double CPU_TEMP = 0; //用于存放温度值
volatile uint32_t CPU_Temp_AD = 0; //用于存放温度AD值
/* Private functions ---------------------------------------------------------*/
/**
* @brief Application Idle Hook
*/
void vApplicationIdleHook(void)
{
if( xIdleHandle == NULL )
{
/* Store the handle to the idle task. */
xIdleHandle = xTaskGetCurrentTaskHandle();
}
}
/**
* @brief Application Idle Hook
*/
void vApplicationTickHook (void)
{
static int tick = 0;
if(tick ++ > CALCULATION_PERIOD)
{
tick = 0;
if(osCPU_TotalIdleTime > 1000)
{
osCPU_TotalIdleTime = 1000;
}
osCPU_Usage = (100 - (osCPU_TotalIdleTime * 100) / CALCULATION_PERIOD);
osCPU_TotalIdleTime = 0;
}
}
/**
* @brief Start Idle monitor
*/
void StartIdleMonitor (void)
{
if( xTaskGetCurrentTaskHandle() == xIdleHandle )
{
osCPU_IdleStartTime = xTaskGetTickCountFromISR();
}
}
/**
* @brief Stop Idle monitor
*/
void EndIdleMonitor (void)
{
if( xTaskGetCurrentTaskHandle() == xIdleHandle )
{
/* Store the handle to the idle task. */
osCPU_IdleSpentTime = xTaskGetTickCountFromISR() - osCPU_IdleStartTime;
osCPU_TotalIdleTime += osCPU_IdleSpentTime;
}
}
/*********************************************
函数名:osGetCPUUsage
功 能:得到CPU使用率 %
**********************************************/
uint16_t osGetCPUUsage (void)
{
return (uint16_t)osCPU_Usage;
}
/*********************************************
函数名:osGetCPUTemp
功 能:得到CPU内部温度
形 参:hadc--ADC选择 Temp_AD--ADC采集的模拟量
返回值:
备 注:(1.43 - 3.3/4095 * SampleValue)/0.0043 + 25
笔 记:MX配置生成的ADC默认1000,未找到原因
**********************************************/
#if CPU_TEMP_EN
double osGetCPUTemp(ADC_HandleTypeDef* hadc)
{
static uint8_t i = 0;
double temp = 0;
if(i == 0)
{
i = 1;
HAL_ADC_Start_DMA(hadc, (uint32_t *)&CPU_Temp_AD, 1);
HAL_Delay(5);
}
for(uint8_t a = 0; a < 10; a++)
{
temp += CPU_Temp_AD;
HAL_Delay(2);
}
return (1.43 - (temp/1000/10)) + 25;
//return CPU_Temp_AD;
}
#endif
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
/**
******************************************************************************
* @file cpu_utils.h
* @author MCD Application Team
* @version V1.1.0
* @date 20-November-2014
* @brief Header for cpu_utils module
******************************************************************************
* @attention
*
* <h2><center>© COPYRIGHT(c) 2014 STMicroelectronics</center></h2>
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of STMicroelectronics nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
******************************************************************************
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef _CPU_UTILS_H__
#define _CPU_UTILS_H__
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "cmsis_os.h"
#include "stm32f1xx_hal.h"
/* Exported types ------------------------------------------------------------*/
/* Exported constants --------------------------------------------------------*/
/* Exported variables --------------------------------------------------------*/
extern volatile double CPU_TEMP;
extern volatile uint32_t CPU_Temp_AD;
/* Exported macro ------------------------------------------------------------*/
#define CALCULATION_PERIOD 1000
/* Exported functions ------------------------------------------------------- */
uint16_t osGetCPUUsage (void);
double osGetCPUTemp(ADC_HandleTypeDef* hadc);
#ifdef __cplusplus
}
#endif
#endif /* _CPU_UTILS_H__ */
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/