前言
-
通过了解 Linux 设备树的编译方法,手动写了一个可以把 dts、dtsi、设备树依赖头文件等编译为设备树 dtb 的 Makefile
-
Makefile 如下
mkfile_path := $(abspath $(lastword $(MAKEFILE_LIST)))
cur_makefile_path := $(dir $(mkfile_path))
DIR_ROOT := $(cur_makefile_path)
suffix_dtb = .dtb
suffix_dts = .dts
dtb_d_pre_tmp = .dtb.d.pre.tmp
dtb_dts_tmp = .dtb.dts.tmp
dtb_d_dtc_tmp = .dtb.d.dtc.tmp
HOSTCC = gcc
HOST_DTC := $(DIR_ROOT)dtc
CFLAGS = -E -Wp,-MMD,
dtc_flags = 0 -Wno-interrupt_provider -Wno-unit_address_vs_reg -Wno-avoid_unnecessary_addr_size \
-Wno-alias_paths -Wno-graph_child_address -Wno-simple_bus_reg -Wno-unique_unit_address
dtc_def = -undef -D__DTS__ -x assembler-with-cpp
dts_src_path = $(DIR_ROOT)
dts_folders := $(shell find $(dts_src_path) -maxdepth 1 -type d)
dts_file_string = $(foreach dir,$(dts_folders),$(wildcard $(dir)/*.dts))
dts_file_basename = $(basename $(dts_file_string))
all:
for dts in ${dts_file_basename} ; do \
$(HOSTCC) -E $(CFLAGS)$$dts$(dtb_d_pre_tmp) -nostdinc -I$(DIR_ROOT)include $(dtc_def) -o $$dts$(dtb_dts_tmp) $$dts$(suffix_dts); \
$(HOST_DTC) -o $$dts$(suffix_dtb) -b $(dtc_flags) -d $$dts$(dtb_d_dtc_tmp) $$dts$(dtb_dts_tmp); \
done
clean:
for dts in ${dts_file_basename} ; do \
rm -f $$dts$(dtb_d_pre_tmp); \
rm -f $$dts$(dtb_dts_tmp); \
rm -f $$dts$(dtb_dts_tmp); \
rm -f $$dts$(dtb_d_dtc_tmp); \
done
distclean:
for dts in ${dts_file_basename}; do \
rm -f $$dts$(dtb_d_pre_tmp); \
rm -f $$dts$(dtb_dts_tmp); \
rm -f $$dts$(dtb_dts_tmp); \
rm -f $$dts$(dtb_d_dtc_tmp); \
rm -f $$dts$(suffix_dtb); \
done
Makefile 说明
-
运行环境: Linux,需要安装 gcc 与 make
-
需要准备:设备树 dts 原文件,以及依赖的 dtsi 与 设备树头文件
-
dtc 编译工具,源码 Linux 内核
scripts/dtc
目录下,编译过 Linux 内核后,就可以产生,默认Linux 每次都是源码编译,这里直接复制出来即可使用,不需要源码编译生成 dtc 工具。
获取 dtc 工具
-
dtc 工具是有Linux 环境 gcc 编译的,也就是 host gcc,不需要交叉编译,Linux 下不能直接编译 dtc 工具,可以编译一个 board,如 qemu
vexpress_defconfig
-
编译方法:
$ make ARCH=arm vexpress_defconfig
$ make ARCH=arm dtbs
- 此时就会生成
scripts/dtc/dtc
,可以查看 dtc 工具的版本号:
$ chmod +x scripts/dtc/dtc
zhangsz@zhangsz:~/linux/kernel/linux-6.0.10$ scripts/dtc/dtc --version
Version: DTC 1.6.1-g0a3a9d34
获取 设备树文件 dts
-
这个可以根据实际需要自己编写或者在相似的平台上修改而来,我这里可以拿一个qemu 的设备树进行编译
-
这里使用:
vexpress-v2p-ca9.dts
,可以在 Linux 内核拷贝出来:./arch/arm/boot/dts/vexpress-v2p-ca9.dts
-
其他的依赖文件,可以 创建 Makefile后,通过 make 的方式编译,缺少的文件会提示
-
当前示例,缺少的文件,从 Linux 内核中复制过来即可。
-
include/dt-bindings 里面,只需要复制几个依赖的 头文件即可,Linux 内核的位置:
include/dt-bindings
make 编译的设备树产物
-
make 通过后,会生成 xxx.dtb 文件,这就是设备树的二进制文件,板子就可以使用了
-
本 Makefile 脚本,会顺便创建几个临时的文件,可以不用关心
手动编译 设备树的流程
-
通过 gcc 预处理,把设备树源文件 dts,当成 C 语言源文件,把
#include
的 设备树头文件 dtsi 与 .h 头文件代码的形式包含到一个临时文件中 -
第二步:通过 dtc 工具,把设备树临时文件 编译为 dtb 文件
-
备注:如果不通过 gcc 预处理,直接使用 dtc 编译 dts 文件,可能依赖文件 dtsi 与 .h 头文件无法正确的加入,造成 转换失败。
小结
-
如今 设备树源文件,就像是 C 语言的源文件一样,可以包含多个 dtsi 设备树头文件,也可以像 C 语言一样,包含 C 语言的头文件,如
include/dt-bindings
中的 .h 头文件 -
可以通过简单的 设备树编译命令,手动编译 设备树文件,方便功能的验证,当然可以放在Linux 内核中进行编译。