尧图网络科技YAOTU DIGITAL 获取报价
获取报价
首页 / 资讯中心 / 文章详情

AD9361+Zynq软件无线电平台从参考设计到PetaLinux与BPSK调测全解析

发布时间:2026/9/19 15:30:23

资讯中心
01
ARTICLE

AD9361+Zynq软件无线电平台从参考设计到PetaLinux与BPSK调测全解析

AD9361+Zynq软件无线电平台从参考设计到PetaLinux与BPSK调测全解析
做AD9361和Zynq这套平台也有几年了从最早的ZedBoard加FMCOMMS3小板到后来自己画板子把AD9361和Zynq贴在同一块PCB上中间踩过的坑说多不多说少不少。群里经常有人问“AD9361参考设计怎么看”“PetaLinux怎么生成boot.bin”“BPSK怎么调出数据来”所以我决定把整个平台从硬件到软件、从Linux构建到通信Demo的完整链路整理成一篇说明给正在入门或者卡在半路的同学一个相对完整的参考。这篇内容主要面向三类人一是刚拿到AD9361相关板卡、想知道参考设计从哪里看起的初学者二是需要用PetaLinux 2025.1给Zynq构建可启动系统、但目前连boot.bin、boot.scr、image.ub三者分工都还不清楚的朋友三是想用AD9361实现BPSK这类基础调制解调、需要有人把发射接收链路讲透的开发者。文章里所有操作和结论都来自实际项目不是从文档里抄的。1. 平台架构解读AD9361与Zynq这对SDR“黄金搭档”先说清楚一个概念AD9361和Zynq不是简单的“射频前端加主控”的关系。理解了这一点后面看参考设计、改驱动、调性能才不会走偏。1.1 AD9361是一颗怎样的射频芯片AD9361是ADI推出的射频捷变收发器频率范围覆盖70MHz到6GHz带宽从200kHz到56MHz可调内部集成了12位ADC和DAC、混频器、滤波器、AGC自动增益控制以及完整的发射和接收链路。也就是说从天线端进来的模拟信号到数字基带IQ数据中间那一大堆射频器件基本都集成在芯片内部了。这颗芯片出来之后软件无线电的门槛被拉低了一大截。以前做射频收发射频前端要自己搭混频本振要自己设计AGC要自己写算法。用AD9361之后大部分射频问题被芯片内部的架构消化掉了你只需要通过SPI配置寄存器然后从数字接口读写IQ数据就行。不过这里有个很容易被忽略的点AD9361虽然集成了很多功能但它不是一个“即插即用”的芯片。它的数字接口有LVDS和CMOS两种模式数据位宽可以配成12位、16位还支持单端和差分这些配置必须和FPGA侧的时序严格匹配否则采出来的数据全是乱的。1.2 Zynq在系统里到底干什么活Zynq-7000系列是Xilinx现在是AMD的异构SoC内部集成了双核ARM Cortex-A9处理器和一块7系列FPGA。ARM那侧叫PSProcessing SystemFPGA那侧叫PLProgrammable Logic两者通过AXI总线互联。在这套SDR系统里Zynq承担的工作很明确PL负责和AD9361的时序接口对接把高速IQ数据通过DMA搬运到内存或者从内存搬出来发往AD9361PS则跑Linux系统负责控制逻辑、协议栈、网络通信、用户应用程序。为什么要这样分工而不是用一颗纯FPGA或者一颗高性能ARM纯FPGA做数字信号处理强但跑协议栈和网络太痛苦纯ARM做控制强但AD9361这种高速并行数据接口对CPU来说太吃力。Zynq正好把两件事分开让专业的人干专业的事。1.3 主流硬件形态与参考设计来源目前最常见的组合是ADI官方的AD-FMCOMMS3-EBZ射频FMC板卡搭配ZedBoard或者ZC706这类带FMC接口的Zynq载板使用。FMCOMMS3就是一片AD9361加上射频前端电路通过FMC连接器把数字IQ数据和控制信号连到Zynq的PL侧。如果是自研板卡通常会把AD9361和Zynq放在同一块PCB上用LVDS差分对直接连接省掉FMC连接器。这种做法的好处是信号完整性更好、成本更低但对硬件设计能力要求更高特别是在时钟和电源设计上。参考设计的获取渠道主要有两个一个是ADI官方的HDL参考设计仓库里面包含了AD9361的FPGA IP核、DMA控制器、完整的Vivado工程另一个是Xilinx/AMD官方的PetaLinux BSP里面包含了设备树、内核配置、U-Boot配置等Linux侧的文件。两套东西配合起来才能构成一套从硬件到软件都能跑的完整参考设计。2. 参考设计文件深度拆解从HDL到Linux驱动很多人拿到参考设计之后的第一反应是打开Vivado点综合然后发现工程巨大、文件巨多完全不知道从哪看起。其实参考设计里的东西是分层组织的每一层解决一个不同的问题。2.1 参考设计里到底有哪些文件先看硬件设计部分。ADI提供的硬件参考设计通常包括原理图、PCB Layout、BOM表格式可能是Cadence或者Altium。拿到原理图之后我建议你先看三处第一AD9361的数字接口连到了FPGA的哪个Bank电平标准配的是LVDS还是CMOS第二AD9361的SPI控制接口挂在哪个控制器上这个决定了Linux设备树里SPI节点的写法第三时钟树AD9361的参考时钟是来自板上有源晶振还是Zynq输出的时钟这关乎频率同步和相位噪声。再看HDL部分。ADI的HDL仓库里的核心是axi_ad9361这个IP核它负责把AD9361的数字接口时序转成AXI4-Stream接口另外还有axi_dmac负责把数据从PS内存和PL之间做DMA搬运。整个数据通路是AD9361物理引脚 - axi_ad9361接口逻辑 - FIFO - axi_dmac - AXI总线 - PS内存。最后是Linux侧包括设备树源文件DTS、内核驱动配置、U-Boot配置。设备树里描述的是AD9361挂在哪条SPI总线上、中断连到哪个引脚、DMA通道是哪个这些信息必须和HDL工程里的实际连接完全对应。2.2 从驱动到应用的数据流路径Linux侧AD9361的驱动在早期版本位于drivers/staging/iio/adc/ad9361.c虽然挂着staging的标签但稳定性其实很好。驱动基于IIOIndustrial I/O框架工作向上注册成IIO设备节点。用户空间可以通过IIO的属性文件配置频率、带宽、采样率通过iio_readdev、iio_writedev这类工具读写IQ数据。这里我想强调一个很多人不太理解的点AD9361的实时数据流其实不经过CPU。数据从AD9361出来之后经过FPGA里的DMA直接写到内存缓冲区应用层读数据是直接从这块内存里拿CPU只是在搬运DMA描述符和处理元数据。所以即使Zynq的ARM主频只有667MHz照样能跑几十MSPS的采样率数据就是因为CPU没有参与逐样本处理。如果要做实时性要求更高的应用比如突发通信或需要精确时间戳的系统可以考虑在PL侧加入自己的信号处理逻辑在数据写入DMA之前先做滤波、下变频、解调等操作这样能大幅降低数据率和CPU负载。2.3 借鉴参考设计做自研板卡的几个关键点参考设计最大的价值不只是“能跑”而是告诉你一套经过验证的工程化做法。我自己的经验是自研板卡时不要轻易偏离参考设计尤其是以下几个地方第一AD9361的数字接口数据和时钟的PCB走线长度匹配很关键LVDS差分对的等长控制直接决定高速数据能否稳定采样。参考设计里的PCB约束文件可以直接拿来用这会省掉很多信号完整性上的麻烦。第二AD9361的电源设计要特别重视。芯片内部有多个电源域模拟电源和数字电源要分开电源纹波会直接影响射频性能。参考设计里的电源方案是经过验证的不要为了省成本随便换LDO。第三器件树里的引脚配置要仔细核对。很多自研板卡会为了布线方便调整引脚但设备树里没跟着改结果SPI不通或者中断不对这种问题查起来特别费时间。3. PetaLinux 2025.1构建全流程boot.bin、boot.scr与image.ub是怎么来的介绍完硬件平台和参考设计接下来进入软件实操环节。这一部分我会按PetaLinux 2025.1的实际构建流程来写把boot.bin、boot.scr、image.ub这三个文件的生成过程和作用讲透。3.1 环境准备版本匹配是第一道坎PetaLinux的版本匹配问题是新手遇到的第一个大坑。PetaLinux 2025.1要求对应的Vivado版本必须是2025.1两者版本对不上在导入硬件描述文件时大概率会报错或者产生不可预期的行为。操作系统方面PetaLinux 2025.1官方支持Ubuntu 22.04但实际上在Ubuntu 20.04上也能跑只是需要手动解决一些依赖库的版本问题。建议直接用Ubuntu 22.04的干净系统省心很多。另外要注意PetaLinux安装时要求使用bash而不是dashUbuntu默认的/bin/sh是指向dash的需要先执行sudo dpkg-reconfigure dash并把默认shell切到bash。磁盘空间至少准备100GB内存16GB以上。构建过程中会同时处理内核、U-Boot、rootfs资源不够的话构建时间和成功率都会受影响。PetaLinux安装完成后用source /opt/petalinux/2025.1/settings.sh把环境变量加载进来然后执行petalinux-version确认安装成功。这一步做完环境才算真正准备就绪。3.2 创建PetaLinux工程并配置内核获取硬件描述文件有两种途径一是从板卡厂商的BSP包里获取ADI的官方BSP会附带完整的FMCOMMS3参考设计二是自己用Vivado打开HDL工程先综合、实现并导出硬件描述文件XSA文件。以ADI参考设计为例官方仓库里提供了完整的Vivado工程打开之后直接Run Synthesis、Run Implementation然后导出XSA。导出时记得勾选“Include bitstream”这样生成的XSA里才会包含可配置FPGA的比特流。拿到XSA文件后创建PetaLinux工程的命令如下petalinux-create -t project --name ad9361_sdr --template zynq cd ad9361_sdr petalinux-config --get-hw-description/path/to/xsa执行配置界面后有几项需要重点检查。在Subsystem AUTO Hardware Settings里确认AD9361相关的设备树自动生成是否正确在Image Packaging Configuration里确认内核镜像格式是uImage还是Image在U-Boot Configuration里确认U-Boot版本和配置。内核配置用petalinux-config -c kernel进入这里至少要确认AD9361的驱动是否编译。如果用的是ADI官方内核驱动通常已经默认开启。自研内核的话需要检查CONFIG_AD9361是否设置为y或m。设备树是这套系统里最需要仔细核对的部分。打开工程里的project-spec/meta-user/recipes-bsp/device-tree/files/system-user.dtsi检查SPI节点是否指向AD9361、DMA通道是否对应HDL里的axi_dmac。ADI的BSP通常已经自动配置好但如果你改了引脚或连接这一处必须跟着改。3.3 打包boot.binbootgen和FSBL的配合boot.bin是Zynq上电后由BootROM加载的第一个镜像文件它内部按顺序打包了三样东西FSBLFirst Stage Boot Loader、FPGA比特流、U-Boot镜像。FSBL的作用是完成PS侧的最基本初始化比如DDR控制器、时钟、MIO引脚配置然后把FPGA比特流加载到PL侧最后跳转到U-Boot。FSBL本身不是手工写的而是由Vitis根据硬件平台工程自动生成的C工程编译出来的PetaLinux构建过程中会自动生成并编译fsbl.elf。在PetaLinux里生成boot.bin的命令是petalinux-package --boot --fsbl --fpga --u-boot --force这个命令会自动在images/linux/目录下查找fsbl.elf、system.bit或system.bit.bin和u-boot.elf然后调用bootgen工具底层就是Xilinx的Bootgen把它们打包成BOOT.BIN。如果构建过程没有报错生成的BOOT.BIN可以直接用于SD卡启动或QSPI烧写。遇到“failed to get fsbl file”这类报错大概率是Vivado导出XSA时没有包含FSBL相关文件或者工程目录里缺少fsbl.elf。解决办法是检查XSA是否完整然后重新执行硬件配置。3.4 生成boot.scr与image.ubboot.scr是U-Boot的启动脚本本质是一个被mkimage工具封装过的文本脚本。正常情况下文件内容类似下面这样echo Loading image.ub... load mmc 0:1 0x10000000 /image.ub bootm 0x10000000load命令把image.ub从SD卡的FAT分区设备mmc 0:1加载到内存地址0x10000000然后bootm命令启动内核镜像。PetaLinux构建时会在images/linux/里自动生成boot.scr如果你需要修改启动参数可以直接编辑脚本源文件然后手动用mkimage重新生成。image.ub则是把Linux内核、设备树、根文件系统如果需要打包合并成一个镜像文件。PetaLinux生成image.ub的方式是petalinux-package --image --format ub --kernel --dtb --ramdisk如果不需要把rootfs打进image.ub可以不加--ramdisk这样image.ub里只有内核和设备树rootfs放在SD卡的ext4分区里由内核通过设备树里的chosen节点指定的root参数挂载。构建完成后images/linux/目录下会有BOOT.BIN、boot.scr、image.ub三个关键文件另外还有uImage、system.dtb、rootfs.tar.gz等中间产物这些就是后续制作SD卡要用到的原料。3.5 三个镜像文件的启动分工这里用一张表把三者的关系列清楚方便对照记忆文件加载阶段实际作用boot.binBootROM启动后第一步包含FSBL比特流U-Boot完成PS初始化、加载FPGA配置、启动U-Bootboot.scrU-Boot启动后执行告诉U-Boot去哪里找内核镜像以什么参数启动image.ubU-Boot根据boot.scr加载包含Linux内核和设备树决定系统启动后的硬件描述三个文件是串行衔接的关系BootROM - FSBL - U-Boot - boot.scr - image.ub - Linux内核这一条链路走完系统才真正启动起来。任何一个环节缺失或损坏都会导致启动失败但失败的现象各不相同后面我会单独写一节排查思路。4. 从零制作可启动SD卡与Zynq启动流程系统构建好之后下一步就是把镜像写进SD卡让Zynq从SD卡启动Linux。这一节内容看起来简单但很多人恰恰是在这里卡住启动日志刷到一半就停了或者根本没有任何输出。4.1 SD卡分区方案与格式化Zynq从SD卡启动时BootROM会先读取SD卡第一个分区里的BOOT.BIN所以第一个分区必须是FAT格式且包含BOOT.BIN。建议的分区方案是第一个分区做FAT32大小建议512MB到1GB存放BOOT.BIN、boot.scr、image.ub第二个分区做ext4大小根据rootfs需要决定一般4GB到8GB足够用于存放根文件系统。用fdisk或parted分区的时候注意调整分区类型并格式化。具体命令如下sudo fdisk /dev/sdX # 删除所有旧分区 # 新建分区1类型为 W95 FAT32 (LBA) (0x0c) # 新建分区2类型为 Linux (0x83) # 写盘退出 sudo mkfs.vfat -F 32 /dev/sdX1 sudo mkfs.ext4 /dev/sdX2分区对齐的问题容易被人忽视但会实际影响性能。建议分区起始扇区设为20481MB对齐这对SD卡这种闪存介质来说能够减少读写放大延长使用寿命。4.2 一步步写入镜像文件分区完成后剩下的就是文件拷贝工作。FAT分区里的拷贝直接挂载后复制即可sudo mount /dev/sdX1 /mnt/boot sudo cp BOOT.BIN /mnt/boot/ sudo cp boot.scr /mnt/boot/ sudo cp image.ub /mnt/boot/ sync sudo umount /mnt/bootrootfs的写入稍微讲究一点。PetaLinux构建完成后生成的是rootfs.tar.gz需要在ext4分区里解包sudo mount /dev/sdX2 /mnt/rootfs sudo tar -xzf /path/to/rootfs.tar.gz -C /mnt/rootfs sync sudo umount /mnt/rootfsrootfs.tar.gz解包的时候注意必须使用root权限否则文件的所有者和权限会出错系统启动后可能会出现各种奇怪的权限问题。另外解包前确认一下ext4分区是否为空或者已经格式化避免残留文件导致启动异常。拷贝完成后使用sync命令确保数据完全写入再拔出SD卡。很多人图快拷贝完直接拔卡结果BOOT.BIN只写了一半启动时bootrom能响应但加载FSBL失败这种问题排查起来特别冤枉。4.3 启动模式引脚设置Zynq-7000的启动模式由BOOT_MODE[3:0]四个引脚的电平决定。不同的板卡丝印不一样有些板子写的是拨码开关位置有些直接标SD、QSPI、JTAG。以最常见的Zynq-7000为例SD卡启动对应BOOT_MODE[3:0]0010即四个引脚中只有BOOT_MODE[1]拉高其余拉低。需要特别注意的是不同厂家的板卡引脚定义可能做了翻转所以设置拨码开关前一定要看原理图确认。设置完成后通过板卡上的串口连接Zynq的UART通常是UART0或UART1波特率115200上电后应该能看到U-Boot的启动日志。如果串口完全没有输出优先检查启动模式引脚是否设置正确、串口电平是否匹配、波特率是否选对。4.4 启动失败现象的快速定位这里整理几种常见的启动失败现象和排查方向现象可能原因排查方向完全没有串口输出启动模式引脚配置不对、电源异常、BOOT.BIN缺失检查拨码开关、测量电源、确认SD卡FAT分区打印一串后停在U-Boot提示符boot.scr没有被自动执行、脚本内容有误手动输入run bootcmd或source命令手动加载U-Boot提示找不到image.ubFAT分区里文件名不对或没有拷贝成功确认文件名是image.ub而不是image.ub.bin内核解压后Kernel panicrootfs挂载失败、设备树root参数错误检查设备树里的bootargs确认root/dev/mmcblk0p2启动过程中网络相关服务卡住设备树网口配置和实际硬件不一致检查是否有网口硬件必要时禁用对应设备树节点还有一个很隐蔽的问题U-Boot环境变量里可能保存了上一次的启动参数。如果之前用TFTP启动过bootcmd已经被改动插上SD卡之后U-Boot不会主动执行SD卡启动脚本。这种情况下在U-Boot提示符里执行env default -a恢复默认环境变量然后saveenv保存复位后再试。5. 用AD9361实现BPSK调制解调从射频链路到比特流系统跑起来之后最让人兴奋的事情就是真正用AD9361发数据、收数据。热词里提到的“AD9361实现BPSK调制解调出数据”是很多人都会做的第一个通信Demo因为BPSK原理简单、实现门槛低但要真正调通收发链路还是有不少细节需要注意。5.1 为什么拿BPSK作为第一个通信DemoBPSK是二进制相移键控用两个相差180度的载波相位来代表0和1。从实现角度来说BPSK的基带映射非常直观发送符号1对应I路幅度为1发送符号0对应I路幅度为-1Q路全为零。接收端只需要判断I路数据的正负就能完成判决不需要复杂的均衡和信道估计。选择BPSK做第一个Demo还有一个重要原因它对载波同步的要求相对宽松。BPSK信号的星座点只有两个即使存在一定的频率偏差和相位旋转只要偏差不是太大通过简单的相位校正就能正确解调。相比之下QPSK或更高阶的QAM对相位精度要求高得多第一次调试就上高阶调制很容易让人崩溃。5.2 发射端IQ基带数据如何变成射频信号发射端的数据流是用户空间的基带IQ数据 - PL侧DMA - axi_ad9361 IP - LVDS接口 - AD9361内部DAC - 射频输出。实际操作中最简单的方式是用libad9361-iio库或者直接写IIO设备节点。配置发射频率、采样率、带宽这些参数时用iio_attr命令即可iio_attr -c ad9361-phy TX_LO frequency 2400000000 iio_attr -c ad9361-phy TX_SAMPL_FREQ 40000000 iio_attr -c ad9361-phy TX_RF_BANDWIDTH 20000000 iio_attr -c ad9361-phy ensm_mode tx配置好射频参数后生成BPSK基带数据。假设符号速率为1Msps每个符号在40MSPS的采样率下对应40个采样点。映射关系是比特1映射为1比特0映射为-1每个符号的采样点都填充这个恒定值。如果要做成型滤波可以让跳变沿更平滑一些最简单的做法是做一个升余弦滚降滤波但第一步验证链路时可以不加。接着用iio_writedev把数据写入设备节点。写入数据时注意格式是交错的I和Q也就是每个采样点两个int16先I后Q。Q路全写0即可。发射链路是否真正出信号可以用频谱仪或者另一台SDR接收机来验证。如果没有频谱仪我常做的一个验证方法是把发射天线和接收天线隔开一段距离直接用同一块板卡的RX通道接收自己发射的信号虽然会有明显的耦合和反射但足以验证链路是否打通。5.3 接收端从射频回推到比特流接收端的配置和发射端对称iio_attr -c ad9361-phy RX_LO frequency 2400000000 iio_attr -c ad9361-phy RX_SAMPL_FREQ 40000000 iio_attr -c ad9361-phy RX_RF_BANDWIDTH 20000000 iio_attr -c ad9361-phy ensm_mode rx然后用iio_readdev把接收到的IQ数据读出来iio_readdev -s 2000000 -b 1024 ad9361-phy | hexdump读出来的数据是原始的IQ采样值直接看是看不出调制信息的需要经过几步处理才能恢复出比特流。第一步是去除DC偏置。AD9361的模拟链路会引入直流偏置尤其是在高增益的情况下。最简单的处理方法是数据减去均值但更稳妥的做法是用一个高通滤波器或者直流估计器因为持续直流的水平会随着增益和温度变化。第二步是载波频率校准。即使发射和接收配置了相同的本振频率两边的晶振误差也会导致残余频偏表现为星座点缓慢旋转。BPSK的频偏检测可以通过估计I和Q路的互相关来做或者简单一点用FFT找信号频谱峰值和期望中心频率的差值。第三步是符号同步。接收端的采样时钟和发射端的符号时钟并不完全同步需要从采样数据中找出每个符号的最佳采样点。最简单可行的方式是先做匹配滤波然后在每个符号周期内取能量最大的点作为判决点。完成这三步之后对I路数据做符号判决大于0判为1小于0判为0然后和发射端原始比特对比误码率不为零基本就说明解调链路已经跑通了。5.4 数据调度与缓存设计经验实测过程中最容易遇到的问题就是数据断流。用iio_readdev从用户空间连续读大量数据时如果DMA缓冲区没有配置好很容易出现丢数据或者流中断的情况。我的经验是AD9361的数据接口一旦开始传输PL侧的DMA必须始终保持“水箱里有水”的状态。接收方向DMA描述符要预先准备好否则进来的数据无处安放只能丢弃发射方向数据缓冲区必须持续供应否则DMA读到空缓冲会直接停止传输导致载波出现间隙。实际工程中比较稳妥的做法是在PL侧做乒乓缓冲也就是两组DMA缓冲区交替填充和读取。一组在写的时候另一组可以被应用读走双缓冲能有效掩盖用户空间调度的抖动。另外DMA传输长度和缓冲数量要配得足够大。默认配置可能只有4个缓冲区每个缓冲区只有4KB在40MSPS下顶多撑几毫秒稍微有一点调度抖动就会断流。把这个配置改成16个缓冲区、每块128KB数据流的稳定性会明显改善。如果用户空间处理不过来可以考虑在PL侧先做下变频和抽取把数据率降下来再送DMA。比如接收40MSPS的数据先在FPGA里做数字下变频抽取到5MSPSCPU的负担会小一个数量级。6. 烧写、USB通信、存储选型与上位机扩展中的高频踩坑记录最后一章把参考设计落地过程中几个频率最高的报错和方案问题整理出来全部是我或者群友实际遇到过的案例。6.1 Flash烧写时的“valid FSBL is required”问题在Vitis或Vivado SDK里使用Program Flash功能时如果打开烧写界面发现FSBL文件一栏是空的点Program会报“A valid FSBL file is required for flash operation”。这个报错的原因非常直白烧写Flash需要一个FSBL来初始化DDR和Flash控制器但工程里没有指定或者指定的路径不存在。解决办法是在Vitis里先创建一个FSBL工程。创建流程是在platform工程上右键New - Application Project模板选择“Zynq FSBL”。编译完成后会生成fsbl.elf文件然后在Program Flash界面里指定这个文件。用命令行方式的话可以用program_flash工具program_flash -f BOOT.BIN -offsets 0 -flash_type qspi-x4-single -fsbl fsbl.elf这里的-fsbl参数就是用来指定FSBL的。如果是烧写NAND Flashflash_type要换成对应的nand型号参数。另外提醒一句烧写QSPI时地址偏移-offsets 0对应的是QSPI Flash的起始地址不要在偏移上设置错否则系统会直接从错误位置启动。6.2 Zynq裸机USB通信基于libusb的实用方案很多项目会要求Zynq在裸机环境下通过USB和上位机通信。Zynq-7000的PS自带USB控制器支持Host和Device模式但在裸机上写USB协议栈比较复杂最实用的做法是让Zynq作为USB Device枚举成一个自定义的Bulk传输设备上位机用libusb直接通信。裸机USB工程的核心工作是配置USB控制器、初始化ULPI PHY、注册设备描述符和端点。这里常踩的坑是ULPI PHY的时钟问题PHY需要60MHz的参考时钟Zynq的MIO可以输出这个时钟但必须在FSBL或者BSP里正确配置MIO引脚和时钟控制器。上位机用libusb的例子很简单初始化、打开设备、claim interface、bulk transfer四个步骤就能完成一次读写libusb_init(NULL); libusb_open_device_with_vid_pid(handle, VID, PID); libusb_claim_interface(handle, 0); libusb_bulk_transfer(handle, EP_OUT, buf, len, actual, 1000); libusb_bulk_transfer(handle, EP_IN, buf, sizeof(buf), actual, 1000);实际使用中Bulk传输的速率上限大概在30-40MB/s左右对于控制指令和低速数据完全够用。如果要更高的吞吐率就得用USB高速的同步传输或者换上位机方案了。6.3 Zynq支持哪些NAND Flash选型与ECC配置被问到最多的问题是“Xilinx Zynq支持的NAND Flash型号有哪些”。Zynq-7000内置的NAND控制器符合ONFI 2.2规范理论上支持大多数符合此标准的NAND芯片。选型时重点确认三点接口电压是1.8V还是3.3V、是否支持ONFI同步模式、Page大小是2KB还是4KB。实际项目中大量使用的型号是Micron的MT29F系列比如MT29F2G08、MT29F4G08等这些芯片在Zynq上被Vivado的FSBL和U-Boot原生支持兼容性问题最少。选型验证时可以把芯片焊到板子上先用FSBL测试能否正确识别再用U-Boot的nand info命令确认实际容量和参数。NAND Flash和QSPI Flash不同它有坏块管理、ECC校验这些额外的要求。在Vivado里配置NAND时ECC算法、扇区大小都要和芯片的数据手册对齐。如果ECC配置错了读出来的数据会频繁报错表面上看是Flash坏了实际上是没有按芯片要求的纠错算法来读。6.4 Qt串口库交叉编译补充很多基于Zynq的Linux应用会用到Qt做上位机或者人机界面其中串口通信是最常见的功能之一。Qt的SerialPort模块在PC上很好用但交叉编译到Zynq时经常会遇到找不到库文件的问题。原因在于SerialPort模块不是Qt核心库的一部分需要单独编译。交叉编译时会遇到Project ERROR: Unknown module(s) in QT: serialport之类的报错。解决办法是在源码构建Qt时确保SerialPort模块被包含进去。Qt配置时加上-module-serialport或者确认configure时的输出日志里出现了serialport关键字。已经编译好的Qt交叉工具链如果缺了SerialPort模块不用整个重编。可以单独进到Qt源码的qtserialport目录用同样的交叉工具链执行qmake和make然后把生成的库文件拷贝到目标系统的Qt库目录。手动拷贝时记得检查libqtserialport.so的软链接关系否则动态加载会失败。最后再分享一个我自己在实际调试中的习惯不管是用参考设计还是自研板卡拿到板子的第一件事不是跑通信Demo而是先用最小系统把启动链路打通再用Loopback模式测试AD9361的数字接口是否正常。所谓Loopback模式是AD9361内部把发射数据直接环回到接收端不经过射频这能排除射频链路的干扰快速验证FPGA时序和DMA搬运是否正常。链路通了之后再开射频整个系统的排错范围会急剧缩小不至于一出问题就从头怀疑硬件。这套从参考设计到实际部署的流程我重复用了很多个版本每次都能在最短时间内定位问题希望对你有用。
02
RELATED NEWS

相关资讯

更多网站建设与数字化升级内容

03
WHY YAOTU

想打造同款高转化官网?

懂行业、懂生意,从建站到增长一站式陪跑

场景化定制

不做模板站,围绕你的业务场景量身设计,小众不撞款。

营销型架构

以转化目标组织内容与路径,让官网真正带来询盘。

全周期服务

设计、开发、运营、运维一体,上线只是开始。

免费获取你的建站方案

留下需求,专属顾问 24 小时内为你输出方案建议。