imx6ull内置温度传感器实践1:输出一个采样

news2025/1/11 18:50:21

前言

        先写代码,然后再一个问题,一个问题分析。不是应该先分析问题,再写代码吗?因为笨呗。分析不明白。只有看到现象,才能明白手册上说的是啥意思。   

        实例1 主要完成以下几个事情

        1 创建一个misc驱动

        2 在驱动中将寄存器remap过来,需要映射的寄存器的列表,不要怕,代码都有。

         3 配置寄存器的值,然后在1秒定时器中输出TEMP_CNT值

 

一 使用到的函数

        映射和解除映射函数

        如下,ioremap其实是一个宏,但是宏看起来不好理解,所以,我就把它当成一个下面这样的函数来用,好理解,ioremap的返回值,可以作为iounmap的参数,ioremap的第一个参数paddr就是前面列表中的寄存器地址,例如0x20c 8180,它是32位寄存器,4个字节,所以参数byte_count传入4。

#include <asm/io.h>
volatile void __iomem *ioremap(void *paddr,int byte_count);
void iounmap (volatile void __iomem *addr)

读寄存器函数

u8 readb ( const volatile void __iomem * addr )
u16 readw ( const volatile void __iomem * addr )
u32 readl ( const volatile void __iomem * addr )
readb readw readl 这三个函数分别对应 8bit 16bit 32bit 读操作,参数 addr 就是要
读取写内存地址,返回值就是读取到的数据。

写寄存器函数

void writeb ( u8 value , volatile void __iomem * addr )
void writew ( u16 value , volatile void __iomem * addr )
void writel ( u32 value , volatile void __iomem * addr )
writeb writew writel 这三个函数分别对应 8bit 16bit 32bit 写操作,参数 value 是要
写入的数值, addr 是要写入的地址。

本次实例,我们使用writel readl

二 实例代码

#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/fs.h>
#include <linux/miscdevice.h>
#include <asm/io.h>
#include <linux/timer.h>
#include <linux/string.h>
#include <linux/delay.h>
#include <linux/time.h>
#include <linux/mutex.h>
#include <linux/slab.h>

#define DEBUG_TEMP(format,...)	printk("%s,%d:"format"\n",	\
	__func__,__LINE__,##__VA_ARGS__)

/* 寄存器物理地址 */
#define		TEMPMON_TEMPSENSE0 		(0x020C8180)
#define		TEMPMON_TEMPSENSE0_SET	(0x020C8184)
#define		TEMPMON_TEMPSENSE0_CLR	(0x020C8188)
#define		TEMPMON_TEMPSENSE0_TOG	(0x020C818C)

#define		TEMPMON_TEMPSENSE1 		(0x020C8190)
#define		TEMPMON_TEMPSENSE1_SET	(0x020C8184)
#define		TEMPMON_TEMPSENSE1_CLR	(0x020C8198)
#define		TEMPMON_TEMPSENSE1_TOG	(0x020C819C)

#define		TEMPMON_TEMPSENSE2 		(0x020C8290)
#define		TEMPMON_TEMPSENSE2_SET	(0x020C8294)
#define		TEMPMON_TEMPSENSE2_CLR	(0x020C8298)
#define		TEMPMON_TEMPSENSE2_TOG	(0x020C829C)

 /* 映射后的寄存器虚拟地址指针 */
static void __iomem *IMX6U_TEMPMON_TEMPSENSE0;
static void __iomem *IMX6U_TEMPMON_TEMPSENSE0_SET;
static void __iomem *IMX6U_TEMPMON_TEMPSENSE0_CLR;
static void __iomem *IMX6U_TEMPMON_TEMPSENSE0_TOG;

static void __iomem *IMX6U_TEMPMON_TEMPSENSE1;
static void __iomem *IMX6U_TEMPMON_TEMPSENSE1_SET;
static void __iomem *IMX6U_TEMPMON_TEMPSENSE1_CLR;
static void __iomem *IMX6U_TEMPMON_TEMPSENSE1_TOG;

static void __iomem *IMX6U_TEMPMON_TEMPSENSE2;
static void __iomem *IMX6U_TEMPMON_TEMPSENSE2_SET;
static void __iomem *IMX6U_TEMPMON_TEMPSENSE2_CLR;
static void __iomem *IMX6U_TEMPMON_TEMPSENSE2_TOG;

struct temperature_register{
	void __iomem *ctrl;
	void __iomem *set;
	void __iomem *clr;
	void __iomem *tog;
};

struct _temperature_sensor_{
	struct miscdevice misc;
	struct file_operations fops;
	struct temperature_register reg[3];
	struct timer_list timer;
};

#define IMX6U_TEMPMON_TEMPSENSE(num)	(IMX6U_TEMPMON_TEMPSENSE##num)
#define IMX6U_TEMPMON_TEMPSENSE_XXX(num,text)	(IMX6U_TEMPMON_TEMPSENSE##num##text)

static int imx_temperature_monitor_init(struct _temperature_sensor_ *p)
{
	int i = 0;
	u32 val;
	IMX6U_TEMPMON_TEMPSENSE0 = ioremap(TEMPMON_TEMPSENSE0,4);
	IMX6U_TEMPMON_TEMPSENSE0_SET = ioremap(TEMPMON_TEMPSENSE0_SET,4);
	IMX6U_TEMPMON_TEMPSENSE0_CLR = ioremap(TEMPMON_TEMPSENSE0_CLR,4);
	IMX6U_TEMPMON_TEMPSENSE0_TOG = ioremap(TEMPMON_TEMPSENSE0_TOG,4);

	DEBUG_TEMP("%p",IMX6U_TEMPMON_TEMPSENSE0);
	DEBUG_TEMP("%p",IMX6U_TEMPMON_TEMPSENSE0_SET);
	DEBUG_TEMP("%p",IMX6U_TEMPMON_TEMPSENSE0_CLR);
	DEBUG_TEMP("%p",IMX6U_TEMPMON_TEMPSENSE0_TOG);

	IMX6U_TEMPMON_TEMPSENSE1 = ioremap(TEMPMON_TEMPSENSE1,4);
	IMX6U_TEMPMON_TEMPSENSE1_SET = ioremap(TEMPMON_TEMPSENSE1_SET,4);
	IMX6U_TEMPMON_TEMPSENSE1_CLR = ioremap(TEMPMON_TEMPSENSE1_CLR,4);
	IMX6U_TEMPMON_TEMPSENSE1_TOG = ioremap(TEMPMON_TEMPSENSE1_TOG,4);

	DEBUG_TEMP("%p",IMX6U_TEMPMON_TEMPSENSE1);
	DEBUG_TEMP("%p",IMX6U_TEMPMON_TEMPSENSE1_SET);
	DEBUG_TEMP("%p",IMX6U_TEMPMON_TEMPSENSE1_CLR);
	DEBUG_TEMP("%p",IMX6U_TEMPMON_TEMPSENSE1_TOG);

	IMX6U_TEMPMON_TEMPSENSE2 = ioremap(TEMPMON_TEMPSENSE2,4);
	IMX6U_TEMPMON_TEMPSENSE2_SET = ioremap(TEMPMON_TEMPSENSE2_SET,4);
	IMX6U_TEMPMON_TEMPSENSE2_CLR = ioremap(TEMPMON_TEMPSENSE2_CLR,4);
	IMX6U_TEMPMON_TEMPSENSE2_TOG = ioremap(TEMPMON_TEMPSENSE2_TOG,4);

	DEBUG_TEMP("%p",IMX6U_TEMPMON_TEMPSENSE2);
	DEBUG_TEMP("%p",IMX6U_TEMPMON_TEMPSENSE2_SET);
	DEBUG_TEMP("%p",IMX6U_TEMPMON_TEMPSENSE2_CLR);
	DEBUG_TEMP("%p",IMX6U_TEMPMON_TEMPSENSE2_TOG);

	p->reg[0].ctrl = IMX6U_TEMPMON_TEMPSENSE(0);
	p->reg[0].set = IMX6U_TEMPMON_TEMPSENSE_XXX(0,_SET);
	p->reg[0].clr = IMX6U_TEMPMON_TEMPSENSE_XXX(0,_CLR);
	p->reg[0].tog = IMX6U_TEMPMON_TEMPSENSE_XXX(0,_TOG);

	p->reg[1].ctrl = IMX6U_TEMPMON_TEMPSENSE(1);
	p->reg[1].set = IMX6U_TEMPMON_TEMPSENSE_XXX(1,_SET);
	p->reg[1].clr = IMX6U_TEMPMON_TEMPSENSE_XXX(1,_CLR);
	p->reg[1].tog = IMX6U_TEMPMON_TEMPSENSE_XXX(1,_TOG);

	p->reg[2].ctrl = IMX6U_TEMPMON_TEMPSENSE(2);
	p->reg[2].set = IMX6U_TEMPMON_TEMPSENSE_XXX(2,_SET);
	p->reg[2].clr = IMX6U_TEMPMON_TEMPSENSE_XXX(2,_CLR);
	p->reg[2].tog = IMX6U_TEMPMON_TEMPSENSE_XXX(2,_TOG);

	for(i = 0;i < 3;i++){
		DEBUG_TEMP("p->reg[%d].ctrl = %p",i,p->reg[i].ctrl);
		DEBUG_TEMP("p->reg[%d].set = %p",i,p->reg[i].set);
		DEBUG_TEMP("p->reg[%d].clr = %p",i,p->reg[i].clr);
		DEBUG_TEMP("p->reg[%d].tog = %p",i,p->reg[i].tog);
	}
	DEBUG_TEMP("");
	DEBUG_TEMP("");
	for(i = 0;i < 3;i++){
		DEBUG_TEMP("p->reg[%d].ctrl = %08x",i,readl(p->reg[i].ctrl));
		DEBUG_TEMP("p->reg[%d].set = %08x",i,readl(p->reg[i].set));
		DEBUG_TEMP("p->reg[%d].clr = %08x",i,readl(p->reg[i].clr));
		DEBUG_TEMP("p->reg[%d].tog = %08x",i,readl(p->reg[i].tog));
	}

	writel(1 << 0,p->reg[0].clr);
	writel(2 << 0,p->reg[0].clr);
	writel(1 << 1,p->reg[0].set);

	
	writel(1,p->reg[1].clr);
	return 0;
}
static long imx_temperature_unlocked_ioctl (
	struct file *file, unsigned int cmd, unsigned long arg)
{
	DEBUG_TEMP("");
	return 0;
}
struct _temperature_sensor_ imx_temperature_sensor = {
	.fops = {
		.owner = THIS_MODULE,
		.unlocked_ioctl = imx_temperature_unlocked_ioctl,
	},
	.misc = {
		.name = "imx_temp",
		.minor = MISC_DYNAMIC_MINOR,
	},
};
void temperature_timer_function(unsigned long arg)
{
	struct _temperature_sensor_ *p = (struct _temperature_sensor_ *)arg;
	u32 val = readl(p->reg[0].ctrl);
	static int last_val = 0;

	while(1){
		if((val & 0x04) == 0){
			break;
		}
		
		DEBUG_TEMP("val = %08x,%d,%d,temperature = %d",val,val-last_val,(val&0xfff00000)>>20,(val&0xfff00)>>8);
		last_val = val;
		
		writel(1 << 0,p->reg[0].clr);
		writel(2 << 0,p->reg[0].clr);
		writel(1 << 1,p->reg[0].set);
		break;
	}
	mod_timer(&p->timer,msecs_to_jiffies(1000) + jiffies);
}
static int __init temperature_init(void)
{
	struct _temperature_sensor_ *p = &imx_temperature_sensor;
	p->misc.fops = &p->fops;
	imx_temperature_monitor_init(p);
	
	
	if(misc_register(&p->misc) != 0){
		DEBUG_TEMP("misc_register error");
		return -EINVAL;
	}
	init_timer(&p->timer);
	p->timer.data = (unsigned long)p;
	p->timer.function = temperature_timer_function;
	mod_timer(&p->timer,msecs_to_jiffies(1000) + jiffies);
	DEBUG_TEMP("");
	return 0;
}
static void __exit temperature_exit(void)
{
	struct _temperature_sensor_ *p = &imx_temperature_sensor;
	int i = 0;
	del_timer_sync(&p->timer);
	for(i = 0;i < 3;i++){
		iounmap(p->reg[i].ctrl);
		iounmap(p->reg[i].set);
		iounmap(p->reg[i].clr);
		iounmap(p->reg[i].tog);
	}
	
	misc_deregister(&p->misc);
	DEBUG_TEMP("");
}
module_init(temperature_init);
module_exit(temperature_exit);
MODULE_LICENSE("GPL");

