当前位置:首页 > 嵌入式 > 嵌入式分享
[导读]很多刚接触嵌入式Linux的工程师看到arch/arm64/boot/dts/下成片的.dts、.dtsi文件就头大。其实设备树(Device Tree)本质就是一份"硬件简历"——用树形结构告诉内核:板子上有啥外设、挂在哪个地址、用哪根中断线、连到哪个GPIO。内核据此匹配驱动,不再把硬件信息写死在代码里。


很多刚接触嵌入式Linux的工程师看到arch/arm64/boot/dts/下成片的.dts、.dtsi文件就头大。其实设备树(Device Tree)本质就是一份"硬件简历"——用树形结构告诉内核:板子上有啥外设、挂在哪个地址、用哪根中断线、连到哪个GPIO。内核据此匹配驱动,不再把硬件信息写死在代码里。

设备树的"语法三件套"

一个典型的设备节点长这样:

/ {

   mydev: uart@40000000 {

       compatible = "mycorp,my-uart";

       reg = <0x40000000 0x1000>;

       interrupts = <GIC_SPI 38 IRQ_TYPE_LEVEL_HIGH>;

       clocks = <&clk 12>;

       status = "disabled";

   };

};

抓住几个核心属性就够了:

compatible:驱动匹配的"身份证",字符串须与驱动中的of_device_id完全一致

reg:设备寄存器基地址和长度,<基地址 大小>

interrupts:中断号和触发方式

status:"okay"启用,"disabled"禁用——SoC级.dtsi通常默认全disabled,板级.dts按需开启

.dtsi是芯片级通用描述(SoC内置IP),.dts是板级描述,通过#include引用dtsi,并用&标签语法覆写节点属性。

实战:给板子加一颗LED

假设要在GPIO0_A0上加一颗状态LED,步骤如下:

1. 在根节点下添加LED节点

/ {

   my_led: led@0 {

       compatible = "gpio-leds";

       label = "sys:status";

       gpios = <&gpio0 0 GPIO_ACTIVE_HIGH>;

       default-state = "on";

       pinctrl-names = "default";

       pinctrl-0 = <&led_pin>;

       status = "okay";

   };

};

2. 配置引脚复用

&pinctrl {

   led_pin: led-grp {

       rockchip,pins = <0 0 0 &pcfg_pull_none>;

   };

};

3. 编译并部署

# 内核源码树内编译

make dtbs -j8


# 或单文件编译

dtc -I dts -O dtb -o myboard.dtb myboard.dts

生成的.dtb放到U-Boot加载路径,重启即可。

上板验证四件套

改完设备树最怕"编译过了但外设不干活",按下面顺序排查:

# 1. 看内核是否解析到节点

dmesg | grep -i "device tree"

# 2. 查看运行时设备树

ls /proc/device-tree/

cat /proc/device-tree/my_led/status

# 3. 反编译当前dtb,确认烧录无误

dtc -I dtb -O dts -o check.dts myboard.dtb

# 4. 确认LED设备是否出现

ls /sys/class/leds/

排查口诀:设备没生效先看status是不是okay;驱动没加载先查compatible字符串是否精确匹配;中断不触发检查interrupt-parent是否指向正确的中断控制器。

新手常踩的三个坑

第一,节点加错位置。必须放在根节点/ { ... };的大括号内,加在外面编译不报错,但节点不会被解析。

第二,引脚复用冲突。同一个物理引脚被两个外设同时声明,SoC会静默使用最后配置的那个,导致前一个外设莫名失效。改DTS前务必核对芯片手册的引脚分配表。

第三,只改.dts忘记重编.dtb。代码改了但烧的还是旧dtb,现象就是"我明明改了啊"——此时用dtc -I dtb -O dts反编译烧录后的dtb一看便知。

写在最后

设备树的学习曲线并不陡,关键是建立"分层修改"的思维:.dtsi不动,只在板级.dts里用&标签覆写;外设默认disabled,用哪个开哪个;所有配置必须对照芯片手册和原理图。掌握这一套,无论是加CAN、调I2C传感器、配SPI屏,还是使能RS485,套路都是一样的——这也是嵌入式Linux硬件适配最硬核的通用能力。



本站声明: 本文章由作者或相关机构授权发布,目的在于传递更多信息,并不代表本站赞同其观点,本站亦不保证或承诺内容真实性等。需要转载请联系该专栏作者,如若文章内容侵犯您的权益,请及时联系本站删除( 邮箱:macysun@21ic.com )。
换一批
延伸阅读

在SPI NOR Flash只有16MB、甚至8MB的嵌入式板上,每一次字节都很贵。Buildroot的优势在于:一条make menuconfig就能通过交叉编译生成工具链、根文件系统和内核镜像,帮开发者把"臃肿"挡在...

关键字: Buildroot 根文件系统 嵌入式Linux

工业主板(如 i.MX6ULL、RK3568、Amlogic A311D 方案)的外设往往不像树莓派那样"默认全开"——CAN、RS485、SPI ADC、I2C 温湿度、GPIO 按键,每款底板的引脚定义都不一样,内核...

关键字: 设备树 驱动加载

设备树(Device Tree, DTB)是嵌入式Linux系统中描述硬件的“骨架”。一个错误的status、一个拼错的compatible,就可能导致外设驱动无法加载或系统崩溃。本文总结十个在ARM/Linux设备树编...

关键字: 嵌入式Linux 设备树

在嵌入式Linux开发中,设备树(Device Tree)已成为描述硬件的标准。它让内核与硬件解耦,实现“一份内核,适配万千板卡”。本文将跳过繁杂的理论,直击设备树节点编写与内核驱动匹配的核心流程。

关键字: 嵌入式Linux 设备树 Device Tree

在物联网设备日益普及的今天,固件空中升级(OTA)已成为设备维护和功能更新的标准方式。A/B分区架构结合差分升级技术,能够在保证系统高可用性的同时,显著降低传输数据量,特别适合带宽受限的嵌入式环境。本文将深入探讨A/B分...

关键字: 固件升级 OTA 嵌入式Linux

在嵌入式Linux开发中,设备树(Device Tree)已成为硬件描述与内核解耦的核心机制。传统静态设备树在编译时固化硬件信息,难以适应多变的硬件配置需求。而动态设备树配置技术通过设备树叠加(Overlay)机制,允许...

关键字: 嵌入式Linux 设备树

在嵌入式Linux开发中,开发者常面临目标设备资源受限(如ARM Cortex-A系列处理器、低内存配置)的挑战,无法直接在设备上完成代码编译与调试。交叉编译与远程调试技术通过“宿主机-目标机”分离架构,将编译与调试任务...

关键字: 嵌入式Linux 交叉编译 远程调试

在嵌入式Linux开发中,多线程技术是提升系统并发处理能力的核心手段。然而,从“能跑”到“稳定”的跨越,需要开发者深入理解并发本质、同步机制与工程实践原则。

关键字: 嵌入式Linux 多线程

在嵌入式Linux开发中,快速获取系统状态信息是调试和监控的关键能力。本文整理了7个高频使用的C语言代码片段,涵盖内存、CPU温度、文件操作等核心场景,帮助开发者高效实现系统状态采集。

关键字: 嵌入式Linux C语言

在物联网设备与工业控制系统广泛应用的嵌入式Linux场景中,系统安全已成为制约产业发展的核心痛点。Red Hat安全报告显示,正确配置的SELinux可拦截超过90%的权限提升攻击,而结合审计子系统(auditd)的实时...

关键字: 嵌入式Linux SELinux
关闭