zoukankan      html  css  js  c++  java
  • linux I/O内存访问

    先看一个在无操作系统的情况下,用C语言访问片上寄存器的范例,这是访问S3C2440UART1的FIFO控制寄存器的示例,先定义FIFO控制寄存器为UFCON1:

    #define UFCON1 (*(volatile unsigned *)Ox50004008) //*UART 1 FIFO控制寄存器

    给UFCON1赋值:

    UFCON1 = Ox00;   //禁止FIFO功能

    这个示例的使用条件是禁止CPU的MMU在禁止MMU的情况下,可以直接访问CPU的物理地址。
      Linux内核运行后,开启了MMU,所以不能直接访问CPU的物理地址,也就是说,不能直接使用物理地址访问系统的IO内存。必须将物理地址转换为虚拟地址,内核通过虚拟地址来访问系统的IO内存。
      在内核中,物理地址到虚拟地址的转换,可以采用静态IO映射,还可以采用动态IO映射。通常情况下,CPU片上寄存器和内部总线都采用静态IO映射外部总线扩展IO则通常采用动态IO映射,也可以添加到系统中,采用静态IO映射的方式。
    下面分别来看这两种方式的实现和使用方法。

     

    1、静态VO映射  、

      静态I/O映射在内核中很常见,最常见的是处理器的片内寄存器的操作,如GPIO、串口、定时器等等这些片上外设的寄存器,在内核中都通过静态IO映射后被访问。一般的操作方式是这样的:

    _raw_writel(camdivn, S3C2440_CAMDIVN);
    submsk =_raw_readl(S3C2410_INTSUBMSK);

    (1)io_p2v  

      要实现静态IO映射,首先需要定义物理地址到虚拟地址的转换规则,在内核中用宏定义io_p2v(x)实现,将物理地址映射到3G~4G的内核地址空间。不同处理器的具体实现是不同的,但是前提是必须能将处理器的全部有效IO空间映射到内核空间。对于一个32位的处理器,最大可访问地址空间为232,即4G,但是实际上绝大部分地址空间都是保留的,可访问的有效地址仅仅局限于有实际物理外设地址空间。

    2、动态IO映射

      动态IO映射无需将物理IO内存空间写入映射表,调用ioremap即可映射到虚拟地址空间。这种方式使用起来比较灵活,不过在外扩总线设备寄存器较多的情况下使用起来就不太方便了,一般建议在寄存器较少的情况下使用。操作完毕后,用iounmap取消IO映射。

    ioremap 和 iounmap相关定义在<asm/io.h>文件中:

    3、IO内存访问函数

    __raw_readb/readb 从 I/O 端口读取 8 位数
    __raw_readw/readw 从 I/O 端口读取 16 位数
    __raw_readl/readl 从 I/O 端口读取 32 位数
    __raw_writeb/writeb 往 I/O 端口写入 8 位数
    __raw_writew/writew 往 I/O 端口写入 16 位数
    __raw_writel/writel 往 I/O 端口写入 32 位数
    

      

     

  • 相关阅读:
    STL的适配器、仿函数学习之一:accumulate和for_each的使用心得
    百度笔试题--------数字拼接,求出最小的那个
    百度面试题----依概率生成
    百度笔试题----C语言版revert
    百度笔度题-----蚂蚁爬杆问题
    Try....Catch......Finally 的执行顺序
    数据库SQL SERVER 2008R2 远程连接配置说明
    C#中的数据库的连接方式分类说明(转载)
    网络通信—udp使用领悟
    (转载)C#网络通信之TCP连接
  • 原文地址:https://www.cnblogs.com/yuanqiangfei/p/15735726.html
Copyright © 2011-2022 走看看