Linux设备树详解

  • 设备树小故事
  • 设备树文件
  • 使用设备树
    • 修改设备树文件
    • 编译设备树
    • 异常处理
  • 编写驱动文件
  • 参考资料

设备树小故事

设备树(Device Tree),将这个词分开就是“设备”和“树”,描述设备树的文件叫做 DTS(Device Tree Source),这个 DTS 文件采用树形结构描述板级设备,也就是开发板上的设备信息,比如CPU 数量、 内存基地址、 IIC 接口上接了哪些设备、 SPI 接口上接了哪些设备等等。

在没有使用设备树的时候,有关板级的硬件信息都被硬编码在内核中,这就导致了内核中描述板级硬件的代码过于庞大,不利于阅读。

随着智能手机的发展,每年新出的 ARM 架构芯片少说都在数十、数百款, Linux 内核下板级信息文件将会成指数级增长!这些板级信息文件都会被硬编码进 Linux 内核中,导致 Linux 内核**“虚胖”**。

当 Linux 之父 linus 看到 ARM 社区向 Linux 内核添加了大量无用、冗余的板级信息文件,不禁的发出了一句This whole ARM thing is a fucking pain in the ass

从此以后 ARM 社区就引入了 PowerPC 等架构已经采用的设备树(Flattened Device Tree)

这个就是设备树的由来,简而言之就是, Linux 内核中 ARM 架构下有太多的冗余的垃圾板级信息文件,导致 linus 震怒,然后 ARM 社区引入了设备树。

设备树文件

设备树源文件扩展名为.dts,另外DTS是设备树源码文件, DTB 是将DTS 编译以后得到的二进制文件。

对于设备树文件的编译我们可以使用DTC 工具对其进行编译,DTC工具源码在Linux内核的scripts/dtc目录下。

DTC 工具依赖于 dtc.cflattree.cfstree.c 等文件,最终编译并链接出 DTC
个主机文件。

如果要编译 DTS 文件的话只需要进入到 Linux 源码根目录下,然后执行如下命
令:

make dtbs

Linux设备树文件在内核源码中的 arch/arm/mach-xxx 文件夹和arch/arm/plat-xxx 文件夹中

使用设备树

我们想要使用设备树首先需要修改设备树文件,设备树文件的位置我们上面已经所过了,大家可以去找一下:

修改设备树文件

我们想要使用设备树首先需要修改设备树文件,我们需要首先找到我们需要修改的设备树文件,如果不知道对应模块的设备树文件在哪个位置的话我上面有讲到,设备树文件都在内核源码中的 arch/arm/mach-xxx 文件夹和arch/arm/plat-xxx 文件夹中。

在文件夹中找到我们芯片或者开发板所对应的DTS文件,例如我使用的开发板是野火公司的I.MX6U开发板,所以我们需要首先找到这个开发板所对应的设备树,我们所有的设备都需要在这个设备树文件中进行描述。如果没有可能是内核版本太老所致。

找到我们需要修改的设备树文件后打开对应的.dts 文件,在根节“/”下创建一个名为“alphaled”的子节点,打开 imx6ull-alientek-emmc.dts 文件,
在根节点“/”最后面输入如下所示内容:

1 alphaled {2   #address-cells = <1>;
3   #size-cells = <1>;
4   compatible = "atkalpha-led";
5   status = "okay";
6   reg = < 0X020C406C 0X04 /* CCM_CCGR1_BASE */
7           0X020E0068 0X04 /* SW_MUX_GPIO1_IO03_BASE */
8           0X020E02F4 0X04 /* SW_PAD_GPIO1_IO03_BASE */
9           0X0209C000 0X04 /* GPIO1_DR_BASE */
10          0X0209C004 0X04 >; /* GPIO1_GDIR_BASE */
11 };
  • 2、 3 行:属性#address-cells#size-cells 都为 1,表示 reg 属性中起始地址占用一个字长(cell),地址长度也占用一个字长(cell)。
  • 4 行:属性 compatbile 设置 alphaled 节点兼容性为“atkalpha-led”
  • 5 行:属性 status 设置状态为“okay”
  • 6~10 行: reg 属性,非常重要! reg 属性设置了驱动里面所要使用的寄存器物理地址,比如第 6 行:“0X020C406C 0X04”表示 I.MX6ULLCCM_CCGR1 寄存器,其中寄存器首地址为 0X020C406C,长度为 4 个字节。

编译设备树

设备树文件修改之后我们需要首先进行编译以下,正如我们编译C语言一样,DTS文件也是需要编译的,我们使用以下命令对设备树文件DTS进行编译。

