在嵌入式系统开发中,串口通信是最基础也最常用的功能之一。Zynq系列芯片虽然集成了强大的ARM处理器(PS侧),但原生只提供两路UART接口。我在实际项目中经常遇到这种情况:当系统需要连接多个传感器、显示屏或与其他设备通信时,两路串口根本不够用。比如最近做的工业控制器项目,需要同时对接触摸屏、温湿度传感器、电机驱动器和上位机,至少需要4路串口。
这时候就需要在PL(可编程逻辑)侧扩展UARTLite IP核。UARTLite是Xilinx提供的一个轻量级串口控制器,占用资源少,配置简单。但网上很多教程只讲基础用法,遇到多路扩展和中断管理就语焉不详。我调试时踩过不少坑,比如中断线没连对导致驱动加载失败,或者波特率设置不生效等问题。
与UART16550相比,UARTLite最大的特点是精简——没有FIFO缓冲区,波特率固定(只能在Vivado中配置)。但它的优势也很明显:占用逻辑资源少,一个Zynq7010芯片轻松实现16路以上的扩展。具体选择哪种方案,要看项目需求。如果需要灵活的波特率调整,那就得用UART16550;如果追求资源利用率,UARTLite是更好的选择。
新建Vivado工程后,关键是在Block Design中添加和配置AXI UARTLite IP。我建议先规划好地址空间,比如从0x43C0_0000开始,每路UART间隔0x10000。这样后续设备树配置不容易出错。具体操作:
这里有个容易忽略的点:中断控制器的选择。默认会用Zynq的PS侧中断控制器,但它只能处理有限的中断。当UART数量超过16路时,必须改用AXI_INTC IP做二级中断管理。我在一个智能网关项目中就遇到过这个问题,后来通过AXI_INTC扩展到了32路中断。
调试阶段建议做硬件自环,把每路UART的TX和RX短接。这样不需要外部设备就能验证通信是否正常。在顶层Verilog文件中可以这样实现:
verilog复制// 示例:8路UART自环连接
assign uart0_rx = uart0_tx;
assign uart1_rx = uart1_tx;
// ... 其他路同理
生成Bitstream时会遇到时序警告,这是因为UARTLite的时钟域问题。实测不影响功能,可以通过降低时钟频率或添加约束解决。我一般先用50MHz时钟,稳定后再尝试提高频率。
Vivado生成的设备树模板往往需要手动调整。以8路UARTLite为例,关键参数如下:
dts复制axi_uartlite_0: serial@42c00000 {
compatible = "xlnx,axi-uartlite-2.0";
reg = <0x42c00000 0x10000>;
interrupt-parent = <&axi_intc_0>;
interrupts = <0 0>;
current-speed = <9600>; /* 需与Vivado配置一致 */
};
特别注意interrupts属性的三个参数:第一个是中断控制器索引,第二个是中断号,第三个是触发类型(1表示边沿触发)。我在一次调试中因为把这个写成电平触发,导致数据接收不完整。
当UART数量超过PS的中断线时,必须使用AXI_INTC。配置示例:
dts复制axi_intc_0: interrupt-controller@41200000 {
#interrupt-cells = <2>;
compatible = "xlnx,axi-intc-4.1";
reg = <0x41200000 0x10000>;
interrupt-controller;
interrupts = <0 29 1>; /* 连接到PS的IRQ */
};
每个UART的中断父节点改为AXI_INTC,中断号从0开始连续分配。实测这种方案在24路UART系统中稳定运行,但要注意Linux内核需要开启CONFIG_XILINX_INTC配置项。
驱动加载失败最常见的原因是中断配置错误。可以通过以下命令检查:
bash复制dmesg | grep tty
cat /proc/interrupts
如果发现UART设备没有注册成功,首先确认:
UARTLite没有FIFO,在高波特率下容易丢数据。我的经验是:
一个实用的调试技巧:通过stty -F /dev/ttyUL0检查当前串口参数,确认波特率是否与硬件一致。因为UARTLite的波特率不能软件修改,这点经常被忽略。
在工业环境中,芯片温度变化会影响UART通信质量。建议:
开发阶段要模拟长期运行,我通常用这个脚本进行压力测试:
bash复制while true; do
echo "test" > /dev/ttyUL0
timeout 1 cat /dev/ttyUL0
done
同时监控/proc/interrupts计数是否均匀增长。曾发现某路UART的中断计数异常,最后查出是PCB走线过长导致信号质量差。
对于需要更多串口的场景,可以考虑:
但要注意资源占用和实时性的平衡。在某个需要32路串口的通信网关项目中,最终采用4片SC16IS752扩展方案,比纯PL实现更节省资源。