IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 嵌入式 -> hisi3516dv300芯片基于hwmon驱动框架的温度获取驱动源码分析 -> 正文阅读

[嵌入式]hisi3516dv300芯片基于hwmon驱动框架的温度获取驱动源码分析

1、内核hwmon驱动框架

参考博客:《内核hwmon驱动框架详解以及海思芯片温度驱动分析》

2、驱动实现的效果

/sys/devices/virtual/hwmon/hwmon0 # pwd
/sys/class/hwmon/hwmon0
/sys/devices/virtual/hwmon/hwmon0 # ls
power        subsystem    temp1_input  uevent
/sys/devices/virtual/hwmon/hwmon0 # cat temp1_input 
41
/sys/devices/virtual/hwmon/hwmon0 # 

(1)在sysfs中可以看到/sys/class/hwmon/hwmon0文件夹,里面有temp1_input文件;
(2)读取temp1_input文件,里面是芯片的温度值;
(3)文件夹名字不一定是hwmon0,如果你注册了不止一个hwmon设备,文件夹名字有可能是hwmon0或者hwmon1,看你注册hwmon设备的先后顺序;

3、获取芯片温度驱动的思路分析

(1)向内核hwmon驱动框架注册我们的驱动,在hwmon类下面创建相应的设备;
(2)填充创建的hwmon类设备的设备属性,创建保存温度值的文件,指定文件的show方法;
(3)对海思芯片温度传感器相关的寄存器进行动态映射;
(4)初始化海思芯片温度相关的寄存器,包括设置温度检测模式为循环模式、循环检测周期、使能等;
(5)应用通过读取temp1_input文件获取温度,实际就是执行temp1_input文件的show方法;
(6)在show方法中,读取温度记录值寄存器的值,计算出温度值并返回;

4、芯片自带的温度传感器

地址偏移量寄存器编号寄存器名字
0x00B4MISC_CTRL45Tsensor控制寄存器
0x00B8MISC_CTRL46Tsensor 状态寄存器
0x00BCMISC_CTRL47Tsensor 温度记录值寄存器 0
0x00C0MISC_CTRL48Tsensor 温度记录值寄存器 1
0x00C4MISC_CTRL49Tsensor 温度记录值寄存器 2
0x00C8MISC_CTRL50Tsensor 温度记录值寄存器 3

5、寄存器功能描述

5.1、Tsensor控制寄存器

在这里插入图片描述

(1)温度检测模式:一般选择循环检测模式,不停的去检测温度;
(2)循环检测周期:当设置为循环检测模式时要设置,就是每隔多长时间去检测一次温度,注意单位是2ms;
(3)温度上/下溢值:往寄存器写入值,表示芯片温度超过这个值时会触发Tsensor 状态寄存器的温度上/下溢报警位。这几个寄存器的位不是直接写温度值,有换算关系,hisi3516dv300的数据手册没有明确写出,但是按照海思其他芯片推测,应该是(tsensor_uplimit -136)/793*165-40

5.2、Tsensor 状态寄存器

在这里插入图片描述

(1)如果在Tsensor控制寄存器寄存器中设置了温度上/下溢值,则需要检测温度下溢告警位;
(2)其他的位不用也没什么影响,不设置也是可以正常工作;

5.3、Tsensor温度记录值寄存器

在这里插入图片描述

(1)总共有4个温度记录值寄存器,每个寄存器的bit位含义都是一样的;
(2)每个温度记录值寄存器都保存了两个温度值,分别保存在[9:0]和[25:16]bit位;
(3)Soc在4个温度记录值寄存器中保存了8个温度值,我们需要读出8个温度值来计算一个平均的温度值;
(4)温度计算公式:Temprature=(tsensor_result[0:1] -136)/793*165-40(单位:度);

6、芯片内部温度检测流程

步骤 1:设置 T-Sensor 采集模式 MISC_CTRL45[30]。
步骤 2:如果设置为循环采集模式,需设置循环采集周期 MISC_CTRL45[27:20];如果设置为单次采集模式,可略过此步骤。循环采集周期计算公式为: T = N × 2(ms),其中 N=MISC_CTRL45[27:20]。
步骤 3:使能 T-Sensor MISC_CTRL45[31],开始温度采集
步骤 4:软件读取T-Sensor采集到的温度码(十六进制值)。单次采集模式下,只有 MISC_CTRL47[9:0]中记录的温度记录码0有效。
循环采集模式下,MISC_CTRL47[31:0]~MISC_CTRL50[31:0]记录了最近八次温度记录码 0~7,其中最新的温度记录值为温度记录码 0。
步骤 5:根据温度记录码计算出对应的温度值。Temprature=(T-Senso -136)/793*165-40(单位:度);

7、驱动源码分析

7.1、驱动的注册函数

