经过基本的流程之后, 接下来进入到正式的开发环节, 首先要知道设备树. 然后接下来要搞明白几个主要问题,

第一个自己写的设备树dts文件应该放在那里?
第二个如何编译dts文件?
第三个如何加载设备树?

本文先绕了点弯路, 后面提供了正确的清晰的步骤, 如果不想看弯路部分,
可以直接跳到最后的正确的方法和步骤 部分…

第一个自己写的设备树dts文件应该放在那里?
根据正点原子的视频教程来看, dts文件都是直接放在LinuxSDK目录下的, 能否将dts文件放到自己的项目中呢? 这个目前还不知道怎么才能做到. . 我这个是放到目录下的.

	LinuxSDK/kernel/arch/arm64/boot/dts/rockchip/rk3399pro-firefly-gpio-demo.dts

rk3399pro-firefly-gpio-demo.dts文件内容如下, 抄自firefly的官网. GPIO一节的示例.

 /dts-v1/;
#include "rk3399pro-firefly-port.dtsi"
#include "rk3399pro-firefly-pcie.dtsi"

/ {
	model = "RK3399pro-firefly-gpio demo";
	compatible = "rockchip,rk3399pro-firefly-gpio", "rockchip,rk3399pro";

	gpio_demo: gpio_demo {
            status = "okay";
            compatible = "firefly,rk3399pro-gpio";
            firefly-gpio = <&gpio0 12 GPIO_ACTIVE_HIGH>;          /* GPIO0_B4 */
            firefly-irq-gpio = <&gpio4 29 IRQ_TYPE_EDGE_RISING>;  /* GPIO4_D5 */
	};

};

第二个如何编译dts文件?
使用dtc 命令 把dts文件编译成可以被linux内核加载的 dtb文件.
例如:把led.dts 编译成led.dtb

$ dtc  -I dts -O dtb -o ./led.dtb ./led.dts 

如果没有dtc命令, 可以单独安装, 安装命令如下:

$ sudo apt-get install device-tree-compiler

正点原子的教程视频里面是直接修改已有的dts文件. 里面也提到过. 如果要新加dts文件, 需要修改对应目录下的Makefile文件. 加进去就会被编译.

经过实践检验发现 上面的dtc命令单独编译一个dts文件会出问题. 提示语法错误… 后来改成了下面的方法

$ cd LinuxSDK/kernel
$ make dtbs

dtb文件 就编译出来了, 注意, 这里一定要在kernel 目录下执行make dtbs修改makefile和编译

第三个如何加载设备树?
正点原子的视频教程中可以看到,

在16分46秒处, 他是直接把dtb文件复制到ftp目录下的, 然后板子通过uboot自动加载了这个dtb.
这里面有很多地方没有澄清, dtb文件是随便放在哪个文件夹下都行的么?
加载不需要配置的么? 会自动加载dtb文件么?

这篇文章<<Linux内核DTB文件启动的几种方式>>里写的比较清晰, 实际上是可以将内核镜像zImage和dtb文件分开的. 但是大家为了省事,选择将dtb和zImage打包到一起, 然后使用U-Boot 一起加载. 加载方式, 在Linux内核DTB文件启动的几种方式 中已经写的很明白, 我这里再贴一下.

主要的Uboot加载设备树的方法图片
Uboot加载设备树的方法.

我个人建议还是把zImage和dtb文件分开的好. 升级简单一些. 万一zImage搞错了. 升级失败, 得不偿失.

但是内核镜像zImage和dtb文件分开的方式, 如何加载呢?
先看下面的部分摘抄. 来自 <<dtb文件的由来与ARM Linux 3.x的设备树(Device Tree)>>

