ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

DTS 改了为什么没生效?一个实用的 .dts.tmp 调试技巧

DTS 改了为什么没生效?一个实用的 .dts.tmp 调试技巧 B站 嵌入式孙老师博主个人介绍博主书籍-京东购买链接Yocto项目实战教程加博主微信进技术交流群jerrydev最近调 Linux BSP 时又碰到一个很典型的问题DTS 明明改了GPIO、PWM 甚至硬件电平却没有按照预期变化。以前遇到这种问题我可能会继续翻.dts、.dtsi或者直接刷机上板测。但最近我越来越习惯先看一个文件*.dts.tmp这是一个很小的技巧但对排查“DTS 到底有没有真正参与编译”很直接尤其在 Yocto 这种构建链比较长的环境里。一、为什么我开始看.dts.tmpLinux 设备树大致经历.dts .dtsi ↓ CPP 预处理 ↓ .dts.tmp ↓ dtc ↓ .dtb简单理解文件我怎么理解.dts我写的板级配置.dtsiinclude 进来的公共配置.dts.tmpCPP 展开后真正交给 dtc 的中间内容.dtb最终二进制设备树所以.dts.tmp最适合回答一个问题我写进去的东西这次 Kernel 编译到底有没有看到找到.dts.tmp直接find.-name*.dts.tmpYocto 下通常会出现在tmp/work/.../linux-xxx/...-build/ └── arch/arm64/boot/dts/文件可能长这样.xxx-board.dtb.dts.tmp注意前面可能有.是隐藏文件。二、一个实际例子DTS 明明加了 GPIO比如背光配置里写backlight { pwms pwm6 0 25000 0; enable-gpios gpio4 RK_PA0 GPIO_ACTIVE_HIGH; pinctrl-names default; pinctrl-0 backlight_en; status okay; };我最关心的是enable-gpios gpio4 RK_PA0 GPIO_ACTIVE_HIGH;到底有没有真正进去。这时候不用继续翻一堆.dtsi直接grep-nenable-gpiosxxx.dts.tmp再看 pinctrlgrep-nbacklight_enxxx.dts.tmp如果源码明明有但.dts.tmp完全搜不到那我首先不会怀疑硬件而是会怀疑构建过程是不是改错 Kernel 源码目录了 是不是 Yocto 还在用旧 commit 是不是 SRCREV 没更新 是不是 Kernel 根本没有重新编 是不是我找到的是旧的 .dts.tmp这一步经常能省掉后面很多无效调试。三、.dts.tmp里宏变成数字是正常的源码可能是enable-gpios gpio4 RK_PA0 GPIO_ACTIVE_HIGH;但.dts.tmp里看到enable-gpios gpio4 0 0;不要认为写错了。因为 CPP 已经把宏展开RK_PA0 → 0 GPIO_ACTIVE_HIGH → 0所以gpio4 RK_PA0 GPIO_ACTIVE_HIGH和展开后的gpio4 0 0表达的是同一件事。这也是.dts.tmp很实用的地方GPIO、IRQ、Clock 等宏最终展开成什么可以直接看到。四、Yocto 下尤其要确认实际 Kernel SourceYocto 项目经常不是直接在当前 Git 仓库里编 Kernel。我现在通常会先执行bitbake-evirtual/kernel|grep^S看看${S}到底指向哪里。再直接检查真正参与编译的 DTSgrep-n-A10backlight\$S/arch/arm64/boot/dts/xxx/xxx-board.dts如果出现自己的 Git 已经有新修改 Yocto ${S} 还是旧代码那就不用继续研究 GPIO 了。问题其实在Git ↓ SRCREV / BitBake ↓ Kernel Source ↓ Kernel Build这条链路没有同步。确认${S}正确以后再重新编bitbake-f-ccompile virtual/kernel然后重新检查.dts.tmp。五、.dts.tmp不是最终答案必要时再反编译 DTB.dts.tmp主要用于确认编译前的 Device Tree 到底是什么。如果还想确认最终 DTB 到底生成了什么再进一步反编译dtc-Idtb-Odts\xxx-board.dtb\-ofinal.dts然后grep-n-A20backlightfinal.dts我现在习惯这样区分DTS ↓ 我写了什么 .dts.tmp ↓ 编译器实际吃到了什么 DTB 反编译 ↓ 最终生成了什么这三层基本足够覆盖大部分设备树构建问题。六、还有一个容易误判的地方GPIO_ACTIVE_HIGH比如enable-gpios gpio4 RK_PA0 GPIO_ACTIVE_HIGH;它并不是说GPIO4_A0 启动以后默认就是 High。它表达的是逻辑 Enable → 输出 High 逻辑 Disable → 输出 Low具体当前是 High 还是 Low还要看驱动状态。例如 Linux 上看到cat/sys/kernel/debug/gpio输出gpio-128 ( |enable ) out lo这只能说明GPIO 已经配置成 Output 当前实际输出 Low还要继续看对应驱动。以 Backlight 为例cat/sys/class/backlight/backlight/bl_powercat/sys/kernel/debug/pwm如果看到bl_power 4 PWM duty 0那 GPIO 被驱动拉低很可能是正常行为Backlight OFF ↓ Enable GPIO LOW ↓ PWM duty 0所以设备树调试不能只看 DTS还要继续结合 Runtime 状态。七、我现在常用的一套排查顺序遇到“DTS 已经改了为什么硬件没变化”我现在基本按这个顺序1. 检查源码 DTS ↓ 2. 确认 Yocto ${S} ↓ 3. grep .dts.tmp ↓ 4. 必要时反编译 DTB ↓ 5. 上板看 /sys/kernel/debug ↓ 6. 最后再用示波器测硬件几个常用命令其实就这些# 找中间设备树find.-name*.dts.tmp# 查修改有没有进去grep-nenable-gpiosxxx.dts.tmp# Yocto 实际 Kernel Sourcebitbake-evirtual/kernel|grep^S# 反编译最终 DTBdtc-Idtb-Odts xxx.dtb-ofinal.dts# 上板看 GPIOcat/sys/kernel/debug/gpio# 上板看 PWMcat/sys/kernel/debug/pwm总结看.dts.tmp其实只是一个很小的 BSP 调试技巧。但它让我少做了不少这种事情改 DTS ↓ 重新编译 ↓ 重新刷机 ↓ 测硬件 ↓ 发现还是不对 ↓ 继续猜现在我更愿意在编译阶段先确认我写的 DTS ↓ Kernel 到底有没有真正看到所以以后再遇到“DTS 明明改了为什么没有生效”不妨先find.-name*.dts.tmp然后grep一下自己刚改的属性。不要只确认自己写了什么更要确认系统最终用了什么。这是.dts.tmp这个小技巧对我最大的价值。
返回列表