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