设备树简介

前言

设备树起源?

device tree 来源于openfirmware,内核中关于设备树的函数都是以of开头。

为什么要用设备树?

  1. 减少储存空间,减少驱动的冗余编码。
  2. 实现一套内核对应多套板级设备。

环境:设备树增加usb3503A、网卡、nfs的支持

编译:设备树被编译后的二进制文件传到内核后,内核有专门的函数解析,处理。

语法

遇到括号就是节点,括号里面就是节点的属性

节点和根节点
 {...} 框起来的结构,称为节点;
 /{...} 在dts中最开头的,称为根节点。
节点的标准结构是xxx@yyy{…},
xxx是节点的名字,yyy则不是必须的,其值为节点的地址(寄存器地址或其他地址)。
节点可以包含属性和子节点,其中子节点也是用{}包围起来的。设备树的节点,可以包含,互相也可以引用--看到“&”,表示做了引用(也可以理解面向对象编程的重写);   
属性
    设备树学习的主要部分:设备树文件中属性的配置,驱动文件中调用设备树中的属性。
    compatible--类似设备名称,
    reg,label,gpios,pwms,status等等
设备树套路

带大家看下官方的设备树介绍文档
(Documentation/devicetree/usage-model.txt 106行)
    设备树的三个主要目标:
    1) platform identification,
    2) runtime configuration, and
    3) device population.

platform identification--确认平台
    通过根节点的compatible属性
    例如:
    compatible = "ti,omap3-beagleboard", "ti,omap3450", "ti,omap3";
    compatible = "ti,omap3-beagleboard-xm", "ti,omap3450", "ti,omap3";
    4412的例子:
    compatible = "topeet,itop4412-elite", "samsung,exynos4412", "samsung,exynos4";

runtime configuration--运行环境配置
    大多数通过chosen节点
    例如:
    chosen {
            bootargs = "console=ttyS0,115200 loglevel=8";
            initrd-start = <0xc8000000>;
            initrd-end = <0xc8200000>;
    };
    4412的例子:
    chosen {
            bootargs = "root=/dev/mmcblk0p2 rw rootfstype=ext4 rootdelay=1 rootwait";
            stdout-path = "serial2:115200n8";
    };

开发板启动之后,通过proc和sys文件系统可以查询到设备树的信息。在/proc/device-tree目录下有所有的node的信息;这个目录下能看到表明有相应的节点。在/sys/devices/platform/目录下有所有设备node的信息。在这个目录下能看到表明设备注册了。这里的信息很真要,因为有设备注册,最后驱动才能进入probe()函数!

增加节点和测试代码

在设备树中增加节点信息:

leds_test_node:leds_test_node {
                compatible = "leds_test";
                status = "disabled";
        //         status = "okay";
        };
根节点之后 &adc之前增加
&leds_test_node {
      status = "okay"; //可以理解为状态使能
};

 在驱动中增加代码

#define DRIVER_NAME "leds_test"
...
static const struct of_device_id of_leds_dt_match[] = {
    {.compatible = DRIVER_NAME},
    {},
};
MODULE_DEVICE_TABLE(of,of_leds_dt_match);

static struct platform_driver leds_driver = {
    .probe     = leds_probe,
    .remove = leds_remove,
    .driver = {
        .name = DRIVER_NAME,
        .owner = THIS_MODULE,
        .of_match_table = of_leds_dt_match,
        },
};
...

匹配的关键是of_leds_dt_match中的compatible和设备树中的compatible相同,
如果相同驱动就会进入probe。

获取属性

Linux引入设备树,把硬件分到设备树文件中,驱动中仍然需要硬件信息。
所以必须将设备树中的硬件信息传到驱动中,

设备树最重要的结构体
设备树属性获取函数头文件:include/linux/of.h

struct device_node {
	const char *name;
	const char *type;
	phandle phandle;
	const char *full_name;
	struct fwnode_handle fwnode;

	struct	property *properties;
	struct	property *deadprops;	/* removed properties */
	struct	device_node *parent;
	struct	device_node *child;
	struct	device_node *sibling;
	struct	kobject kobj;
	unsigned long _flags;
	void	*data;
    ...
};

设备树中使用 device_node 结构体描述节点

驱动中获取device_node方法: struct device_node *node = pdev->dev.of_node;

根据属性名称,提取属性值,如果不需要lenp可以赋值为NULL
struct property *of_find_property(const struct device_node *np, const char *name, int *lenp);

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值