Chinaunix首页 | 论坛 | 博客
  • 博客访问: 313386
  • 博文数量: 169
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 12
  • 用 户 组: 普通用户
  • 注册时间: 2013-07-10 12:00
文章分类

全部博文(169)

文章存档

2014年(38)

2013年(131)

我的朋友

分类: 嵌入式

2013-07-22 11:25:19

几乎每一种外设都是通过读写设备上的寄存器来进行的,通常包括控制寄存器、状态寄存器和数据寄存器三大类,外设的寄存器通常被连续地编址。根据CPU体系结构的不同,CPUIO端口的编址方式有两种:

  (1I/O映射方式(I/O-mapped

  典型地,如X86处理器为外设专门实现了一个单独的地址空间,称为"I/O地址空间"或者"I/O端口空间"CPU通过专门的I/O指令(如X86INOUT指令)来访问这一空间中的地址单元。

  (2)内存映射方式(Memory-mapped

  RISC指令系统的CPU(如ARMPowerPC等)通常只实现一个物理地址空间,外设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 中列出.

内存区在不再需要时应当释放:

void release_mem_region(unsigned long start, unsigned long len);

 

2、物理地址映射到虚拟内存地址

#include
void *ioremap(unsigned long phys_addr, unsigned long size);
void iounmap(void * addr);

ioremap 返回的地址不应当直接解引用; 相反, 应当使用内核提供的存取函数.

 

3 I/O 内存读写

使用 I/O 内存的正确方式是通过一系列为此而提供的函数(通过 定义的).

I/O 内存读, 使用下列之一:

unsigned int ioread8(void *addr);
unsigned int ioread16(void *addr);
unsigned int ioread32(void *addr);

这里, addr 应当是从 ioremap 获得的地址(也许与一个整型偏移); 返回值是从给定 I/O 内存读取的.

有类似的一系列函数来写 I/O 内存:

void iowrite8(u8 value, void *addr);
void iowrite16(u16 value, void *addr);
void iowrite32(u32 value, void *addr);

 

阅读(682) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~