首页 > 其他分享 >设备驱动-14.userspace进行IP的寄存器读写

设备驱动-14.userspace进行IP的寄存器读写

时间:2023-08-27 16:56:43浏览次数:50  
标签:addr 14 IP top fifo keyscan userspace reg define

1 定义寄存器

以键盘keyscan为例,定义一个IP寄存器描述头文件,IOCRREG, IOCWREG定义了两个ioctl命令,用来读写寄存器。struct msg用来存放寄存器地址和值。
image
image

/* Keyscan register: addr + offset + mask */
#define keyscan_top_keyscan_config1			0x0
#define keyscan_top_keyscan_config2			0x4
#define keyscan_top_keyscan_config3			0x8
#define keyscan_top_keyscan_config4			0xc

#define keyscan_top_reg_fifo_count				0x20
#define keyscan_top_reg_fifo_count_OFFSET			0
#define keyscan_top_reg_fifo_count_MASK				0xf
#define keyscan_top_reg_fifo_not_empty				0x20
#define keyscan_top_reg_fifo_not_empty_OFFSET			4
#define keyscan_top_reg_fifo_not_empty_MASK			0x10
struct msg {
	long unsigned int addr;
	unsigned int data;
};
#define IOC_MAGIC 'k'
#define IOCRREG _IOR(IOC_MAGIC, 1, struct msg)
#define IOCWREG _IOW(IOC_MAGIC, 2, struct msg)

2 驱动代码

image

static long keyscan_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
	struct msg m;
	memset(&m, 0, sizeof(m));
	void __iomem* base = dev->base;
	switch (cmd) {
	case IOCRREG:
		if (copy_from_user(&m, (struct msg __user *)arg, sizeof(m)))
			return -EFAULT;
		m.data = readl(base + m.addr);
		printk(KERN_DEBUG "base_addr:0x%lx, offset:0x%lx, read data: 0x%x \n", base, m.addr, m.data);
		if (copy_to_user((struct msg __user *)arg, &m, sizeof(m)))
			return -EFAULT;
		break;
	case IOCWREG:
		if (copy_from_user(&m, (struct msg __user *)arg, sizeof(m)))
			return -EFAULT;
		printk(KERN_DEBUG "base_addr:0x%lx, offset:0x%lx, write data: 0x%x \n", base, m.addr, m.data);
		writel(m.data, base + m.addr);
		break;
	default:
		return -EINVAL;
	}
	return 0;
}

驱动先定义IP base addr,然后透过ioctl进行arg参数接收,确定msg中的addr和data, 接收cmd调用writel, readl进行读写。

3 用户态代码

image

static inline void clrsetbits_32(long unsigned int addr, unsigned int clear, unsigned int set) {
	int ret;
	struct msg m;
	memset(&m, 0, sizeof(m));
	m.addr = addr;
	ret = ioctl(fd, IOCRREG, &m);
	if (ret) {
		perror("ioctl: read error!");
		return;
	}
	m.data = (m.data & (~clear)) | set;
	ret = ioctl(fd, IOCWREG, &m);
	if (ret) {
		perror("ioctl: write error");
		return;
	}
	return;
}
static unsigned int read_reg(long unsigned int addr) {
	int ret;
	struct msg m;
	memset(&m, 0, sizeof(m));
	ret = ioctl(fd, IOCRREG, &m);
	if (ret) {
		perror("ioctl: read reg error!");
		return -1;
	}
	return m.data;
}

首先实现基础读写函数进行寄存器读写,reg_read函数传入addr即可得到val, clrsetbits_32需要先读,在写入val.

#define KEYSCAN_MASK(REG_NAME) keyscan_top_##REG_NAME##_MASK
#define KEYSCAN_OFFSET(REG_NAME) keyscan_top_##REG_NAME##_OFFSET
#define KEYSCAN_SET(REG_NAME, VAL)                                             \
	clrsetbits_32(keyscan_top_##REG_NAME, KEYSCAN_MASK(REG_NAME),          \
			  (VAL) << KEYSCAN_OFFSET(REG_NAME))
