分类: 嵌入式
2012-07-26 17:23:08
几乎每一种外设都是通过读写设备上的寄存器来进行的,通常包括控制寄存器、状态寄存器和数据寄存器三大类,外设的寄存器通常被连续地编址。根据CPU体系结构的不同,CPU对IO端口的编址方式有两种:
(1)I/O映射方式(I/O-mapped)
典型地,如X86处理器为外设专门实现了一个单独的地址空间,称为"I/O地址空间"或者"I/O端口空间",CPU通过专门的I/O指令(如X86的IN和OUT指令)来访问这一空间中的地址单元。
(2)内存映射方式(Memory-mapped)
RISC指令系统的CPU(如ARM、PowerPC等)通常只实现一个物理地址空间,外设I/O端口成为内存的一部分。此时,CPU可以象访问一个内存单元那样访问外设I/O端口,而不需要设立专门的外设I/O指令。
但是,这两者在硬件实现上的差异对于软件来说是完全透明的,驱动程序开发人员可以将内存映射方式的I/O端口和外设内存统一看作是"I/O内存"资源。
设备I/O内存访问流程
1. I/O 内存分配
I/O 内存区必须在使用前分配. 分配内存区的接口是( 在 定义):
struct resource *request_mem_region(unsigned long start, unsigned long len, char *name);
这个函数分配一个 len 字节的内存区, 从 start 开始. 如果一切顺利, 一个 非NULL 指针返回; 否则返回值是 NULL. 所有的 I/O 内存分配来 /proc/iomem 中列出.
内存区在不再需要时应当释放:
2、物理地址映射到虚拟内存地址
从 ioremap 返回的地址不应当直接解引用; 相反, 应当使用内核提供的存取函数.
3、 I/O 内存读写
使用 I/O 内存的正确方式是通过一系列为此而提供的函数(通过 定义的).
从 I/O 内存读, 使用下列之一:
这里, addr 应当是从 ioremap 获得的地址(也许与一个整型偏移); 返回值是从给定 I/O 内存读取的.
有类似的一系列函数来写 I/O 内存: