设备树中ranges属性理解[通俗易懂]

作者

彭东林
pengdonglin137@163.com

文章来源

http://www.cnblogs.com/pengdonglin137/p/7401049.html

正文

一、设备树
  • 下面是我们将要实验的设备树的例子:
/ {
#address-cells = <1>;
#size-cells = <1>;
demo_level0 {
compatible = "simple-bus";
ranges = <0x0 0x3000000 0x3000>;
#address-cells = <1>;
#size-cells = <1>;
range@0 {
compatible = "range";
reg = <0x100 0x200>;
reg-names = "range0";
};
range@1 {
compatible = "range";
reg = <0x300 0x200>;
reg-names = "range1";
};
range@2 {
compatible = "range";
reg = <0x600 0x200>;
reg-names = "range2";
};
demo_level1 {
compatible = "simple-bus";
ranges = <0x0 0x1000 0x1000>;
#address-cells = <1>;
#size-cells = <1>;
range@3 {
compatible = "range";
reg = <0x100 0x200>;
reg-names = "range3";
};
demo_level1-1 {
compatible = "simple-bus";
ranges = <0x0 0x300 0x500>;
#address-cells = <1>;
#size-cells = <1>;
range@4 {
compatible = "range";
reg = <0x100 0x200>;
reg-names = "range4";
};
range@5 {
compatible = "range";
reg = <0x300 0x100>;
reg-names = "range5";
};
demo_level1-1-1 {
compatible = "simple-bus";
ranges = <0x0 0x400 0x100>;
#address-cells = <1>;
#size-cells = <1>;
range@6 {
compatible = "range";
reg = <0x50 0x30>;
reg-names = "range6";
};
demo_level1-1-1-1 {
compatible = "simple-bus";
ranges = <0x0 0x20 0x20>;
#address-cells = <1>;
#size-cells = <1>;
range@7 {
compatible = "range";
reg = <0x10 0x10>;
reg-names = "range7";
};
range@8 {
compatible = "range";
reg = <0x0 0x10>;
reg-names = "range8";
};
};
};
};
range@9 {
compatible = "range";
reg = <0x800 0x50>;
reg-names = "range9";
};
demo_level1-2 {
compatible = "simple-bus";
ranges = <0x0 0x900 0x100>;
#address-cells = <1>;
#size-cells = <1>;
range@10 {
compatible = "range";
reg = <0x0 0x50>;
reg-names = "range10";
};
demo_level1-2-1 {
compatible = "simple-bus";
ranges;
#address-cells = <1>;
#size-cells = <1>;
range@11 {
compatible = "range";
reg = <0x50 0x30>;
reg-names = "range11";
};
};
};
};
demo_level2 {
compatible = "simple-bus";
ranges;
#address-cells = <1>;
#size-cells = <1>;
range@12 {
compatible = "range";
reg = <0x2000 0x1000>;
reg-names = "range12";
};
};
}
};
二、驱动
  • 下面是一个简单的驱动,功能很简单,只是在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\n",
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属性值的格式
四、示意图
  • 对照上面的log理解下面的框图
    image

Published by

风君子

独自遨游何稽首 揭天掀地慰生平

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注