#define KEYSCAN_GET(REG_NAME)                                                  \
	((read_reg(keyscan_top_##REG_NAME) & KEYSCAN_MASK(REG_NAME)) >>        \
	 KEYSCAN_OFFSET(REG_NAME))

image

例如,当调用

KEYSCAN_GET(reg_fifo_count); //表示read_reg(keycan_top_reg_fifo_count) & keycan_top_reg_fifo_count_MASK >> keycan_top_reg_fifo_count_OFFSET

reg_fifo表示IP的某一个寄存器,count表示位域,因此对OFFSET定义成位域在该寄存器的偏移量(count位域是bit[3:0])定义为0,因此MASK定义为0xf.
同理not_empty也是一个位域,bit[4],OFFSET定义成4,MASK定义成0x10,来屏蔽除bit[4]的其他bit.

KEYSCAN_GET(reg_fifo_count);最终就获取到了reg_fifo寄存器的count位域的内容。
KEYSCAN_GET(reg_fifo_not_empty);最终就获取到了reg_fifo寄存器的not_empty位域的内容

又例如,当调用

KEYSCAN_SET(reg_enable, 1);//表示clrsetbits_32(keycan_top_reg_enable, keycan_top_reg_enable_MASK, 1 << keycan_top_reg_enable_OFFSET

image

#define keyscan_top_reg_row_mask			0x0
#define keyscan_top_reg_row_mask_OFFSET			0
#define keyscan_top_reg_row_mask_MASK			0xff
#define keyscan_top_reg_col_mask			0x0
#define keyscan_top_reg_col_mask_OFFSET			8
#define keyscan_top_reg_col_mask_MASK			0xff00
#define keyscan_top_reg_enable				0x00
#define keyscan_top_reg_enable_OFFSET			16
#define keyscan_top_reg_enable_MASK			0x10000

可以看到offset定义为16,mask定义为0x10000,用来屏蔽除bit[16]的其他位。clrsetbits_32会先读出该寄存器,然后对该位set1, mask掉其他位,再次写入该寄存器。

标签:addr,14,IP,top,fifo,keyscan,userspace,reg,define
From: https://www.cnblogs.com/fuzidage/p/17649929.html

相关文章

  • NOIP2018提高组初赛易错题解析
    2.下列属于解释执行的程序设计语言是()A.C B.C++ C.Pascal D.Python错误原因:忘记了正解:C、C++和Pascal都是编译性语言,而Python是解释性语言 5.设某算法的时间复杂度函数的递推方程是 T(n)=T(n-1)+n(n 为正整数)及 T(0)=1,则该算法的时间复杂度为()A.O(logn) ......
  • P7414 [USACO21FEB] Modern Art 3 G 题解
    思路考虑区间DP。设\(f_{i,j}\)表示要刷到\([i,j]\)这一段的目标需要的最小次数。对于\(f_{i,j}\),如果\(color_i\)与\(color_j\)相等,那么再子区间合并的时候就可以少刷一次,即\(f_{i,j}=\min\limits_{k=i}^{j-1}f_{i,k}+f_{k+1,j}-1\)。否则\(f......
  • 原来可以用代码这样查询IP归属地
    哈喽,大家好,我是指北君。最近各大社交媒体平台都发布了显示用户IP归属地的功能,有同学可能还不知道如何查询自己的IP归属地,其实很简单,你只需要打开Web浏览器,用百度搜索“IP归属地”就能显示自己的当前归属信息。以上是使用网页的方式,有没有使用代码获取的方式?如果自己的公司也要求加......
  • vue项目打包之后, 生成一个可修改IP地址的文件
     在做项目的时候遇到了一个问题,就是把项目部署到不同的服务器上,但不能每次修改IP的时候就打包一次,这就增加了前端的工作量,经过百度,发现有一些方法是可以的,亲测可用。具体操作是,1,在static文件夹下面建立一个config.js文件, 1234567(function (){ ......
  • 哪些行业都可以用高防ip
    高防IP适用于电商、金融、政府、媒资、教育、企业门户等网站类场景的DDoS攻击防护,恶意竞争对手可以通过攻击等手段让您的业务瘫痪用户无法访问,最终导致用户流失。高防ip可以防御各种游戏类的DDoS攻击,且对用户体验实时性要求较高的场景,快速发现攻击,启动清洗,保证游戏业务的安全。1、......
  • JavaScript的变量提升
    参考资料:https://time.geekbang.org/column/article/126339目录变量提升变量形式声明的函数变量提升导致的问题变量被覆盖变量不被销毁避开变量提升引入let和const关键字块级作用域变量提升是在代码执行时,把变量和函数的声明部分提升到代码开头的行为,变量被提升后,会被默认设置......
  • oracle学习笔记(14)——安全管理
        数据库的安全性主要包括两个方面的含义:一方面是防止非法用户对数据库的访问,未授权的用户不能登录数据库;另一方面是每个数据库用户都有不同的操作权限,只能进行自己权限范围内的操作。Oracle数据库的安全可以分为两类:    1)系统安全性       系统安全......
  • CF1423K Lonely Numbers
    思路因为对于\(\gcd(a,b)\),\(\fraca{\gcd(a,b)}\),\(\fracb{\gcd(a,b)}\)中\(a\)和\(b\)是等价的,可以交换的。所以我们先令\(a>b\)。令\(\gcd(a,b)=d\),因为\(\fraca{\gcd(a,b)}\)有除法,所以我们应该想办法去除除法,就同乘以一个\(d\),即\(d^2\),\(a\),\(b\)三条边。......
  • CF1444A Division
    思路首先特判特殊情况,若\(p_i\)本身不可被\(q_i\)整除,那么\(x_i\)就直接取\(p_i\)最大。否则的话,\(p_i=q_i\timesk\)。所以\(q\)的质因数,\(p\)都有,并且数量一定大于等于\(q\)的这个质因数的数量。那么如果\(x_i\)的某个质因数个数小于\(q_i\)的话,\(x_i\)就......
  • 最完美WIN10_Pro_22H2.19045.3393软件选装纯净特别版VIP52.0
    【系统简介】=============================================================1.本次更新母盘来自UUP_WIN10_PRO_22H2.19045.3393。进一步精简优化调整。2.只为呈现最好的作品,手工精简优化部分较多。3.OS版本号为19045.3393。个别要求高的就下MSDN吧,里面啥功能都有。4.集成《DrvCeo......