浅析request_mem_region和ioremap函数的理解

在了解这两个函数之前我们首先要明白CPU的寻址。任何一种外设都是通过读写寄存器来控制的,寄存器又通常包括三大类:控制寄存器,状态寄存器和数据寄存器。根据CPU体系的不同,CPU对I/O端口的编址方式分为I/O映射和内存映射两种方式。


(1).I/O映射方式:


     以intel为代表的i386系列处理器中,内存和外部I/O是独立编址独立寻址。即在该体系中存在两种地址空间:内存空间和I/O空间。从处理器的角度来说,i386提供了两种不同的指令分别用来访问I/O地址空间和内存空间,两种指令相互独立。


(2).内存映射方式:


   在嵌入式领域的处理器中,通常只能操作内存地址空间,并没有单独的I/O地址空间可供操作。换句话说该体系中没有单独的I/O指令用来操作外设。这种情况我我们只能通过将I/O端口的物理地址映射到内存空间,从而CPU像访问内存一样访问I/O地址空间。

 

很显然,在s3c2440中是内存映射方式来访问外设。一般来说,外设的I/O物理地址有硬件决定,在datasheet中可以查到相应外设的I/O物理地址。由于CPU不提供单独的指令操作I/O外设,因此驱动程序并不能对其物理地址访问。而必须把它们映射到虚拟地址空间,然后通过操作映射得到的虚拟地址从而实现对I/O资源的操作。request_mem_region和ioremap函数就是实现物理地址到虚拟地址映射的功能。

/* 从 start 开始,分配一个 len 字节的内存区域。成功返回一个非NULL指针,否则返回NULL。所有的 I/O 内存分配情况都 /proc/iomem 中列出。*/
struct resource *request_mem_region(unsigned long start, unsigned long len, char*name);
/*I/O内存区域在不再需要时应当释放*/
void release_mem_region(unsigned long start, unsigned long len); 

/*一个旧的检查 I/O 内存区可用性的函数,不推荐使用*/
int check_mem_region(unsigned long start, unsigned long len);


申请完内存分配后必须设置一个映射,由 ioremap 函数实现,此函数专门用来为I/O 内存区域分配虚拟地址。经过ioremap 之后,设备驱动即可访问任意的 I/O 内存地址。注意:ioremap 返回的地址不应当直接引用;应使用内核提供的 accessor 函数。以下为函数定义:

#include 
void *ioremap(unsigned long phys_addr, unsigned long size);
void *ioremap_nocache(unsigned long phys_addr, unsigned long size);/*如果控制寄存器也在该区域,应使用的非缓存版本,以实现side effect。*/
void iounmap(void * addr);

总的来说只需记住,对于内存映射方式,操作寄存器之前一定要先申请内存空间,申请之后再建立映射关系。操作结束之后同样要先释放申请的内存空间,再取消映射关系。



你可能感兴趣的:(FL2440驱动,linux学习笔记,学习心得)