news 2026/9/19 2:24:09

FT2004 U-Boot 移植与 BL31/设备树镜像合成烧写指南

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
FT2004 U-Boot 移植与 BL31/设备树镜像合成烧写指南

简介:围绕飞腾FT2004/FT2000C平台uboot移植、合成与下载的PDF实战文档,面向嵌入式Linux驱动、BSP开发及bootloader调试的初中级工程师,也可供需要完成板卡适配与固件烧录任务的技术人员参考。压缩包仅含1个PDF文件,大小约5.03MB,以图文并茂的实操记录形式呈现,便于离线查阅与对照复现。内容覆盖GCC-ARM V8.2交叉编译环境搭建、飞腾官方uboot源码定制(FT2004C.h、FT2004C_defconfig及PEU1 X16配置)、编译脚本编写、image_fix打包工具配置PCIE与DDR控制器、串口调试,以及GZUT_EZP_XPro烧录flash等完整链路,所有截图与测试结果均来自实测。目前已有504人学习,可作为FT2004系列uboot移植的流程参考与排错依据,帮助读者理解从源码修改到可启动镜像落地的关键节点。

1. FT2004 板子上那条从源码到点亮的链路

拿到一块 FT2004 的板子,能用的资料往往只有一页原理图、一个调试串口和几个名字各异的二进制文件:bl31.bin、u-boot.bin、fip.bin、.itb,谁先谁后、各自烧到哪个地址,没有一份能直接照抄的说明。FT2004 是 ARMv8-A 的四核处理器,上电后由片内 BootROM 起步,经固件层(PBF 或 ARM Trusted Firmware 的 BL31)把控制权交给 U-Boot,U-Boot 再去拉内核。这条链路上任何一环的加载地址、对齐方式或者设备树节点写错,串口就是一行字都不吐。

所谓移植,是让 U-Boot 认识这块板的 DDR、串口、时钟、存储和网口;所谓合成,是把 BL31、U-Boot 和 DTB 按固件约定的偏移拼成一个可烧录镜像;所谓下载,是通过串口、网口或者烧录器把镜像送进 QSPI Flash、eMMC、SD 卡或直接加载到内存里跑起来。这三件事在 FT2004 上互相咬合,单独做对一件没有意义。下面按准备工具链、板级移植、镜像合成、下载固化、调优排错的顺序,把每一步能复现的命令和参数写清楚。

2. FT2004 的 U-Boot 源码与 aarch64 交叉工具链怎么准备

动手改代码之前,先把编译环境和源码布局理顺。FT2004 上跑的都是 64 位 ARM 代码,宿主机上装一套能用的 aarch64 工具链是底线。这一步做不扎实,后面所有报错都会指向错误的方向。

2.1 交叉工具链的选型与自检

常见做法是用gcc-aarch64-linux-gnu,Debian/Ubuntu 下直接apt install gcc-aarch64-linux-gnu,也可以用厂商 SDK 里自带的裸机工具链。两者都能编 U-Boot,区别在于前者带 glibc 头文件,后者更干净,编出来的镜像体积略小。BL31 和 PBF 一般用同一套工具链即可,除非固件方明确要求某个版本。

装完先自检,别等到编译到一半才发现路径不对:

# 确认工具链可用,输出里要有 aarch64 前缀 aarch64-linux-gnu-gcc -v # 写进环境变量,注意结尾那个短横线不能丢 export ARCH=arm export CROSS_COMPILE=aarch64-linux-gnu- export PATH=$PATH:/opt/toolchain/bin # 快速验证能否产出目标文件 aarch64-linux-gnu-gcc -c -o /tmp/t.o -xc - <<'EOF' int main(void){return 0;} EOF

ARCH在 U-Boot 里填arm而不是arm64,这是很多人第一次编 64 位 U-Boot 时踩的坑;CROSS_COMPILE结尾的短横线是 U-Boot Makefile 拼接工具名前缀用的,漏掉会报aarch64-linux-gnu-gcc: not found。验证用的那段代码只是确认工具链能出目标文件,输出物在 /tmp 下,不影响仓库。

SDK 目录建议按职责分开,避免 U-Boot 的编译产物和固件产物混在一起:

sdk/ ├── boot/ │ ├── pbf/ # 片内固件,通常是二进制形式交付 │ ├── atf/ # BL31 源码,产物 bl31.bin │ └── uboot/ # 移植主战场 ├── images/ # 合成后的可烧录镜像 └── tools/ # mkimage、fiptool、打包脚本

