十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

复旦微FMQL45T900国产化替代实战:从Zynq迁移的完整指南

复旦微FMQL45T900国产化替代实战:从Zynq迁移的完整指南 这两年国产化替代的项目一个接一个我上手复旦微FMQL45T900这块芯片的第一感觉可以说既惊喜又熟悉。惊喜的是它的架构几乎死磕Xilinx ZYNQ的路子——PS端四核ARM Cortex-A7PL端可编程逻辑内部AXI高速互联熟悉是因为如果你之前调过ZYNQ那么整个迁移过程就是一套从硬件管脚到启动流程再到驱动适配的翻新工程。这篇文章就是我从项目实战角度整理的完整迁移笔记覆盖方案选型、工具链切换、FSBL/U-Boot启动移植、PS与PL协同调试以及图像采集与高速接口落地时踩过的坑。想在这类国产化ARMFPGA平台做开发的工程师建议直接收藏。1. 迁移前的方案评估FMQL45T900到底对标谁1.1 复旦微FMQL45T900的核心架构速览我用的这颗FMQL45T900单从架构上说完全可以理解为“国产ZYNQ”PS端是四核ARM Cortex-A7PL端是复旦微的FPGA逻辑资源PL与PS之间通过AXI总线桥接配套的DDR控制器、UART、GEM以太网、SD/SDIO、QSPI、I2C、SPI、USB这些外设也全部集成在PS内部。在这颗芯片上跑Linux和裸机程序PC寄存器跳转、中断控制器GIC、定时器这些和Cortex-A7原生的使用方法是一样的。和Xilinx Zynq-7045这类器件相比单看资源数量和接口规格FMQL45T900的PL端处于同一量级做图像采集、信号处理、接口转换这些中规模设计完全够用。需要注意的一点是虽然架构相似但FMQL45T900并不是每一处寄存器地址都和Zynq一致。片上的UART、QSPI、SD、GPIO等外设基地址和Zynq手册里的地址有差异。这一点后面移植驱动时最坑。1.2 迁移之前必须想清楚的三个问题第一确认移植的目标是“硬件兼容替换”还是“重新设计”。所谓硬件兼容替换是希望把原来Zynq板卡上的型号直接换成FMQL45T900保持管脚和板卡基本不变这种模式省板卡改版成本但对封装的引脚定义要求很高。重新设计则是利用FMQL45T900的资源从原理图开始调整灵活度最高工作量也最大。第二评估PL资源占用。迁移之前把你原来Vivado工程里LUT、FF、Block RAM、DSP的数量统计出来再到FMQL45T900对应的器件手册里核对。如果原设计里的DSP使用量逼近上限就要提前考虑把部分算法挪到PS端用ARM算或者优化算法架构。第三摸清外设依赖。如果原设计用了Zynq PS内置的MIG DDR控制器、GEM网口、USB控制器这些硬核外设迁移时就要对比FMQL45T900的PS外设实现方式。比如DDR部分时序参数要根据板卡实际内存颗粒重新配置不是简单地Vivado里改一改芯片型号就行的。2. 开发环境重构从Vivado到Procise/FMSDK2.1 工具链选型与版本选择复旦微FPGA配套的开发环境叫Procise负责PL端的工程管理、综合、布局布线、约束、比特流生成PS端嵌入式软件开发用FMSDK负责FSBL、U-Boot、应用代码的编译与调试。第一次打开Procise的时候熟悉感很强。工程树、约束文件、时序报告、逻辑利用率这些模块布局和Vivado的交互逻辑很相似。实际用下来综合和布局布线的速度中规中矩对于中等规模的图像算法工程一次全编译大概比Vivado慢一些但不至于耽误开发节奏。版本建议用复旦微官方比较新的稳定版本。我踩过的一个坑是旧版Procise对新器件的小批次型号支持不全结果布局布线阶段报奇怪的单元找不到错误换新版工具后问题消失。另外FMSDK基于Eclipse框架如果你之前用过Xilinx SDK里面许多快捷键和工程导入导出逻辑可以直接复用。2.2 工程结构设计与IP移植策略工程结构上Procise同样支持Tcl脚本批处理如果你之前的Vivado工程有比较完善的后仿真、时序约束脚本可以转换成Procise的Tcl语法保留下来。关键的是PL端IP核怎么办。分三种情况第一种纯逻辑的IP比如FIFO、移位寄存器、简单的数学运算这些在Procise的IP核库里通常有对应或替代型号直接重新生成替换就好。第二种高速接口类IP比如MIPI RX、LVDS收发、PCIe、Ethernet MAC这类IP往往和FPGA厂商的硬核高度耦合迁移时要重点看复旦微有没有对应IP或者提供开放的原语级方案。我这次做的MIPI输入链路原先是Xilinx的MIPI CSI-2 IP迁移到FMQL45T900上是用原语状态机重构的。第三种软核CPU类IP比如MicroBlaze核这类没法直接迁移。如果你的原设计里用MicroBlaze做软核控制可以考虑直接把控制逻辑合并到PS端ARM中减少PS与PL的交互复杂度。2.3 交叉编译环境搭建从armcc到arm-linux-gnueabihfFMQL45T900的PS端是Cortex-A7跑Linux的话用arm-linux-gnueabihf-gcc交叉编译器即可常见的选择是Linaro提供的工具链。很多朋友在搜索引擎里搜“arm compiler 5.06”这类关键词这里要多说一句ARM Compiler 5.06是ARM自家面向Cortex-M系列MCU的编译器Keil MDK内置的就是它如果目标是给Cortex-A7上跑Linux做交叉编译用手册里推荐的Linaro GCC更合适。我之前见过一个项目组用错编译器编出来的裸机程序能跑但一接Linux应用就各种段错误排查半天发现是工具链sysroot不匹配。搭建交叉编译环境时我习惯把工具链放在/opt下并配置系统PATH。最关键的是sysroot你交叉编译的应用依赖的libc、libstdc、zlib这些运行库必须和板卡上rootfs里的版本对应否则就会出现“运行时找不到GLIBC_2.28”之类的错误。给一个最基础的编译验证示例export PATH/opt/gcc-linaro-7.5.0-2019.12-x86_64_arm-linux-gnueabihf/bin:$PATH export CROSS_COMPILEarm-linux-gnueabihf- export ARCHarm arm-linux-gnueabihf-gcc -o hello hello.c -static编译完成后通过NFS或者tftp把hello传到板卡上执行打印正常说明环境没问题。如果项目UI是基于Qt的比如热搜里常出现的Qt5.5.10 ARM Linux开发交叉编译时记得加上tslib支持触摸屏和显示设备通过QPA插件linuxfb或eglfs指定。我个人经验Qt5.5.10版本偏老很多显示驱动和OpenGL ES适配都是独立patch迁移到国产ARM平台时要确认对应版本的libQt5Gui、libqlinuxfb等库是否完整。3. 第一块FSBL启动流程完整移植3.1 FMQL45T900启动流程解析FMQL45T900的启动流程和Zynq大体一致上电后芯片内部固化的BootROM先接管根据启动模式引脚的电平状态选择启动介质把BootROM引导程序对应Zynq里的FSBL加载到片上RAM再由FSBL完成DDR初始化、外设初始化、加载U-Boot或裸机应用。启动模式常见的有QSPI Flash启动、SD卡启动、JTAG启动。板卡上一般通过拨码开关配置启动模式。一个需要注意的差异点是启动镜像的格式。Zynq生成的BOOT.bin里包含FSBL、U-Boot、bit流等分区FMQL45T900虽然概念类似但镜像头的魔数、分区表格式不一定相同。我在网上找资料的时候看到不少朋友直接用Zynq的bootgen工具生成镜像写到复旦微板卡里结果启动失败基本都是格式不匹配导致的。3.2 FSBL与DDR初始化的实战FMQL45T900的FSBL工程在FMSDK里创建主要的修改点集中在DDR配置上。DDR的时钟频率、行列地址宽度、Bank数量、时序参数每一项都要和板卡上实际用的DDR颗粒严格对应。修改的思路是找到FSBL工程里的DDR配置头文件对照DDR颗粒的datasheet填写参数。如果板卡DDR频率从1066Mbps调整到1600Mbps还要检查PS端DDR控制器的时钟源配置保证PLL输出频率在芯片支持的范围内。这里分享一个排查DDR问题的经验FSBL阶段如果DDR配置错误现象很多样有的表现为U-Boot直接卡死有的表现为Linux内核启动早期报“undefined instruction”异常。我习惯用JTAG调试器连接板卡在FSBL的main函数入口处查看PC指针是否还在预期地址如果PC值跑飞或者反复触发data abort优先怀疑DDR参数不对。3.3 U-Boot适配与调试U-Boot使用起来比FSBL复杂一些。需要准备的东西包括对应芯片的defconfig、设备树文件、U-Boot源码中关于复旦微特定外设的驱动。最初的调试阶段我建议先用tftp从网络加载内核和rootfs这样每次修改内核不需要反复烧写存储介质。U-Boot环境变量设置大致如下setenv ipaddr 192.168.1.100 setenv serverip 192.168.1.10 setenv bootcmd tftp 0x20000000 zImage; tftp 0x21000000 fmsdk.dtb; bootz 0x20000000 - 0x21000000 saveenv如果U-Boot阶段串口没有打印优先检查串口引脚配置和时钟。FMQL45T900的UART外设引脚分配和Zynq不完全一样设备树里的uart节点地址也要跟着改否则内核起来后ttyAMA0不出数。内核阶段我建议在设备树里先禁用不用的外设比如SATA、USB、DisplayPort减少调试干扰。把网络、串口、SD先跑通再逐步放开。4. PS与PL协同的关键细节4.1 AXI互联与地址映射PS与PL的数据交互主要靠AXI总线。FMQL45T900内部有多个AXI接口分别提供不同的带宽和延迟特性。PL端自定义外设通常通过AXI GP接口映射到PS地址空间。迁移过程里原来Zynq工程中PL外设的基地址很可能变了因为PS外设地址空间和Zynq不同。修改时注意设备树里的reg属性、驱动里的ioremap地址、以及U-Boot或裸机程序里访问PL外设的地址三处要一致。我实际遇到的一个问题原驱动里硬编码了0x43C00000这个Zynq默认的AXI外设地址换到FMQL45T900后该地址被其它外设占用驱动一访问就直接oops。改成设备树动态获取资源后解决。这类硬编码地址问题在代码审查的时候要多留个心眼。4.2 复位与时钟设计先解决亚稳态PL端的复位信号问题可以说是FPGA迁移后最容易爆发的一类毛病。很多同学在Xilinx平台上习惯直接使用外部按键复位信号驱动内部逻辑的复位网络迁移到FMQL45T900后由于时钟和复位的相位关系改变复位释放时刻不稳定就会触发亚稳态。标准的做法是“异步复位、同步释放”。简单说就是把外部异步复位经过两级触发器同步后再作为系统复位使用。下面是一个经典的处理代码reg sync_rst_n_1, sync_rst_n_2; always (posedge clk or negedge rst_n) begin if (!rst_n) sync_rst_n_1 1b0; else sync_rst_n_1 1b1; end always (posedge clk or negedge rst_n) begin if (!rst_n) sync_rst_n_2 1b0; else sync_rst_n_2 sync_rst_n_1; end assign sys_rst_n sync_rst_n_2;复位信号这一条我在文章里把它单独拎出来是因为它太容易出问题又太难排查。重启一百次可能挂一次用示波器又抓不到最后定位到复位释放时间和时钟沿太近操作系统起来后在启动早期随机死机。时钟部分FMQL45T900上PL端的时钟输入、MMCM/PLL的使用方式与Xilinx 7系列的同架构逻辑基本一致。FPGA内部的时钟约束文件XDC/SDC需要根据新的器件名重新做时序约束原来的时钟周期约束可以沿用但I/O延迟和管脚位置必须重新填写。4.3 常见外设踩坑记录QSPI、GEM、UARTQSPI Flash启动是个高频场景。FMQL45T900的QSPI控制器和Zynq QSPI控制器在寄存器级有较大差异不要指望Vivado自动生成的QSPI驱动在复旦微平台上直接编译通过。要确认QSPI Flash的读ID、写状态寄存器、擦除、编程指令是否被当前BSP支持。另一个容易踩坑的地方是Flash写保护。有些Flash默认上电后状态寄存器里写保护位是打开的直接烧写会报擦除失败或写失败。我们一般用烧写工具先发指令关闭写保护再烧写BOOT镜像。GEM以太网部分FMQL45T900的PS端集成的以太网控制器和外部PHY芯片之间的接口模式可以是RGMII或GMII需要和设备树里的phy-mode保持一致。我们项目里出现过U-Boot下ping不通、但Linux下网络正常的情况排查下来发现是U-Boot里PHY驱动没有正确读取芯片地址改成强制指定PHY地址后解决。UART打印乱码也是常见问题。串口波特率不对、基准时钟配置错误都会导致乱码。在设备树里检查clocks属性是否指向了正确的时钟源再量一下板卡上的UART TX波形确认波特率。一般115200和921600这两种波特率下波形规格能看出问题。5. 图像处理与高速接口在FMQL45T900上的落地5.1 MIPI/ISP图像采集链路搭建图像采集是FMQL45T900非常典型的一个应用场景毕竟国产化替代项目中做红外、可见光、多光谱成像的板卡几乎离不开MIPI和ISP。MIPI RX的接收链路原先是Xilinx的MIPI CSI-2 IP核内部包含D-PHY物理层和协议层解析。迁移到FMQL45T900后如果IP库中没有对应核就要用Cmos Sensor输出的RAW数据直接进PL由PL端逻辑完成D-PHY差分接收、字节对齐、Lane合并、数据包解析得到RAW图像数据。ISP处理链路里去马赛克Demosaic是核心模块。Sensor输出的是Bayer格式的RAW图每个像素只有一个颜色通道要去马赛克插值成RGB三通道。实现去马赛克有多种算法最基础的双线性插值后续可以做边缘自适应、甚至利用卷积神经网络。在FPGA里做这部分处理复杂度高的是资源与实时性的权衡。关于FPGA图像处理里的定点数这里多说一句。很多算法在ARM上用浮点算一遍得到结果迁移到PL里就习惯性地想用浮点IP资源开销立刻就上去了。正确的做法是先做定点化分析确定整数位宽和小数位宽用定点运算替代浮点运算。和ARM上用IQmath做定点数学运算的思路类似只是FPGA里位宽可调灵活度和优化空间更大。5.2 LVDS、信号发生器与外围驱动电路除了MIPILVDS收发也是图像传输和显示接口里的常客。FPGA的LVDS接收需要关注的是差分信号的电平标准、串行化因子、以及时钟恢复方式。LVDS接进来后用IDELAY和ISERDES这类原语做位对齐和字对齐迁移到复旦微平台时要注意原语的命名和参数可能不同从7系列同构逻辑来看多数原语用法可以对照Xilinx的UG471等文档来适配。有些项目里还会用FPGA做信号发生器通过DDS原理生成正弦波、方波、扫频信号等。DDS的实现核心是相位累加器和查找表纯逻辑代码在FMQL45T900上几乎不用改动就能综合。这个模块比较适合作为迁移后PL设计的“冒烟测试”综合布线通过、上板后能正常输出波形说明PL端的时钟和基本逻辑已经跑通。外围驱动方面如果PL的IO要驱动继电器、风扇这类大电流器件中间需要达林顿管、MOS管或专用驱动芯片。这里要注意FPGA IO的电平标准、最大灌电流/拉电流参数以及上电时序。FMQL45T900的IO上电时序和Xilinx 7系列类似如果FPGA核心电源和IO电源在板卡上不是同时上电PL端的配置引脚状态会不确定有可能导致外部器件在启动瞬间误动作。设计时可以在达林顿管基极加下拉电阻保证FPGA未配置前输出被拉到确定电平。6. 迁移适配中的高频问题速查表下面这组问题基本覆盖了我这次迁移过程中遇到的高频问题按“现象-原因-排查方向”整理成表工程现场可以直接对照参考。现象可能原因排查方向FSBL阶段PC指针跑飞DDR参数不匹配、PLL未正确初始化检查DDR颗粒参数、FSBL中的DDR头文件、时钟配置U-Boot无串口打印串口管脚复用、时钟源错误、启动介质选择不对核对设备树引脚配置、检查UART基准时钟频率Linux启动随机死机PL复位亚稳态、电源噪声、DDR时序裕量不足先做异步复位同步释放再检查电源纹波QSPI烧写失败/写保护报错Flash状态寄存器写保护位为1用烧录器发指令解除保护确认指令时序网络ping通但UDP丢包GEM驱动中断未正确注册、MAC地址冲突检查设备树中断配置确认PHY芯片地址图像采集花屏/偏色MIPI lane对齐失败、ISP Bayer通道顺序错误抓取RAW数据检查lane顺序确认Bayer排列方式温度异常风扇不转PWM控制极性错误、IO未配置检查风扇驱动电路电平改用推挽输出交叉编译应用链接报GLIBC版本错sysroot和板卡rootfs libc版本不一致统一两边工具链和运行库版本除了表格里的问题再补充一点关于低功耗调试的经验。搜索里也有人提到“ACPI sleep state suspend disabled”“suspend to arm”这类关键词在把Linux配置成可挂起/恢复模式时需要注意板卡在suspend状态下的DDR自刷新、时钟停振等参数是否被正确配置。国产化板卡由于硬件上可能没有完全复刻参考设计suspend/resume功能经常会出现恢复后网口不通、系统时间漂移等问题。如果不是产品硬性要求建议先关闭suspend能力以减少状态机复杂度。下载器部分我们用的是常规的JTAG调试器例如常见的USBN-2A这类CPLD/FPGA下载器。使用这类下载器时要注意驱动版本和软件版本匹配在FMSDK里如果识别不到芯片IDCODE大概率是驱动没装好或下载器固件版本太旧。换用官方推荐的新版驱动后基本能解决。写在最后做完整个迁移项目之后我最大的体会是国产化替换不是“换个芯片重新编译”而是一个系统工程。工具链的习惯差异、启动流程的格式差异、外设寄存器的地址差异、PL与PS交互时的时序细节每一处都可能在移植的半路冒出来咬你一口。就把这篇当作一份踩坑地图吧能帮你把方向性的问题先绕开剩下的细节文档多翻官方手册多用JTAG实测比什么都强。如果你正准备把Zynq项目迁到FMQL45T900我个人的建议是先跑通最小系统FSBL能起U-BootU-Boot能引导LinuxLinux能稳定跑一天不重启再往上叠加图像、网络、外设这些业务功能。地基打牢了上层再复杂也不慌。
返回列表