• 内核里面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)
  • 相关阅读:
    HIVE之 Sqoop 1.4.6 安装、hive与oracle表互导
    Sqoop之 Sqoop 1.4.6 安装
    PIG之 Hadoop 2.7.4 + pig-0.17.0 安装
    hadoop之 node manager起不来, 执行mapreduce 程序hang住
    Maven 简介
    graphviz 的节点形状
    graphviz 的绘图布局
    Graphviz 的命令行参数说明
    golang使用graphviz
    IDEA 项目相关基础设置
  • 原文地址:https://www.cnblogs.com/icefree/p/8539133.html
Copyright © 2020-2023  润新知