make dtbs

编译完成以后得到 imx6ull-alientek-emmc.dtb,使用新的 imx6ull-alientek-emmc.dtb 启动Linux 内核。 Linux 启动成功以后进入到/proc/device-tree/目录中查看是否有“alphaled”这个节点,结果如图:

异常处理

如果没有“alphaled”节点的话请重点下面两点:

  • 检查设备树修改是否成功,也就是 alphaled 节点是否为根节点“/”的子节点。
  • 检查是否使用新的设备树启动的 Linux 内核。

可以进入到图 44.3.1 中的 alphaled 目录中,查看一下都有哪些属性文件,结果如图 所示:

大家可以查看一下 compatiblestatus 等属性值是否和我们设置的一致。如果不一致修改过来即可。

编写驱动文件

在编写驱动文件过程中我们只需要关注一下设备树的改动,其他例如申请设备号啥的和原来是一样的,我们现在不需要关注,如果你对字符设备驱动框架的理解还不是很深,你可以看我写的这篇文章:

  • 手把手带你编写一个规范的字符设备驱动
  • 字符设备驱动程序的三种写法
  • Linux字符驱动开发

回归主题,我们现在开始修改设备树相关代码,我们首先在驱动入口处添加以下代码:

/* 获取设备树中的属性数据 */
/* 1、获取设备节点: alphaled */
dtsled.nd = of_find_node_by_path("/alphaled");
if(dtsled.nd == NULL) {printk("alphaled node not find!\r\n");return -EINVAL;
} else {printk("alphaled node find!\r\n");
}/* 2、获取 compatible 属性内容 */
proper = of_find_property(dtsled.nd, "compatible", NULL);
if(proper == NULL) {printk("compatible property find failed\r\n");
} else {printk("compatible = %s\r\n", (char*)proper->value);
}/* 3、获取 status 属性内容 */
ret = of_property_read_string(dtsled.nd, "status", &str);
if(ret < 0){printk("status read failed!\r\n");
} else {printk("status = %s\r\n",str);
}/* 4、获取 reg 属性内容 */
ret = of_property_read_u32_array(dtsled.nd, "reg", regdata, 10);
if(ret < 0) {printk("reg property read failed!\r\n");
} else {u8 i = 0;printk("reg data:\r\n");for(i = 0; i < 10; i++)printk("%#X ", regdata[i]);printk("\r\n");
}/* 初始化 LED */
#if 0/* 1、寄存器地址映射 */IMX6U_CCM_CCGR1 = ioremap(regdata[0], regdata[1]);SW_MUX_GPIO1_IO03 = ioremap(regdata[2], regdata[3]);SW_PAD_GPIO1_IO03 = ioremap(regdata[4], regdata[5]);GPIO1_DR = ioremap(regdata[6], regdata[7]);GPIO1_GDIR = ioremap(regdata[8], regdata[9]);
#elseIMX6U_CCM_CCGR1 = of_iomap(dtsled.nd, 0);SW_MUX_GPIO1_IO03 = of_iomap(dtsled.nd, 1);SW_PAD_GPIO1_IO03 = of_iomap(dtsled.nd, 2);GPIO1_DR = of_iomap(dtsled.nd, 3);GPIO1_GDIR = of_iomap(dtsled.nd, 4);
#endif

看到上面的代码是不是感觉加入设备树之后代码结构变得好复杂啊!还要获取那么多设备树属性和数据,这不是妥妥的给自己找不爽吗?

其实设备树的加入主要是为了减少这些板级信息被写入Linux内核中,因为如果不使用设备树的话我们每一个开发板都需要加入到Linux内核中,否者你就无法使用该款开发板,基于此,设备树就此诞生了,让我们每一个开发板都有一棵属于自己的树,板上的硬件相当于树上的分支,这样Linux在启动的时候就会先去找你所对应的设备树,相当于读到了你板子的信息,你就可以使用设备树了!

其实设备树的知识远不止于此,我目前也是囫囵吞枣,也有很多不明白的地方,大家可以多读几篇文章,看看大佬们怎么总结的。

参考资料

  • 正点原子 I.MX6U 嵌入式 Linux 驱动开发指南

