随着芯片的集成度提高,芯片内部的晶体管数量也不断增多,产生的热量也难以通过小小芯片封装散发出去(常用封装材料有塑料、陶瓷、玻璃、金属,CPU一般采用金属材料封装),高温是会对芯片的性能产生极其有害影响的。研究表明,芯片温度每升高1℃其运行可靠性降低3.8%,而芯片温度每下降10%其寿命增加50%,而在电子设备失效统计中也有超过50%是由于过热导致的。大数据后起之秀贵州,就凭借着优越的温和气候条件吸引了众多科技公司在那部署数据中心,这也充分表明散热对设备的稳定运行的影响。
CPU芯片温度的检测模块给产品设计散热提供了可能,在多变的产品应用场景中,需要提供智能散热设计,在节能的同时又能够提升产品工作的稳定性。以常规的风冷散热为例,通过检测CPU工作的温度,来获取产品工作的热环境,并配套以PWM风冷风扇转速调节,以保证产品工作在比较良好的热环境中。海思HI35xx平台系列的CPU也提供相应的温度检测模块,安防监控领域中有不少设备是暴露在户外的工作环境,这对散热设计提供了更苛刻的要求,基于CPU内部自带温度监测单元可以减少不必要的温度传感器外设设计,既能节约成本,又大大方便了开发设计的过程。
海思CPU芯片内部集成了温度传感器,温度的检测范围为-40~125℃,支持设置温度上下限阈值报警输出。作为芯片工作的热环境晴雨表,内部温度传感器提供了单次采集模式和循环采集模式两种选择,其中循环采集模式需要用户设定采集周期,它由一个8位的寄存器配置,采集周期设置范围为2ms~512ms。此外,该单元还提供了8个温度数据寄存器,用于记录最近8次采集到的温度值,可以方便了解温度变化的趋势,在实际应用中可以利用此温度变化梯度进行温度PID调节。
海思CPU温度采集单元软件开发分为驱动程序部分和用户态软件开发,其中驱动程序部分主要是与硬件交互,实现底层数据采集转换工作,而用户态则主要是程序应用逻辑控制设计。用户态程序设计流程如下:
1.设置温度采集模式
2.设置温度采集周期
3.设置温度报警上限阈值
4.设置温度报警下线阈值
5.使能启动温度采集
6.读取CPU温度值
7.读取温度报警上限标志
8.读取温度报警下限标志
/************************************************************************************************
*****Describe: This program is writen to get HI35xx CPU Chip Temperature. *****
*****Email: [email protected] *****
*****Author: shuang liang li *****
*****Date: 2018-10-18 *****
*************************************************************************************************/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include "Hi_Tsensor.h"
#ifdef debugprintf
#define debugpri(mesg, args...) fprintf(stderr, "[HI Serial print:%s:%d:] " mesg "\n", __FILE__, __LINE__, ##args)
#else
#define debugpri(mesg, args...)
#endif
#define HITSENSORDEV "/dev/hi_tsensor"
int hifd;
void Hi_Tsensor_sigsegv(int dummy)
{
if(hifd > 0)
close(hifd);
fprintf(stderr, "Hi Tsensor Caught SIGSEGV, Abort!\n");
fclose(stderr);
abort();
}
void Hi_Tsensor_sigterm(int dummy)
{
if(hifd > 0)
close(hifd);
fprintf(stderr, "Hi Tsensor Caught SIGTERM, Abort!\n");
fclose(stderr);
exit(0);
}
void Hi_init_signals(void)
{
struct sigaction sa;
sa.sa_flags = 0;
sigemptyset(&sa.sa_mask);
sigaddset(&sa.sa_mask, SIGSEGV);
sigaddset(&sa.sa_mask, SIGTERM);
sigaddset(&sa.sa_mask, SIGPIPE);
sa.sa_handler = Hi_Tsensor_sigsegv;
sigaction(SIGSEGV, &sa, NULL);
sa.sa_handler = Hi_Tsensor_sigterm;
sigaction(SIGTERM, &sa, NULL);
sa.sa_handler = SIG_IGN;
sigaction(SIGPIPE, &sa, NULL);
}
int GetCurTemperature(int fd, float *tempera)
{
float tmp;
Hi_Tsensor_info hitsensor;
//读取当前CPU温度值
memset(&hitsensor,0,sizeof(Hi_Tsensor_info));
if(ioctl(fd, GET_TEMPER, &hitsensor) != 0)
{
debugpri("GET_TEMPER,value %d,error\r\n",hitsensor.value);
return -1;
}
debugpri("tmp %04x\n",hitsensor.value );
tmp = ((hitsensor.value - 125)/806.0)*165-40;
*tempera = tmp;
printf("Hisi CPU current Temperature: %3.2f degree\n",tmp);
//读取温度上限报警
memset(&hitsensor,0,sizeof(Hi_Tsensor_info));
if(ioctl(fd, GET_OVERUP, &hitsensor) != 0)
{
debugpri("GET_OVERUP,value %d,error\r\n",hitsensor.value);
return -1;
}
if(hitsensor.value)
printf("Hisi CPU current Temperature OVERUP\n");
//读取温度下限报警
memset(&hitsensor,0,sizeof(Hi_Tsensor_info));
if(ioctl(fd, GET_OVERDN, &hitsensor) != 0)
{
debugpri("GET_OVERDN,value %d,error\r\n",hitsensor.value);
return -1;
}
if(hitsensor.value)
printf("Hisi CPU current Temperature OVERDOWN\n");
return 0;
}
int main(int argc, char **argv)
{
int ret = 0, i;
float temperature;
Hi_Tsensor_info hitsensor;
Hi_init_signals();
hifd = open(HITSENSORDEV,O_RDWR);
if(hifd <= 0)
{
printf("open %s error\n",HITSENSORDEV);
return -1;
}
//设置采集模式为循环采集
memset(&hitsensor,0,sizeof(Hi_Tsensor_info));
hitsensor.value = 1;
if(ioctl(hifd, SET_MODE, &hitsensor) != 0)
{
debugpri("SET_MODE,value %d,error\r\n",hitsensor.value);
return -1;
}
//设置采集周期为16ms
memset(&hitsensor,0,sizeof(Hi_Tsensor_info));
hitsensor.value = 16;
if(ioctl(hifd, SET_PERIOD, &hitsensor) != 0)
{
debugpri("SET_PERIOD,value %d,error\r\n",hitsensor.value);
return -1;
}
//设置温度报警上限阈值为85摄氏度
memset(&hitsensor,0,sizeof(Hi_Tsensor_info));
hitsensor.value = 85;
hitsensor.value = (int)(((hitsensor.value+40)/165.0)*806+125);//温度值转换
if(ioctl(hifd, SET_OVERUP, &hitsensor) != 0)
{
debugpri("SET_OVERUP,value %d,error\r\n",hitsensor.value);
return -1;
}
//设置温度报警下限阈值为5摄氏度
memset(&hitsensor,0,sizeof(Hi_Tsensor_info));
hitsensor.value = 5;
hitsensor.value = (int)(((hitsensor.value+40)/165.0)*806+125);//温度值转换
if(ioctl(hifd, SET_OVERDN, &hitsensor) != 0)
{
debugpri("SET_OVERDN,value %d,error\r\n",hitsensor.value);
return -1;
}
//启动温度采集
memset(&hitsensor,0,sizeof(Hi_Tsensor_info));
hitsensor.value = 1;
if(ioctl(hifd, SET_START, &hitsensor) != 0)
{
debugpri("SET_START,value %d,error\r\n",hitsensor.value);
return -1;
}
while(1)
{
GetCurTemperature(hifd,&temperature);
sleep(1);
system("clear");
printf("HiTsensor device detecting...\n");
}
if(hifd > 0)
close(hifd);
return 0;
}
样例运行效果图:
海思芯片内部温度检测单元给我们提供了一个窗口了解芯片运行的热环境,方便进行散热设计,提高产品运行的稳定性。驱动源码与应用样例源码已经由云托管,点此下载。原创不易,转载说明出处。