4. UART DMA设备树配置:dmas与dma-names属性详解、DMA通道与UART端口绑定、中断号配置
在全志T113平台上,要使UART驱动工作在DMA模式,设备树(Device Tree)的配置是核心环节。错误的配置将导致DMA传输失败、数据错乱甚至系统崩溃。本节将深入解析dmas、dma-names属性的语法规则,阐明DMA通道与UART端口的绑定逻辑,并说明中断号的配置要点。
关键认知:设备树中的DMA配置本质上是将UART的硬件FIFO事件(RX满/TX空)映射到DMA控制器的请求线(Request Line)上。T113的DMA控制器支持8个独立通道,每个UART端口需要占用2个通道(RX + TX)。
4.1 dmas属性详解:DMA通道描述符
dmas属性是一个phandle数组,用于描述UART外设所连接的DMA控制器及通道参数。其标准格式如下:
dmas = <dma_controller_phandle dma_channel_id dma_request_id>,
<dma_controller_phandle dma_channel_id dma_request_id>;
每个三元组代表一个DMA通道的描述:
| 字段 | 说明 | T113典型值 |
|---|---|---|
| dma_controller_phandle | DMA控制器的设备节点引用 | &dma 或 &dma0 |
| dma_channel_id | DMA控制器内部的物理通道编号(0~7) | 0~7,由驱动分配或静态指定 |
| dma_request_id | 外设DMA请求线编号,由SoC设计决定 | UART0_RX=14, UART0_TX=15 |
常见错误:将
dma_request_id误写为通道编号。T113的DMA请求线编号是SoC硬件固定的,必须查阅芯片手册确认。例如UART1的RX请求线为16,TX为17,与UART0不同。
以UART0为例,正确的dmas配置如下:
&uart0 {
pinctrl-names = "default";
pinctrl-0 = <&uart0_pins>;
status = "okay";
dmas = <&dma 2 14>, /* RX通道:使用DMA通道2,请求线14 */
<&dma 3 15>; /* TX通道:使用DMA通道3,请求线15 */
dma-names = "rx", "tx";
};
配置要点:
- RX通道和TX通道必须使用不同的DMA物理通道,避免资源冲突。
- 请求线编号必须与UART端口匹配:UART0=14/15, UART1=16/17, UART2=18/19, UART3=20/21。
- DMA通道编号(2和3)可以任意选择,只要不与系统中其他DMA用户冲突即可。
4.2 dma-names属性详解:通道语义映射
dma-names属性是一个字符串列表,为dmas中的每个通道赋予语义名称。驱动代码通过名称来获取对应的DMA通道资源,而不是依赖数组索引。这种设计提高了代码的可读性和可维护性。
dma-names = "rx", "tx";
名称与dmas数组中的顺序一一对应:
| dmas索引 | dma-names值 | 语义 | 驱动获取方式 |
|---|---|---|---|
| 0 | "rx" | 接收DMA通道 | dma_request_slave_channel(dev, "rx") |
| 1 | "tx" | 发送DMA通道 | dma_request_slave_channel(dev, "tx") |
命名规范:全志T113的UART驱动强制要求使用"rx"和"tx"作为dma-names。如果使用其他名称(如"uart0_rx"),驱动将无法正确获取DMA通道,导致DMA模式初始化失败。
4.3 DMA通道与UART端口绑定机制
DMA通道与UART端口的绑定分为静态绑定和动态分配两种模式。T113的DMA控制器支持动态分配,但设备树配置通常采用静态指定以确保确定性。
绑定流程如下:
- 设备树解析阶段:内核解析
dmas属性,获取DMA控制器phandle、通道ID和请求线ID。 - DMA引擎注册:DMA控制器驱动向内核注册DMA通道池。
- 通道请求:UART驱动调用
dma_request_slave_channel(),根据dma-names请求通道。 - 请求线映射:DMA引擎根据请求线ID配置硬件路由,将UART的FIFO事件连接到指定的DMA通道。
- 通道确认:UART驱动获得
dma_chan结构体指针,完成绑定。
4.4 中断号配置
即使UART工作在DMA模式,中断配置仍然必不可少。DMA模式下的中断分为两类:
| 中断类型 | 作用 | 配置位置 | 是否必需 |
|---|---|---|---|
| UART外设中断 | 处理错误、超时、DMA完成等事件 | UART节点中的interrupts属性 |
必需 |
| DMA控制器中断 | DMA传输完成、错误通知 | DMA控制器节点内部管理 | 自动管理 |
UART节点的中断配置示例:
&uart0 {
interrupt-parent = <&gic>; /* 中断控制器:GIC */
interrupts = <GIC_SPI 32 IRQ_TYPE_LEVEL_HIGH>;
/* GIC_SPI: 共享外设中断类型
32: UART0的中断号(T113硬件分配)
IRQ_TYPE_LEVEL_HIGH: 高电平触发 */
};
中断号速查表(全志T113 UART):
- UART0: GIC_SPI 32
- UART1: GIC_SPI 33
- UART2: GIC_SPI 34
- UART3: GIC_SPI 35
注意:中断号是SoC硬件设计决定的,不同芯片型号可能不同,务必以T113数据手册为准。
4.5 完整配置示例与验证
以下是一个完整的UART0 DMA模式设备树配置:
&uart0 {
pinctrl-names = "default";
pinctrl-0 = <&uart0_pins>;
status = "okay";
/* DMA配置 */
dmas = <&dma 2 14>, /* RX: DMA通道2, 请求线14 */
<&dma 3 15>; /* TX: DMA通道3, 请求线15 */
dma-names = "rx", "tx";
/* 中断配置 */
interrupt-parent = <&gic>;
interrupts = <GIC_SPI 32 IRQ_TYPE_LEVEL_HIGH>;
/* 可选:DMA缓冲区大小配置 */
dma-rx-buffer-size = <4096>;
dma-tx-buffer-size = <4096>;
};
配置完成后,可以通过以下方式验证DMA是否生效:
- 查看内核启动日志:搜索"uart0: DMA mode enabled"或类似信息。
- 检查DMA通道状态:
cat /sys/kernel/debug/dmaengine/channels查看通道分配情况。 - 性能测试:使用
dd或自定义程序进行大数据量收发,对比CPU占用率。
调试陷阱:如果配置后DMA不工作,首先检查
dma_request_id是否正确。T113的DMA请求线编号与UART端口号不是线性关系,例如UART2的RX请求线是18而不是16。务必对照芯片手册逐位确认。
4.6 常见配置错误与排查
| 错误现象 | 可能原因 | 排查方法 |
|---|---|---|
| DMA传输无响应 | dma_request_id错误 | 核对芯片手册请求线编号 |
| 数据错位或丢失 | DMA通道ID冲突 | 检查其他外设的DMA通道使用情况 |
| 中断风暴 | 中断触发类型配置错误 | 确认IRQ_TYPE_LEVEL_HIGH与硬件匹配 |
| 驱动初始化失败 | dma-names拼写错误 | 检查"rx"/"tx"是否小写且无空格 |