4. Zynq PS端外设与接口配置

Zynq-7000 的 PS(Processing System)并不是“ARM 核 + 若干外设”的简单堆叠,而是一套由时钟、复位、存储控制器和互连总线共同支撑的子系统。高速数据采集工程中,PL 侧负责采样与预处理,PS 侧则承担数据搬运、缓存、协议交互和任务调度。如果 PS 的时钟树、DDR 控制器或 MIO 分配没有配置正确,即使 PL 逻辑完全正确,系统也会出现数据丢失、DMA 超时或启动失败。本节围绕 PS 时钟与 DDR 控制器、MIO/EMIO 分配、UART/SPI/I2C/SD 初始化,以及中断控制器与 GPIO 使用展开,重点说明“配置什么、为什么这样配、如何判断配置生效”。

PS 时钟与 DDR 控制器配置

PS 时钟由 PLL 和分频器产生,主要涉及 ARM PLL、DDR PLL、IO PLL 以及 S_AXI、S_AXI_HP 等总线时钟。以常见的 Zynq-7020 为例,若目标为 ARM 主频 667 MHz、DDR3 工作频率 533 MHz(数据率 1066 Mbps),则需要在 Vivado 的 PS 配置中设置输入晶振频率(通常 33.333 MHz),再由 PLL 倍频得到目标频率。DDR 控制器配置的关键参数包括 DDR 类型、位宽、容量、时序参数(tRCD、tRP、CL 等)和 Bank 地址映射。这些参数必须与开发板实际 DDR 芯片一致,否则会出现读写错误或无法启动。

配置完成后,PS 会通过 DDR 控制器初始化序列完成上电校准。判断 DDR 是否正常,最直接的方法是在 FSBL 或 U-Boot 阶段观察串口输出;若出现 “DDR init failed” 或校准超时,应优先检查 DDR 型号、位宽和时序参数是否匹配。对于高速采集,S_AXI_HP 接口的时钟应尽量与 PL 数据流匹配,避免跨时钟域带来的额外延迟。

Zynq PS 时钟、DDR 与外设接口配置关系 33.333 MHz PS_CLK 晶振 PLL 倍频/分频 ARM PLL → 667 MHz DDR PLL → 533 MHz DDR 控制器 DDR3 / 1066 Mbps 时序 + 校准 DDR3 颗粒 位宽 16/32 bit 容量 512MB/1GB MIO / EMIO 引脚分配 MIO 0~53 PS 专用引脚 EMIO 经 PL 扩展 UART / SPI I2C / SD GPIO / 中断 GIC + GPIO PS 侧 ARM Cortex-A9 + 缓存 + DDR 控制器 中断控制器 GIC / GPIO / 外设控制器 S_AXI_HP 高速数据通道 PL 侧 ADC 接口 / 数据缓存 / 预处理 AXI DMA / AXI Stream 中断输出至 PS GIC 数据/命令 中断/状态

MIO 与 EMIO 分配

MIO 是 PS 直接引出的 54 个多功能引脚,UART、SPI、I2C、SD、GPIO 等外设信号默认映射到 MIO。分配时要注意两点:一是同一 MIO 不能同时分配给两个外设;二是部分外设对 MIO 位置有固定约束,例如 SD0 通常占用 MIO 40~45,UART1 常用 MIO 48~49。EMIO 则是把 PS 外设信号通过 PL 引出,适合 MIO 数量不足或需要灵活布线的场景。例如,当 UART0 已用于调试串口、UART1 又需要额外流控信号时,可将 UART1 的 RTS/CTS 通过 EMIO 扩展到 PL 引脚。

在 Vivado 的 PS 配置界面中,MIO 分配以图形化方式呈现,每个引脚可下拉选择功能。配置完成后,应在 “MIO Configuration” 摘要中核对引脚编号、方向和电压标准(如 LVCMOS 3.3V)。若后续在 SDK/Vitis 中初始化外设失败,首先应回查 MIO 是否被重复占用或方向配置错误。

UART、SPI、I2C、SD 外设初始化

PS 外设初始化通常分为两步:在 Vivado 中使能外设并分配 MIO,然后在软件中调用驱动完成时钟使能、寄存器配置和中断绑定。以 UART1 为例,典型初始化流程包括:使能 UART1 时钟、设置波特率(如 115200)、配置数据位 8、停止位 1、无校验,最后使能收发。SPI 初始化需设置主/从模式、时钟极性/相位、片选和波特率分频;I2C 需设置总线速率(100 kHz 或 400 kHz)和从机地址;SD 控制器则需配置总线宽度(1 bit 或 4 bit)和时钟频率。

下面是一段基于 Xilinx 驱动库的 UART 初始化示例,用于说明关键参数如何落地:

XUartPs_Config *cfg = XUartPs_LookupConfig(XPAR_XUARTPS_1_DEVICE_ID);
XUartPs_CfgInitialize(&uart, cfg, cfg->BaseAddress);
XUartPs_SetBaudRate(&uart, 115200);
XUartPs_SetDataFormat(&uart, &format);  // 8N1
XUartPs_EnableUart(&uart);

判断初始化是否成功,可通过回环测试或串口打印验证。例如,向 UART1 发送 “AT” 后观察是否收到预期回显;SPI 可读取已知 ID 的传感器寄存器;I2C 可用扫描函数遍历地址,确认目标从机应答。若某外设无响应,应检查 MIO 分配、时钟使能和引脚电压是否一致。

PS 端中断控制器与 GPIO 使用

Zynq PS 的中断控制器为 GIC(Generic Interrupt Controller),支持 SPI、PPI 和 SGI 三类中断。PL 侧产生的中断通常通过 SPI 接入 GIC,例如 AXI DMA 的完成中断。配置时需要在 Vivado 中使能 “PL to PS Interrupt”,并在软件中注册中断服务函数、设置优先级和触发类型(上升沿或高电平)。GPIO 则可用于控制外设复位、LED 指示或按键输入。MIO GPIO 可直接操作,EMIO GPIO 需经 PL 引脚映射。

以采集系统为例:ADC 数据通过 AXI DMA 搬入 DDR,DMA 完成中断触发 PS 中断服务函数,在 ISR 中置位标志或释放信号量,主循环再处理数据。GPIO 可用于控制前端增益切换或读取板卡状态。中断服务函数应尽量简短,避免在 ISR 中执行耗时操作。若中断无法触发,应检查 GIC 使能位、中断号映射和 PL 中断信号是否已正确连接。

配置顺序建议:先确认时钟与 DDR 正常,再分配 MIO/EMIO,最后初始化外设和中断。每一步都通过串口输出或寄存器读回验证,避免问题叠加后难以定位。
DDR 时序参数必须与开发板实际颗粒一致,不可直接套用其他板卡配置。MIO 分配冲突在 Vivado 中通常会有提示,但电压标准不匹配可能到硬件阶段才暴露,需提前核对原理图。

综上,PS 端配置的核心是“时钟—存储—引脚—外设—中断”这条链路。时钟和 DDR 决定系统能否稳定运行,MIO/EMIO 决定外设能否正确连接,UART/SPI/I2C/SD 初始化决定协议交互是否可用,GIC 与 GPIO 则决定系统能否响应外部事件。在高速数据采集工程中,建议将 PS 配置与 PL 逻辑分开验证:先确保 PS 能启动、串口有输出、DDR 可读写,再逐步加入 PL 数据通路和中断,这样出现问题时可以快速缩小排查范围。