2.2 编译前先跑通一次原厂配置

在改任何一行代码之前,先确认这套源码本身能编出产物。这一步的价值在于把「源码问题」和「我的改动问题」分开。用厂商提供的板级配置名跑一遍(配置名以源码configs/目录下实际存在的为准):

cd sdk/boot/uboot make distclean make ft2004_defconfig # 板级配置名按 defconfig 实际文件名替换 make -j$(nproc) 2>&1 | tee build.log

distclean清掉上一次编译留下的.config和中间文件,避免旧配置残留;-j$(nproc)按 CPU 核数并行编译;tee build.log把日志同时落到文件,便于后面grep -i error定位。如果这一步就失败,先解决工具链和源码完整性问题,别急着动设备树。

编译通过后,make menuconfig可以进去核对几个关键项:CONFIG_SYS_TEXT_BASE(U-Boot 自身被加载的地址)、CONFIG_BAUDRATE(调试串口波特率)、CONFIG_DEFAULT_DEVICE_TREE(默认设备树文件名)、CONFIG_SYS_LOAD_ADDRtftpboot这类命令的默认加载地址)。这四个值的取值范围必须落在板子的 DDR 可用区间内,抄别的板子的值十有八九起不来。

2.3 产物清单与各自用途

一次完整编译会吐出好几个文件,名字相近,用途完全不同。合成镜像时拿错文件是常见事故,先对照这张表:

产物文件内容用途
u-boot.bin纯二进制,不含设备树单独烧写或作为 fip 的 nt-fw
u-boot-nodtb.bin去掉 DTB 的 U-Boot与外部 DTB 拼 FIT 时用
u-boot.dtbU-Boot 自己用的设备树拼 FIT、确认节点是否生效
u-boot.itb打开 FIT 后自动生成的组合镜像部分平台可直接烧写
u-bootELF 格式,带符号表用 gdb 或 addr2line 定位崩溃
System.map符号地址表分析启动卡死的现场地址

判断某个配置项有没有真正生效,最直接的办法是去.config里查,而不是看menuconfig界面上的勾。看出u-boot.dtb的修改是否生效,用fdtdump u-boot.dtb | grep -A3 uart之类的命令确认节点确实编进去了,比反复烧板子快得多。

提示:u-boot.bin和设备树是两份独立数据,烧写时如果只更新了其中一份,会出现「驱动认得到、地址却不对」的诡异现象,改动 dts 后一定要两份一起更新。

3. 板级移植:让 FT2004 跑出第一行串口输出

移植的第一目标不是让 U-Boot 完整启动,而是让串口先吐出第一行字。只要有一行输出,就说明 DDR、时钟和串口三件事里至少有两条是对的,后面的调试才有反馈渠道。这一章围绕设备树、板级配置和外设驱动三块展开。

3.1 设备树里必须先对上的几个节点

FT2004 平台的 U-Boot 使用设备树描述硬件,根节点的compatible会和板级文件的匹配表比对,对不上就走不到初始化流程。控制台输出靠chosen节点里的stdout-path指定,别名则让命令行能用serial0这种短名字引用。

/ { model = "FT2004 EVB"; compatible = "phytium,ft2004", "phytium,e2000"; chosen { stdout-path = &uart0; /* 决定控制台往哪个串口打印 */ }; aliases { serial0 = &uart0; /* 让命令行可以用 serial0 引用 */ }; }; &uart0 { status = "okay"; clock-frequency = <100000000>; /* 必须与实际输入时钟一致,否则波特率全错 */ };

compatible的第一项要和板级文件的of_match表一致;clock-frequency写错会出现「有输出但全是乱码」,因为分频算出来的波特率偏离了 115200;stdout-path指向的节点status必须是okay,标成disabled就没输出。检查设备树有没有编对,用dtc -I dtb -O dts u-boot.dtb反编译出来比对着看。

3.2 defconfig 与板级开关的对应关系

板级配置项在configs/下的 defconfig 里,每一条都影响最终镜像行为。改的时候按用途分组,别一股脑往里加。

配置项含义常见错误
CONFIG_TARGET_xxx选择板级目录和初始化代码名字和board/下目录不一致
CONFIG_DEFAULT_DEVICE_TREE默认加载的 dts 名字与实际 dts 文件名差一个后缀
CONFIG_SYS_TEXT_BASEU-Boot 重定位前的运行地址落在 DDR 未初始化区间
CONFIG_SYS_LOAD_ADDR下载命令的默认落点与内核加载区重叠
CONFIG_BAUDRATE调试串口波特率与上位机终端不一致