Linux设备树详解相关推荐

  1. linux 设备树详解

    2 Linux 设备树 2.1 什么是设备树? 设备树(Device Tree),将这个词分开就是"设备"和"树",描述设备树的文件叫做DTS(Device T ...

  2. 正点原子----Linux设备树详解

    linux设备树 1.什么是设备树 2.DTS.DTB.DTC的关系 3.如何编译设备树 4.DTS基本结构 4.1.语法 4.2.设备树在系统中的体现 4.3.尝试自己添加节点 4.4.尝试对根节点 ...

  3. 【Linux驱动开发】Linux设备树详解

    目录 一.设备树基础 1.概念 2.文件格式 3.编译工具 二.DTS语法 1..dtsi 头文件 2. 设备节点 3.标准属性 4.compatible 属性详解 5.修改设备树文件,增加或修改节点 ...

  4. 奇小葩讲设备树(5/5)-- Linux设备树详解(五)设备树的使用

    对于任何的知识来说,了解了理论的知识,知道了设备树怎么解析用以代替传统的范式之后,我们需要知道怎么使用设备树.对于使用我们分两部分,一部分是它有哪些接口,能做些什么,至于怎么编写dts文件本章不讨论. ...

  5. 奇小葩讲设备树(4/5)-- Linux设备树详解(四)kernel的解析

    uboot将一些参数,设备树文件传给内核,那么内核如何处理这些设备树文件呢?本章就kernel解析设备树的过程和原理,本章的主要内容以Device Tree相关的数据流分析为索引,对ARM linux ...

  6. 奇小葩讲设备树(2/5)-- Linux设备树详解(二)文件构成

    设备树就是描述单板资源以及设备的一种文本文件.至于出现的原因,基本的语法和使用方法,上一章节做了基本的介绍.本篇文章主要是更深层次的探讨设备文件的构成. 1. devie tree的编译 Device ...

  7. 奇小葩讲设备树(1/5)-- Linux设备树详解(一) 基础知识

    关于设备树,之前就经过详细的系统培训,但是本着会用就行的原则,对各个知识点都没有进行系统的总结.都是用到哪里学哪里,时间长了,基本也忘记了.所以对于后期知识各个知识点进行总结,本章主要讨论一下内容,能 ...

  8. linux 视频教程 韦山东,韦东山 linux 设备树详解

    简 介 设备树视频录制完毕,29节,现在只要69元.学员对此课程的评价:这是最翔实最实惠最精益求精的设备树教程,感兴趣的了解一下, 以下是课程详情~ [设备树是什么?] 设备树是一种机制,用文本的方式 ...

  9. 奇小葩讲设备树(3/5)-- Linux设备树详解(三)u-boot设备树的传递

    前面两节介绍了设备的基本概念.编译.结构的组成,本章讨论的主要内容为 dtb如何通过Bootloader引导程序加载到内核 bootloader如何解析dbt bootloader支持哪些dtb的操作 ...

最新文章

  1. [笔记]C#基础入门(八)——C#标识符的命名规则
  2. 将div垂直居中放置在另一个div中[重复]
  3. 图像处理和计算机视觉中的经典论文
  4. “影响100活动”答记者问(二)
  5. Springboot与抓拍系统对接实现查询违章数据与预览抓拍照片
  6. check generated report by SE16
  7. 在PowerDesigner中设计物理模型1——表和主外键
  8. 二叉树的深度优先遍历原理及python实现
  9. jquery 事件,注册 与重复事件处理
  10. multisim二极管_快恢复二极管与肖特基二极管有何区别?你用对了吗
  11. 2.掌握Python基本数据类型,从python陌路人到熟人!
  12. (十七)spring cloud微服务分布式云架构-eureka 基础
  13. 时机论:早起的鸟儿也要选对“用户”季节
  14. 抖音很火的小程序表白html,最近抖音很火的表白小程序写法C#版
  15. leetcode——第322题——零钱兑换
  16. PS如何精确设置参考线,标尺,辅助线
  17. 解决Request header field XXX is not allowed by access-control-allow-headers in preflight response
  18. CX32l003 点亮0.96寸OLED屏幕
  19. python的mysql数据查询及报错AttributeError: 'Connection' object has no attribute 'curson'
  20. arduino 红外遥控器控制LED灯

热门文章

  1. 代码规范-html,图片,css,命名等规范
  2. 冷源法测试噪声系数(Noise Figure)详细步骤
  3. vuex基础-Vuex是什么呢?
  4. Pytorch实战1:LeNet手写数字识别 (MNIST数据集)
  5. Java 定时发送邮件
  6. Thymeleaf在IDEA中的红色波浪线问题
  7. 项目介绍|Mirror:用户创造,用户所有
  8. 如何在Data Lake Analytics中使用临时表
  9. Spinnaker微服务如何自建
  10. 温州医科大学计算机考研,牛!温州医科大学寝室6人全考研进985顶尖名校:浙大、复旦、上交...