linux系统中,硬件访问实质就是对寄存器的访问,或者说是对外部ram的访问。
1、硬件访问的实质
驱动程序控制设备,主要是通过访问设备内的寄存器来达到控制目的,因此我们讨论如何访问硬件,就成了如何访问这些寄存器了。
2、地址映射
在linux系统中,无论是内核程序还是应用程序,都只有使用虚拟地址,而芯片手册中给出的硬件寄存器地址或者RAM地址则是物理地址,无法直接使用,因此,我们读写寄存器的第一步就是将它的物理地址映射为虚拟地址。
2.1动态映射
所谓的动态映射,是指在驱动程序中采用ioremap函数将物理地址映射为虚拟地址。
原型:void * ioremap(physaddr, size)
参数:
Physaddr:待映射的物理地址
Size:映射的区域长度
返回值:映射后的虚拟地址
2.2、静态映射
所谓静态映射,是指linux系统根据用户事先指定的映射关系,在内核启动时,自动地将物理地址映射为虚拟地址。
在静态映射中,用户是通过map_desc结构来指明物理地址与虚拟地址的映射关系。
struct map_desc
{
unsigned long virtual; //映射后的虚拟地址
unsigned long pfn; //物理地址所在的页帧号
unsigned long length; // 映射长度
unsigned int type; //映射的设备类型
};
pfn:利用_phys_to_pfn(物理地址)可以计算出物理地址所在的物理页帧号(除以2^12(4k),因为一个页有4k)。
3、寄存器的读写
在完成地址映射后,就可以读写寄存器了,linux内核提供了一系列函数,来读写寄存器。
unsigned ioread8(void *addr)
unsigned ioread16(void *addr)
unsigned ioread32(void *addr)
unsigned readb(address)
unsigned readw(address)
unsigned readl(address)
void iowrite8(u8 value, void *addr)
void iowrite16(u16 value, void *addr)
void iowrite32(u32 value, void *addr)
void writeb(unsigned value, address)
void writew(unsigned value, address)
void writel(unsigned value, address)