问问自己:
- 怎么编译目标dtb?
- 编译dtb时Makefile执行过程是什么?
如果你是能轻松回答上面的问题老鸟,可以关闭页面阅读其他文章。对于新手,我或许不能深入浅出地解答2个问题,但我的思路或许能借鉴。
这篇文章是平反的一天工作记录,犯了很低级的dts文件命名错误,瞎鼓捣,浪费20min记录如下内容。
怎么生成设备树(dtb)
言简意赅列出手动创建dtb和在内核工程下创建dtb指令
出错
近期某项目结束,想备份工程设备树,龙芯官方的Linux-3.10内核生成设备树不支持 “make dtbs”,直接make就能生成dtb,以前没出问题也就没管过它。
- 复制 2k1000_board.dtb为 LS2K-myproject-v6.dts
- 修改Makefile和Kconfig添加编译选项
编译出错
红色区域提示:在处理 LS2K-myproject-v6.dts.S 文件时遇到指令错误。
刚刚仅复制dts文件没弄S文件,搜遍整个工程都没有搜索到这个2k1000_board.S,考虑着S文件有可能是动态生成的。再次检查make错误输出内容,确认了我的猜想。
绿色区域提示:rm LS2K-board-myproject-v6.S
接下来是找到S文件是怎么生成的。
2k1000_board.dtb.S生成过程
光靠读取Makefile是找不到S文件具体内容的,唯一能看一行图片中紫色区域提示。
sudo apt-get install device-tree-compilerdtc -I dts -O dtb -o devicetree_file_name.dtb devicetree_file_name.dtscd linux-kernelmake dtbs
于是打开Makefile调试选项: “make -n” 。下面Start和End之间框选的是动态生成脚本。
接下来找具体哪个Makefile文件、哪一行执行下面的内容。
2k1000_board.dtb.S在哪生成
一般工程里的makefile有三种命名规则:Makefile、Makefile.、.mk。 根据上文 “set -e; echo ’ DTC arch/mips/loongson2/dts/2k1000_board.dtb’;” ,以 “DTC” 为关键词工程搜索:
- find Makefile scripts/ -name "Makefile.*" | xargs grep DTC
锁定到两个文件
- scripts/Makefile.lib
- scripts/dtc/Makefile.dtc
Barry Song指导的方法,先嗅一下工程有没有什么Bed Smell, Makefile.dtc这个文件不用去看,从工程字面上去理解它的功能,猜测:应该是创建dtc工具和解析dts文件的,里面相关代码与平台无关。
# Makefile.dtc## This is not a complete Makefile of itself. Instead, it is designed to# be easily embeddable into other systems of Makefiles.#DTC_SRCS = \ checks.c \ data.c \ dtc.c \ flattree.c \ fstree.c \ livetree.c \ srcpos.c \ treesource.c \ util.cDTC_GEN_SRCS = dtc-lexer.lex.c dtc-parser.tab.cDTC_OBJS = $(DTC_SRCS:%.c=%.o) $(DTC_GEN_SRCS:%.c=%.o)
其中Makefile.lib文件的若干echo格式就是 “make -n” 解析看到的内容
echo ' DTB arch/mips/loongson2/dts/2k1000_board.dtb.S'; ( echo '#include <asm-generic/vmlinux.lds.h>';
# scripts/Makefile.lib# DTC# ---------------------------------------------------------------------------# Generate an assembly file to wrap the output of the device tree compilerquiet_cmd_dt_S_dtb= DTB $@cmd_dt_S_dtb= \( \ echo '\#include <asm-generic/vmlinux.lds.h>'; \ echo '.section .dtb.init.rodata,"a"'; \ echo '.balign STRUCT_ALIGNMENT'; \ echo '.global __dtb_$(*F)_begin'; \ echo '__dtb_$(*F)_begin:'; \ echo '.incbin "$<" '; \ echo '__dtb_$(*F)_end:'; \ echo '.global __dtb_$(*F)_end'; \ echo '.balign STRUCT_ALIGNMENT'; \) > $@$(obj)/%.dtb.S: $(obj)/%.dtb$(call cmd,dt_S_dtb)
cmd_dt_S_dtb执行依赖目标文件名,原始目标 2k1000_board.dtb.S,则创建 __dtb_2k1000_board_begin、__dtb_2k1000_board_end,设备树2k1000_board.dts以 include的方式夹在这两个符号中间 .incbin “$<”, STRUCT_ALIGNMENT 表示符号对齐方式,本工程里STRUCT_ALIGNMENT=32。
生成/tmp/b.txt
因为这个dtb.S文件生成立即使用,用完就删掉,图片红色区域提示说:第5行存在指令错误。 懒得去分析若干 echo 生成的是什么鬼。 为了探寻它究竟是什么内容,临时修改Makefile.lib,把末尾的管道重定向到 /tmp/b.txt
cmd_dt_S_dtb= \( \echo '\#include <asm-generic/vmlinux.lds.h>'; \------------略-------------) > /tmp/b.txt
查看a.txt第四行瞬间明白错误原因,好像拍断自己大腿——“命名规则错误”。
/work/ls2k/linux-3.10-ls2k-git# cat /tmp/a.txt -n1 #include <asm-generic/vmlinux.lds.h>2 .section .dtb.init.rodata,"a"3 .balign 4 .global __dtb_LS2K-myproject-v6_begin5 __dtb_LS2K-myproject-v6_begin:6 .incbin "arch/mips/loongson2/dts/LS2K-myproject-v6.dtb" 7 __dtb_LS2K-myproject-v6_end:8 .global __dtb_LS2K-myproject-v6_end9 .balign STRUCT_ALIGNMENTroot@debian-hub:/work/ls2k/linux-3.10-ls2k-git#
创建段
根据最初编译的提示,对比/tmp/b.txt可知第四行没有 "__dtb_LS2K-myproject-v6_begin" 这个段
arch/mips/loongson2/dts/LS2K-myproject-v6.dtb.S:4: Error: : no such section
重命名就dts文件就OK了,横岗改成下划线。
# arch/mips/loongson2/dts/Makefile# obj-$(CONFIG_CPU_LOONGSON2K) := 2k1000_board.dtb.o# obj-$(CONFIG_CPU_LOONGSON2K_MYPRJ_v6) := LS2K-myproject-v6.dtb.oobj-$(CONFIG_CPU_LOONGSON2K_MYPRJ_v6) := LS2K_myproject_v6.dtb.o
资料
获取资料方式:关注我,私信【linux进阶】