<div>
<h2>1 设备树的说明</h2>
<p>在写完嵌入式驱动总结后,对于设备树相关的语法和使用一直都想进行系统的描述,但是因为最近比较忙碌,所以一直拖到现在才完成初版,对于整个嵌入式Linux驱动开发中,设备树语法和构建是其中比较核心的部分,是需要比较系统的去学习掌握的。本文参考设备树说明文档<Devicetree Specification Release v0.2>, 在结合日常驱动开发中积累的经验,总结完成的一篇设备树语法的说明。对于驱动的编写来说,设备树语法的了解自然必不可少,但大多数情况下我们模仿厂商的实现,在结合芯片手册就可以增加自己需要的功能,不过如何来添加设备节点,保证添加的有效性,这时候就需要掌握理和解设备树语法。随着设备树逐渐成为嵌入式驱动开发中的主流,并逐渐取代寄存器的访问方式,设备树对于驱动开发越来越重要,<b>另外如果在本章了解中对于设备树中有疑惑不理解的部分,这很正常,可以先大概浏览下,做到心中有着概念,在带着疑问去学习驱动的内容,当你困惑的时候,可以回来系统的理解设备树的语法(不理解不要纠结),不要在缺少积累的时候去钻牛角尖,这也是嵌入式学习的重要经验。</b></p>
<h2>1.1 设备树综述</h2>
<p>对SOC构造和嵌入式硬件有了解的话,芯片一般由内核(Cortex-A), 以及通过系统总线(AHB, AXI等)挂载的GPIO,I2C,SPI,PWM,Ethernet等外设模块构成。而对于具体的外设模块,如I2C外设,又支持访问多个器件来满足不同功能的需求。而设备树,就是基于系统总线作为主干,将芯片SOC和各类外设以及外部器件用数据结构的形式组合起来描述硬件结构的文件,是对硬件模型的抽象,总结来说,设备树就是对硬件结构的抽象描述。</p>
<p></p>
<div style="text-align:center;">
<img alt="e5c9089db1245a711cc93237036b26a6.png" src="https://beijingoptbbs.oss-cn-beijing.aliyuncs.com/cs/5606289-d93eb18c56534bb950caed8b9cfe8e7f.png">
</div>
<p>上面就是比较常见的基于SOC构建的嵌入式应用系统,包含芯片和外围的设备,虽然总线可能不指一条,外设模块的设备连接情况也会更加复杂,但都没有树结构模型,而设备树也是按照如此模型进行设计的,理解这一点,也可以更深刻的知道设备树的实现思路。</p>
<p> 在对嵌入式整个硬件框架有一定了解后,下面还要理解几个名词。</p>
<p> DTS 设备树的源码文件,用于描述设备硬件情况的抽象</p>
<p> DTSI 和C语言的#include类似,也是描述设备树的源码文件,另外DTS同样被#include包含</p>
<p> DTB 基于DTS源码编译的二进制文件,用于内核调用读取设备树信息的文件。</p>
<p> DTC 用于编译DTS到DTB的工具,由内核编译时使用make dtbs编译设备树二进制文件过程中生成。</p>
<p> 基于以上信息,我们理解DTS/DTSI是基于DTS语法实现的设备描述文件,DTB则是用于内核解析,需要下载的文件,下面正式开始设备树语法的讲解。</p>
<h2>1.2 设备树语法</h2>
<p>在上一小节,我们将设备树的概念有基本的认知,下面更重要的就是DTS语法了,这里我么结合实际的代码区理解设备树语法。</p>
<h3>1.2.1 #include语法</h3>
<p>DTS中#include语法和C语言中类似,支持将包裹的文件直接放置在#include位置从而访问到其它文件的数据,如官方设备树内使用的</p>
<div class="blockcode">
<pre class="blockcode"><code>#include <dt-bindings/input/input.h>
#include "imx6ull.dtsi"
</code></pre>
</div>
<p>另外,也可以用来包含dts文件,如下</p>
<div class="blockcode">
<pre class="blockcode"><code>#include "imx6ull-14x14-evk.dts"</code></pre>
</div>
<h3>1.2.2 节点描述</h3>
<p>对于设备树来说,都是有根节点开始,在添加不同的设备节点描述的,以比较简单的LED设备树为例:</p>
<div class="blockcode">
<pre class="blockcode"><code>/{<!-- --> //根节点
//......
led {<!-- --> //节点名(子节点) <name>
compatible = "gpio-led"; //节点属性
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_gpio_leds>;
led-gpio = <&gpio1 3 GPIO_ACTIVE_LOW>;
status = "okay";
};
gpio_keys: gpio_keys@0 {<!-- --> //节点名(子节点) <label>:<name>[@<unit_address>]
compatible = "gpio-keys"; //节点属性
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_gpio_keys>;
#address-cells = <1>;
#size-cells = <0>;
autorepeat;
|
|