static int hisi3516d_hwmon_init(void)
{
	int ret;

	//向hwmon驱动框架注册我们的驱动
	hisi3516d_hwmon_dev = hwmon_device_register(NULL);
	if(IS_ERR(hisi3516d_hwmon_dev)){
		
		printk(KERN_ERR "hwmod device register faild\n");
		ret = PTR_ERR((void *)hisi3516d_hwmon_dev);
		goto err_exit_3;
	}

	//填充hwmon驱动框架返回的设备,也就是创建设备下面的文件以及show、store方法
	ret = sysfs_create_group(&hisi3516d_hwmon_dev->kobj,
                                &hisi3516d_hwmon_attribute_group);
	if(ret){

		printk(KERN_ERR "create sysfs group faild\n");
		goto err_exit_2;
	}

	//映射芯片温度相关寄存器的地址
	ret = reg_remap();
	if(ret){
		printk(KERN_ERR "hi3559a hwmon ioremap faild\n");
		goto err_exit_1;
	}

	//初始化海思芯片的Tsensor寄存器
	hisi3516d_temp_init();

	return 0;
	
err_exit_1:
	sysfs_remove_group(&hisi3516d_hwmon_dev->kobj,&hisi3516d_hwmon_attribute_group);
err_exit_2:
	hwmon_device_unregister(hisi3516d_hwmon_dev);
err_exit_3:
	return ret;
	
}

module_init(hisi3516d_hwmon_init);

(1)向hwmon驱动框架注册我们的驱动,得到一个设备结构体;
(2)填充设备结构体,给设备创建文件以及show、store方法;
(3)映射芯片温度相关寄存器的地址,这里采用的动态映射;
(4)初始化海思芯片的Tsensor寄存器,设置温度检测模式为循环模式、循环检测周期、使能等;

7.2、驱动的卸载函数

static void hisi3516d_hwmon_exit(void)
{
	//解除寄存器的映射
	reg_unmap();
	
	//注销设备下的文件
	sysfs_remove_group(&hisi3516d_hwmon_dev->kobj,&hisi3516d_hwmon_attribute_group);
	
	//从hwmon驱动框架中注销驱动
	hwmon_device_unregister(hisi3516d_hwmon_dev);
}

module_exit(hisi3516d_hwmon_exit);

就是注册函数的逆过程,释放资源,删除sysfs中创建的文件,从hwmon驱动框架中注销驱动;

7.3、创建temp1_input文件

struct device *hisi3516d_hwmon_dev;

static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp1_input, NULL, 0);

static struct attribute *hisi3516d_hwmon_attributes[] = {
	&sensor_dev_attr_temp1_input.dev_attr.attr,
	NULL,
};

static struct attribute_group hisi3516d_hwmon_attribute_group = {
	.attrs = hisi3516d_hwmon_attributes,
};

(1)hisi3516d_hwmon_attribute_group变量是用来创建设备下的文件以及文件show、store方法的;
(2)文件名字是temp1_input,show方法是show_temp1_input()函数;
(3)SENSOR_DEVICE_ATTR宏的分析参考博客:https://blog.csdn.net/weixin_42031299/article/details/124890370;

7.4、读取Tsensor寄存器温度的函数

static ssize_t show_temp1_input(struct device *dev,
		struct device_attribute *da, char *buf)
{
	volatile unsigned int reg_val = 0;
	unsigned int tmp_val = 0;
	int32_t temperature_val = 0;
	int32_t i = 0;

	//获取温度记录值寄存器0寄存器中保存的两个温度值
    reg_val = ioread32((void __iomem *)tsensorviraddr + T_SENSOR_RESULT0);
    for(i = 0; i < 2; i++)
    {
        tmp_val = (reg_val >> (16*i)) & 0x3ff;
        temperature_val += (tmp_val - 136)/793*165 - 40;
    }

	//获取温度记录值寄存器1寄存器中保存的两个温度值
    reg_val = ioread32((void __iomem *)tsensorviraddr + T_SENSOR_RESULT1);
    for(i = 0; i < 2; i++)
    {
        tmp_val = (reg_val >> (16*i)) & 0x3ff;
        temperature_val += (tmp_val - 136)/793*165 - 40;
    }

	//获取温度记录值寄存器2寄存器中保存的两个温度值
    reg_val = ioread32((void __iomem *)tsensorviraddr + T_SENSOR_RESULT2);
    for(i = 0; i < 2; i++)
    {
        tmp_val = (reg_val >> (16*i)) & 0x3ff;
        temperature_val += (tmp_val - 136)/793*165 - 40;
    }

	//获取温度记录值寄存器3寄存器中保存的两个温度值
    reg_val = ioread32((void __iomem *)tsensorviraddr + T_SENSOR_RESULT3);
    for(i = 0; i < 2; i++)
    {
        tmp_val = (reg_val >> (16*i)) & 0x3ff;
        temperature_val += (tmp_val - 136)/793*165 - 40;
    }

	//温度值除以8,获取平均值
	temperature_val = temperature_val >> 3;
	
	sprintf(buf, "%d", temperature_val);
	return strlen(buf);
}

(1)tsensorviraddr:温度相关寄存器动态映射后得到的基地址;
(2)获取8个温度值,然后再返回温度的平均值;
(3)当我们用"cat /sys/class/hwmon/hwmon0/temp1_input"命令读取temp1_input文件时,驱动里就调用show_temp1_input()函数,这是temp1_input文件的show方法;

  嵌入式 最新文章
基于高精度单片机开发红外测温仪方案
89C51单片机与DAC0832
基于51单片机宠物自动投料喂食器控制系统仿
《痞子衡嵌入式半月刊》 第 68 期
多思计组实验实验七 简单模型机实验
CSC7720
启明智显分享| ESP32学习笔记参考--PWM(脉冲
STM32初探
STM32 总结
【STM32】CubeMX例程四---定时器中断(附工
上一篇文章      下一篇文章      查看所有文章
加:2022-05-24 18:23:18  更:2022-05-24 18:23:36 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 1:34:05-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码