UART¶
1. UART 驱动说明¶
1.1 简介¶
UART 是通用异步收发传输器(Universal Asynchronous Receiver/Transmitter),是设备间异步通信的关键模块。 思澈平台 UART 特性主要包括:
全双工异步通信;
支持 16 或 8 倍过采样,兼顾速度与时钟容差;
可编程数据字长(7、8、9 位);
可配置停止位(1 或 2 个停止位);
支持 DMA 连续传输;
支持硬件流控(CTS/RTS)。
UART 总线工作原理可参考 UART设备
1.2 UART 资源分布¶
思澈平台最多支持 6 个 UART 实例,其中 3 个位于 HCPU,3 个位于 LCPU。
平台 |
HCPU |
LCPU |
|---|---|---|
52x |
UART1/UART2/UART3 |
|
56x |
UART1/UART2/UART3 |
UART4/UART5/UART6 |
55x |
UART1/UART2 |
UART3/UART4/UART5 |
58x |
UART1/UART2/UART3 |
UART4/UART5/UART6 |
UART 总线名称依次为 uart1~uart6。
UART 总线配置信息可参考 uart_config.h。
备注
HCPU 可以使用 LCPU 的 UART,但 LCPU 只能使用 LCPU 的 UART。
IO 口灵活性差异¶
55x/58x 系列:UART IO 口固定分配,需参考芯片规格书确认具体 IO 与 UART 的对应关系,不可随意切换。
52x/56x 系列:灵活性更高,任何带有 I2C_UART 功能的 IO 均可通过映射配置为 UART。
规格对比参考图:
1.3 UART 工作模式¶
UART 支持轮询(polling)、中断(INT)和 DMA 三种模式。
模式 |
CPU 占用 |
代码复杂度 |
适用场景 |
|---|---|---|---|
轮询 |
高,CPU 持续参与检查状态 |
低 |
低速、小数据量、简单应用 |
中断 |
中,事件发生时响应中断 |
低 |
中等数据量、实时性要求较高 |
DMA |
低,DMA 控制器直接传输 |
高 |
高速、大数据量、高吞吐量 |
下面流程图展示三种模式区别:
中断模式和 DMA 模式均通过缓存接收 UART 数据,应用层从缓存获取数据。 区别在于:
中断模式每个字节到来时触发中断,由 CPU 将数据搬运到缓存;
DMA 模式由 DMA 自动搬运数据到缓存,CPU 参与较少。
备注
DMA 模式适合高吞吐、低 CPU 占用的场景,通信过程不需 CPU 参与,减少被打断的概率。
对于 UART RX,建议优先使用 DMA 模式,避免中断导致接收异常。
1.4 UART 硬件流控¶
UART 硬件流控通过 CTS(Clear To Send)和 RTS(Request To Send)控制信号线实现流量控制,防止接收方缓冲区满导致丢包。
优点:
适用于高速传输时双方速率不匹配或数据突发场景。
缺点:
需要额外引脚 CTS/RTS,增加硬件设计复杂度。
1.5 UART 总线接口¶
打开并配置 UART 的常用接口如下:
函数 |
描述 |
|---|---|
|
查找设备 |
|
打开设备 |
|
读取数据 |
|
写入数据 |
|
控制设备 |
|
设置接收回调 |
|
设置发送完成回调 |
|
关闭设备 |
UART 总线一般使用流程:
rt_device_find() -> rt_device_open() -> rt_device_control() -> rt_device_set_rx_indicate()/rt_device_set_tx_complete() -> rt_device_read()/rt_device_write()
2. UART 使用流程¶
UART 使用一般包含配置选型、硬件绑定、参数设置和驱动调用四个核心步骤。
2.2 Pinmux 配置(绑定 IO 与 UART 总线)¶
Pinmux 配置用于建立物理 IO 引脚与 UART 总线的硬件映射关系,只有完成绑定后,UART 才能正常通信。
示例:使用 PA19 作为 USART1_TXD,PA18 作为 USART1_RXD。
// 函数:HAL_PIN_Set(引脚标识, 功能别名, 上下拉配置, 核心选择)
HAL_PIN_Set(
PAD_PA19, // 物理 IO 引脚
USART1_TXD, // UART1 发送
PIN_PULLUP, // 上下拉配置
1 // 1:HCPU,0:LCPU
);
HAL_PIN_Set(
PAD_PA18, // 物理 IO 引脚
USART1_RXD, // UART1 接收
PIN_PULLUP, // 上下拉配置
1 // 1:HCPU,0:LCPU
);
2.3 应用层选择 UART 总线¶
在应用层选择要使用的 UART 总线。
示例配置界面:
2.4 打开与配置 UART¶
通过 RT-Thread 接口完成 UART 初始化与控制,常见流程如下:
// 查找 UART 总线
rt_device_find(device_name);
// 打开 UART 总线
rt_device_open(dev, oflag);
// 设置接收回调
rt_device_set_rx_indicate(dev, finsh_rx_ind);
// 配置波特率、数据字长、停止位
rt_device_control(dev, RT_DEVICE_CTRL_CONFIG, &config);
// 读取 UART 数据
rt_device_read(shell->device, -1, &ch, 1);
2.5 UART 模式配置¶
通过 flag_open 选择 UART 工作模式。
轮询模式:
flag_open = RT_DEVICE_OFLAG_RDWR | RT_DEVICE_FLAG_STREAM;
中断模式:
flag_open = RT_DEVICE_OFLAG_RDWR | RT_DEVICE_FLAG_STREAM | RT_DEVICE_FLAG_INT_RX | RT_DEVICE_FLAG_INT_TX;
DMA 模式:
flag_open = RT_DEVICE_OFLAG_RDWR | RT_DEVICE_FLAG_STREAM | RT_DEVICE_FLAG_DMA_RX | RT_DEVICE_FLAG_DMA_TX;
所有支持的 flag 如下:
#define RT_DEVICE_FLAG_RDONLY 0x001 /**< read only */
#define RT_DEVICE_FLAG_WRONLY 0x002 /**< write only */
#define RT_DEVICE_FLAG_RDWR 0x003 /**< read and write */
#define RT_DEVICE_FLAG_REMOVABLE 0x004 /**< removable device */
#define RT_DEVICE_FLAG_STANDALONE 0x008 /**< standalone device */
#define RT_DEVICE_FLAG_ACTIVATED 0x010 /**< device is activated */
#define RT_DEVICE_FLAG_SUSPENDED 0x020 /**< device is suspended */
#define RT_DEVICE_FLAG_STREAM 0x040 /**< stream mode */
#define RT_DEVICE_FLAG_INT_RX 0x100 /**< INT mode on Rx */
#define RT_DEVICE_FLAG_DMA_RX 0x200 /**< DMA mode on Rx */
#define RT_DEVICE_FLAG_INT_TX 0x400 /**< INT mode on Tx */
#define RT_DEVICE_FLAG_DMA_TX 0x800 /**< DMA mode on Tx */
2.6 DMA 模式配置¶
DMA 模式配置包括:menuconfig 使能 UART DMA、配置 dma_config、并在 rt_device_open 时打开 DMA 标志。
2.6.2 配置 dma_config¶
在 dma_config.c 中配置 DMA 相关宏,例如:
#define UART1_DMA_RX_IRQHandler DMAC1_CH7_IRQHandler /* DMA 中断回调 */
#define UART1_RX_DMA_IRQ_PRIO 0 /* DMA 中断优先级 */
#define UART1_RX_DMA_INSTANCE DMA1_Channel7 /* DMA 通道实例 */
#define UART1_RX_DMA_IRQ DMAC1_CH7_IRQn /* DMA 中断 */
#define UART1_RX_DMA_REQUEST DMA_REQUEST_5 /* UART1 RX DMA 请求号 */
下表展示各平台 UART 总线对应的 DMA_REQUEST:
UART 总线 |
52x |
55x |
56x |
58x |
|---|---|---|---|---|
UART1_TX |
DMAC1_4 |
DMAC1_4 |
DMAC1_4 |
DMAC1_4 |
UART1_RX |
DMAC1_5 |
DMAC1_5 |
DMAC1_5 |
DMAC1_5 |
UART2_TX |
DMAC1_6 |
DMAC1_6 |
DMAC1_6 |
DMAC1_6 |
UART2_RX |
DMAC1_7 |
DMAC1_7 |
DMAC1_7 |
DMAC1_7 |
UART3_TX |
DMAC1_26 |
DMAC2_0 |
DMAC1_26 |
DMAC1_26 |
UART3_RX |
DMAC1_27 |
DMAC2_1 |
DMAC1_27 |
DMAC1_27 |
UART4_TX |
DMAC2_2 |
DMAC2_0 |
DMAC3_0 |
|
UART4_RX |
DMAC2_2 |
DMAC2_1 |
DMAC3_1 |
|
UART5_TX |
DMAC2_4 |
DMAC2_2 |
DMAC3_2 |
|
UART5_RX |
DMAC2_5 |
DMAC2_3 |
DMAC3_3 |
|
UART6_TX |
DMAC2_4 |
DMAC3_4 |
||
UART6_RX |
DMAC2_5 |
DMAC3_5 |
2.6.3 启用 DMA 模式¶
打开 UART 时使用 DMA 标志:
flag_open = RT_DEVICE_OFLAG_RDWR | RT_DEVICE_FLAG_STREAM | RT_DEVICE_FLAG_DMA_RX | RT_DEVICE_FLAG_DMA_TX;
3. 其他注意事项¶
3.1 UART 波特率建议¶
当 UART 波特率超过 1M 时,建议选择 1M、2M、3M、4M、6M 等档位。 原因:UART 的时钟由 48M 分频生成,使用整除分频值可降低速率误差。
3.2 HCPU 使用 LCPU UART 的说明¶
3.2.1 适用平台与风险¶
对于 56x/55x/58x 平台,HCPU 使用 LCPU UART DMA 通讯为非推荐方案。 因为 HCPU 访问 LCPU UART 需要经过 APB 总线,若系统处于 LCPU RC10K 校准阶段,APB 总线会被占用 2~3us,可能导致连续数据传输过程中出现丢包。
建议:仅在无法避免时,才使用 HCPU 访问 LCPU UART DMA。
3.2.2 必要条件¶
若必须使用 HCPU 访问 LCPU UART DMA,必须满足以下两个要求:
使用外部 32k 晶振。
HCPU 的 UART 缓冲区使用 LCPU 的 SRAM 空间。
3.2.3 外部 32k 晶振要求¶
原因如下:
56x/55x/58x 平台的 RC10K 校准在 LCPU 上完成;
校准期间 PCLK2 会降频到 6M;
访问 PMU 寄存器会占用 APB 总线约 2~3us;
HCPU 访问 LCPU UART 也需经过 APB 总线,因此连续通信时可能发生 1 字节丢失。
总线结构:
配置方式:
电路图:
3.2.4 HCPU 缓冲区使用 LCPU SRAM¶
HCPU 使用LCPU 的 UART 时,建议将 UART 缓冲区分配到 LCPU SRAM,以避免跨核访问带来的数据不一致和延迟问题。
修改 LCPU
mem_map.h,调整 LCPU SRAM 分布,从LCPU_RAM_DATA预留 SRAM 空间。
修改驱动文件
serial.c,在打开 UART 时判断 HCPU 使用 LCPU UART 场景,并使用 LCPU 预留的 SRAM 空间。
发布版本未包含HCPU 使用LCPU 的 UART的支持,用户可以自己修改或向我司索要相关patch.
