Ultra96开发板实战:MPSoC架构解析与Linux系统快速启动指南
如果你之前一直在和 Zynq-7000 系列的板子打交道比如 Zybo、ZedBoard 这类第一次拿到 Ultra96 时最直观的感受反而不是性能数据而是这板子真的太tm小了。85×54 毫米跟一张信用卡差不多大上面却挤了一颗四核 Cortex-A53、双核 Cortex-R5、Mali-400 GPU、可编程逻辑、2GB DDR4、WiFi、蓝牙和一堆高速接口。当年我拆开包装时的第一反应是这不像是一块民用开发板更像一台被压缩进信用卡尺寸的小服务器。Ultra96 是 Avnet 和 Xilinx 联合推的一块 96Boards 标准开发板核心是 Xilinx Zynq UltraScale MPSoC定位非常明确给嵌入式视觉、边缘 AI、机器人和教学实验提供一个能跑 Linux、又能玩 FPGA 的硬件平台。这个系列我打算拆成两篇来写Part 1 专注一件事——帮你把这块板子彻底看懂并且完整地把系统跑起来Part 2 再深入 PL 开发、AXI 外设和 PYNQ 这类进阶玩法。这篇文章适合刚入手 Ultra96、或者正在评估要不要买它的人也适合从 Zynq-7000 迁移过来的老用户。读完你至少能回答三个问题这板子内部到底怎么分工的MPSoC 是怎么启动的以及拿到手之后怎么用最小的代价让它先跑起来。1. 为什么值得花一整篇文章来理解Ultra961.1 Ultra96 到底是什么从名字讲起很多人第一次听到 Ultra96 这个名字会以为它是某个系列的第 96 款产品其实不是。96 来自 96Boards——这是 Linaro 主导的一套开放硬件规范定义了板卡的物理尺寸、接口排布和电源标准。符合这个规范的板子上可以插统一的 Mezzanine 扩展子板理论上在 DragonBoard、Jetson Nano 上用的扩展模块也能在 Ultra96 上插这对原型验证来说非常方便。但真正让 Ultra96 区别于 96Boards 家族里其他成员的不是这个外壳标准而是它里面的那颗芯片Zynq UltraScale MPSoC具体型号是 XCZU3EG。这是一个异构 SoC和之前 Zynq-7000 系列的双核 ARM FPGA不是一个量级的玩法。ZU3EG 里不只有四核 ARM Cortex-A53 应用处理器还塞了双核 Cortex-R5 实时处理器、Mali-400 GPU以及一块 15 万逻辑单元级别的可编程逻辑。换句话说它同时覆盖了通用计算、实时控制、图形处理和硬件加速四个领域。所以理解 Ultra96 的第一件事就是不要把它当成一块能跑 Linux 的 FPGA 板。它是一台完整的微型计算机加一块可重构硬件CPU 和 FPGA 不是主从关系而是通过片内高速总线进行对等通信的两种资源。整个 Ultra96 的价值恰恰来自于这种异构计算能力而不是某个单一处理器的频率。1.2 谁应该看 Part 1看完能做什么我给不同背景的读者画个大概的画像。如果你以前只玩过 MCU比如 STM32、ESP32那你看完这篇文章会知道系统级的启动流程异构 SoC 的内存共享这些概念到底是怎么回事如果你以前玩过 Zynq-7000你能对比出 MPSoC 在启动链路和系统架构上的巨大变化如果你完全是冲着 AI 推理来的想跑 DPU 或者 PYNQ那 Part 1 更是绕不开的基础——因为后面所有 AI 例程都要依赖这里讲的镜像烧写、串口调试和网络配置。这篇文章的实操目标是让你在一个晚上之内把这块板子从拆箱推进到能够在串口终端敲 Linux 命令的状态。中间会涉及 SD 卡烧写、串口连接、板级启动配置、基础系统验证以及大量我在实际过程中踩过的坑。我不打算在这里展开 Vivado 工程从零创建的细节那是 Part 2 的内容但我会把一切和系统能跑起来相关的路径都讲透。你不需要是 Linux 高手甚至不需要写过 FPGA 代码只要有一台 x86_64 的 Ubuntu 电脑、一块 Ultra96 和一根靠谱的 USB 线就够了。2. 硬件架构拆解一颗芯片上的异构王国2.1 PS 与 PL芯片内部的两套人马要理解 Ultra96绕不开 Xilinx 提出的 PS/PL 划分。PSProcessing System是芯片内的固定硬化处理系统PLProgrammable Logic是可编程逻辑。它俩不是两个芯片封装在一起而是在同一颗裸片上的两部分通过片内的 AXI 总线互联。PS 端可以独立启动跑操作系统PL 端则像一块白纸等着你通过比特流去定义它变成什么硬件。在 ZU3EG 上PS 端的 ARM 部分分成了两个应用域。一个叫 APUApplication Processing Unit包含四颗 Cortex-A5364 位最高工作频率在 1.5GHz 左右带 NEON SIMD 指令集这是主力运算单元跑 Linux、跑用户程序全靠它。另一个叫 RPUReal-time Processing Unit包含两颗 Cortex-R5F这是专门给实时任务用的处理器能够提供比 Linux 上的线程更确定的响应延时。另外还有一个 Arm Mali-400 GPU负责 2D/3D 图形输出DisplayPort 显示通路里就是它在出力。PL 端在 ZU3EG 上的资源相对克制约 15 万逻辑单元、360 个 DSP Slice、216 块 BRAM 和 96 块 UltraRAM。这个规模比起高端的 ZU9EG 要小很多但对于做图像预处理、跑小规模神经网络加速、实现自定义外设接口这些场景完全够用。关键是 PL 和 PS 之间有多组高速 AXI 端口包括用于一致性缓存的 CCI 端口和高带宽的 HP 端口数据搬运的实际性能远不是外挂芯片方案能比的。2.2 板级资源在 85×54 毫米里塞了什么Ultra96 的板级设计属于那种看起来不起眼但该有的全都有的类型。先说存储板上有 2GB DDR4 颗粒连接在 PS 的 DDR 控制器上频率跑在 1200MHz 左右。注意这里不像很多 FPGA 开发板一样为 PL 单独挂一组内存PL 想访问 DDR 必须经过 PS 的 AXI 端口这在实际开发中会影响你的数据通路设计我后面会专门强调。存储方面有板载 eMMC、一个 MicroSD 卡槽和一个 QSPI Flash。eMMC 在量产后很方便但开发阶段基本用不到最常用的启动介质就是 SD 卡这也是官方默认方案。无线方面板载 WiFi 802.11ac 和蓝牙 4.2天线是板载的贴片天线面积不大信号强度中规中矩后面讲网络时会提到它的脾气。接插件方面有一个 USB 3.0 Type-C 口它支持 DisplayPort Alt Mode也就是说它能直接转接输出 DP 视频信号同时还保留 USB 3.0 和 USB 2.0 的扩展能力。另一个 MIPI CSI-2 摄像头接口是给视觉应用留的位置15 pin 的 FPC 座接官方摄像头模组很方便。比较容易被忽略的是板上那个低速扩展排针和高速扩展排针这是 96Boards 规格强制要求的。低速排针上引出了 I2C、UART、SPI、GPIO 和电源高速排针则引出 USB、PCIe、DisplayPort 这类信号。我手头有几个 96Boards 的传感器子卡直接怼上去就能用这一点在原型验证的时候省了很多飞线。2.3 和 Zynq-7000 的差异以及 V1 和 V2 怎么选如果你之前用过 Zynq-7000比如 Zybo 上那颗 Z-7010你会发现 PS 端的差距不是一点半点。最重要的一条是 CPU 从双核 Cortex-A9 变成了四核 Cortex-A53从 32 位变成了 64 位。这意味着你可以在上面跑完整的 Ubuntu 桌面、跑 Docker、跑更大的虚拟内存空间。其次是实时域的出现Cortex-R5 可以在 Linux 完全卡死的情况下独立运行关键控制逻辑这在电机控制、汽车域控制器这类场景里非常有价值。然后是启动流程上的变化。Zynq-7000 的启动是 BootROM→FSBL→U-Boot→Linux三步就完事。MPSoC 多了两级ATFARM Trusted Firmware负责安全启动和运行时特权切换PMUFWPlatform Management Unit Firmware负责电源域和时钟管理。这会导致两个问题一是编译 BOOT.BIN 时你不能再像以前那样只给 FSBL 和 U-Boot 了必须把 PMUFW 也打包进去二是如果 PMUFW 和数据不匹配板子会以非常诡异的方式启动失败比如卡在某个阶段没任何输出。很多人第一次从 Zynq-7000 迁移过来在这一步最容易卡住。再说 V1 和 V2 怎么选。Ultra96 出了两个硬件版本V1 用的是 ZU3EG 的 SBVA484 封装V2 换成了 DFVF 封装主芯片从-1 速度等级升级到-2。V2 在散热、电源设计和高速信号完整性上做了优化官方对更高版本 Vivado 的支持也更好。我的建议是如果现在买直接买 V2价格差距不大但开发体验好不少。V1 也完全可以跑只是你下载镜像时一定要看清楚是 V1 专用还是 V2 专用两者不能通刷这我后面在问题章节会重点讲。3. 启动流程MPSoC 是怎么一步步醒过来的3.1 从 BOOT.BIN 到 Linux 挂载的完整链路Ultra96 上电之后发生的事情比很多人想象中复杂。芯片内部的第一段代码是固化在 ROM 里的 BootROM它不会执行任何外部指令只做一件事根据启动模式引脚的状态决定从 SD、QSPI 还是 JTAG 去加载下一段代码。在这个过程中 BootROM 还会初始化时钟的基本配置但完全不碰 DDR。之所以不初始化 DDR是因为 DDR 控制器参数和你的硬件设计相关BootROM 不可能提前知道。在 SD 卡启动模式下BootROM 会跳到 SD 卡的第一个分区查找一个名叫 BOOT.BIN 的文件。这个文件是编译过程打包而成的里面包含多段内容FSBL第一级引导程序、ATF、PMUFW、U-Boot以及可选的 FPGA 比特流。FSBL 负责把 DDR 控制器初始化好把 ATF、PMUFW、U-Boot 加载到 DDR 对应的内存地址然后跳转执行。ATF 在 EL3 异常级别接管安全监控PMUFW 被加载到 PMC 的专用 RAM 里负责整个芯片的电源域管理。之后 U-Boot 接管它会读取环境变量、加载设备树并把 Linux 内核从 SD 卡的 image.ub 或者独立内核镜像中解压到内存最终把控制权交给 Linux。理解整个链路的核心要点是BOOT.BIN 不只是引导文件这么简单它是一个多段式加载包并且每一段都有严格的加载地址和依赖关系。PetaLinux 的打包工具就是根据你传入的 FSBL、PMUFW、ATF、U-Boot 和 FPGA bit 文件自动生成这个 BOOT.BIN 的。如果你手动操作最容易犯的错就是把 Zynq-7000 时代的习惯带过来——只给 FSBL 和 U-Boot结果 PMUFW 缺失导致上电后完全没有输出或者输出的日志戛然而止。3.2 三种启动模式以及拨码开关的正确姿势Ultra96 板上有一个启动模式拨码开关丝印上一般标着 BOOT MODE 或者 SD/QSPI/JTAG 三档。出厂默认一般是在 SD 位置这也是绝大多数开发流程里用的模式。我的建议是刚拿到板子先别动任何拨码直接用默认 SD 模式跑官方镜像等你有明确需求了再切换。三种模式的实际使用场景差异很大。SD 模式最灵活镜像修改方便SD 卡拔下来插电脑上就能换系统适合日常开发和实验。QSPI 模式适合部署阶段的启动板载 Flash 里存一份小而精简的引导镜像配合 eMMC 或网络启动根文件系统可以实现快速上电启动。JTAG 模式则完全不是给跑系统用的它适合硬件调试、裸机开发以及需要单步追踪的场景。在 JTAG 模式下你可以通过 Vivado Hardware Manager 直接下载比特流并调试 PL 逻辑也可以把 FSBL 和 U-Boot 单独加载进内存做一些低层诊断。需要特别提醒一点切换拨码之前一定要断电。热切换拨码开关会让芯片在上电瞬间读到不确定的引脚电平轻则启动失败重则造成 SD 卡文件系统损坏。这听起来像废话但我真的见过有人因为板子上电状态下去拨启动开关导致 BOOT.BIN 被写坏的案例。3.3 为什么 PMUFW 和 ATF 在 MPSoC 时代不可绕过很多从 Zynq-7000 过来的同学在第一次构建 Ultra96 镜像时都会产生一个疑问FSBL 和 U-Boot 我理解PMUFW 和 ATF 是干什么的它们真的必须存在吗答案是必须。PMUFW 跑在芯片内部的微控制器 PMC 上负责整个 SoC 的电源域管理、热管理、时钟和复位控制Linux 内核里的电源管理驱动要靠它来实现各种功耗模式切换。没有 PMUFW芯片上电后电源域的默认配置就可能不对轻则某些外设行为异常重则直接在 U-Boot 阶段崩溃。ATF 的作用则是构建安全世界和非安全世界之间的防火墙。它运行在最高特权级 EL3负责系统启动早期的特权状态切换以及提供运行时服务调用接口。Linux 运行在非安全世界的 EL1所以 U-Boot 在跳转内核前必须通过 ATF 完成异常级别的切换。如果你尝试绕过 ATF 直接把 U-Boot 的跳转目标指向 Linux 内核入口系统大概率会挂死在启动早期。简单说PMUFW 管电ATF 管权。这两段固件的代码量都不大但缺一不可。它们不是 Xilinx 故意给你添麻烦而是 MPSoC 系统复杂度提升的必然产物。好在 PetaLinux 的流程已经把这些固化到了工具链里你只要保证在 petalinux-package 时把正确的 pmufw.elf 传进去就行不需要手动关心内部细节。4. 环境准备与首次启动让板卡先跑起来4.1 必备物料清单与硬件接线按照少花钱、能干活的原则我列一下让 Ultra96 跑起来的最低物料清单。首先是 Ultra96 主板本身和官方 12V DC 电源适配器。电源不要省Ultra96 虽然静态功耗不高但跑 Linux 满载加上外设时电流会明显上升劣质电源带来的纹波会引发各种莫名其妙的死机。其次是 MicroSD 卡建议 16GB 起步Class 10 或 U1 以上卡的速度直接影响系统启动和软件安装体验。然后是 USB 转串口模块注意必须是 3.3V TTL 电平的我用的是经典的 CP2102 模块低成本、驱动稳定USB 转串口的线序后面会讲。接下来是 USB Type-C 数据线要支持 USB 3.0 而且能传输数据不要拿那种只能充电的线。如果你还想看桌面图形界面需要一根 USB Type-C 转 DP 的线或者一个 Type-C 扩展坞扩展坞最好带 HDMI 输出和 USB-A 口这样能顺便解决键鼠连接问题。最后一个建议准备的东西是 WiFi 热点或者一台能开热点的手机因为 Ultra96 没有网口联网基本靠 WiFi后面配置网络时会用到。接线顺序上我先接串口模块与板上的调试串口排针再接 SD 卡和 Type-C 电源最后上电。串口模块的 TX 接板子的 RXRX 接板子的 TXGND 一定要共地。这个顺序看起来简单但我在教学时至少有三分之一的人把 TX 和 RX 接反了导致终端完全没输出。如果你接好之后发现屏幕上什么都没显示第一反应应该是检查线序而不是怀疑板子坏了。4.2 镜像下载与 SD 卡烧写现在到了很多人最纠结的一步到底该烧哪个镜像Ultra96 可用的镜像有好几种官方和第三方都有维护。我的建议是第一次别折腾直接用 Avnet 官方发布的 Ultra96 板卡镜像它包含完整的 Linux 内核、设备树和根文件系统打开串口终端就能进系统。如果你下一步打算玩 PYNQ那也可以直接烧 PYNQ 官方为 Ultra96 编译的镜像它是基于 Ubuntu 定制的预装了 Python 环境和一系列 FPGA 交互库。我对新手的推荐顺序是先用官方 Linux 镜像确认板子硬件没问题再换 PYNQ 镜像进入真正的开发阶段。烧写工具方面Windows 用户直接用 balenaEtcherLinux 用户我更推荐用 dd 命令因为快而且可控。先把xz压缩的镜像解压然后确认 SD 卡设备名。这里我要强调一个反人类但极其重要的细节/dev/sdX这个 X 不一定是 b你必须在插卡前后分别执行一次lsblk来比对确认哪个是新出现的设备。曾经有人把整块硬盘当成 SD 卡烧了数据全没这种事故一次就能让你长记性。解压和烧写的命令类似这样xz -dk Ultra96_Linux_2020_1.img.xz sudo dd ifUltra96_Linux_2020_1.img of/dev/sdb bs4M statusprogress convfsync烧写完成后Windows 可能会提示分区无法识别这是正常的因为 SD 卡上同时有 FAT32 和 ext4 两种分区Windows 只能看到前者。如果你的目标机器上没有读卡器可以用sudo eject /dev/sdb安全弹出后再拔卡。4.3 串口与 DisplayPort 双路验证开机把烧好的 SD 卡插进板子连好串口接上电源观察串口终端。终端参数设置为 115200 波特率、8 数据位、无校验、1 停止位也就是最常见的 115200-8-N-1。我用的是 minicom启动命令是sudo minicom -D /dev/ttyUSB0 -b 115200Windows 下用 PuTTY 选择 Serial 模式同样的参数。上电后如果一切正常你会在一两秒内看到密密麻麻的启动日志从 BootROM 的信息开始经过 FSBL 打印版本号、U-Boot 打印板卡信息再到 Linux 内核解压。第一次看到这些日志滚动的时候你会对 3.1 节讲的启动流程有非常直观的感受。整个启动过程在 30 秒到一分钟不等取决于 SD 卡速度和镜像大小。启动完成后会跳到登录提示符官方镜像一般有预设账号在镜像说明页里能找到通常是root用户和空密码或者特定密码我建议登录后第一件事就是修改默认密码。如果你想看桌面把 Type-C 转 DP 线插上显示器应该会输出图形界面。注意不是所有 Type-C 线都支持 DP Alt Mode如果你买的是普通的 USB 线它是识别不到显示器的。另外启动过程中拔插 Type-C 线大概率不会有反应DP 输出必须在启动前接好我猜和 PS 端 DP 控制器的初始化时序有关。如果你遇到串口显示启动成功但显示器黑屏八成是线缆或者显示器兼容性问题可以换个接口尝试。5. 基础操作与快速验证确认板卡真正在为你干活5.1 串口控制台常用检查命令系统登录之后我建议按一个固定的顺序做几步验证确认板子的关键硬件都工作正常。第一步看系统版本和内核信息执行uname -a你会看到aarch64架构、内核版本号以及你烧的镜像编译时间。看到aarch64就意味着你真的跑在 64 位 ARM 上了这在 Zynq-7000 时代是做不到的。第二步查看 CPU 信息cat /proc/cpuinfo | grep processor正常会列出来 4 个 A53 核心你可以用nproc确认。如果你之前在 Zynq-7000 上习惯了双核看到 4 个核会非常愉快。然后是查看内存和存储。free -h会显示 2GB 总内存可用内存一般在 1.7GB 左右因为有一小部分被 GPU 和固件保留。df -h能看到 SD 卡的两个分区FAT32 的 /boot 分区和 ext4 的根分区根分区剩余空间取决于你烧的镜像大小和 SD 卡容量。如果你插了 USB 存储设备也可以用lsblk检查是否识别。最后看温度。ZU3EG 虽然在 MPSoC 里算低功耗的那档但四核 A53 全部满载跑编译任务时芯片温度还是会轻松超过 60 摄氏度。用cat /sys/class/thermal/thermal_zone0/temp查看当前温度输出单位是毫摄氏度比如 55000 就是 55 度。如果连续高负载下温度接近 85 度我建议加个小散热风扇长期高温对芯片寿命和稳定性的影响是实实在在的。5.2 没有网口怎么办WiFi 与 USB 网卡的配置思路第一次用 Ultra96 的 Linux 镜像时很多人会下意识找网口然后发现板上根本没有 RJ45。这是 96Boards 设计规范决定的结果无线为主。官方 Linux 镜像里一般已经带好了 WiFi 驱动配置方式和桌面 Ubuntu 不太一样需要用nmcli或者wpa_supplicant来连。我个人比较推荐用 NetworkManager 的nmcli语法简单直观sudo nmcli radio wifi on sudo nmcli device wifi list sudo nmcli device wifi connect 你的WiFi名 password 你的密码连上之后用ip addr show wlan0查看分配的 IP 地址。如果你在局域网内之后就可以通过 SSH 连上板子不需要一直趴着看串口了。我在实际使用中发现 Ultra96 的板载 WiFi 信号强度一般尤其是把板子放在金属外壳或桌下时信号衰减很明显。如果连不上先别怀疑系统问题而是把板子挪到路由器近一点的地方试试。如果你需要更稳定的有线网络可以用一个 USB 转千兆网卡Ultra96 的 USB 3.0 端口对常见 RTL8153 芯片的网卡支持很好插上之后用ip link就能看到新网卡然后通过 DHCP 自动获取地址。这个方法比 WiFi 稳定得多在做大规模文件传输、镜像下载或远程调试时我会一直保持插着这样一块网卡。还有一个小技巧如果没有外网环境你可以用 Type-C 线把 Ultra96 直接连到电脑然后配置 USB 网络共享或者使用 RNDIS 协议在 Linux 主机上把它识别为一个 USB 网卡这样就能在没有 WiFi 的情况下通过网线共享电脑的网络。这个方式我用得不多但在实验室里没有无线网络的环境下非常救命。5.3 从裸机到 PYNQ一条稳妥的进阶路线当你完成了上面的步骤你已经拥有了一块能稳定运行 Linux 的 Ultra96。接下来怎么走我根据自己带过不少学员的经验给出三条阶梯式的路线供参考。第一条是 PYNQ 路线最适合纯软件背景、只想快速验证算法的开发者。PYNQ 镜像在 Ultra96 上非常成熟它把 FPGA 包装成了 Python 可以调用的库你不需要自己写 RTL只要用 PYNQ 的 Overlay 接口加载预编译的 bit 流然后通过 Python 控制外设和 PL 逻辑。我建议这个方向的人先跑一遍 PYNQ 自带的 Notebook 例程然后把官方 DPU 的示例执行一遍体验自动驾驶目标检测在边缘设备上是如何跑的。第二条是嵌入式 Linux 路线适合想深入理解系统底层的开发者。用 PetaLinux 或者 Yocto 从零构建一个自己的镜像裁剪内核、配置设备树、自定义 rootfs把启动日志里每一行打印都弄清楚。这条路比较苦但走完一遍之后你对 Ultra96 的理解会比单纯跑镜像的人高出不止一个层次。第三条是 FPGA 开发路线适合硬件出身的同学。直接用 Vivado 创建工程从最简单的 AXI GPIO 点灯开始慢慢过渡到自定义 IP、AXI DMA 和 PL/PS 协同搬运数据。这条路在 Part 2 我会详细展开。无论选哪条我都不建议跳过 Part 1 里的基础验证因为你后面遇到问题排查时能否熟练查看启动日志、能否判断 SD 卡镜像是否正确往往决定了排错速度。6. 常见问题与排坑实录6.1 启动阶段的翻车现场我见过最多的启动类问题都出在完全无输出上。这个问题先排除硬件接线再排除镜像。首先确认串口线序TX 接 RX、RX 接 TX、GND 接 GND这个顺序错了就是黑屏。其次确认串口参数是 115200-8-N-1不要用 9600 或者 57600那是很多 MCU 板子的参数拿到 Ultra96 上不通用。然后确认 SD 卡里的 BOOT.BIN 确实存在并且镜像和板卡版本匹配V1 的镜像刷到 V2 上启动到某一步骤就会卡死。如果你能看到 U-Boot 的信息但卡在加载 Linux 内核大概率是设备树和内核版本不匹配。我遇到过一种情况镜像里的内核是 5.4 版本设备树却是从别的板子拷过来的结果外设初始化全部失败。解决方法是重新完整地烧写官方镜像不要手动从不同来源拼接组件。PetaLinux 构建时会自动校验组件匹配性而手动下载的组件之间没有这层保障。还有一种比较隐蔽的问题是 SD 卡供电不足。少数 USB 读卡器或者劣质 SD 卡在写入大镜像时看起来成功了实际文件系统不完整启动时在 FSBL 阶段报错。我的排查流程很简单先用 Etcher 或者 dd 完整烧一遍再用fsck检查文件系统最后如果还有问题就换一张正规品牌的卡。6.2 网络与显示问题网络问题中最常见的是 WiFi 连不上或者连接后不稳定。我的排查建议是先用nmcli device status确认无线模块是否被识别为wlan0。如果没有这个设备说明驱动的模块没有加载需要检查内核版本和镜像版本是否配套。如果 WiFi 识别正常但连接不上先把板子拿到路由器旁边排除信号问题。Ultra96 的板载天线在金属桌面附近表现不佳这个我前面提到过。显示问题主要是 DP 输出黑屏或者闪屏。DP Alt Mode 依赖线缆质量强烈建议买通过认证的 Type-C 转 DP 线。有些 USB 3.0 数据线虽然做工不错但内部没有捆绑 DP 信号线自然无法输出画面。另外部分老款显示器对 Type-C 转 DP 输入支持不好换一个支持 DP 输入的显示器或者通过扩展坞转 HDMI 会好很多。最后要注意的坑是不要在 Linux 启动之后再插 Type-C 转 DP 线。Ultra96 的 DP 控制器在系统启动阶段已经初始化过了启动后热插拔显示输出经常不生效。正确的操作是开机前接好视频线开机后显示器才能正常点亮。我一开始不知道每次都是系统起来后再插线导致桌面一直出不来折腾了一个晚上才意识到是这个问题。6.3 硬件层面的几个值得留意的点硬件部分我最后提几个容易被忽略的点。散热方面Ultra96 模块很小芯片裸晶正上方没有大散热器长时间高负载下温度容易飙高。我见过有人连续跑 AI 推理 8 小时后板子突然死机重启后一切正常猜测就是过热保护。建议至少加一个低功率风扇或者用一个小型散热片加导热垫贴在芯片上效果立竿见影。电源方面官方适配器是 12V DC不要在板上同时插 USB 供电和 DC 电源两条供电路径如果没有隔离轻则无法启动重则损坏电源芯片。我本人没有烧过板子但在社区看到过类似的案例。最后是静电防护。这点一般没人提但我带学生做实验时真遇到过有人冬天穿毛衣摸板子结果 USB 口直接识别不到。开发板不像量产电子产品有完整外壳手上的静电对敏感芯片威胁很大。建议拿板子之前先摸一下金属水龙头放电或者买一块防静电垫成本不高但能帮你省下一块板子的钱。我在实际操作中的体会是Ultra96 的学习曲线其实不在硬件本身而在于它横跨了 Linux 系统、嵌入式 ARM、FPGA 开发三个领域任何一个短板都会卡住你。如果你能把 Part 1 讲的启动链路和基础操作完整走一遍之后无论是切到 PYNQ 跑 AI 应用还是转向 Vivado 做自定义硬件都会有非常扎实的认知基础。另外有一个小技巧可以分享把官方镜像的启动日志保存一份每次遇到奇怪的硬件问题先对比日志在哪个阶段停止输出能帮你快速定位是电源、固件、内核还是设备树的问题。这一招我用了很多年从来没有让我失望过。