zoukankan      html  css  js  c++  java
  • 设备树中ranges属性分析(1)【转】

    转自:https://www.cnblogs.com/pengdonglin137/p/7401049.html

    作者

    彭东林
    pengdonglin137@163.com
     

    软件环境

    Linux-4.10.17
    Qemu+vexpress
     

    概述

    在设备树中有时会看到ranges属性,这个ranges属性可以达到什么效果呢? 今天看到宋宝华老师的设备树讲座,才知道。为了有一个直观的印象,下面我们结合一个实际的例子来看看
     

    正文

    一、设备树

    下面是我们将要实验的设备树的例子:
    复制代码
      1 / {
      2     #address-cells = <1>;
      3     #size-cells = <1>;
      4 
      5     demo_level0 {
      6         compatible = "simple-bus";
      7         ranges = <0x0 0x3000000 0x3000>;
      8         #address-cells = <1>;
      9         #size-cells = <1>;
     10 
     11         range@0 {
     12             compatible = "range";
     13             reg = <0x100 0x200>;
     14             reg-names = "range0";
     15         };
     16 
     17         range@1 {
     18             compatible = "range";
     19             reg = <0x300 0x200>;
     20             reg-names = "range1";
     21         };
     22 
     23         range@2 {
     24             compatible = "range";
     25             reg = <0x600 0x200>;
     26             reg-names = "range2";
     27         };
     28 
     29         demo_level1 {
     30             compatible = "simple-bus";
     31             ranges = <0x0 0x1000 0x1000>;
     32             #address-cells = <1>;
     33             #size-cells = <1>;
     34 
     35             range@3 {
     36                 compatible = "range";
     37                 reg = <0x100 0x200>;
     38                 reg-names = "range3";
     39             };
     40 
     41             demo_level1-1 {
     42                 compatible = "simple-bus";
     43                 ranges = <0x0 0x300 0x500>;
     44                 #address-cells = <1>;
     45                 #size-cells = <1>;
     46 
     47                 range@4 {
     48                     compatible = "range";
     49                     reg = <0x100 0x200>;
     50                     reg-names = "range4";
     51                 };
     52 
     53                 range@5 {
     54                     compatible = "range";
     55                     reg = <0x300 0x100>;
     56                     reg-names = "range5";
     57                 };
     58 
     59                 demo_level1-1-1 {
     60                     compatible = "simple-bus";
     61                     ranges = <0x0 0x400 0x100>;
     62                     #address-cells = <1>;
     63                     #size-cells = <1>;
     64 
     65                     range@6 {
     66                         compatible = "range";
     67                         reg = <0x50 0x30>;
     68                         reg-names = "range6";
     69                     };
     70 
     71                     demo_level1-1-1-1 {
     72                         compatible = "simple-bus";
     73                         ranges = <0x0 0x20 0x20>;
     74                         #address-cells = <1>;
     75                         #size-cells = <1>;
     76 
     77                         range@7 {
     78                             compatible = "range";
     79                             reg = <0x10 0x10>;
     80                             reg-names = "range7";
     81                         };
     82 
     83                         range@8 {
     84                             compatible = "range";
     85                             reg = <0x0 0x10>;
     86                             reg-names = "range8";
     87                         };
     88                     };
     89                 };
     90             };
     91 
     92             range@9 {
     93                 compatible = "range";
     94                 reg = <0x800 0x50>;
     95                 reg-names = "range9";
     96             };
     97 
     98             demo_level1-2 {
     99                 compatible = "simple-bus";
    100                 ranges = <0x0 0x900 0x100>;
    101                 #address-cells = <1>;
    102                 #size-cells = <1>;
    103 
    104                 range@10 {
    105                     compatible = "range";
    106                     reg = <0x0 0x50>;
    107                     reg-names = "range10";
    108                 };
    109 
    110                 demo_level1-2-1 {
    111                     compatible = "simple-bus";
    112                     ranges;
    113                     #address-cells = <1>;
    114                     #size-cells = <1>;
    115 
    116                     range@11 {
    117                         compatible = "range";
    118                         reg = <0x50 0x30>;
    119                         reg-names = "range11";
    120                     };
    121                 };
    122             };
    123         };
    124 
    125         demo_level2 {
    126             compatible = "simple-bus";
    127             ranges;
    128             #address-cells = <1>;
    129             #size-cells = <1>;
    130 
    131             range@12 {
    132                 compatible = "range";
    133                 reg = <0x2000 0x1000>;
    134                 reg-names = "range12";
    135             };
    136         };
    137     }
    138 };
    复制代码
     

    二、驱动

    下面是一个简单的驱动,功能很简单,只是在probe函数中将memory资源的start和(end+1)打印出来.
    demo_range.c:
    复制代码
    #include <linux/init.h>
    #include <linux/module.h>
    #include <linux/platform_device.h>
    #include <linux/of.h>
    
    static int demo_range_probe(struct platform_device *pdev)
    {
        struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
    
        printk(KERN_INFO "%s start: 0x%x, end: 0x%x
    ",
            res->name, res->start, res->end + 1);
    
        return 0;
    }
    
    static int demo_range_remove(struct platform_device *pdev)
    {
        return 0;
    }
    
    static const struct of_device_id demo_range_of_match[]  = {
        { .compatible = "range"},
        {},
    };
    
    static struct platform_driver demo_range_driver = {
        .driver = {
            .name = "demo_range",
            .owner = THIS_MODULE,
            .of_match_table = demo_range_of_match,
        },
        .probe = demo_range_probe,
        .remove = demo_range_remove,
    };
    module_platform_driver(demo_range_driver);
    
    MODULE_LICENSE("GPL v2");
    复制代码
    在驱动中会获得memory资源,然后将start和(end+1)打印出来,之所以这里用(end+1),仅仅是为了便于理解下面的kernel log。

    三、验证

    编译驱动,然后加载,可以看到下面的打印信息:
    复制代码
    [root@vexpress mnt]# insmod demo_range.ko 
    [  382.940402] range0 start: 0x3000100, end: 0x3000300
    [  382.940697] range1 start: 0x3000300, end: 0x3000500
    [  382.941448] range2 start: 0x3000600, end: 0x3000800
    [  382.941657] range3 start: 0x3001100, end: 0x3001300
    [  382.941855] range4 start: 0x3001400, end: 0x3001600
    [  382.942057] range5 start: 0x3001600, end: 0x3001700
    [  382.942262] range6 start: 0x3001750, end: 0x3001780
    [  382.942470] range7 start: 0x3001730, end: 0x3001740
    [  382.942684] range8 start: 0x3001720, end: 0x3001730
    [  382.949796] range9 start: 0x3001800, end: 0x3001850
    [  382.950023] range10 start: 0x3001900, end: 0x3001950
    [  382.950603] range11 start: 0x3001950, end: 0x3001980
    [  382.950805] range12 start: 0x3002000, end: 0x3003000
    复制代码
     
    总结:
    1、ranges属性值的格式 <local地址, parent地址, size>, 表示将local地址向parent地址的转换。
    比如对于#address-cells和#size-cells都为1的话,以<0x0  0x10 0x20>为例,表示将local的从0x0~(0x0 + 0x20)的地址空间映射到parent的0x10~(0x10 + 0x20)
     
    其中,local地址的个数取决于当前含有ranges属性的节点的#address-cells属性的值,size取决于当前含有ranges属性的节点的#size-cells属性的值。
    parent地址的个数取决于当前含有ranges属性的节点的parent节点的#address-cells的值。
     
    2、对于含有ranges属性的节点的子节点来说,其reg都是基于local地址
     
    3、ranges属性值为空的话,表示1:1映射
     
    4、对于没有ranges属性的节点,代表不是memory map区域
     

    四、示意图

    对照上面的log理解下面的框图
     
     
     
     
    完。
    【作者】张昺华
    【大饼教你学系列】https://edu.csdn.net/course/detail/10393
    【新浪微博】 张昺华--sky
    【twitter】 @sky2030_
    【微信公众号】 张昺华
    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利.
  • 相关阅读:
    【todo】深入理解设计模式
    一个最简单的LRUCache实现 (JAVA)
    Redis之AOF重写及其实现原理
    【todo】nosql 的几种类型研究
    【todo】redis 中的hyperloglog原理
    【todo】ER分片
    【todo】研究一下mycat的原理
    【todo】研究一下sharding-jdbc的原理
    为什么存储过程比sql语句效率高?
    存储过程这一篇就够了
  • 原文地址:https://www.cnblogs.com/sky-heaven/p/14981271.html
Copyright © 2011-2022 走看看