Chinaunix首页 | 论坛 | 博客
  • 博客访问: 30677
  • 博文数量: 15
  • 博客积分: 15
  • 博客等级: 民兵
  • 技术积分: 58
  • 用 户 组: 普通用户
  • 注册时间: 2012-03-14 16:41
文章分类
文章存档

2013年(7)

2012年(8)

我的朋友

分类:

2012-05-31 14:52:39

原文地址:IO端口与IO内存 作者:hubertx

 概念:     

     IO空间与内存空间

   讲这个问题,就涉及到硬件知识,X86体系中,具有两个地址空间:IO空间和内存空间,RISC指令系统的CPU(如ARMPowerPC等)通常只实现一个物理地址空间,即内存空间

      内存空间:内存地址寻址范围,32位操作系统内存空间为2的32次幂,即4G。

      IO空间:X86特有的一个空间,与内存空间彼此独立的地址空间,32位X86有64K的IO空间。

      IO端口:当寄存器或内存位于IO空间时,称为IO端口。一般寄存器也俗称I/O端口,或者说I/O ports,这个I/O端口可以被映射在Memory Space,也可以被映射在I/O Space。

      IO内存:当寄存器或内存位于内存空间时,称为IO内存

      CPU对外设端口物理地址的编址方式有两种:一种是IO映射方式,另一种是内存映射方式,而具体采用哪一种则取决于CPU的体系结构Linux将基于IO映射方式的和内存映射方式的IO端口统称为IO区域(IO region))。

    有些体系结构的CPU(如,ARM, PowerPCm68k等)通常只实现一个物理地址空间(RAM)。在这种情况下,外设I/O端口的物理地址就被映射到CPU的单一物理地址空间中,而成为内存的一部分。此时,CPU可以象访问一个内存单元那样访问外设I/O端口,而不需要设立专门的外设I/O指令。这就是所谓的内存映射方式Memorymapped)。

    而另外一些体系结构CPU(典型地如X86)则为外设专门实现了一个单独地地址空间,称为“I/O地址空间或者“I/O端口空间。这是一个与CPURAM物理地址空间不同的地址空间,所有外设的I/O端口均在这一空间中进行编址。CPU通过设立专门的I/O指令(如X86INOUT指令)来访问这一空间中的地址单元(也即I/O端口)。这就是所谓的“I/O映射方式I/Omapped)。与RAM物理地址空间相比,I/O地址空间通常都比较小,如x86 CPUI/O空间就只有64KB00xffff)。这是“I/O映射方式的一个主要缺点。

     下面是摘抄:

   结合下图,我们彻底讲述IO端口和IO内存以及内存之间的关系。主存16M字节的SDRAM,外设是个视频采集卡,上面有16作为缓冲区。                                

1. CPU是X86架构linux内核的情况

   i386系列的处理中,内存和外部IO是独立编址,也是独立寻址的。MEM的内存空间是32位可以寻址到4GIO空间是16位可以寻址到64K

     Linux内核中,访问外设上的IO Port必须通过IO Port的寻址方式。而访问IO Mem就比较罗嗦,外部MEM不能和主存一样访问,虽然大小上不相上下,可是外部MEM是没有在系统中注册的。访问外部IO MEM必须通过remap映射到内核的MEM空间后才能访问。为了达到接口的同一性,内核提供了IO PortIO Mem的映射函数。映射后IO Port就可以看作是IO Mem,按照IO Mem的访问方式即可。 

2. CPUARM PPC架构的情况

   在这一类的嵌入式处理器中,IO Port的寻址方式是采用内存映射,也就是IO bus就是Mem bus。系统的寻址能力如果是32位,IO PortMem(包括IO Mem)可以达到4G

   访问这类IO Port时,我们也可以用IO Port专用寻址方式。至于在对IO Port寻址时,内核是具体如何完成的,这个在内核移植时就已经完成。在这种架构的处理器中,仍然保持对IO Port的支持,完全是i386架构遗留下来的问题,在此不多讨论。而访问IO Mem的方式和i386一致。 

注意:linux内核给我提供了完全对IO PortIO Mem的支持,然而具体去看看driver目录下的驱动程序,很少按照这个规范去组织IO PortIO Mem资源。对这二者访问最关键问题就是地址的定位C语言中,使用volatile 就可以实现。很多的代码访问IO Port中的寄存器时,就使用volatile关键字,虽然功能可以实现,我们还是不推荐使用。就像最简单的延时莫过于while,可是在多任务的系统中是坚决避免的!

    一般来说,在系统运行时,外设的I/O内存资源的物理地址是已知的,由硬件的设计决定。但是CPU通常并没有为这些已知的外设I/O内存资源的物理地址预定义虚拟地址范围,驱动程序并不能直接通过物理地址访问I/O内存资源,而必须将它们映射到核心虚地址空间内(通过页表),然后才能根据映射所得到的核 心虚地址范围,通过访内指令访问这些I/O内存资源。Linuxio.h头文件中声明了函数ioremap(),用来将I/O内存资源的物理地址映射到 核心虚地址空间(3GB4GB)中。   

1.对IO端口的操作:

申请->访问->释放

申请 :request_region

访问:

8位  读 intb 写 outb

16位  intw      outw

32位 intl         outl

释放:release_region


2.对IO内存的操作:

申请->映射->访问->释放

申请:request_mem_region 申请到的是物理地址

映射:ioremap                          将申请到的物理地址映射成虚拟地址

访问:ioread8 iowrite8

            ioread16 iowrite16

            ioread32 iowrite32

释放:

iounmap

release_mem_region

阅读(703) | 评论(0) | 转发(0) |
0

上一篇:ioremap和ioport_map

下一篇:ioremap函数解析

给主人留下些什么吧!~~