在Linux下,我们可以单独编译Device Tree文件。当我们在Linux内核下运行make dtbs时,若我们之前选择了ARCH_VEXPRESS,上述.dtb都会由对应的.dts编译出来。因为arch/arm/Makefile中含有一个dtbs编译target项目。
Device Tree Blob (.dtb)
.dtb是.dts被DTC编译后的二进制格式的Device Tree描述,可由Linux内核解析。通常在我们为电路板制作NAND、SD启动image时,会为.dtb文件单独留下一个很小的区域以存放之,之后bootloader在引导kernel的过程中,会先读取该.dtb到内存。
Binding
对于Device Tree中的结点和属性具体是如何来描述设备的硬件细节的,一般需要文档来进行讲解,文档的后缀名一般为.txt。这些文档位于内核的Documentation/devicetree/bindings目录,其下又分为很多子目录。
Bootloader
Uboot mainline 从 v1.1.3开始支持Device Tree,其对ARM的支持则是和ARM内核支持Device Tree同期完成。
为了使能Device Tree,需要编译Uboot的时候在config文件中加入
#define CONFIG_OF_LIBFDT
在Uboot中,可以从NAND、SD或者TFTP等任意介质将.dtb读入内存,假设.dtb放入的内存地址为0×71000000,之后可在Uboot运行命令fdt addr命令设置.dtb的地址,如:
U-Boot> fdt addr 0×71000000
fdt的其他命令就变地可以使用,如fdt resize、fdt print等。
对于ARM来讲,可以透过bootz kernel_addr initrd_address dtb_address的命令来启动内核,即dtb_address作为bootz或者bootm的最后一次参数,第一个参数为内核映像的地址,第二个参数为initrd的地址,若不存在initrd,可以用 -代替。

从摘抄的部分可以大致理解为, dtb文件的加载是由各引导程序例如Uboot 控制的, 也就是说dtb文件的加载需要查阅UBoot的相关内容… 当然, 本文上面的图片 主要的Uboot加载设备树的方法图片 已经写明了如何加载单独的dtb文件.

后来我一直在寻找是否有单独更新dtb文件而不需要重新编译boot.img的方法.
文章如下, 似乎是有的. 好像可以修改uEnv.txt文件.
参考 这里.
https://software-dl.ti.com/jacinto7/esd/processor-sdk-linux-jacinto7/latest/exports/docs/linux/How_to_Guides/Target/How_to_Change_dtb_File.html#
在这里插入图片描述
不过我没有找到 这个uEnv.txt文件在哪里.

额, 后来经过与firefly 的客服沟通, 他们给的建议是 编写dts文件, 然后重新编译kernel , 然后只烧写boot.img即可. 由此可见, dts设备树, 是存在boot.img中的 .

后经过验证. 我上面的方法有些是错误的.

正确的方法和步骤.

第一个自己写的设备树dts文件应该放在那里?
实时证明, dts设备树文件已经写好了, 不需要新建dts文件.
我的开发板是firefly-rk3399-pro-jd4对应的dts文件是.

LinuxSDK/kernel/arch/arm64/boot/dts/rockchip/rk3399pro-firefly-aiojd4.dts

直接在这个文件里增加自己的节点即可.

如果你是类似firefly 的硬件设备供应商, 需要复制已有的dts文件, 改个名, 然后搜索相关的文件, 主要是Makefile文件要改一下.

第二个如何编译dts文件?
如果你是使用的firefly的开发板, 直接编译kernel即可. 命令如下, 注意路径.

$ cd LinuxSDK
~/LinuxSDK/$ ./build.sh kernel

其它的开发板估计有所不同, 应该是.

$ cd LinuxSDK/kernel
$ make kernel

主要目的是编译出boot.img

第三个如何加载设备树?
将编译出来的boot.img, 使用工具烧写进开发板即可 . 只需要烧写boot区. 然后重新启动即可自动加载不需要特殊配置,

如果你是硬件设备供应商.那么肯定是需要改某些配置的.

firefly 开发板的烧写boot区命令如下, 其它开发板请参考供应商提供的相关文档说明.

~/LinuxSDK/$ sudo upgrade_tool di -boot ./kernel/boot.img

简洁的步骤,
1. 改dts文件,
2. 编译 dts文件 进 boot.img
3. 烧写boot.img

Logo

更多推荐