Makefile

export ARCH=arm
export CROSS_COMPILE=arm-linux-gnueabihf-
KERN_DIR = /home/lkmao/imx/linux/linux-imx

FILE_NAME=temperature
obj-m += $(FILE_NAME).o

all:
    make -C $(KERN_DIR) M=$(shell pwd) modules
    sudo cp $(FILE_NAME).ko /big/nfsroot/buildrootfs/home/root/
    sudo scp $(FILE_NAME).ko root@192.168.0.3:/home/root/
.PHONY:clean
clean:
    make -C $(KERN_DIR) M=$(shell pwd) clean
    rm app -rf

测试结果

[ 1428.046419] temperature_timer_function,166:val = 49a4d006,256,1178,temperature = 1232
[ 1429.046419] temperature_timer_function,166:val = 49a4cf06,-256,1178,temperature = 1231
[ 1430.046420] temperature_timer_function,166:val = 49a4cf06,0,1178,temperature = 1231
[ 1431.046419] temperature_timer_function,166:val = 49a4cf06,0,1178,temperature = 1231
[ 1432.046418] temperature_timer_function,166:val = 49a4d006,256,1178,temperature = 1232
[ 1433.046425] temperature_timer_function,166:val = 49a4d006,0,1178,temperature = 1232
[ 1434.046415] temperature_timer_function,166:val = 49a4cf06,-256,1178,temperature = 1231
[ 1435.046418] temperature_timer_function,166:val = 49a4cf06,0,1178,temperature = 1231
[ 1436.046420] temperature_timer_function,166:val = 49a4cf06,0,1178,temperature = 1231
[ 1437.046420] temperature_timer_function,166:val = 49a4cf06,0,1178,temperature = 1231
[ 1438.046419] temperature_timer_function,166:val = 49a4cf06,0,1178,temperature = 1231
[ 1439.046418] temperature_timer_function,166:val = 49a4cf06,0,1178,temperature = 1231
[ 1440.046419] temperature_timer_function,166:val = 49a4cf06,0,1178,temperature = 1231
[ 1441.046421] temperature_timer_function,166:val = 49a4cf06,0,1178,temperature = 1231

