当前位置: 首页 > news >正文

设备树引入

一、设备树的基本知识

1、什么是设备树?为什么会有设备树?

        2011年,Linux之父Linus Torvalds发现这个问题后,就通过邮件向ARM-Linux开发社区发了一封邮件,不禁的发出了一句“This whole ARM thing is a f*cking pain in the ass”。之后ARM Linux社区引入了设备树。为什么LinusTorvalds会爆粗口呢?
        平台总线模型是把驱动分成了俩个部分,一部分是device,一部分是driver,设备信息和驱动分离这个设计非常的好。device部分是描述硬件的。一般device部分的代码会放在内核源码中arch/arm/plat-xxx和arch/arm/mach-xxx下面。但是随着Linux支持的硬件越来越多,在内核源码下关于硬件描述的代码也越来越多。并且每修改一下就要编译一次内核。长此以往Linux内核里面就存在了大量“垃圾代码”,而且非常多,这里说的“垃圾代码”是关于对硬件描述的代码。从长远看,这些代码对Linux内核本身并没有帮助,所以相当于Linux内核是“垃圾代码”。但是并不是说平台总线这种方法不好。

        为了解决这个问题,设备树就被引入到了Linux上。使用设备树来剔除相对内核来说的“垃圾代码”,既用设备树来描述硬件信息,用来替代原来的device部分的代码。虽然用设备树替换了原来的device部分,但是平台总线模型的匹配和使用基本不变。并且对硬件修改以后不必重新编译内核。直接需要将设备树文件编译成二进制文件,在通过bootloader传递给内核即可。

        所以设备树就是用来描述硬件资源的文件

2、设备树的基本概念

①为什么叫设备树?

设备树是描述硬件的文本文件,因为语法结构像树一样。所以叫设备树.

如下图:

②基本名词解释

<1>DT:DeviceTree //设备树
<2>FDT:Flattened Device Tree //开放设备树,起源于OpenFirmware(OF)
<3>DTS:DeviceTree source的缩写 //设备树源码
<4>DTSI:DeviceTree sourcein Clude的缩写 //通用的设备树源码
<5>DTB:DeviceTree Blob的缩写 //编译设备树源码得到的文件
<6>DTC:DeviceTree Compiler的缩写 //设备树编译器

DTS、DTSI、DTC、DTB之间的关系:

Linux内核通过读取设备树的描述文件(通常是.dtb或.dts文件),来构建一个内存中的表示,内核和驱动程序则使用这个表示来识别和配置硬件设备。设备树文件在编译时从设备树源文件(.dts)转换成二进制形式(.dtb),然后通常被包含在内核映像或者作为独立文件提供给引导加载程序

补充:

dts    

dts文件是一种ASCII文本格式的设备树描述文件,此文件适合人类阅读,主要是给用户看的。 硬件的相应信息都会写在.dts为后缀的文件中,每一款硬件可以单独写一份xxxx.dts,一般在Linux源码中存在大量的dts文件,对于 arm 架构可以在arch/arm/boot/dts找到相应的dts。对于rk3399开发板arch/arm/boot/dts/rk3399-nanopi4-common.dtsi中一般会包含一个公共部分的dtsi文件,如下:#include "rk3399-nanopi4-rkisp1.dtsi"

dtsi    

对于一些相同的dts配置可以抽象到dtsi文件中,然后类似于 C 语言的方式可以include到dts文件中

二、编译设备树 (DTC编译器的使用)

DTC编译器命令格式

编译设备树:dtc -I dts -O dtb -o xxx.dtb xxx.dts
反编译设备树:dtc -I dtb -O dts -o xxx.dts xxx.dtb

三、设备树的基本语法

1、设备树根节点

根节点是设备树必须要包含的节点。根节点的名字是/。

/dts-v1/;      //第一行表示dts文件的版本
/{                //根节点
};

2、设备树子节点格式

格式:

label: node-name @unit-address{
        properties definitions
        child nodes

};

举例:

nodel{                        //子节点,节点名称为nodel
        nodel_child{                //子子节点,节点名称为nodel_child

        }
};

注意:同级节点下节点名称不能相同。不通级节点名称可以相同  

3、节点名称

在对节点进行命名的时候,一般要体现设备的类型,比如网口一般命名成ethernet,串口一般命名成uart,对于名称一般要遵循下面的命令格式。
格式:标签:名称@<设备地址>
其中,[标签]和[@<设备地址>]是可选项,<名称>是必选项。另外,这里的设备地址没有实际意义,只是让节点名称更人性化,更方便阅读。
举例:
uart: serial@02288000
其中,uart就是这个节点标签,也叫别名,serial@02288000就是节点名称。 

4、reg属性

reg属性可以来描述地址信息。比如寄存器的地址。
reg属性的格式如下:
reg =<address1 length1 address2 length2 address3 length3...>
举例:
reg= <0x02200000 0x4000>;

reg= <x022000000x4000
          0x02205000 0x4000>;

5、#address-cell和#size-cells属性

#address-cell和#size-cells用来描述子节点中的reg信息中的地址和长度信息
举例:

nodel{
        #address-cells = <1>;
        #size-cells = <0>;
   nodel-child {
           reg = <0>;

        };

};

6、model属性

model属性的值是一个字符串,一般用model描述一些信息。比如设备的名称,名字等。
举例1:
model ="wm8960-audio”;
举例2:
model = "This is Linux board";

7、status属性

status属性是和设备的状态有关系的,status的属性值是字符串。属性值有下面几个状态可选:

