
第2章 设备树核心语法与常用属性本章目标掌握设备树的树状拓扑结构与节点组织逻辑吃透5个核心必备属性的语法、作用与工业级规范掌握驱动开发高频使用的标准属性含多状态pinctrl深度理解芯片级dtsi的硬件映射逻辑与节点设计理解芯片级dtsi与板级dts的分工与联动机制通过典型场景实操掌握设备树的标准修改方法一、设备树核心属性设备树通过属性描述硬件的各类参数属性是驱动与设备树交互的核心载体。本节分为核心必备属性和高频常用属性两部分全部基于i.MX6ULL官方设备树规范。1. 5个核心必备属性所有节点通用这5个属性是设备树的基石几乎所有硬件节点都会用到是设备树语法的核心。1compatible驱动匹配的唯一标识作用设备和驱动之间的“对接暗号”总线通过该字符串完成设备与驱动的匹配是设备树最核心的属性。语法规范compatible 厂商前缀,设备型号;必须带厂商前缀避免不同厂商的同名设备冲突可写多个值从具体到通用排列内核按顺序匹配驱动字符串严格区分大小写示例取自板级dtsgpioled { compatible alientek,gpioled; /* 厂商设备名与驱动匹配表完全对应 */ };2reg 地址长度规范地址/范围描述作用描述硬件的寄存器基地址、内存区域大小或总线设备的地址如I2C地址、SPI片选号。语法依赖reg的格式由父节点的两个属性决定#address-cells地址部分占用几个32位单元cell#size-cells长度部分占用几个32位单元示例132位外设控制器最常见父节点soc定义soc { #address-cells 1; /* 地址用1个32位单元表示 */ #size-cells 1; /* 长度用1个32位单元表示 */ };子节点reg格式gpio1: gpio0209c000 { reg 0x0209c000 0x4000; /* 基地址0x0209c000寄存器空间大小16KB */ };示例2I2C从设备只有地址没有长度父节点i2c1定义i2c1 { #address-cells 1; #size-cells 0; /* 从设备只有地址没有长度部分 */ };子节点reg格式ap3216c1e { reg 0x1e; /* I2C从设备地址 */ };3interrupts中断配置作用描述硬件使用的中断类型、中断号、触发方式驱动通过它申请中断资源。语法依赖由中断控制器节点的#interrupt-cells决定每个中断的描述长度。i.MX6ULL的GIC中断控制器定义了#interrupt-cells 3因此所有外设的中断描述均为3个参数。3个参数定义中断类型GIC_SPI共享外设中断绝大多数片上外设属于此类或GIC_PPICPU私有中断中断号硬件对应的中断编号触发方式电平触发或边沿触发触发方式标准值1上升沿触发2下降沿触发4高电平触发8低电平触发示例取自imx6ull.dtsi的uart1uart1: serial02020000 { interrupt-parent gpc; /* 中断父控制器外设中断先经GPC再汇总到GIC */ interrupts GIC_SPI 26 IRQ_TYPE_LEVEL_HIGH; /* 3个参数SPI类型、26号中断、高电平触发 */ };4status设备启用状态作用控制该硬件节点是否生效无需删除节点通过修改状态即可裁剪硬件功能。常用取值okay设备正常启用disabled设备禁用内核不会匹配驱动芯片级dtsi中所有外设控制器默认均为status disabled由板级dts按需启用。示例/* 板级dts中启用uart1覆盖dtsi的disabled状态 */ uart1 { status okay; };5#address-cells / #size-cells子节点地址规范作用定义当前节点的子节点中reg属性的地址和长度分别占用多少个32位单元。核心规则定义在父节点约束所有子节点的reg格式64位地址系统用#address-cells 2分高低32位纯总线设备如I2C没有长度设#size-cells 02. 驱动开发高频常用属性除核心属性外以下属性是驱动开发中最常接触的标准属性内核提供了专门的解析API。1gpiosGPIO引脚配置led-gpios gpio1 3 GPIO_ACTIVE_HIGH;解释描述GPIO引脚配置格式为控制器标签 引脚号 有效极性。2clocks绑定设备使用的时钟源clocks clks IMX6UL_CLK_UART1_IPG;解释声明当前设备需要哪个时钟源驱动通过时钟API申请、使能时钟。 注意设备节点中写的clocks是“我要用这个时钟”的声明不是定义时钟本身。3pinctrl-x多状态引脚复用配置pinctrl-names default, sleep; pinctrl-0 pinctrl_uart1_default; pinctrl-1 pinctrl_uart1_sleep;解释引脚复用支持多状态配置pinctrl-names定义状态名称列表pinctrl-0、pinctrl-1、pinctrl-2按顺序与名称一一对应驱动会根据当前工作状态自动切换对应引脚配置。常见使用场景default sleep 双状态最常用的组合。正常工作时用default配置系统进入休眠时内核自动切换到sleep配置一般改为下拉/高阻模式降低休眠功耗。多速率档位SD卡、以太网等高速外设不同速率下引脚驱动强度、压摆率不同对应多组pinctrl如default/state_100mhz/state_200mhz。多工作模式如串口在RS232/RS485模式间切换对应不同的引脚功能配置。编号规则pinctrl-0对应pinctrl-names里第0个字符串pinctrl-1对应第1个以此类推数量必须严格匹配。4label设备的可读名称label user-led-red;解释设备的可读名称用于sysfs界面显示。5自定义属性default-brightness 50;解释驱动自定义的参数支持整数、字符串、数组等类型驱动中通过of_property_read_*系列函数直接读取。二、芯片级dtsi深度详解芯片级.dtsi由NXP官方提供是i.MX6ULL芯片的完整硬件寄存器地图100%对应芯片内部的物理硬件所有同芯片开发板共用一般不做修改。下面结合官方dtsi代码逐段拆解。1. dtsi整体结构文件开头先引入绑定宏、引脚定义、基础骨架然后从根节点开始按硬件层级从核心到外设逐层展开根节点/ ├─ aliases 外设别名映射 ├─ cpus CPU核心配置 ├─ intc GIC总中断控制器 ├─ clocks 顶层外部时钟输入 └─ soc 片上系统总线所有外设的载体 ├─ 公共外设busfreq/pmu/ocram/dma/gpmi ├─ aips1 第一组外设总线 ├─ aips2 第二组外设总线 └─ aips3 第三组外设总线2. 顶层节点逐段详解1aliases 别名节点对应代码来自imx6ull.dtsialiases { can0 flexcan1; can1 flexcan2; ethernet0 fec1; gpio0 gpio1; i2c0 i2c1; serial0 uart1; ... };讲解相当于芯片外设的“通讯录”给每个控制器起一个统一编号的别名比如serial0对应uart1i2c0对应i2c1作用内核启动时按编号枚举设备用户空间看到的/dev/ttymxc0就对应uart1板级dts也可以直接用别名快速引用对应外设2cpus CPU集群节点对应代码来自imx6ull.dtsicpus { #address-cells 1; #size-cells 0; cpu0: cpu0 { compatible arm,cortex-a7; device_type cpu; reg 0; clock-latency 61036; operating-points /* kHz uV */ 996000 1275000 792000 1225000 528000 1175000 396000 1025000 198000 950000 ; fsl,soc-operating-points /* KHz uV */ 996000 1175000 792000 1175000 528000 1175000 396000 1175000 198000 1175000 ; fsl,low-power-run; clocks clks IMX6UL_CLK_ARM, clks IMX6UL_CLK_PLL2_BUS, clks IMX6UL_CLK_PLL2_PFD2, ... ; clock-names arm, pll2_bus, pll2_pfd2_396m, ...; }; };讲解对芯片唯一的Cortex-A7内核的完整硬件描述reg 0CPU核心编号为0operating-pointsCPU的“变频档位表”从198MHz到996MHz共5档每档对应一个电压内核根据负载自动调频调压平衡性能与功耗fsl,soc-operating-points外设总线的配套档位表CPU降频时总线也同步降频clocksCPU运行依赖的所有时钟源列表相当于告诉内核“我要跑起来得先打开这几个时钟”3intc GIC总中断控制器对应代码来自imx6ull.dtsiintc: interrupt-controller00a01000 { compatible arm,cortex-a7-gic; #interrupt-cells 3; interrupt-controller; reg 0x00a01000 0x1000, 0x00a02000 0x100; };讲解整个芯片的“中断总机”ARM标准GIC通用中断控制器所有外设的中断最终都汇总到这里再上报给CPUinterrupt-controller专门标记这是中断控制器和普通外设区分开#interrupt-cells 3强制规定所有外设的中断描述必须用3个参数中断类型、中断号、触发方式两组reg分别对应GIC的分发器寄存器和CPU接口寄存器4clocks 顶层时钟源对应代码来自imx6ull.dtsiclocks { #address-cells 1; #size-cells 0; ckil: clock0 { compatible fixed-clock; reg 0; #clock-cells 0; clock-frequency 32768; clock-output-names ckil; }; osc: clock1 { compatible fixed-clock; reg 1; clock-frequency 24000000; clock-output-names osc; }; ipp_di0: clock2 { ... }; ipp_di1: clock3 { ... }; };讲解整个芯片时钟树的“源头水源”都是芯片外部输入的晶振时钟不是芯片内部产生的ckil32.768kHz低速晶振专门给RTC、低功耗模块提供时钟主电源关了还能跑osc24MHz主晶振是绝大多数外设时钟的源头内部PLL倍频后给CPU、总线、外设使用ipp_di0/ipp_di1两个外部时钟输入引脚可外接专用时钟源注意这里只是输入源真正的分频、倍频、时钟开关管理在soc内部的ccm时钟控制模块里。3. soc 片上系统总线对应代码来自imx6ull.dtsisoc { #address-cells 1; #size-cells 1; compatible simple-bus; interrupt-parent gpc; ranges; ... };讲解芯片所有外设的“主干大街”compatible simple-bus告诉内核这是一条简单的片上总线下面挂的都是片上外设interrupt-parent gpcsoc下所有外设默认的中断父控制器是GPC外设中断先经过GPC处理再到GICranges地址直通子节点写的寄存器地址就是物理地址不需要转换soc下的公共外设这些是不归属某条AIPS总线、服务整个芯片的公共模块。① busfreq 总线频率管理器对应代码来自imx6ull.dtsibusfreq { compatible fsl,imx_busfreq; clocks clks IMX6UL_CLK_PLL2_PFD2, clks IMX6UL_CLK_PLL2_198M, clks IMX6UL_CLK_PLL2_BUS, clks IMX6UL_CLK_ARM, ... ; clock-names pll2_pfd2_396m, pll2_198m, pll2_bus, arm, ...; fsl,max_ddr_freq 400000000; };通俗讲解整个芯片总线的“自动变速箱”系统高负载时把AHB、AXI、DDR总线拉到最高频率保证数据传输速度系统空闲时自动降低总线时钟大幅降低功耗还限定了DDR的最高运行频率保证内存稳定② pmu 性能监控单元对应代码来自imx6ull.dtsipmu { compatible arm,cortex-a7-pmu; interrupts GIC_SPI 94 IRQ_TYPE_LEVEL_HIGH; status disabled; };通俗讲解CPU的“性能计数器”统计CPU跑了多少指令、缓存命中率、分支预测正确率调试性能、优化程序的时候用平时默认禁用③ ocram系列 片上内置内存对应代码来自imx6ull.dtsiocrams: sram0090000 { compatible fsl,lpm-sram; reg 0x00900000 0x4000; }; ocrams_ddr: sram00904000 { compatible fsl,ddr-lpm-sram; reg 0x00904000 0x1000; }; ocram: sram00905000 { compatible mmio-sram; reg 0x00905000 0x1B000; };通俗讲解芯片内部自带的三块高速小内存比外部DDR响应快得多各有分工ocrams低功耗模式专用内存系统休眠时DDR断电关键代码和数据放这儿ocrams_ddrDDR控制器专用小内存DDR初始化训练的时候用ocram通用片上内存共108KBSDMA控制器的脚本就存在这儿也可以放需要快速访问的关键数据④ dma_apbh APBH总线DMA控制器对应代码来自imx6ull.dtsidma_apbh: dma-apbh01804000 { compatible fsl,imx6ul-dma-apbh, fsl,imx28-dma-apbh; reg 0x01804000 0x2000; interrupts GIC_SPI 13 IRQ_TYPE_LEVEL_HIGH, GIC_SPI 13 IRQ_TYPE_LEVEL_HIGH, GIC_SPI 13 IRQ_TYPE_LEVEL_HIGH, GIC_SPI 13 IRQ_TYPE_LEVEL_HIGH; interrupt-names gpmi0, gpmi1, gpmi2, gpmi3; #dma-cells 1; dma-channels 4; clocks clks IMX6UL_CLK_APBHDMA; };通俗讲解专门给GPMI NAND控制器服务的“数据搬运工”一共4个通道对应NAND的4个数据通道读写NAND时不需要CPU一个字节一个字节地搬直接告诉DMA起始地址和长度硬件自动搬完发中断通知CPU极大节省CPU资源大批量数据传输优势特别明显⑤ gpmi GPMI NAND控制器对应代码来自imx6ull.dtsigpmi: gpmi-nand01806000{ compatible fsl,imx6ull-gpmi-nand, fsl, imx6ul-gpmi-nand; #address-cells 1; #size-cells 1; reg 0x01806000 0x2000, 0x01808000 0x4000; reg-names gpmi-nand, bch; interrupts GIC_SPI 15 IRQ_TYPE_LEVEL_HIGH; interrupt-names bch; clocks clks IMX6UL_CLK_GPMI_IO, ...; dmas dma_apbh 0; dma-names rx-tx; status disabled; };通俗讲解专门驱动NAND Flash的硬件控制器自带硬件BCH ECC校验读写NAND时自动纠错比软件纠错快几十倍配合dma_apbh实现NAND高速读写完全不用CPU干预如果用GPIO模拟NAND不仅速度慢CPU还得全程盯着根本没法干别的事4. 三条AIPS外设总线架构AIPS到底是什么你可以把AIPS理解成芯片里的“外设产业园”芯片外设太多都挤在一条总线上会地址不够、传输拥堵、互相干扰按功能、速度、地址范围分成3个产业园aips1/2/3每个产业园有自己的总线入口每个产业园里再按类型细分比如aips1里还专门划了一块“串行产业园”spba-bus放SPI、UART这些串行外设① aips1: aips-bus02000000地址段0x02000000 ~ 0x020FFFFF定位系统控制类与低速串行外设总线是芯片的核心控制区。对应代码来自imx6ull.dtsiaips1: aips-bus02000000 { compatible fsl,aips-bus, simple-bus; #address-cells 1; #size-cells 1; reg 0x02000000 0x100000; ranges; spba-bus02000000 { compatible fsl,spba-bus, simple-bus; ... /* 里面是ECSPI1~4、UART1/7、SAI1~3、ESAI、ASRC等串行外设 */ }; /* 其他控制器TSC、PWM1~4、FlexCAN、GPIO1~5、gpc、iomuxc、ccm、anatop... */ gpio1: gpio0209c000 { ... }; gpio2: gpio020a0000 { ... }; ... gpio5: gpio020ac000 { ... }; iomuxc: iomuxc020e0000 { ... }; clks: ccm020c4000 { ... }; gpc: gpc020dc000 { ... }; ... };内部构成spba-bus串行专属子总线专门放SPI、UART、音频这类串行外设共享DMA资源传输效率更高系统控制类外设GPIO1~5、GPC电源控制、IOMUXC引脚复用、CCM时钟控制、ANATOP模拟模块都是管芯片本身运行的核心模块低速外设PWM、FlexCAN、GPT定时器、看门狗、TSC触摸屏② aips2: aips-bus02100000地址段0x02100000 ~ 0x021FFFFF定位高速接口、存储与显示类外设总线。核心外设USB OTG1/2、FEC以太网、uSDHC1/2、I2C14、ADC、CSI摄像头、LCDIF显示、PXP图像加速、QSPI、UART26特点都是高速接口数据吞吐量大单独放一条总线避免和低速外设抢带宽。③ aips3: aips-bus02200000地址段0x02200000 ~ 0x022FFFFF定位安全、低功耗与扩展外设总线。核心外设DCP加密、RNGB随机数发生器、EPDC电子纸、iomuxc_snvs低功耗引脚复用、UART8特点主要是安全加密和低功耗相关外设很多和SNVS低功耗域联动。三、板级dts硬件定制与dtsi联动板级dts是针对具体开发板的硬件描述文件核心逻辑是**「继承芯片级dtsi 补充板级定制」**无需重复定义芯片已有硬件只做增量修改。1. dts对dtsi的作用机制板级dts通过#include imx6ull.dtsi将芯片级的完整设备树完整引入在此基础上通过两种方式修改1根节点新增补充板级独有硬件芯片内部不存在、焊接在开发板PCB上的硬件直接在根节点/ { }内新建节点。 例如代码中的gpioled、beep、key、backlight、regulators、DDR内存等都属于板级独有dtsi中没有对应定义。2标签引用修改配置芯片已有外设通过节点标签定位到dtsi中已定义的芯片外设节点对其进行属性覆盖、属性追加、新增子节点三类操作属性覆盖同名属性会覆盖dtsi中的值最常见的是将status disabled改为status okay属性追加添加dtsi中没有的属性如pinctrl引脚配置、clock-frequency时钟频率新增子节点在总线控制器节点内添加板载从设备如I2C下挂传感器、SPI下挂Flash示例对应代码中的uart1dtsi中uart1默认定义uart1: serial02020000 { compatible fsl,imx6ul-uart, ...; reg 0x02020000 0x4000; interrupts GIC_SPI 26 IRQ_TYPE_LEVEL_HIGH; clocks clks IMX6UL_CLK_UART1_IPG, ...; status disabled; /* 默认禁用 */ };板级dts中修改uart1 { pinctrl-names default; /* 追加引脚状态名 */ pinctrl-0 pinctrl_uart1; /* 追加引脚复用配置 */ status okay; /* 覆盖启用外设 */ };最终合并后uart1节点同时保留dtsi的寄存器、中断、时钟配置加上板级的引脚配置和启用状态。2. 板级dts核心结构头文件与版本声明dts版本包含绑定宏和芯片级dtsi根节点板级标识、DDR内存、板载外设LED、蜂鸣器、按键、电源、音频等标签引用段芯片外设的启用、引脚配置、子设备添加iomuxc配置段所有外设的引脚复用组集中定义四、设备树标准修改方法与实操1. 通用修改原则只改板级.dts不动芯片级.dtsi芯片固有硬件参数由厂商保证我们只做启用、配引脚、加外设。芯片已有控制器用标签引用追加不重复定义硬件只补充板级相关配置。板载新器件挂在对应控制器下如I2C传感器挂在i2c1内LED挂在GPIO控制器下。凡对外接线必配pinctrl所有用到芯片物理引脚的外设必须先配置引脚复用。跨电源域引脚分节点配置普通域引脚在iomuxc配置SNVS低功耗域引脚在iomuxc_snvs配置可在同一个外设的pinctrl-0中同时引用。2. 通用步骤与模板步骤1引入芯片基准树板级dts开头引入芯片级dtsi所有修改基于此增量完成。#include imx6ull.dtsi步骤2配置引脚复用pinctrl按引脚所属硬件域在对应iomux节点定义所有用到的引脚组。支持单状态和多状态配置。单状态模板iomuxc { 板级标识 { pinctrl_外设名: 外设分组名 { fsl,pins 引脚复用宏 电气配置值 ; }; }; };多状态模板default sleepiomuxc { 板级标识 { pinctrl_uart1_default: uart1_def { fsl,pins /* 正常工作引脚配置 */ ; }; pinctrl_uart1_sleep: uart1_slp { fsl,pins /* 休眠低功耗引脚配置 */ ; }; }; };规则SNVS域引脚需放到iomuxc_snvs节点配置可与普通域引脚组同时被外设引用。步骤3启用总线控制器引用dtsi中已有的总线控制器节点追加引脚引用覆盖启用状态。单状态总线控制器标签 { pinctrl-names default; pinctrl-0 pinctrl_总线名; status okay; };多状态总线控制器标签 { pinctrl-names default, sleep; pinctrl-0 pinctrl_总线名_default; pinctrl-1 pinctrl_总线名_sleep; status okay; };步骤4新增从设备节点在总线控制器内部新增板载外设子节点命名遵循「设备类型地址」规范。总线控制器标签 { ... 设备标签: 设备类型总线地址 { compatible 厂商,器件型号; reg 总线地址/片选号; /* 外设专属配置项 */ status okay; }; };步骤5编译与验证# 编译设备树 make ARCHarm CROSS_COMPILEarm-linux-gnueabihf- dtbs启动后验证节点# 查看设备树节点属性 cat /sys/firmware/devicetree/base/总线控制器路径/设备名地址/compatible3. 分场景实操结合原理图下面结合ENET以太网、RS485、LED/KEY/BEEP三个实际硬件电路对应三种典型修改场景每段代码都标注对dtsi的操作方式。场景1启用芯片内部已有外设控制器适用场景外设控制器是芯片内部自带的如以太网FEC、UART、I2Cdtsi中已经定义完整硬件参数默认禁用我们需要启用并配置板级引脚。操作步骤在iomuxc及iomuxc_snvs中新增pinctrl引脚组配置对应引脚功能用外设标签引用dtsi中的控制器节点追加pinctrl引用、板级硬件参数写入status okay覆盖dtsi的禁用状态实操示例启用ENET1以太网控制器FEC1对应原理图ENET1电路芯片内置FEC1以太网控制器外接SR8201F PHY芯片复位引脚使用SNVS域引脚需分两个域配置。我们配置复用时首先根据自己所选的模式要求比如该ENET1中RMII模式只需要TX_CLK,TXD0/1,RXD0/1,TXEN,RXER,MDC,MDIO,那么在配置ENET时只需要这几根线其他相关的信号线即使连接也可以不配但像RESET这样的非信号部分的还是必须按照原理图配。第一步配置以太网引脚复用板级新增dtsi无对应内容iomuxc { imx6ul-evk { /* ENET1主信号引脚组普通域 */ pinctrl_enet1: enet1grp { fsl,pins /* 对应原理图TX_CLK、TXD0/1、TXEN、RXD0/1、MDIO、MDC等引脚 */ MX6UL_PAD_ENET1_RX_EN__ENET1_RX_EN 0x1b0b0 MX6UL_PAD_ENET1_RX_ER__ENET1_RX_ER 0x1b0b0 MX6UL_PAD_ENET1_RX_DATA0__ENET1_RDATA00 0x1b0b0 MX6UL_PAD_ENET1_RX_DATA1__ENET1_RDATA01 0x1b0b0 MX6UL_PAD_ENET1_TX_EN__ENET1_TX_EN 0x1b0b0 MX6UL_PAD_ENET1_TX_DATA0__ENET1_TDATA00 0x1b0b0 MX6UL_PAD_ENET1_TX_DATA1__ENET1_TDATA01 0x1b0b0 MX6UL_PAD_ENET1_TX_CLK__ENET1_REF_CLK1 0x4001b031 MX6UL_PAD_ENET1_MDIO__ENET1_MDIO 0x1b0b0 MX6UL_PAD_ENET1_MDC__ENET1_MDC 0x1b0b0 ; }; }; }; iomuxc_snvs { imx6ul-evk { /* ENET1复位引脚组SNVS域 */ pinctrl_enet1_reset: enet1resetgrp { fsl,pins MX6ULL_PAD_SNVS_TAMPER7__GPIO5_IO07 0x10b0 ; }; }; };第二步引用dtsi的fec1节点启用并追加板级配置fec1 { /* 追加引脚状态与pinctrl引用dtsi无该属性同时引用两个域的引脚组 */ pinctrl-names default; pinctrl-0 pinctrl_enet1 pinctrl_enet1_reset; /* 追加板级硬件参数对应原理图RMII接口与复位电路 */ phy-mode rmii; phy-handle ethphy0; phy-reset-gpios gpio5 7 GPIO_ACTIVE_LOW; phy-reset-duration 200; /* 覆盖dtsi默认status disabled此处改为启用 */ status okay; };场景2在已有总线控制器下挂接板载外设适用场景芯片提供总线控制器MDIO、I2C、SPI板载外设芯片挂在该总线上需要在总线控制器下新增从设备子节点。操作步骤确认总线控制器已启用并配置好引脚在总线控制器节点内部新增板载设备子节点命名遵循「设备类型地址」规范填写核心属性compatible、reg总线地址、status补充外设专属参数实操示例ENET1 MDIO总线挂载SR8201F PHY芯片对应原理图SR8201F通过MDIO/MDC接口和FEC1相连PHY地址0x02原理图右下角标注PHY ADDR0x02。 操作说明在场景1启用的fec1节点内部新增MDIO总线和PHY从设备。fec1 { /* ... 场景1的配置保持不变 ... */ status okay; /* 新增MDIO总线子节点dtsi的fec1中无此节点 */ mdio { #address-cells 1; #size-cells 0; /* 新增板载PHY芯片地址0x02 */ ethphy0: ethernet-phy2 { compatible ethernet-phy-ieee802.3-c22; reg 2; /* PHY的MDIO总线地址 */ }; }; };场景3新增完全自定义的板级设备适用场景板载外设不是标准总线设备需要用GPIO自定义控制dtsi中没有对应节点需要在根节点下全新建设备节点。操作步骤配置pinctrl引脚复用将用到的引脚设为对应功能在根节点/ { }下新建设备节点设置compatible字符串与驱动匹配表完全一致传入所有硬件参数GPIO、中断、自定义属性示例1用户LED对应原理图LED电路硬件LED0通过限流电阻接GPIO引脚高电平点亮。/* 第一步配置LED引脚pinctrl */ iomuxc { imx6ul-evk { pinctrl_gpioled: ledgrp { fsl,pins MX6UL_PAD_GPIO1_IO03__GPIO1_IO03 0x10b0 ; }; }; }; /* 第二步根节点下新增LED设备节点dtsi无对应节点完全板级新增 */ / { gpioled { compatible alientek,gpioled; pinctrl-names default; pinctrl-0 pinctrl_gpioled; led-gpios gpio1 3 GPIO_ACTIVE_HIGH; /* 高电平点亮对应原理图 */ status okay; }; };示例2按键KEY对应原理图KEY电路硬件KEY0按键下拉接地按下为低电平支持中断触发。iomuxc { imx6ul-evk { pinctrl_key: keygrp { fsl,pins MX6UL_PAD_UART1_CTS_B__GPIO1_IO18 0x1b0b0 ; }; }; }; / { key { compatible alientek,key; pinctrl-names default; pinctrl-0 pinctrl_key; key-gpios gpio1 18 GPIO_ACTIVE_LOW; /* 低电平有效对应下拉电路 */ interrupt-parent gpio1; interrupts 18 IRQ_TYPE_EDGE_BOTH; /* 双边沿触发 */ status okay; }; };示例3蜂鸣器BEEP对应原理图BEEP电路硬件BEEP引脚通过三极管驱动蜂鸣器低电平导通。iomuxc_snvs { imx6ul-evk { pinctrl_beep: beepgrp { fsl,pins MX6ULL_PAD_SNVS_TAMPER1__GPIO5_IO01 0X10b0 ; }; }; }; / { beep { compatible alientek,beep; pinctrl-names default; pinctrl-0 pinctrl_beep; beep-gpios gpio5 1 GPIO_ACTIVE_LOW; /* 低电平触发蜂鸣器 */ status okay; }; };五、常见踩坑与规范compatible不带厂商前缀极易和其他厂商设备重名导致驱动匹配错误工业级代码必须加前缀中断参数数量不匹配i.MX6ULL的GIC为3个cell中断必须写3个参数节点命名不规范禁止用自定义名称当节点名必须遵循「设备类型地址」的标准格式reg与父节点cells不匹配父节点设置#size-cells 0时子节点reg不能写长度引脚重复配置同一个物理引脚不能同时配置给两个外设会触发引脚冲突错误pinctrl编号与名称数量不匹配pinctrl-names有几个字符串就必须对应几个pinctrl-x字符串漏加双引号所有字符串属性必须用双引号包裹否则编译报错数值单位混淆设备树中数值默认是十进制加0x前缀才是十六进制跨域引脚配置错误SNVS域引脚必须在iomuxc_snvs中配置不能放在普通iomuxc节点本章总结5个核心属性是设备树的基石compatible负责匹配、reg描述地址、interrupts配置中断、status控制启用、地址cells定义reg格式i.MX6ULL平台中断为标准3参数格式。引脚复用支持多状态配置pinctrl-0/1/2与pinctrl-names按顺序一一对应常用于工作/休眠切换、多速率档位、多工作模式场景。芯片级dtsi是芯片的完整硬件地图从CPU、中断、时钟到外设控制器100%对应物理硬件所有开发板共用。soc是片上外设主干三条AIPS总线按功能分类管理外设专用硬件控制器和GPIO模拟有本质性能区别是MPU多任务并发的基础。板级dts对dtsi的操作分为两类根节点新增板载硬件、标签引用修改芯片外设覆盖属性、追加属性、新增子节点。普通域和SNVS域引脚分属两个iomux节点配置可被同一个外设同时引用。下一章我们将讲解设备树与驱动的匹配机制看compatible字符串如何让设备和驱动精准对接。