小结

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/11123.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【HDU No. 1232】 畅通工程

【HDU No. 1232】 畅通工程 杭电OJ 题目地址 【题意】 现有城镇道路统计表&#xff0c;表中列出了每条直接相连的城镇道路。“畅通工程”的目标是使全省任意两个城镇间都可以通过道路连接&#xff08;间接通过路连接也可以&#xff09;。问最少还需要建设多少条道路&#xff…

JUC并发编程第一篇,复习线程基础知识

JUC并发编程第一篇&#xff0c;复习线程基础知识一、为什么多线程极其重要&#xff1f;二、从start一个线程开始认识多线程三、进程、线程和管程四、用户线程和守护线程一、为什么多线程极其重要&#xff1f; 硬件方面&#xff1a;摩尔定律失效 摩尔定律 价格不变时&#xff0…

Java毕业设计基于springboot 美妆化妆品销售购物网站多商家 前后端分离node

美妆化妆品是当前很多女性的必备用品&#xff0c;所以为了能够让更多的女士用上物美价廉的化妆品我们开发了本系统。基于springboot 美妆化妆品销售购物网站本系统以java为核心开发技术&#xff0c;结合springboot VUE框架实现了一个美妆化妆品销售管理系统。美妆化妆品销售管理…

InheritableThreadLocal