修改后执行make olddefconfig让新增项补齐默认值,再重新编译。想看某个配置是否真的被选中,直接grep CONFIG_TARGET_xxx .config,比在图形界面里翻菜单可靠。

3.3 从有输出到能敲命令:串口与存储的衔接

串口有输出只是起点,接下来要让命令行可用、让存储设备能被识别。U-Boot 进命令行前会初始化board_initdram_initmisc_init_r等钩子,DDR 容量报错会导致后续内存操作全部失败,典型的症状是bdinfo里 DRAM 容量显示为 0 或明显偏小。

# 板上执行,确认 DDR 和启动参数 FT2004> bdinfo FT2004> dm tree FT2004> mmc list FT2004> sf probe 0

bdinfo看 DDR 起始地址和容量,dm tree看驱动模型里各设备有没有绑定成功,mmc listsf probe 0分别验证 eMMC/SD 和 SPI Flash 能不能被探测到。sf probe失败通常是 SPI 控制器节点的reg或片选引脚配错,先回到设备树核对,别急着怀疑硬件。

注意:DDR 初始化参数(时序、容量、位宽)属于最不该凭经验猜的部分,务必用固件方给出的配置或参数表,写错会表现为随机的偶发死机,极难定位。

4. 把 BL31、U-Boot 与 DTB 合成为可烧录镜像

合成这一步决定了板子能不能从存储介质里被正确加载。核心是三件事:各部分放在镜像的什么偏移、用什么工具拼、拼完怎么校验。FT2004 平台上常见的合成方式有 FIT 镜像和 fip 两种,选哪种取决于固件层怎么解析。

4.1 合成前的镜像布局

动手拼之前,先把布局画清楚。固件层加载时按固定偏移去取 BL31、U-Boot 和 DTB,偏移对不上就加载到一片空白。下面是一种常见的布局示意,具体数值必须以所用固件的说明为准:

偏移内容说明
0x0引导头/预留区部分平台留出头部空间
0x1000bl31.bin通常要求 4KB 对齐
0x40000u-boot.bin与 BL31 之间留足空间
0x100000u-boot.dtb或直接编进 FIT

预留空间宁可留大不留小,BL31 后续升级体积变大时不用重排整个布局。对齐要求来自固件层的解析逻辑,常见的对齐粒度是 4KB 或 64KB。

4.2 用 mkimage 合成 FIT 镜像

FIT 的好处是把多份镜像和它们的加载地址、入口地址写在一份 its 描述文件里,加载时由 U-Boot 自己解析,不需要固件层知道固定偏移。

