如何解决Allwinner A40i平台UART4(RS485)发送后挂死问题?
硬件与环境信息
- UART4
- 串口驱动:dw-apb-uart
- 仅包含Rx、Tx两路
使用Linux内核v6.5.8,Allwinner A40i处理器,UART4连接RS485收发器,通过GPIO PH13模拟RTS引脚实现半双工传输。
DTS配置
&uart4 { pinctrl-names = "default"; compatible = "snps,dw-apb-uart"; pinctrl-0 = <&uart4_ph_pins>; rts-gpios = <&pio 7 13 GPIO_ACTIVE_HIGH>; //PH13 //rs485-rts-delay = <0 200>; linux,rs485-enabled-at-boot-time; status = "okay"; };
问题现象
使用screen工具打开端口后接收正常,但发送首个字符/行后端口立即挂死(发送内容已成功送达),RTS引脚保持高电平,端口无法再收发。更换9600~115200波特率无改善。
调试情况
调试dw8250_dw.c驱动时发现,在spin_lock_irqsave(&port->lock, flags);前添加dev_err()/dev_info()输出后,端口恢复正常,但控制台会收到端口消息;若在该锁之后添加则无效,端口出现死锁,uart_unlock_and_check_sysrq_irqrestore(port, flags);无法解锁。
问题询问
- 如何让UART4正常工作且不向控制台输出端口消息?
- 该问题是否由驱动导致?
问题分析与解决方案
根源判断
从调试现象来看,这大概率是dw-apb-uart驱动(dw8250_dw.c)在模拟RTS引脚的RS485半双工场景下存在时序或锁竞争问题。添加日志打印本质上是引入了微小延迟,刚好规避了锁死的时序窗口,并非真正解决问题。
解决方案
1. 替换日志打印为无输出延迟
在spin_lock_irqsave前添加无输出的微延迟操作,既打破死锁时序,又不会向控制台输出信息:
// 在dw8250_dw.c对应位置添加 #include <linux/delay.h> // 需先引入头文件 udelay(1); spin_lock_irqsave(&port->lock, flags);
2. 启用RS485时序配置
尝试开启DTS中的RS485 RTS延迟参数,匹配RS485收发器的电平切换时序要求:
&uart4 { pinctrl-names = "default"; compatible = "snps,dw-apb-uart"; pinctrl-0 = <&uart4_ph_pins>; rts-gpios = <&pio 7 13 GPIO_ACTIVE_HIGH>; //PH13 rs485-rts-delay = <0 200>; // 发送前延迟0us,发送后延迟200us,可根据收发器手册调整 linux,rs485-enabled-at-boot-time; status = "okay"; };
3. 升级内核或应用补丁
检查Linux内核社区是否有针对dw-apb-uart RS485模拟RTS的修复补丁,可尝试升级到v6.6.x系列内核,这类较新内核通常会修复v6.5.x版本中的边角问题。
总结
问题核心是驱动在特定时序下的锁竞争或状态同步异常,添加微延迟或调整DTS时序可临时解决,长期建议关注官方驱动的修复更新。
内容的提问来源于stack exchange,提问作者Rarebeast
相关产品推荐
相关产品推荐

