内核中访问物理寄存器

时间:2022-10-20 17:06:20

有过裸板驱动程序编写经历的都清楚,在编写裸板驱动程序时我们是通过访问物理地址来操作寄存器的。但是在内核中根本不可能使用物理地址,只可以使用4G虚拟地址的高1G。这就需要我们把物理地址映射到虚拟地址。

下面是一个例子:

#include <linux/ioport.h>//io端口头文件

//GPIO物理基地址和偏移

#define GPIO+BASE 0x7F008000

#define GPIO_SIZE 0x28c

/* 将物理地址转换为虚拟地址(一定在3G以上的内核空间) */
void __iomem *vir_base;
vir_base = ioremap(GPIO_BASE, GPIO_SIZE);
if (!vir_base)
    return -EIO;
...
/* 使用虚拟基地址和寄存器偏移,来访问物理寄存器 */
...

/* 释放虚拟地址的映射 */
iounmap(vir_base);


(2)寄存器的访问函数
内核根据寄存器的宽度,定义了一系列寄存器的访问函数,要求驱动开发人员使用:

#include <linux/io.h>

/* 8位寄存器 */
char value;
value = readb(vir_base + offset);
writeb(value, (vir_base + offset));
__raw_readb()/__raw_writeb();

/* 16位寄存器 */
short value;
value = readw(vir_base + offset);
writew(value, (vir_base + offset));

/* 32位寄存器 */
int value;
value = readl(vir_base + offset);
writel(value, (vir_base + offset));