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)获取。
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是否与驱动要求一致。
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信号唤醒系统。
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设备树编写后,建议按以下清单逐项验证,避免低级错误导致串口无法工作。
- compatible 是否与内核驱动中的of_match_table完全匹配?
- reg 地址是否在SoC内存映射表中正确?地址范围是否覆盖所有寄存器?
- interrupts 中断号是否与SoC手册一致?触发类型是否正确?
- clocks 是否提供了驱动所需的所有时钟?clock-names是否拼写正确?
- pinctrl 引脚复用功能是否与硬件原理图一致?TX/RX是否接反?
- status 是否显式设置为"okay"?
- DMA(如使用)通道号是否与DMAMUX配置一致?
- 编译检查 使用
make dtbs编译,确认无语法错误。
调试提示:如果UART在系统启动后无输出,首先检查
/sys/firmware/devicetree/base/下对应节点是否存在,然后查看dmesg | grep uart确认驱动是否成功probe。常见错误包括时钟未使能、中断号冲突、引脚复用被其他外设占用。
3.6 本章小结
UART设备树绑定是蓝牙串口驱动开发的基础环节。通过本章学习,你应该能够:
- 理解compatible、reg、interrupts、clocks等通用属性的语义和写法;
- 掌握i.MX6ULL双时钟UART绑定的具体方法;
- 掌握STM32MP157带DMA和唤醒功能的UART绑定方法;
- 使用检查清单和调试流程快速定位设备树问题。