3. UART控制器设备树绑定:通用属性与SoC示例

设备树(Device Tree)是嵌入式Linux系统中描述硬件拓扑与资源的关键机制。对于UART控制器,设备树节点需要准确声明寄存器地址、中断号、时钟源等资源,以便内核驱动能够正确初始化和控制串口硬件。本章将系统讲解通用UART节点属性,并结合i.MX和STM32MP1两款典型SoC给出完整绑定示例。

学习目标:掌握UART设备树节点的标准属性写法,理解compatible匹配机制,能够独立为i.MX6ULL和STM32MP157编写UART设备树片段。

3.1 通用UART节点属性

一个标准的UART设备树节点通常包含以下核心属性,这些属性在Linux内核的串口驱动框架(如8250、amba-pl011、imx-uart)中具有通用语义。

属性名 类型 说明 示例值
compatible string list 驱动匹配字符串,用于将节点绑定到具体驱动 "fsl,imx6ul-uart", "fsl,imx-uart"
reg address-cells × size-cells UART控制器的寄存器基地址和地址范围 <0x02020000 0x4000>
interrupts interrupt specifier UART中断号及触发类型 <0 26 IRQ_TYPE_LEVEL_HIGH>
clocks phandle list UART模块时钟和总线时钟的引用 <&uart_clk>, <&bus_clk>
clock-names string list 时钟名称,与clocks属性一一对应 "uart", "bus"
pinctrl-0 phandle 引脚复用配置状态 <&pinctrl_uart1>
pinctrl-names string list 引脚状态名称,通常为"default" "default"
status string 设备启用状态:"okay"或"disabled" "okay"
属性解析要点:
  • compatible 采用"厂商,型号"格式,内核驱动通过of_match_table进行精确匹配;
  • reg 的地址长度由父节点的#address-cells和#size-cells决定,ARM平台通常为<1 1>;
  • interrupts 的编码格式依赖中断控制器(GIC或NVIC),需参考SoC手册;
  • clocks 必须与clock-names顺序一致,驱动通过clk_get(dev, name)获取。
通用UART设备树节点结构 uart@02020000 compatible = "fsl,imx-uart" reg = <0x02020000 0x4000> interrupts = <0 26 4> clocks = <&uart_clk> pinctrl-0 = <&pinctrl_uart1> status = "okay" 每个属性都是驱动与硬件之间的契约, 缺失或错误将导致串口无法正常工作。 资源属性 中断/时钟 配置属性

3.2 NXP i.MX6ULL UART绑定示例

i.MX6ULL是NXP基于Cortex-A7内核的工业级MPU,其UART模块兼容8250风格,但具有独立的FIFO和自动流控。以下是一个完整的UART1设备树节点示例,包含时钟、中断和引脚复用配置。

/* i.MX6ULL UART1 设备树节点 */
&uart1 {
    compatible = "fsl,imx6ul-uart", "fsl,imx-uart";
    reg = <0x02020000 0x4000>;
    interrupts = <GIC_SPI 26 IRQ_TYPE_LEVEL_HIGH>;
    clocks = <&clks IMX6UL_CLK_UART1_IPG>,
             <&clks IMX6UL_CLK_UART1_SERIAL>;
    clock-names = "ipg", "per";
    pinctrl-names = "default";
    pinctrl-0 = <&pinctrl_uart1>;
    status = "okay";
};

/* 对应的引脚复用配置 */
&iomuxc {
    pinctrl_uart1: uart1grp {
        fsl,pins = <
            MX6UL_PAD_UART1_TX_DATA__UART1_DCE_TX  0x1b0b1
            MX6UL_PAD_UART1_RX_DATA__UART1_DCE_RX  0x1b0b1
        >;
    };
};
常见错误:i.MX的UART驱动需要两个时钟——ipg(接口时钟)和per(波特率时钟)。如果只提供一个时钟,驱动将无法正确计算波特率,导致串口输出乱码。务必检查clock-names是否与驱动要求一致。
i.MX6ULL UART1 时钟与中断拓扑 PLL3 (USB PLL) PLL2 (Sys PLL) CCM 分频器 (ipg / per) UART1 0x02020000 GIC #26 480 MHz 528 MHz clocks interrupts

3.3 STM32MP1 UART绑定示例

STM32MP1是ST推出的异构双核处理器(Cortex-A7 + Cortex-M4),其UART模块基于ST的USART设计,支持同步/异步模式、智能卡和LIN总线。设备树绑定需要额外注意DMA通道和唤醒中断的配置。

