[国嵌攻略][111][硬件访问技术]
硬件访问实质
驱动程序控制设备,主要是通过访问设备内的寄存器来达到控制目的的,因此我们讨论如何访问硬件,就成了如何访问这些寄存器。
访问流程
1.地址映射
在Linux系统中,无论是内核程序还是应用程序,都只能使用虚拟地址,而芯片手册中给出的硬件寄存器地址或RAM地址都是物理地址,无法直接使用。因此我们读写寄存器的第一步就是将它的物理地址映射为虚拟地址。
1.1.动态映射
所谓动态映射是指在驱动程序中采用ioremap函数将物理地址映射为虚拟地址。
原型:void *ioremap(physaddr, size)
参数:
physaddr:待映射的物理地址
size:映射的区域长度
返回值:映射后的虚拟地址
1.2.静态映射
所谓静态映射是指Linux系统根据用户事先指定的映射关系,在内核启动时自动地将物理地址映射为虚拟地址。
映射关系:
在静态映射中,用户通过map_desc结构来指明物理地址与虚拟地址的映射关系。
struct map_desc{
unsigned long virtual; //映射后的物理地址
unsigned long pfn; //物理地址所在的页帧号
unsigned long long; //映射长度
unsigned int type; //映射的设备类型
}
pfn:利用__phys_to_pfn(物理地址)可以计算物理地址所在的物理页帧号
2.寄存器读写
在完成地址映射后,就可以读写寄存器了,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)