IoT之嵌入式Linux设备树机制

系统 Linux
Linux内核v3.x之后提供了一个管理设备节点的机制,即设备树,其描述了硬件资源的板级信息。

Part 01

  Linux设备树机制的介绍   

1.1 概念

设备树(device tree)是一种描述硬件资源的数据结构,起源于Open Firmware(OF:开源固件)。在Linux kernel v2.6之前的版本,关于ARM架构的板级硬件资源均通过.c和.h文件写“死”在arch/arm/plat-xxx和arch/arm/mach-xxx目录下,在开发一款设备时,Linux kernel中充斥着许多无用的硬件信息,不利于阅读和维护。在Linux ARM kernel v3.x之后正式引入设备树机制,主要是为减少这类无用的硬件板级信息被写入Linux kernel中污染内核,有了设备树,则可通过它来将所需的硬件信息传递给Linux kernel。

1.2 组成

设备树主要包含dts(device tree source,源文件)、dtc(device tree compiler,编译工具)和dtb(device tree blob,二进制文件)。

dts 是设备树描述的源文件,在ARM架构下,一个dts对应一个设备,一般位于arch/arm(64)/boot/dts目录下,该文件一般会有包含对应名称的.dtsi文件,类似于c语言的头文件,主要是一些SOC的宏定义共性部分。

dtc 是设备树的编译工具,类似于gcc等编译器,但与gcc不同的是dtc无需外部安装,是由内核自带的。可以将.dts文件编译成.dtb文件。

dtb 是设备树二进制文件,可被Linux kernel识别解析,也可被bootloader解析。

dtbo 是overlay编译出来的二进制文件。

dts、dtc和dtb三者间的关系如下图:

图片

Part 02

  设备树框架和dts文件语法格式   

2.1 设备树基本框架

设备树文件基本结构主要有以下几部分,其形式有点类似xml文件。

  • 单根节点(root):/
  • 节点名称:图中的"node1"和"node2"
  • 子节点:"child-node1"和"child-node2"
  • 节点地址:node@xxx
  • 属性(property):是一组键值对,包括属性名称(property name)和属性值(property value)
  • 标签(label,可选项)

图片

​https://elinux.org/Device_Tree_Usage#Basic_Data_Format​

值得注意的是,“/”是根节点,每个设备树文件仅有一个,当在设备树中发现有多个根节点时,在编译过程中这些根节点会合并成一个。

2.2 dts文件语法格式

与c语言类似,dts同样支持头文件,其头文件扩展名为.dtsi,一般通过#include xxx来引用。

例如,以全志H616这款芯片为例,基于Linux v4.9版本的orangepi开发板的时钟节点(部分)如下:

​/dts-v1/;
/memreserve/ 0x0000000048000000 0x0000000001000000;
/ {
interrupt-parent = <0x1>;
#address-cells = <0x2>;
#size-cells = <0x2>;
model = "Orange Pi Zero 2";
compatible = "allwinner,h616", "arm,sun50iw9p1";
clocks {
compatible = "allwinner,clk-init";
device_type = "clocks";
#address-cells = <0x2>;
#size-cells = <0x2>;
ranges;
reg = <0x0 0x3001000 0x0 0x1000 0x0 0x7010000 0x0 0x400 0x0 0x7000000 0x0 0x4>;
};
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.

上述中,特别重要的compatible属性,它可以以“,”格式指定名称的优先选择。设备树中每个代表设备的节点都要有一个compatible属性,它是OS用于决定绑定到设备驱动的关键特征。

Part 03

  设备树的修改与内核编译安装  ● 

在编写模块的驱动程序时,为不影响内核结构,通常在外部目录下建立一个用于存放编写的驱动源码和编译生成的.ko的文件夹,生成的.ko可以在系统启动后单独加载运行,且无需和内核一起编译,方便更新。其流程一般为:makefile文件编写,接着进行驱动源码编写(可找优秀的架构进行修改,填充细节,如compatible,读、写操作等),然后编译生成.ko文件,进一步修改与单板相关的设备树文件(.dts),在.dts文件中添加或删除相应的设备节点信息,最后编译整个内核文件,当内核编译完成后,使用如下命令卸载旧版本的内核与安装新版本内核:

apt purge -y linux-image-xxx.deb // 卸载内核dpkg -i linux-image(dtb)-xxx.deb // 安装内核
  • 1.

重启单板后,用uname -a 命令查看内核信息,在新编译的内核上,用insmod 命令将生成的.ko模块加载上,cat 命令查看设备节点信息。

需要注意的是,设备树的使用需要在编译kernel时做好对应的配置,还需bootloader支持,否则也无法将数据结构传参给kernel。

责任编辑:庞桂玉 来源: 移动Labs
相关推荐

2011-01-14 13:13:23

嵌入式Linux开发

2009-12-09 10:12:28

嵌入式Linux

2009-04-20 21:20:32

Linux文件系统存储机制

2013-12-09 11:28:44

2009-12-16 15:41:40

嵌入式Linux入门

2009-12-17 10:33:05

嵌入式Linux

2021-11-05 22:47:44

冒泡排序选择插入

2009-12-23 16:52:26

Linux自学嵌入式

2009-12-09 10:50:53

嵌入式Linux

2010-01-20 13:20:26

嵌入式设备实验室

2022-01-04 22:19:38

Linux开发嵌入式

2021-12-19 22:34:45

Linux容器系统

2022-01-03 23:33:40

Linux组件系统

2010-09-25 15:05:49

LINUXJVM

2009-12-24 17:21:38

嵌入式Linux

2011-06-17 08:59:27

QT Embedded Arm

2011-07-05 15:59:18

Qt 嵌入式 linux

2011-06-13 14:00:55

Qt Designer linux

2011-08-05 09:11:56

2009-12-24 17:27:52

嵌入式Linux
点赞
收藏

51CTO技术栈公众号