/* STM32MP157 UART4 设备树节点 */
&uart4 {
    compatible = "st,stm32h7-uart";
    reg = <0x40010000 0x400>;
    interrupts = <GIC_SPI 52 IRQ_TYPE_LEVEL_HIGH>;
    clocks = <&rcc UART4_K>;
    clock-names = "uart";
    pinctrl-names = "default", "sleep";
    pinctrl-0 = <&uart4_pins_a>;
    pinctrl-1 = <&uart4_sleep_pins_a>;
    dmas = <&dmamux1 34 0x400 0x05>,
           <&dmamux1 35 0x400 0x01>;
    dma-names = "rx", "tx";
    wakeup-source;
    status = "okay";
};

/* 引脚复用:使用AF7功能 */
&pinctrl {
    uart4_pins_a: uart4-0 {
        pins1 {
            pinmux = <STM32_PINMUX('B', 2, AF7)>; /* TX */
            bias-disable;
            drive-push-pull;
            slew-rate = <0>;
        };
        pins2 {
            pinmux = <STM32_PINMUX('B', 1, AF7)>; /* RX */
            bias-pull-up;
        };
    };
};
STM32MP1 绑定特点:
  • DMA支持:通过dmas属性指定RX/TX通道,可大幅降低CPU占用率,适合蓝牙串口的高吞吐场景;
  • 休眠引脚:pinctrl-1定义休眠态引脚配置,在系统低功耗时自动切换;
  • 唤醒源:wakeup-source属性使UART能在挂起状态下通过RX信号唤醒系统。
STM32MP1 UART4 DMA数据路径 UART4 RX FIFO / TX FIFO DMAMUX1 通道34/35 DMA1 Stream0 / Stream1 DDR 内存 串口缓冲区 dmas DMA请求 内存搬运 DMA路径使UART收发不经过CPU核心, 显著降低蓝牙串口在高波特率下的CPU占用率。

3.4 通用属性与SoC绑定对比

下表对比了i.MX6ULL和STM32MP157在UART设备树绑定中的关键差异,帮助你在不同平台间快速迁移。

对比项 i.MX6ULL STM32MP157
compatible "fsl,imx6ul-uart" "st,stm32h7-uart"
时钟数量 2个(ipg + per) 1个(uart)
中断触发类型 IRQ_TYPE_LEVEL_HIGH IRQ_TYPE_LEVEL_HIGH
DMA支持 可选(通过SDMA) 标配(通过DMAMUX)
休眠引脚 不支持 支持pinctrl-1
唤醒源 不支持 支持wakeup-source
波特率范围 最高4 Mbps 最高6.75 Mbps
迁移建议:从i.MX迁移到STM32MP1时,重点关注时钟属性从双时钟变为单时钟,以及新增的DMA和唤醒配置。反之,从STM32MP1迁移到i.MX时,需要补全ipg和per两个时钟,并移除DMA相关属性(除非使用SDMA)。

3.5 设备树绑定检查清单

在完成UART设备树编写后,建议按以下清单逐项验证,避免低级错误导致串口无法工作。

  1. compatible 是否与内核驱动中的of_match_table完全匹配?
  2. reg 地址是否在SoC内存映射表中正确?地址范围是否覆盖所有寄存器?
  3. interrupts 中断号是否与SoC手册一致?触发类型是否正确?
  4. clocks 是否提供了驱动所需的所有时钟?clock-names是否拼写正确?
  5. pinctrl 引脚复用功能是否与硬件原理图一致?TX/RX是否接反?
  6. status 是否显式设置为"okay"?
  7. DMA(如使用)通道号是否与DMAMUX配置一致?
  8. 编译检查 使用make dtbs编译,确认无语法错误。
调试提示:如果UART在系统启动后无输出,首先检查/sys/firmware/devicetree/base/下对应节点是否存在,然后查看dmesg | grep uart确认驱动是否成功probe。常见错误包括时钟未使能、中断号冲突、引脚复用被其他外设占用。
UART设备树绑定检查流程 1. 编写DTS 2. make dtbs 3. 烧录启动 4. 检查节点 节点存在? dmesg查错 驱动probe? 检查compatible 串口通信测试 修改DTS

3.6 本章小结

UART设备树绑定是蓝牙串口驱动开发的基础环节。通过本章学习,你应该能够:

  • 理解compatible、reg、interrupts、clocks等通用属性的语义和写法;
  • 掌握i.MX6ULL双时钟UART绑定的具体方法;
  • 掌握STM32MP157带DMA和唤醒功能的UART绑定方法;
  • 使用检查清单和调试流程快速定位设备树问题。