跳到主要内容PetaLinux 配置 Zynq-7000 PS 端外设实战指南 | 极客日志C
PetaLinux 配置 Zynq-7000 PS 端外设实战指南
本文介绍了在 PetaLinux 环境下配置 Zynq-7000 PS 端外设(UART、SPI、I2C、GPIO 等)的完整流程。涵盖 Vivado 硬件 IP 配置、PetaLinux 工程初始化、内核驱动编译选项设置、设备树节点修改以及系统构建部署。重点讲解了如何通过修改 system-user.dtsi 启用默认禁用的外设,并提供了常见问题的排查方法,如设备节点缺失、SPI 通信失败及 GPIO 中断未触发等场景的解决方案。
ArchDesign0 浏览 PetaLinux 配置 Zynq-7000 PS 端外设实战指南
本文以真实项目视角,带你一步步打通'Vivado 硬件配置 → PetaLinux 系统构建 → 外设驱动加载 → 应用层验证'这条完整链路。重点解决如何让 Zynq-7000 的 PS 端外设,在 PetaLinux 下真正跑起来的问题。
理解 Zynq 的三层控制模型
Zynq-7000 的 PS(Processing System)部分虽然集成了双核 Cortex-A9 和一堆标准外设控制器,但这些外设并不是'通电即用'的。它们需要经过三个层级的协同配置才能正常工作:
第一层:硬件固化 —— Vivado 里的 PS IP 配置
这是整个流程的起点。你在 Vivado 中打开 Zynq UltraScale+ Processing System IP 核,做的每一步选择都会被固化到比特流中:是否启用 UART1?SPI0 的工作模式是 Master 还是 Slave?MIO48 接的是 UART1_RX 还是 CAN0_RX?UART 参考时钟是 50MHz 还是 100MHz?这些设置一旦生成.bit 和.hdf 文件,就不可更改。哪怕你在 Linux 里把设备树写得再完美,如果这里没开对应功能,硬件层面就是'不存在'的。
第二层:软件映射 —— 设备树(Device Tree)
Linux 内核不会主动去扫描硬件寄存器来识别外设有多少个、地址在哪。它完全依赖设备树提供的信息。PetaLinux 会根据.hdf 文件自动生成初始设备树(如 system-conf.dtsi),但它默认只启用关键外设(比如 UART0 用于调试)。其他外设节点即使存在,状态也是 status = "disabled"。所以你需要手动修改设备树,告诉内核:'这个 UART1 是真的要用了,请加载驱动。'
第三层:运行时驱动加载
当内核启动时,解析设备树,发现某个外设节点的 status = "okay" 且 compatible 属性匹配已编译的驱动模块,就会自动加载相应驱动,创建设备节点(如 /dev/ttyPS1)。但如果内核根本没有编译那个驱动(比如 CONFIG_SPI_XILINX 被设为 或 ),即使设备树写了也没用。
总结一句话:外设要工作 = Vivado 中启用 + 设备树中标记 okay + 内核中编译驱动。三者缺一不可。
Step 1:Vivado 阶段 —— 把硬件'画'清楚
这是最容易忽视却又最关键的一环。很多后期问题,根源都在这里。
启动 Vivado 并创建 Block Design
- 创建新工程,添加 ZYNQ7 Processing System IP。
- 双击进入配置界面,切换到'Peripheral I/O Pins'标签页。
关键操作清单
| 外设 | 配置要点 |
|---|
| UART | 勾选 UART1,并为其分配 MIO 引脚(如 MIO48=RX, MIO49=TX) |
| SPI | 勾选 SPI0,设置为主模式(Master),分配 MOSI/MISO/SCLK/SS0 |
| I2C | 勾选 I2C0,连接 EEPROM 或传感器时需外接上拉电阻 |
| SDIO | 若使用 eMMC 或 SD 卡,务必勾选,并注意电压选择(1.8V/3.3V) |
| GPIO | 使用 EMIO 扩展时,可在'GPIO'标签页中指定数量(如 4 位 LED+4 位按键) |
⚠️ 注意:每个 MIO 只能属于一个外设。如果你把 MIO48 既给了 UART1_RX 又给了 CAN0_RX,Vivado 会报错:'Pin conflict'。
时钟配置不能省!
切换到'Clock Configuration'页面,检查各外设时钟是否已使能:
- uart0_ref_clk → 推荐设为 100MHz(便于生成标准波特率)
- spi0_ref_clk → 至少 50MHz(支持高速 Flash)
- sdio_ps_clk → 一般设为 100MHz(兼容高速 SD 卡)
🔍 小知识:Zynq 的 PS 有独立的时钟管理单元(PMC)。如果某外设时钟未开启,其寄存器将无法访问,即使设备树正确也无法工作。
导出 HDF 文件
Tools → Export → Export Hardware
勾选'Include bitstream',输出.hdf 文件(通常位于 .sdk/system.hdf)。
✅ 最佳实践:每次修改 PS 配置后都重新导出 HDF,并同步更新 PetaLinux 工程,避免软硬不一致。
Step 2:PetaLinux 工程搭建 —— 让系统'认得清'硬件
有了 HDF,就可以开始构建嵌入式 Linux 系统了。
初始化 PetaLinux 项目
petalinux-create -t project --name zynq-demo
cd zynq-demo
petalinux-config --get-hw-description=/path/to/hardware/description/
第二条命令会触发 PetaLinux 解析 HDF,生成基础配置文件,包括:
- project-spec/configs/config(系统通用配置)
- project-spec/meta-user/recipes-bsp/device-tree/files/system-user.dtsi
- 自动生成的内核与 u-boot 模板
💡 提示:不要手动编辑 system-conf.dtsi!它是自动生成的,下次 petalinux-config 可能被覆盖。所有自定义都应写在 system-user.dtsi 中。
内核配置:确保驱动编译进内核
petalinux-config -c kernel
| 功能 | 路径 | 推荐设置 |
|---|
| UART 驱动 | Device Drivers → Serial drivers → ARM AMBA PL011 FPGA mode | Y |
| SPI 驱动 | Device Drivers → SPI support → Xilinx SPI controller | Y |
| I2C 驱动 | Device Drivers → I2C support → Xilinx I2C adapter | Y |
| SDIO/MMC | Device Drivers → MMC/SD/SDIO card support → AMD/Xilinx Zynq 7xxx/MPSoC SDHCI | Y |
| GPIO 子系统 | Device Drivers → GPIO Support → GPIO Support for Xilinx devices | Y |
❗ 强烈建议将关键驱动设为 Y(内置)而非(模块),避免因根文件系统缺少 modprobe 而无法加载。
Step 3:设备树定制 —— 给外设'发通行证'
现在来到最关键的一步:修改设备树,启用那些默认禁用的外设。
vim project-spec/meta-user/recipes-bsp/device-tree/files/system-user.dtsi
示例 1:启用 UART1 作为用户串口
&uart1 { status = "okay"; };
就这么简单?没错。原始设备树中 uart1 节点已经存在,只是 status="disabled"。我们在这里用同名节点进行'覆盖',将其状态改为'okay'。
petalinux-build
ls /dev/ttyPS*
🛠 调试技巧:若看不到 ttyPS1,查看 dmesg | grep uart 是否有错误日志。常见报错如:zynq_uart e0001000.uart: no clock defined,表明 HDF 中未启用 UART1 时钟。
示例 2:挂载 W25Q32 Flash 通过 SPI0
假设你的 SPI Flash 接在 SPI0 上,片选为 CS0。
&spi0 { status = "okay"; num-cs = <1>; flash@0 { compatible = "jedec,spi-nor"; reg = <0>; // 片选索引 spi-max-frequency = <50000000>; // 最大 50MHz }; };
ls /dev/mtd*
dmesg | grep spi
⚠️ 注意:某些 Flash 芯片需要特定的 compatible 字符串。例如 MX25L 系列可用 "winbond,w25q32" 更精确匹配。
示例 3:配置 EMIO 按键输入
&gpio0 { status = "okay"; };
&amba_pl {
gpio_keys {
compatible = "gpio-keys";
user_btn {
label = "User Button";
gpios = <&gpio0 54 0>; // EMIO 起始于 54
linux,code = <0x100>; // KEY_ENTER
debounce-interval = <20>; // 消抖 20ms
};
};
};
- gpios = <&gpio0 54 0>:表示使用 gpio0 bank,第 54 号引脚(即 EMIO[0]),触发方式为下降沿有效(最后一个参数 0 表示 active low)
- linux,code = <0x100>:上报事件类型为 KEY_ENTER
- debounce-interval = <20>:软件消抖 20ms
cat /proc/interrupts | grep gpio
evtest /dev/input/event0
Step 4:构建与部署 —— 生成可启动镜像
- images/linux/BOOT.BIN:包含 FSBL、bitstream、u-boot
- images/linux/image.ub:整合了 kernel、dtb、rootfs 的 U-Boot 镜像
petalinux-package --boot --fsbl images/linux/zynq_fsbl.elf --fpga system.bit --u-boot --force
将 BOOT.BIN 和 image.ub 拷贝至 FAT32 格式的 SD 卡根目录,插入开发板,串口连接,上电!
Step 5:现场验证与排错 —— 让外设'动起来'
系统启动后,进入第一个 Shell,立刻执行以下命令快速验证:
快速诊断四件套
dmesg | grep -i "uart\|spi\|i2c\|mmc"
ls /dev/ttyPS*
ls /dev/spi*
ls /dev/i2c*
ls /dev/mmcblk*
ls /sys/class/gpio/
cat /proc/interrupts | grep -i "spi\|uart\|gpio"
spidev_test -D /dev/spidev0.0 -l 10
常见问题与解决方案(实战经验总结)
❌ 问题 1:/dev/ttyPS1 不存在,但 dmesg 无明显报错
- 检查 system-user.dtsi 中是否写了 &uart1 { status = "okay"; };
- 检查 Vivado 中是否真的启用了 UART1 并分配了 MIO
- 执行 grep -r "uart1" build/tmp/work/ 查看最终合并的设备树内容
- 使用 devmem 0xe0001000 读取 UART1 基地址寄存器,看能否访问(非法地址会段错误)
✅ 解决方案:多数情况下是因为 HDF 旧了。重新导出 HDF,删除 PetaLinux 缓存目录(rm -rf components/plnx_workspace),再 petalinux-config --get-hw-description 重导入。
❌ 问题 2:SPI 设备识别失败,提示'No response from device'
spi_nor_read_id failed: -2
- Flash 未供电或焊接虚焊
- SCK/MOSI 等信号未输出(可用示波器测量)
- spi-max-frequency 超过 Flash 规格(W25Q32 最高支持 104MHz,但 PCB 走线差的话建议降频至 50MHz)
- 片选极性不匹配(有些 Flash 是低有效,有些是高有效)
spi-max-frequency = <10000000>; // 先试 10MHz
❌ 问题 3:GPIO 按键无法触发中断
- 是否启用了 CONFIG_GPIO_XILINX?
- EMIO 引脚对应的 Bank 电压是否与外部电路一致?(如 Bank 0 为 3.3V,Bank 1 为 1.8V)
- 是否需要内部上下拉?可通过设备树添加:
&gpio0 {
xlnx,has-ip-reset = <0>;
xlnx,external-intr-enable = <1>;
xlnx,gpio-width = <64>; // 总共 64 位(MIO+EMIO)
};
echo "in" > /sys/class/gpio/gpio54/direction
echo "pull_up" > /sys/class/gpio/gpio54/bias
工程级建议:提升稳定性和可维护性
1. 做一张 MIO 资源分配表
| MIO | 功能 | 备注 |
|---|
| 48 | UART1_RX | 不可复用 |
| 49 | UART1_TX | 不可复用 |
| 50 | SPI0_MOSI | 可用于普通 GPIO |
| … | … | … |
2. 使用版本控制系统
将整个 PetaLinux 工程纳入 Git 管理,提交时附带说明:
git commit -m "enable spi0 and w25q32 flash, update hdf from vivado v2023.1"
3. 自动化构建脚本
#!/bin/bash
petalinux-build && petalinux-package --boot --fsbl images/linux/zynq_fsbl.elf --fpga ../vivado/system.bit --u-boot --force
微信扫一扫,关注极客日志
微信公众号「极客日志」,在微信中扫描左侧二维码关注。展示文案:极客日志 zeeklog
相关免费在线工具
- Base64 字符串编码/解码
将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online
- Base64 文件转换器
将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online
- Markdown转HTML
将 Markdown(GFM)转为 HTML 片段,浏览器内 marked 解析;与 HTML转Markdown 互为补充。 在线工具,Markdown转HTML在线工具,online
- HTML转Markdown
将 HTML 片段转为 GitHub Flavored Markdown,支持标题、列表、链接、代码块与表格等;浏览器内处理,可链接预填。 在线工具,HTML转Markdown在线工具,online
- JSON 压缩
通过删除不必要的空白来缩小和压缩JSON。 在线工具,JSON 压缩在线工具,online
- JSON美化和格式化
将JSON字符串修饰为友好的可读格式。 在线工具,JSON美化和格式化在线工具,online