• 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 位数
    

      

     

  • 相关阅读:
    Python之路-(js正则表达式、前端页面的模板套用、Django基础)
    Python之路-jQuery
    单例模式实际应用
    hibernate联合主键注解配置
    spring:ContextLoaderListener接口
    Struts2 校验
    Control character in cookie value, consider BASE64 encoding your value-Cookie保存中文出错[转]
    基于Cookie跨域的单点登录问题
    Spring:启动项目时加载数据库数据(总结)
    Oracle表分区[转]
  • 原文地址:https://www.cnblogs.com/yuanqiangfei/p/15735726.html
Copyright © 2020-2023  润新知