有过裸板驱动程序编写经历的都清楚,在编写裸板驱动程序时我们是通过访问物理地址来操作寄存器的。但是在内核中根本不可能使用物理地址,只可以使用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));