补充:关于ThreadLocal,请看这篇文章关于ThreadLocal内存泄漏的问题_小星向上的博客-CSDN博客 引言:最近在查看shiro登录成功后,获取当前登录人的信息时发现了里面使用了InheritableThreadLocal,,但是我好奇,如果我在里面新建了一个线程,那怎么获取登录人的信息呢,结果发现shir…

(经典dp) 骨牌问题 2*n 3*n n*m

文章目录前言题目2*n3*nn*mn < 5 && m < 1e9n*m < 100END前言 用1*2的骨牌铺满一个平面&#xff0c;是非常经典的一系列dp题目 (各大平台几乎都有这类题) 并且随着平面的要求不同&#xff0c;难度也是层层递增 对于n*m若数据量不同&#xff0c;则对应处理的…

2022IDEA的下载、安装、配置与使用

文章目录1.IntelliJ IDEA 介绍1.2 JetBrains 公司介绍1.2 IntelliJ IDEA 介绍1.3 IDEA 的主要功能介绍1.3.1 语言支持上1.3.2 其他支持1.4 IDEA 的主要优势&#xff1a;(相较于 Eclipse 而言)1.5 IDEA 的下载地址1.6 官网提供的详细使用文档2.windows 下安装过程2.1 安装前的准…

CANdelaStudio中的状态跳转图无法查看

诊断协议那些事儿 诊断协议那些事儿专栏系列文章&#xff0c;本文将介绍如何解决CANdelaStudio中的状态跳转图无法查看的问题。 参考文章&#xff1a; CDD文件——CANdelaStudio 10服务-DiagnosticSessionControl States To display a graphical representation of the stat…

安装kafka和相关配置解析

1选择操作系统 kafka是一个java应用程序&#xff0c;可以运行在很多系统上Windows, MacOS, Linux, 等 一般都是Linux 2安装java环境 3安装zk zk存储的是metadata 架构图如下 Kafka已经用稳定的zk的3.4.6版本进行了广泛的测试&#xff0c;它可以从apache.org的http://bit.ly/2sD…

摩尔斯电码笔记

文章目录1. 前言2. 什么是摩尔斯电码&#xff1f;3. 摩尔斯电码是如何发明的&#xff1f;4. 摩尔斯电码还在使用吗&#xff1f;5. 如何快速记住6. 体验7. 形式表达8. 相关电影1. 前言 最近突然想起之前学习过的莫斯密码已经忘记了&#xff0c;发现如果不实践的话&#xff0c;就…

OOM和JVM最详细介绍

什么是OOM&#xff1f; OOM&#xff0c;全称“Out Of Memory”&#xff0c;翻译成中文就是“内存用完了”&#xff0c;来源于java.lang.OutOfMemoryError。看下关于的官方说明&#xff1a; Thrown when the Java Virtual Machine cannot allocate an object because it is out…

windows服务器证书算法升级

由于前段时间&#xff0c;服务器检查出证书算法较弱&#xff0c;服务器算法采用的SHA1&#xff0c;这个算法在当前已经较落后了。 第一步在命令端输入certsrv.msc&#xff08;如果打不开&#xff0c;请看我的另一篇文章&#xff0c;先安装服务器证书&#xff09; 第二步打开证…

