关于设备树的心得体会(待完善)

为什么要设备树?
设备信息和驱动分离。
个人理解就是将操作函数与设备信息进行分类,从而减少代码冗余。以前的描述板级细节的代码都被放在内核中,不同厂家的产品描述信息不尽相同,致使内核越来越大。在Linux3.x版本后,arch/arm/plat-xxx和arch/arm/mach-xxx中,描述板级细节的代码(比如platform_device、i2c_board_info等)被大量取消,取而代之的是设备树,其目录位于arch/arm/boot/dts,采用Device Tree后,许多硬件的细节可以直接透过它传递给Linux,而不再需要在kernel中进行大量的冗余编码

什么是设备树?
设备树是由一系列被命名的结点(node)和属性(property)组成,而结点本身可包含子结点
DTS 是设备树源码文件
DTB 是 DTS 编译后的二进制文件
DTC 工具 编译 DTB文件
DTS(Device Tree Source) : 描述设备树的文件
DTS文件采用 树形结构描述板级设备
如:CPU数目,内存基地址,IIC接口的设备,SPI接口的设备
Device Tree文件的格式为dts,包含的头文件格式为dtsi,但是uboot和linux不能直接识别,他们只能识别二进制文件,所以需要把dts文件编译成dtb文件。dtb文件是一种可以被kernel和uboot识别的二进制文件。

早期的Linux内核(Linux-3.0以前)里的设备信息(platform_device)和驱动信息(platform_driver)都是通过C代码硬写入到Linux内核里去了,这些源文件都在arch/arm/mach-xxx或plat-xxx下
请添加图片描述

ARM 架构的 SOC 有很多种,打开boot/dts/Makefile文件,每个板子都有一个对应的 DTS 文件
请添加图片描述
Linux-3.x之后的内核统一启用Device Tree机制之后,所有的设备硬件信息描述都会放到 arch/arm/boot/dts/ 路径下的 xxx.dts文件中描述。这些dts(Device Tree Source)文件并不是C代码,而是具有相应语法格式的源文件。在编译内核时,我们可以使用 make dtbs 命令编译生成相应开发板的dtb(Device Tree Blob)文件。因为这些源文件并不是C程序,所以不是用gcc来编译,而是由其相应的编译工具dtc(Device Tree Compiler)来编译。

即内核中保留了操作函数,把硬件信息放入dts中,dts文件很小,而且可以删除同一目录下多余的dts,经内核的dtc编译形成dtb二进制文件,设备树属性获取函数头文件:include/linux/of.h,且设备树中使用device_node结构体描述节点,of.h中的API需要device_node作为参数传入

设备树属性的获取

struct device_node {
		const char *name;
 		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;
#if defined(CONFIG_OF_KOBJ)
 		struct kobject kobj;
#endif

 		unsigned long _flags;
 		void *data;
#if defined(CONFIG_SPARC)
 		unsigned int unique_id;
 		struct of_irq_controller *irq_trans;
#endif
};

要想获取设备树中的属性,必须先获取device_node,这个节点会在probe初始化的时候传入。
驱动中获取device_node方法:

struct device_node *node = pdev->dev.of_node

节点中属性的结构体property,定义了属性常用的值

struct property {
 		char *name;
 		int length;
 		void *value;
 		struct property *next;
#if defined(CONFIG_OF_DYNAMIC) || defined(CONFIG_SPARC)
 		unsigned long _flags;
#endif

#if defined(CONFIG_OF_PROMTREE)
 		unsigned int unique_id;
#endif

#if defined(CONFIG_OF_KOBJ)
 		struct bin_attribute attr;
#endif
};

获取属性参数的函数

根据属性名称,提取属性值
		struct property *of_find_property(const struct device_node *np, const char *name, int *lenp);

驱动测试代码

#include <linux/init.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/of.h>
#include <linux/of_gpio.h>

#define DRIVER_NAME "seedling"

static int leds_probe(struct platform_device * pdev)
{
    struct device_node *node = pdev->dev.of_node;
    printk("node name is %s!\n",node->name);
    printk("node fullname is %s!\n",node->full_name);
    
    struct property *comprop = NULL; 
    comprop = of_find_property(node,"compatible",NULL);
    printk("comprop name is %s!\n",comprop->name);
    printk("comprop value is %s!\n",comprop->value);

    comprop = of_find_property(node,"status",NULL);
    printk("comprop name is %s!\n",comprop->name);
    printk("comprop value is %s!\n",comprop->value);
    
    printk(KERN_ALERT "probe init\n");
    
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值