8、compatible属性

compatible属性是非常重要的一个属性。compatible是用来和驱动进行匹配的,匹配成功以后
会执行驱动中的probe函数。

举例:
compatible ="xunwei”, "xunwei-board";
在匹配的时候会先使用第一个值xunwei进行匹配,如果没有就会使用第二个值xunwei-board进行匹配。

示例:

9、设备树特殊节点

aliases

        特殊节点aliases用来定义别名。定义别名的目的就是为了方便引用节点。当然,除了使用aliases来命名别用,也可以在对节点命名的适合添加标签来命名别名。
举例:

aliases{
        mmc0 = &sdmmc0;
        mmcl = &sdmmcl;
        mmc2 = &sdhci;
        serial0 ="/simple@fe000000/serial@llc500”;

};

chosen

chosen节点用来uboot给内核传递参数。重点是bootargs参数。chosen节点必须是根节点的子节点
举例:

chosen{
        bootargs = "root=/dev/nfs rw nfsroot=192.168.1.1 console=ttyS0,115200”; 

}

device_type属性

在某些设备树文件中,可以看到device_type属性,device_type属性的值是字符串,只用于cpu节点或者memory节点进行描述。
举例1:

memory@30000000{
        device_type =“memory”;
        reg =<0x30000000    0x4000000>;

 举例2:

cpu1: cpu@1{
        device_type = "cpu”;
        compatible = "arm,cortex-a35″, "arm, armv8”;
        reg = <0x0  0x1>;

};

自定义属性

设备树中规定的属性有时候并不能满足我们的需求,这时候我们可以自定义属性。
举例:

自定义一个管脚标号的属性pinnum。
pinnum = <0 1 2 3 4>; 

示例:

 

四、DTS基本框架

设备树由一系列被命名的节点(Node)和属性(Property)组成,而节点本身可包含子节点。在设备树中,可描述的信息包括:

·  CPU的数量和类别。

·  内存基地址和大小。

·  总线和桥。

·  外设连接。

·  中断控制器和中断使用情况。

·  GPIO控制器和GPIO使用情况。

·  时钟控制器和时钟使用情况。

基本上就是画一棵电路板上CPU、总线、设备组成的树,Bootloader会将这棵树传递给内核,然后内核可以识别这棵树,并根据它展开出Linux内核中的platform_device、i2c_client、spi_device等设备,而这些设备用到的内存、IRQ等资源,也被传递给了内核,内核会将这些资源绑定给展开的相应的设备。

//一级节点:会展开成platfor_device

//内核会把这个节点展开成平台设备,设备名是ff720000.xyd-leds

补充:增加设备树属性信息,可以自动生成设备端代码。

对平台设备驱动模型来说,平台设备代码(platform_device.c)不需要实现,被设备树中设备文件所替代了。

如何添加设备树?

以rk3399作为例子

kernel-rockchip-nanopi4-linux-v4.4.y/arch/arm64/boot/dts/rockchip/rk3399-nanopi4-common.dtsi

需要添加的硬件资源:

xyd-leds@FF720000{

     compatible="xyd-rk3399-leds";

     reg=<0x0 0xFF720000 0x0 0x10000>;

     reg-names="gpio0-reg-for-leds";

     led-total=<1>;

    };

 

编译:在内核源码的顶层目录执行以下命令:

make nanopi4-images -j8    

把生成的resource.img 和 kernel.img 烧写到开发板上。

编写平台驱动模型里面的驱动代码,修改设备树,编译内核kernel.img and resource.img文件烧写到板子上.

最终结果:

http://www.xdnf.cn/news/1073395.html

相关文章:

  • 【Java--SQL】${}与#{}区别和危害
  • 【EDA软件】【联合Modelsim 同步FIFO仿真】
  • git 挑选:git cherry-pick
  • springboot+Vue逍遥大药房管理系统
  • python中学物理实验模拟:瞬间推力与摩擦力作用下的物体运动
  • 【数据标注师】目标跟踪标注
  • 概述-4-通用语法及分类
  • Word之空白页删除2
  • 基于Pandas和FineBI的昆明职位数据分析与可视化实现(二)- 职位数据清洗与预处理
  • UniApp Vue3 模式下实现页面跳转的全面指南
  • SQL关键字三分钟入门:ROW_NUMBER() —— 窗口函数为每一行编号
  • FreeSWITCH配置文件解析(2) dialplan 拨号计划中xml 的action解析
  • 西门子S7-200 SMART PLC:小型自动化领域的高效之选
  • C语言---常见的字符函数和字符串函数介绍
  • STM32[笔记]--7.MDK5调试功能
  • 关于ubuntu 20.04系统安装分区和重复登录无法加载桌面的问题解决
  • 医疗标准集中标准化存储与人工智能智能更新协同路径研究(上)
  • 基于Spring Boot的网上购物平台设计与实现
  • 最后的生还者2:重制版 免安 中文离线运行版+整合包
  • Vue 项目中 Excel 导入导出功能笔记
  • 【数据标注师】3D标注
  • 【数据标注师】事件标注2
  • kubectl get pod返回数据研究
  • 访问不了/druid/index.html (sql.html 或 login.html)
  • 在单片机中如何实现一个shell控制台
  • 权限提升-工作流
  • Go开发工程师-Golang基础知识篇
  • Element Plus el-button实例类型详解
  • Kioptrix Level1
  • TCP 在高速网络下的大数据量传输优化:拥塞控制、效率保障与协议演进​