[LeetCode周赛复盘] 第 91 场双周赛补20221015

[LeetCode周赛复盘] 第 91 场双周赛补20221015 一、本周周赛总结二、 [Easy] 2465. 不同的平均值数目1. 题目描述2. 思路分析3. 代码实现三、[Medium] 2466. 统计构造好字符串的方案数1. 题目描述2. 思路分析3. 代码实现四、[Medium] 2467. 树上最大得分和路径1. 题目描述2. 思…

2.2、物理层下面的传输媒体

2.2、物理层下面的传输媒体 注意&#xff1a; 传输媒体不属于网络体系结构的任何一层。若非要将它添加到体系结构中&#xff0c;那只能放在物理层之下 传输媒体大致分为 2 类 2.2.1、导引型传输媒体 导引型传输媒体 电磁波被导引沿着固体媒体传播常见的导引型传输媒体有同…

电子元器件解析01——电阻

摘要电阻是最基本的电子元器件之一&#xff0c;了解电阻的各方面特性对正确选用合适的电阻很有帮助。本文总结了关于电阻的各个性能参数&#xff0c;包括电阻的标称值、精度、温度系数、耐压、封装与功率&#xff1b;总结了电阻的分类&#xff0c;有多种分类依据&#xff0c;包…

基于jsp+mysql+ssm的校园OTO超市系统-计算机毕业设计

项目介绍 本网站主要是针对高校学生以超市购物为重点开发的网站。系统从用户上分为三种&#xff1a;卖家、买家和游客。系统从模块分为买家模块和卖家模块&#xff0c;买家模块包括用户注册登录、商品浏览、商品详情、商品加入购物车、购物车中商品删除、购物车商品数量变更、…

腾讯代码安全指南开源,涉及 C/C++、Go 等六门编程语言

腾讯代码安全指南旨在梳理 API 层面的风险点并提供详实可操作的编码指引&#xff0c;是我们开展 DevSecOps 安全左移实践探索过程中&#xff0c;梳理沉淀面向开发人员的代码安全参考材料。 本次开源涉及 C/C、JavaScript、Node、Go、Java、Python 六门编程语言的安全指南。 一…

详解风控模型中的逻辑回归评分卡与模型评估内容

今天我们来输出一篇风控长文&#xff0c;关于大家熟悉关注的逻辑评分卡的开发的内容&#xff0c;文章篇幅较长&#xff0c;大纲目录如下&#xff1a; 建模前准备 1.1特征预处理与转化 1.2特征衍生与提取 1.3特征选择与降维 分箱 2.1分箱概述 2.2分箱方法 Woe计算 3.1 WOE 3.2…

【用户画像】功能实现值写入ClickHouse人群包、预估和更新分群人数,NoSQL数据库介绍

文章目录一 写入ClickHouse人群包1 组合查询Bitmap表SQL代码实现&#xff08;1&#xff09;SQL语句分析&#xff08;2&#xff09;实现思路&#xff08;3&#xff09;实现过程controller层service层Taginfo实现类mapper层2 人群包代码实现&#xff08;1&#xff09;配置文件&am…

一个注解干翻所有Controller

1. 概览 日常开发中&#xff0c;最繁琐的便是编写 Controller。很多公司都制定了规范&#xff1a;Controller 不能存在任何的业务逻辑&#xff0c;主要完成参数解析和结果转换。不过查看项目源码&#xff0c;你会发现 Controller 中存在了大量不该存在的逻辑&#xff0c;对此&…

【MFC】打砖块小游戏(下)(7)

任务点&#xff1a; 1、键盘左右键消息处理&#xff1b; 2、碰撞检测&#xff08;与砖块、挡板、上、左、右&#xff09;&#xff1b; 3、控制转向&#xff1b; 程序shix 解决思路&#xff1a; 1、左右键消息处理&#xff1a; 响应 WM_KEYDOWN 消息&#xff0c;移动挡板…