• readb(), readw(), readl(),writeb(), writew(), writel() 宏函数【转】


    转自:http://www.netfoucs.com/article/hustyangju/70429.html

    readb(), readw(), readl()函数
    功能:
    从内存映射的 I/O 空间读取数据。
    readb  从 I/O 读取 8 位数据 ( 1 字节 );
    readw 从 I/O 读取 16 位数据 ( 2 字节 );
    readl 从 I/O 读取 32 位数据 ( 4 字节 )。
    原型:
    #include <asm/io.h>


    unsigned char readb (unsigned int addr )
    unsigned char readw (unsigned int addr )
    unsigned char readl (unsigned int addr )
           
    变量:
    addr    I/O 地址。


    返回值: 从 I/O 空间读取的数值。




    writeb(), writew(), writel() 宏函数


    功能:
    往内存映射的 I/O 空间上写数据。
    writeb()   I/O 上写入 8 位数据 (1字节)
    writew()  I/O 上写入 16 位数据 (2字节)
    wirtel()   I/O 上写入 32 位数据 (4字节)
    原型:
    引用
    #include <asm/io.h>


    void writeb (unsigned char data, unsigned short addr)
    void writew (unsigned char data, unsigned short addr)
    void writel (unsigned char data, unsigned short addr)




    变量:
    data   I/O 地址;

    data   数据。

    内核里面writel(readl)是如何实现的?

    writel和readl,这两个个函数实现在操作系统层,有内存保护的情况下,往一个寄存器或者内存地址写一个数据。先说一下writel:
     
    在arch/alpha/kernel/io.c中有
    188 void writel(u32 b, volatile void __iomem *addr)
    189 {
    190     __raw_writel(b, addr);
    191     mb();
    192 }
     
     
    这样一个writel函数的作用应该是向一个地址上写一个值,我想知道这个函数底下具体实现的细节,于是往下继续跟踪代码:__raw_writel(b, addr);(发现在同目录下)
     
    129 void __raw_writel(u32 b, volatile void __iomem *addr)
    130 {
    131     IO_CONCAT(__IO_PREFIX,writel)(b, addr);
    132 }
     
    再往下跟踪 IO_CONCAT,在对应的io.h中的定义如下:
    134 #define IO_CONCAT(a,b)  _IO_CONCAT(a,b)
    135 #define _IO_CONCAT(a,b) a ## _ ## b
    这段代码前几天问过了,是标示将两边的字符串连接起来的意思。
     
    跟踪__IO_PREFIX 定义如下
    501 #undef __IO_PREFIX
    502 #define __IO_PREFIX     apecs
     
    继续阅读代码,看看定义__IO_PREFIX之后紧接着包含了哪个头文件。在哪个头文
    件里面寻找答案。对于你的apsec,看看以下代码段(linux-2.6.28-rc4)


    arch/alpha/include/asm/core_apecs.h
    ------------------------------------------
    #undef __IO_PREFIX
    #define __IO_PREFIX             apecs
    #define apecs_trivial_io_bw     0
    #define apecs_trivial_io_lq     0
    #define apecs_trivial_rw_bw     2
    #define apecs_trivial_rw_lq     1
    #define apecs_trivial_iounmap   1
    #include <asm/io_trivial.h>
    ------------------------------------------


    前往arch/alpha/include/asm/io_trivial.h
    ------------------------------------------
    __EXTERN_INLINE void
    IO_CONCAT(__IO_PREFIX,writel)(u32 b, volatile void __iomem *a)
    {
           *(volatile u32 __force *)a = b;
    }
     
    就是最终通过*(volatile u32 __force *)a = b;
    来写入数据的。
    同样的readl读取数据也和writel类似,这里就不重复了。
     
    (如果在没有os,没有mmu的情况下,当开发板裸跑的时候,我们只需要一句话就一切ok:
    *(unsigned long *)addr = value)

  • 相关阅读:
    在centos7下 布隆过滤器2种安装方式
    Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running?
    redis lua --eval报错1: Lua redis() command arguments must be strings or integers
    redis+lua脚本 分布式锁初步学习
    redis中通用命令(key)和补充
    redis基本数据类型有序集合(zset)学习笔记
    redis基本数据结构集合(set)学习笔记
    大道至简读后感
    第一周
    《大道至简》读后感
  • 原文地址:https://www.cnblogs.com/sky-heaven/p/4905198.html
Copyright © 2020-2023  润新知