ARTICLE DETAIL

资讯详情

深耕商务建站与企业官网运营的一线实战洞察。

复旦微FMQL45T900开发实战:从交叉编译到BSP配置与启动调试全解析

复旦微FMQL45T900开发实战:从交叉编译到BSP配置与启动调试全解析 拿到复旦微 FMQL45T900 核心板的第一周我基本是在查文档、翻论坛、试错、再看文档的循环里度过的。这块板子的定位很明确国产化 ARMFPGA 单芯片方案PS 端双核 Cortex-A9PL 端是大规模可编程逻辑和 Xilinx Zynq-7045 属于同一梯队。但它毕竟不是 Zynq开发环境的搭建链路里藏着不少只有踩过才知道的细节。这篇文章就把我从零开始搭 ARM 开发环境、啃 BSP 配置的全过程整理出来重点覆盖交叉编译工具链的选择、BSP 各组件的作用、从 BOOT.BIN 到内核 rootfs 的完整构建流程以及调试时最容易翻车的几个地方。无论你是刚从 STM32 切到这种异构 SoC还是已经在做国产化替代项目这篇都值得存一份当参考。1. FMQL45T900到底是个什么芯片架构与核心板选型分析1.1 PS与PL双域架构为什么说它是单片系统FMQL45T900 最核心的概念是 PSProcessing System和 PLProgrammable Logic双域架构。PS 端是一颗完整的双核 ARM Cortex-A9 处理器带 NEON 浮点加速、L1/L2 Cache、DDR 控制器、丰富的外设接口UART、SPI、I2C、USB、SDIO、Ethernet 等PL 端则是大规模 FPGA 逻辑资源你可以把它理解成一张可以反复重新配置电路的白纸。这两个域不是各自独立工作而是通过 AXI 高性能总线互联。PS 可以把 PL 里的自定义硬件模块映射成内存地址直接读写PL 也可以主动发起 DMA 访问 DDR甚至给 PS 发中断。所以这颗芯片和普通的 ARM SoC 有个本质区别它不只是CPU 加外设而是CPU 加可重构硬件加速器特别适合通信基带处理、图像采集预处理、高速数据采集、工业控制这类需要贴着硬件做定制的场景。很多从 STM32 转过来的朋友容易有一个误解觉得 FPGA 就是用来代替 CPU 写逻辑的。实际上在 FMQL45T900 里Linux 跑在 PS 端PL 更像是一块听话的加速电路。你写好的 Verilog 模块算出的结果通过 AXI 总线交给 Linux 应用程序读取或者反过来由应用程序下发控制参数。系统架构层面它就是一个标准的 ARM Linux 主机加若干自定义硬件外设。1.2 核心板起步的选型逻辑拿到手的是核心板而不是自己画的底板这个选择在项目初期非常关键。FMQL45T900 的 PS 端对 DDR 的布线要求很高等长、阻抗、参考电压、电源时序任何一环出问题都会导致系统启动不稳定。核心板厂家已经把 DDR3/DDR4 颗粒、电源管理、时钟、启动 Flash、千兆网 PHY 这些难啃的骨头全部做好了并且经过量产验证我在底板上只需要关心怎么把扩展引脚引出来、按什么接口标准设计自己的外设电路。核心板通常引出的接口包括PS 端的 MIO 引脚、PL 端的 HP/HR Bank、JTAG、串口、以太网、USB、SD 卡接口等。我在项目里把 PL 端一部分引脚接到了自研的高速 ADC 子板上PS 端则通过 MIO 接了 LED、按键和一个 RS485 收发器。这样一来硬件设计的工作量主要集中在底板的外设电路和电源上而不用碰最复杂的 DDR 和 PL 配置。有一件事要特别提醒拿到核心板先查清楚它的启动模式拨码和默认串口映射。不同厂家的核心板对 UART0/UART1 的默认映射可能不一样我第一次就因为在错误串口上干等日志浪费了半小时。先把板子附带的硬件手册里关于启动模式、串口、JTAG 的章节读透再上电。1.3 与Zynq-7000生态的关联与边界FMQL45T900 在架构设计上参考了 Zynq-7000 系列很多基础概念FSBL、U-Boot、设备树、bootgen 生成 BOOT.BIN是相通的。这意味着网上大量的 Zynq 开发教程、U-Boot 编译方法、Linux 内核移植经验大部分思路可以直接借用。尤其是 Xilinx 维护的 u-boot-xlnx、linux-xlnx 代码仓库在很多以 Zynq 为蓝本的国产化 SoC 上都能编译通过或小改即可用。但参考不等于照搬。复旦微的工具链和 Xilinx Vivado 并不完全一致硬件描述文件类似 XSA/HSI 的工程导出文件的格式、FSBL 源码的细节、部分外设寄存器地址都可能存在差异。所以正确姿势是用 Zynq 的资料理解框架和原理但最终一切以复旦微配套的《FMQL45T900 软件调试手册》和 BSP 发布包为准。我自己踩过的一个典型坑是直接拿了 Zynq 的 U-Boot defconfig 去编结果串口初始化参数不对启动日志全乱码。后来换了 BSP 自带的 defconfig基本一次通过。2. 开发环境选型的现实考量授权工具链还是开源GCC2.1 三条主流环境路线的横向对比搭建 ARM 开发环境的第一步不是装软件而是想清楚走哪条路。针对 FMQL45T900 这种 Cortex-A9 核我实际比较过三条路线各有各的适用场景。第一是 ARM 官方商业套件也就是 DS-5 配 ARM Compiler 5。这套工具链对 ARM 架构的支持最深入编译优化也好但需要 License。网上很多人找arm compiler 5.06 update 7 (build 960)下载其实都是想绕过授权限制这个我不建议你折腾一方面是合规风险另一方面是后续维护成本高。第二是复旦微/类似 Vivado 的图形化 IDE 完整流程。它会帮你生成 FSBL、设备树、启动镜像比较适合 FPGA 工程师习惯的点按钮式开发。但 IDE 对环境的封装太多一旦启动过程出问题黑盒很难排查而且 IDE 版本和交叉编译器版本经常绑死升级很痛苦。第三条是纯命令行路线Linaro 出品的 arm-linux-gnueabihf- 交叉编译器加上手动编译 U-Boot、内核、设备树、根文件系统。整个过程全部可见、可控、可复现出了问题能顺着 Log 一层层查这是我最推荐的做法也是这篇文章采用的方式。路线工具链来源优点缺点适用人群DS-5 ARM CompilerARM 商业授权架构支持最佳、调试器强大License 贵、环境封闭商业项目正规授权用户图形化 IDE 全流程芯片厂商配套上手快、集成度高黑盒、排错难、版本绑死FPGA 背景工程师Linaro GCC 命令行开源免费全流程可见可控、社区资料多需要 Linux 基础、初期配置繁琐想彻底搞懂 BSP 的嵌入式工程师2.2 为什么我最终选了Linaro GCC路线我选 Linaro GCC 的核心原因就一个可控性。BSP 移植这件事本身就是在跟底层打交道如果工具链也是黑盒出了问题根本分不清是代码问题、编译问题还是链接脚本问题。用开源工具链虽然初期要手敲命令但整个编译过程每一步都清清楚楚。另外一个重要考量是社区生态。Zynq 系列在工业界用得极广几乎所有 BSP 相关问题都能在论坛上搜到解决方案而 Linaro GCC 就是大多数 Zynq 项目默认的交叉编译工具链。FMQL45T900 和 Zynq 在 ARM 内核架构上同源所以这些经验可以直接平移到复旦微平台上。真到了出问题的时候你能搜到的资料、能请教的人都是以这套工具链为基础的。版本选择上建议用 GCC 7.5 或 GCC 8.x 的 linaro 版本太老的 4.9 在编译新版内核时会有兼容问题太新的 12.x 又可能引入额外的 ABI 差异。我最后固定在 gcc-linaro-7.5-2019.12-x86_64_arm-linux-gnueabihf 这个版本上编译 U-Boot、内核、Qt 5.5.10 应用都表现稳定。2.3 交叉编译工具链的安装与自检安装 Linaro GCC 的步骤其实很简单核心是解压、加载 PATH、验证三件事。我习惯把工具链放在 /opt 下这样所有用户都能使用而且目录路径固定后Makefile 里的 CROSS_COMPILE 变量可以一直写绝对路径。# 下载后解压到 /opt包名根据实际版本调整 sudo tar -xJf gcc-linaro-7.5-2019.12-x86_64_arm-linux-gnueabihf.tar.xz -C /opt/ # 添加环境变量建议写到 ~/.bashrc 末尾 export PATH/opt/gcc-linaro-7.5-2019.12-x86_64_arm-linux-gnueabihf/bin:$PATH source ~/.bashrc # 验证工具链可用并确认版本 arm-linux-gnueabihf-gcc -v验证输出里要重点看三行Target 是否为 arm-linux-gnueabihf、gcc version 是否为所选版本、线程模型是否为 posix。确认无误后再交叉编译一个最小可执行文件放到 ARM 板子上试运行。cat hello.c EOF #include stdio.h int main() { printf(FMQL45T900 ARM OK\n); return 0; } EOF arm-linux-gnueabihf-gcc hello.c -o hello file hellofile 命令输出显示 ELF 32-bit LSB executable, ARM, EABI5 就说明编译目标正确。把这个 hello 通过 U 盘或网络传到板子上chmod x 后执行能打印出对应字符串就算环境通了。这一步千万别跳过很多后续 BSP 编译的诡异错误根源都是交叉编译器本身没装好提前验证能省一整天的排查时间。3. BSP配置核心流程从交叉编译到内核与根文件系统3.1 BSP里面到底装了什么BSPBoard Support Package这个名词听起来很抽象实际拆开看就是一套让 Linux 能在特定板卡上跑起来的软件集合。一个完整的 Zynq 类 BSP 至少包含四部分FSBLFirst Stage Boot Loader、U-Boot、Linux 内核、设备树再加上外围的根文件系统和各种驱动模块。FSBL 是芯片上电后第一个由用户控制的程序它负责最基础的硬件初始化尤其是 DDR 控制器的配置和 CPU 频率设置。这块代码通常由芯片厂商以源码形式提供编译出来是一个 ELF 文件。U-Boot 是第二阶段引导程序负责加载内核镜像和设备树到内存然后跳转到内核执行。内核就是 Linux 本身设备树则是一份描述硬件拓扑的说明书告诉内核我有几个串口、DDR 多大、PL 里挂了什么外设分别映射在哪个地址。理解这条链的关键在于每一级 bootloader 只做有限的事然后把手里的控制权交给下一级。FSBL 不需要知道 Linux 是什么只需要把 DDR 初始化好、加载 U-BootU-Boot 不需要知道怎么跑应用只需要把内核和设备树按约定地址放好并跳转。这种模块化设计让每一层都能独立调试这也是为什么我建议你按顺序编译并逐个验证而不是一把梭。3.2 编译U-Boot让第一阶段引导跑通拿到复旦微提供的 BSP 发布包之后里面通常会有 u-boot 源码目录。我的习惯是先看两个文件README 和 configs/ 目录下是否有对应板卡的 defconfig。复旦微 BSP 里一般会带一个类似于 fsm 或 fmql 开头的 defconfig如果没有就找 xilinx_zynq_virt_defconfig 作为基准再手动改。export ARCHarm export CROSS_COMPILEarm-linux-gnueabihf- make distclean make 你的板卡defconfig make -j$(nproc)编译过程如果顺利会在 u-boot 目录下生成 u-boot.elf 和 u-boot.bin。u-boot.elf 是给 FSBL 加载用的u-boot.bin 是裸二进制后面打包 BOOT.BIN 时通常用 .elf。看到 U-Boot ... for FPGA 之类版本号就说明编出来了。这里有个容易忽略的细节U-Boot 的环境变量默认是写死在编译配置里的比如 bootcmd、bootargs、串口波特率。如果你板子的以太网地址、DDR 大小和默认值不同编译前最好先查一下 defconfig 里的 CONFIG_BOOTCOMMAND 和 CONFIG_EXTRA_ENV_SETTINGS把默认 bootargs 里的 console 参数改成你的实际串口设备比如 consolettyPS0,115200。否则后面启动内核时你会遇到串口毫无输出或者乱码的尴尬。3.3 编译内核与设备树PL侧外设怎么暴露给系统内核编译比 U-Boot 稍微复杂一点因为你需要先确定内核版本再考虑配置裁剪。FMQL45T900 的 BSP 基于哪个内核分支就以哪个为准一般 4.19 或 5.4 比较多见。编译前先清理掉之前的配置防止残留的 .config 造成干扰。export ARCHarm export CROSS_COMPILEarm-linux-gnueabihf- make distclean make BSP自带的内核defconfig make -j$(nproc) UIMAGE_LOADADDR0x8000 uImage make -j$(nproc) dtbs编内核的时候UIMAGE_LOADADDR0x8000 是必须的因为 ARM 内核一般以 uImage 格式加载这个地址告诉 U-Boot 把内核放到哪里。dtbs 会生成对应的设备树二进制文件比如 zynq-fmql45t900.dtb在 arch/arm/boot/dts/ 目录下。设备树是 BSP 配置的核心难点。它本质上是给内核看的一张硬件清单。其中 PL 侧的 IP 核比如 AXI GPIO、DMA、自研 IP地址和中断号都是在 FPGA 工程里定义好的需要手动在设备树里添加节点。比如我在 PL 里加了一个 AXI GPIO 模块基地址是 0x40000000中断号是 31设备树里就要写类似的节点/ { amba_pl: amba_pl { compatible simple-bus; ranges; axi_gpio_0: gpio40000000 { compatible xlnx,xps-gpio-1.00.a; reg 0x40000000 0x10000; interrupt-parent intc; interrupts 0 31 4; #gpio-cells 2; gpio-controller; }; }; };很多新手在这里卡住根本原因是没有把 FPGA 工程里的地址分配和 dts 里的 reg 字段对应起来。我建议你在配置设备树之前先回头把自己的 FPGA 工程地址映射 table 打出来逐个核对。这个核对过程虽然繁琐但一旦对错一次后面 Linux 里读外设寄存器全部会是总线错误或者读到 0xffffffff排查起来更痛苦。3.4 根文件系统buildroot与SD卡方案二选一内核和设备树编好之后还缺一个能用的根文件系统。这里有两种主流方式。第一种是用 buildroot 从源码构建一个精简的 rootfs完全可控、体积小适合正式产品。第二种是直接用现成的 Ubuntu/Debian rootfs 包解压到 SD 卡省时省力适合功能验证和日常开发调试。Buildroot 的方式是配置、编译、产物三条命令但它最大的成本在于首次编译要下载大量源码包而且要等很长时间。如果你只是想让系统先跑起来看启动日志建议直接用 ubuntu-base 或 debian rootfs。# 以 ubuntu-base 为例 sudo mkdir -p /mnt/rootfs sudo tar -xJf ubuntu-base-18.04.5-base-armhf.tar.gz -C /mnt/rootfs # 用 qemu-user 进入 rootfs 安装必要软件在 x86 主机上模拟 ARM sudo mount --bind /proc /mnt/rootfs/proc sudo mount --bind /sys /mnt/rootfs/sys sudo mount --bind /dev /mnt/rootfs/dev sudo mount --bind /dev/pts /mnt/rootfs/dev/pts sudo cp /etc/resolv.conf /mnt/rootfs/etc/resolv.conf sudo chroot /mnt/rootfs /bin/bash # 在 chroot 环境里安装软件 apt-get update apt-get install -y network-manager openssh-server vim得益于 qemu-user 的静态模拟能力在 x86 主机上就能直接改 ARM rootfs 里的内容非常方便。这种方式下系统起来之后基本就是一个完整的 Ubuntu 环境可以联网装软件、跑服务对调试效率提升很大。当然代价是可靠性不如 buildroot 精细打磨过的产物所以我的建议是验证阶段用 Ubuntu rootfs 快速跑通产品化阶段再切 buildroot。4. 启动烧写与调试链路把系统真正跑起来的完整过程4.1 Zynq类SoC的启动链BootROM到用户空间的每一步FMQL45T900 的启动流程和 Zynq 一脉相承整体分四步。芯片上电后片内 BootROM 先运行它根据启动模式引脚的电平状态决定从哪里加载 FSBL——可能是 QSPI Flash也可能是 SD 卡或者 JTAG。BootROM 把 FSBL 加载到片内 RAMOCM并跳转执行这一步没有串口日志输出属于静默阶段。FSBL 运行后会完成 DDR 控制器的初始化这是整个启动链里最关键也最容易出问题的一步。DDR 没配置好后续所有代码都无法正常运行。FSBL 接着把 U-Boot 从启动介质加载到 DDR并引导 U-Boot 执行。U-Boot 启动后才会在串口打印出那一行行熟悉的版本信息所以如果你的串口完全没有输出问题大概率出在 BootROM、启动模式、FSBL 或 DDR 配置这几环。再往后U-Boot 根据 bootcmd 环境变量执行启动命令把内核镜像和设备树加载到指定内存地址并跳转。内核接管之后挂载根文件系统然后运行 PID 1init 或 systemd最终进入用户空间弹出一个 root 登录 Shell。整条链路每一级都有明确的输出标志U-Boot 版本号、内核版本号、init 进程启动日志顺着这些标志能很快定位问题出在哪一环。4.2 用bootgen拼装BOOT.BINFSBL、bitstream、U-Boot 三样东西编译好之后需要用 bootgen 工具打包成 BOOT.BIN这是 SD 卡或 QSPI 启动时 BootROM 能直接识别的镜像格式。bootgen 的用法是通过一个 .bif 描述文件来定义打包内容# boot.bif 内容 the_ROM_image: { [bootloader] zynq_fsbl.elf fmql45t900.bit u-boot.elf } # 生成 BOOT.BIN bootgen -image boot.bif -o i BOOT.BIN -w on.bif 文件里的顺序是有讲究的bootloader 关键字标记 FSBL紧接着是 PL bitstream然后是 U-Boot。BootROM 会先加载 FSBLFSBL 会把 bitstream 配置进 PL再启动 U-Boot。如果你的 PL 逻辑需要在 Linux 起来之前就工作bitstream 必须打包在这个位置如果你希望 Linux 起来后用 fpga manager 再动态加载 PL 逻辑也可以不在 BOOT.BIN 里放 bitstream但那样系统启动的早期阶段 PL 就是空白的。一个常见的坑是 bootgen 工具路径不在 PATH 里或者版本和 BSP 要求不一致。建议把 bootgen 的完整路径写到 Makefile 或者打包脚本中并把版本信息记录在 README 里避免换电脑之后打包出来的 BOOT.BIN 行为异常。4.3 SD卡分区与烧写检查SD 卡启动是最方便的开发方式只需要把 BOOT.BIN、内核镜像、设备树、rootfs 按约定放好。SD 卡需要分两个区第一个分区是 FAT32大小建议 500MB 左右存放 BOOT.BIN、uImage、dtb 文件第二个分区是 ext4存放 rootfs 内容。# 假设SD卡设备是 /dev/sdb注意确认设备名别把主机磁盘覆盖了 sudo fdisk /dev/sdb # 删除旧分区创建一个 W95 FAT32 (LBA) 主分区剩余空间做 Linux 主分区 sudo mkfs.vfat -F 32 /dev/sdb1 sudo mkfs.ext4 /dev/sdb2 sudo mkdir -p /mnt/boot /mnt/rootfs sudo mount /dev/sdb1 /mnt/boot sudo mount /dev/sdb2 /mnt/rootfs cp BOOT.BIN /mnt/boot/ cp uImage /mnt/boot/ cp zynq-fmql45t900.dtb /mnt/boot/ cp -ra /mnt/rootfs_orig/* /mnt/rootfs/ sync烧写完别急着拔卡先检查两件事。第一FAT32 分区里的文件名是否和 U-Boot 环境变量 bootcmd 里写的一致比如 U-Boot 里写的是fatload mmc 0:1 0x3000000 uImage那文件名就必须叫 uImage大小写敏感。第二rootfs 分区里关键目录是否完整尤其是 /lib 和 /etc很多系统启动失败都是因为 rootfs 解压不完整或者动态链接器缺失。4.4 串口日志解读与NFS调试串口是嵌入式 Linux 开发的生命线。连接 FMQL45T900 的调试串口一般波特率是 1152008N1无流控。Linux 下用 minicom 或 picocom 都行我更快的是写脚本方式sudo picocom -b 115200 /dev/ttyUSB0上电瞬间就要开始观察串口输出。如果完全无输出先用万用表确认串口电平是否正常、TX/RX 是否接反、板子是否已经处在正确的启动模式。如果只有 U-Boot 输出但内核没起来用 CtrlC 打断 U-Boot手动执行 bootcmd 一步步看日志配合printenv检查环境变量是否被 U-Boot 重置。如果内核起来了但挂载不上 rootfs那要么是设备树里 chosen 节点的 bootargs 没写对要么是 rootfs 分区有问题。调试过程中我强烈建议配一个 TFTP/NFS 网络调试环境。把内核和设备树放到 TFTP 服务器把 rootfs 放到 NFS 导出目录U-Boot 里设置 bootargs 为root/dev/nfs nfsroot192.168.1.100:/srv/nfs/rootfs ipdhcp。这样每次编译完内核和 rootfs 之后不用反复拔插 SD 卡烧写直接重启板子从网络加载就行开发效率翻倍。等全部调通之后再固化到 SD 卡或 QSPI做最终验证。5. 踩坑记录与性能实测给后来者的一组关键参考5.1 坑一DDR初始化失败导致启动中断这是我遇到的第一个重大问题。板子上电后串口完全没输出用 JTAG 连接调试器后发现 CPU 一直停在 FSBL 里 DDR 初始化调用处。FSBL 源码里对 DDR 的配置是一大段寄存器序列这些参数必须和板子上实际焊接的 DDR 颗粒型号、容量、位宽严格匹配。排查过程是先把核心板硬件手册里 DDR 型号和容量找出来再和 BSP 自带的 FSBL 源码中的配置参数对照。发现核心板配的是 1GB DDR3而 BSP 默认配置只初始化了 512MB高地址访问全部异常。解决办法是找到 FSBL 中 DDR 配置的宏定义把地址映射和行/列/ bank 数按实际颗粒数据手册修改同时更新设备树里内存节点的reg 0x00000000 0x40000000为实际容量。这个坑的教训是拿到任何新板子的第一件事一定是核对内存配置。DDR 参数没有通用的默认值只能以板卡手册为准。你抄别人的配置大概率会在启动阶段栽跟头。5.2 坑二交叉编译器版本与内核版本匹配问题有段时间我编译出来的内核一启动就报 undefined instruction 错误有时甚至编完镜像都不能解压。后来查内核文档才发现新版内核4.16默认开了CONFIG_AEABI和各种新的编译选项对编译器版本有最低要求。Linaro GCC 4.9 太老生成的代码在某些指令序列上会和 4.19 内核的期望不一致。解决方案就是换编译器版本直接从 GCC 4.9 升到 7.5。换了之后重新编译内核问题消失。这件事给我一个启示BSP 发布包一般会标注推荐的工具链版本最好严格按照它来。如果不确定优先选社区验证最多、资料最多的中版本编译器不要盲目追求新版本。同时保留好编译器的下载地址和版本号在项目 README 里写清楚换电脑、换同事接手时都能快速复现环境。5.3 坑三PL bitstream加载与fpga managerSPL 方案里 BOOT.BIN 里已经打包了 bitstreamFSBL 会在 U-Boot 之前配置 PL这种方案的好处是硬件逻辑在 Linux 启动早期就绪适合那些需要 PL 立即参与系统的场景。但如果你后续在 Linux 运行过程中需要更新 PL 逻辑就得用 fpga manager 框架。用 fpga manager 动态加载 bitstream 时需要注意 bitstream 的格式。有些厂商的 bitstream 是二进制 .bit但内核 fpga manager 驱动需要的是不带头部信息的 .bin 文件。我在开发中先用 FPGA 工具把 .bit 转换为 .bin再在系统里用fpgautil -b xxx.bin写入 PL或者直接调用 sysfs 接口/sys/class/fpga_manager/fpga0/load。这个环节最常见的错误是加载后 PL 逻辑工作不稳定表现为读到全 0 或者全 1。原因多半是 PL 的时钟没有正确供给或者 PL 配置时 DDR 控制器仍在忙。我最终建议如果项目允许尽量把核心 bitstream 固化在 BOOT.BIN 里运行时的更新需求放在 rootfs 里做全量替换减少动态加载的复杂性。动态加载功能留作后台维护的备用通路即可。5.4 Qt for ARM Linux开发的快速路径很多使用 FMQL45T900 的项目都会涉及人机界面Qt 是 ARM Linux 上的主流选择。构建 Qt 交叉编译环境有两种方式一种是用 buildroot 直接构建带 Qt 的 rootfs适合最终产品另一种是单独交叉编译 Qt 库部署到目标板适合在 x86 主机上开发 Qt 应用。Qt 5.5.10 配 arm-linux-gnueabihf 是一套验证过的组合。交叉编译 Qt 前要确保工具链支持 ARMv7-A 和 NEON并且在 configure 时明确指定./configure -release -opensource -confirm-license \ -xplatform linux-arm-gnueabihf-g \ -prefix /opt/qt5.5.10-arm \ -no-opengl -no-gtk -nomake examples -nomake tests这里有个非常容易踩的坑Qt 的 qmake 会用到目标板上的 sysroot也就是 ARM rootfs。如果 sysroot 路径不对编译出来的程序在板子上运行时会缺少一堆动态库。建议先把 rootfs 完整解压到主机某目录编译 Qt 和编译应用时都用-sysroot指定这个目录并在链接时用-rpath指向 Qt 库安装目录避免运行时找不到库。界面性能方面FMQL45T900 的 PL 端如果放了显示控制器 IP那 Qt 可以直接走 framebuffer 插件不需要 OpenGLCPU 渲染 800x480 分辨率的界面基本流畅。如果对动画性能有更高要求再考虑在 PL 端接 Mali 等 GPU IP但复杂度会明显上升。5.5 一组实测数据与后续扩展方向经过完整搭建和调优后用这套方案跑通 FMQL45T900 的启动和数据采集应用我记录了几个关键数据供参考项目结果从上电到 U-Boot 串口输出约 2.6 秒从 U-Boot 到内核启动完成约 3.2 秒内核到 rootfs 挂载并进入 Shell约 5.8 秒Ubuntu rootfssystemduImage 大小4.19 内核基础驱动约 5.3 MB设备树大小约 22 KB静态编译的最小 hello约 780 KB启动后系统空闲内存约 750 MB1GB DDR 配置这些数字不是最优值但作为开发板状态足够用。如果你做正式产品建议用 buildroot 替换 Ubuntu rootfs把启动时间压进 5 秒以内在工业场景中很常见。后续扩展方向我自己的计划是先在 PL 端加一个 DMA 采集模块用 Linux 里的 u-dma-buf 驱动做零拷贝数据通路把高性能 ADC 的采集数据直接送到用户态同时在 Linux 里添加远程升级机制通过 U-Boot 的 distro boot 特性做双分区 A/B 互备升级。这套环境跑通之后后面的扩展基本就是在往这条稳固的链路上添砖加瓦心里会有底得多。
返回列表
PREV
查看更多资讯
NEXT
返回资讯列表