/dts-v1/; / { description = "FT2004 firmware"; #address-cells = <1>; images { bl31 { description = "ARM Trusted Firmware BL31"; data = /incbin/("bl31.bin"); /* 相对 its 文件的路径 */ type = "firmware"; os = "arm-trusted-firmware"; arch = "arm64"; compression = "none"; load = <0x80000000>; /* 按实际内存布局填写 */ entry = <0x80000000>; }; uboot { description = "U-Boot"; data = /incbin/("u-boot-nodtb.bin"); type = "firmware"; os = "u-boot"; arch = "arm64"; compression = "none"; load = <0x80200000>; entry = <0x80200000>; }; fdt { description = "FT2004 device tree"; data = /incbin/("u-boot.dtb"); type = "flat_dt"; arch = "arm64"; compression = "none"; }; }; configurations { default = "conf"; conf { description = "FT2004 boot"; firmware = "bl31"; /* 先被加载并跳转的镜像 */ loadables = "uboot"; /* 由前一级转交控制权 */ fdt = "fdt"; }; }; };

生成与检查:

mkimage -f ft2004.its firmware.itb mkimage -l firmware.itb # 列出各镜像的地址与校验信息

firmware字段指定第一级被加载的镜像,loadables是后续交接的对象,两者顺序颠倒会直接卡在第一级;load/entry必须落在有效 DDR 区间内且不能互相覆盖;mkimage -l能列出每份子镜像的哈希和地址,合成后必查一次,比烧到板子上再猜要省事。

4.3 fip 方式与直接拼接的差异

如果固件层不解析 FIT,就要用 fip 或者裸拼。fiptool 是 ATF 自带工具,优点是会自动校验各段对齐:

fiptool create \ --soc-fw bl31.bin \ --nt-fw u-boot.bin \ fip.bin # 不打包、只按偏移直接拼时,用 dd 预留空间再覆盖写入 dd if=/dev/zero of=fw.bin bs=1M count=16 dd if=bl31.bin of=fw.bin bs=1K seek=4 conv=notrunc dd if=u-boot.bin of=fw.bin bs=1K seek=256 conv=notrunc

seek的单位由bs决定,上面用bs=1Kseek=4就是偏移 4KB,写错单位是最常见的低级错误;conv=notrunc保证不把已写入的内容截断。合成完做一次完整性校验:

sha256sum fw.bin cmp -n $(stat -c%s bl31.bin) bl31.bin <(dd if=fw.bin bs=1K skip=4 count=64 2>/dev/null)

cmp确认镜像里对应区间的内容和源文件逐字节一致,通过之后再进入烧写环节。

5. 下载与烧写:从串口 XMODEM 到 QSPI/eMMC

镜像合成了,接下来要把它送进板子。FT2004 平台上常用的路径有三条:串口传文件到内存、网口 TFTP 到内存、以及把内存里的内容固化进 Flash。三条路径适用场景不同,速度差得很远。

5.1 内存下载:XMODEM、YMODEM 与 TFTP

串口下载不依赖网络,只要串口通就能用,代价是慢。U-Boot 侧执行接收命令,宿主机侧用sx/sb或 kermit 发送:

# 宿主机:把文件通过串口发给板子,设备名按实际替换 sx -b firmware.itb < /dev/ttyUSB0 > /dev/ttyUSB0 # 或者用 kermit,参数更可控 kermit -i -l /dev/ttyUSB0 -b 115200 -s firmware.itb
FT2004> loadx ${loadaddr} # XMODEM 接收,配合宿主机 sx FT2004> loady ${loadaddr} # YMODEM 接收,配合 sb,速度更快 FT2004> md ${loadaddr} 0x20 # 看接收到的头几个字,确认不是空的

loadx用 128 字节块,loady用 1KB 块,同样波特率下后者快将近八倍。传输完一定要用md看内存内容,镜像没传完整时前几个字往往就是全 0 或全 F。

有网络的情况下走 TFTP 更快:

FT2004> setenv ipaddr 192.168.1.100 FT2004> setenv serverip 192.168.1.10 FT2004> tftpboot ${loadaddr} firmware.itb

ipaddr是板子自己的地址,serverip是宿主机上 TFTP 服务的地址,两者必须在同一网段。tftpboot成功后filesize环境变量会自动更新为收到的字节数,后面的写 Flash 命令直接引用它,比自己算长度可靠。

5.2 固化到 QSPI Flash / eMMC / SD

内存里跑通之后才轮到固化。三种介质的命令和坑各不相同:

FT2004> sf probe 0 # 探测 SPI Flash FT2004> sf erase 0x0 0x200000 # 擦除 2MB,地址和长度都是十六进制 FT2004> sf write ${loadaddr} 0x0 ${filesize} # 从内存写入 Flash
FT2004> mmc dev 0 # 选中设备 0 FT2004> mmc write ${loadaddr} 0x0 0x1000 # 第三个参数是块数,不是字节数

sf erase的第二个参数是长度,单位字节;mmc write的第三个参数是从哪个块开始写多少块,一块 512 字节,写 2MB 要传0x1000而不是0x200000。这两个命令的参数单位不一致,是烧写失败中最常见的来源之一。写之前务必先擦除,Flash 只能把 1 写成 0,不擦除直接写会得到一堆不可预期的数据。

方式典型速度依赖适用场景
串口 XMODEM/YMODEM只需串口首板点亮、网络未通
TFTP网口和 TFTP 服务日常迭代
烧录器最快专用工具量产、批量刷写

5.3 上电验证与环境变量落盘

烧完不要立刻断电,先在当前会话里验证能不能从烧写位置正常加载:

FT2004> sf probe 0; sf read ${loadaddr} 0x0 0x200000 FT2004> bootm ${loadaddr}

sf read把刚写进去的内容读回内存,bootm尝试启动,能走到内核或 U-Boot 二次加载界面说明写入位置和长度都对。随后把启动命令固化下来:

FT2004> setenv bootcmd 'sf probe 0; sf read ${loadaddr} 0x0 0x200000; bootm ${loadaddr}' FT2004> saveenv

bootcmd是上电后自动执行的命令序列,saveenv把它写进环境变量存储区。如果saveenvCannot save environment,先确认环境变量分区在配置里指向了可写介质,而不是默认的nowhere

6. 把 FT2004 的 U-Boot 调稳的几个技巧

前几章走完,板子基本能启动了,剩下的问题往往更零碎:网口时通时不通、偶发卡死、换个批次的核心板行为不一样。这一章集中处理这类疑难。

6.1 网口不通的排查顺序

千兆网口在移植阶段是最容易出问题的外设,同类平台上的经验基本通用。按这个顺序查,能覆盖大部分情况:

症状优先排查点
mii info读不到 PHYPHY 地址、MDIO 时钟、复位 GPIO 时序
能链路但 ping 不通RGMII 收发延时、时钟方向、PHY 模式配置
大包丢、小包通DMA 描述符数量与缓冲区对齐
FT2004> mii info # 逐个地址扫 PHY FT2004> mii read 0 0 # 读寄存器 0,确认 PHY 是否响应

PHY 复位时序是最容易被忽略的一环:复位脚拉低后需要保持一段时间再释放,很多板子因为释放太快导致 PHY 内部寄存器还没准备好,表现为「第一次上电通、热重启不通」。这类问题在设备树里加一个复位延时节点往往就能解决。

6.2 启动卡死的定位手段

串口完全没有输出时,先把早期调试串口打开,让打印从 U-Boot 重定位之前就开始:

CONFIG_DEBUG_UART=y CONFIG_DEBUG_UART_BASE=0x... CONFIG_DEBUG_UART_CLOCK=100000000 CONFIG_DEBUG_UART_ANNOUNCE=y

这四个配置项让debug_uart_init在 SPL 或早期阶段就初始化串口,输出的是不走驱动模型的裸打印,能在 DDR 初始化之前就给出反馈。如果这样还是没有任何字符,问题就在 DDR 初始化或更前面的固件层,不在 U-Boot 本身,此时应该换一个已知能启动的镜像回来对比。

进了命令行之后,bootstage report能列出各阶段耗时,卡在哪一段一目了然;dm tree看驱动绑定情况;bdinfo看内存布局。偶发死机这类问题,把System.map里的地址和串口打印出的 PC 值对照,用addr2line -e u-boot -f -i <地址>反查函数名,比反复改代码试要快得多。

本文还有配套的精品资源,点击获取

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/19 2:19:36

高分二号影像预处理全流程:从L1A到正射融合

简介&#xff1a;面向使用高分二号卫星影像的遥感从业者、GIS学习者及科研人员&#xff0c;这份PDF以问答形式系统梳理了数据版本与分辨率、WGS84坐标系、原始数据挑选标准、处理成果格式及适用软件等六类高频问题。资源共1个文件&#xff0c;为PDF格式&#xff0c;压缩包大小约…

作者头像 李华
网站建设 2026/9/19 2:19:17

AI治理实战:从模型部署到Agent落地的四层管控框架

1. AI治理困局&#xff1a;从“跑得快”到“走得稳”的转折点过去两年&#xff0c;我身边几乎所有技术团队都在做同一件事&#xff1a;把AI能力塞进产品里。有人用大模型重写了客服系统&#xff0c;有人用AI Agent做了自动化运维&#xff0c;还有人干脆把代码生成的活全交给了A…

作者头像 李华
网站建设 2026/9/19 2:16:35

数字频带传输系统全解析:2ASK/2FSK/2PSK原理、带宽与误码率仿真

简介&#xff1a;面向通信工程、电子信息等专业学生的数字频带传输系统学习资料&#xff0c;系统讲解数字调制系统的基本框架与核心原理&#xff0c;涵盖2ASK、2FSK等键控方式的信号产生、功率谱分析及带宽计算&#xff0c;可辅助课程复习、考研备战与自学入门。资源为单个PDF文…

作者头像 李华
网站建设 2026/9/19 2:13:49

electerm 快速上手指南:从安装到拖拽传文件只需 5 步

electerm 快速上手指南&#xff1a;从安装到拖拽传文件只需 5 步 【免费下载链接】electerm &#x1f4fb;Free and open-sourced terminal/ssh/sftp/ftp/telnet/serialport/RDP/VNC/Spice client(Linux, Mac, Windows, Android, HarmonyOS, iOS) 项目地址: https://gitcode.…

作者头像 李华