1. 项目概述为什么USB烧录是嵌入式开发的“救命稻草”在嵌入式开发领域尤其是基于全志这类SoC的方案开发中固件烧录是每个开发者都绕不开的“家常便饭”。你可能已经习惯了使用TF卡、串口或者J-Link等工具但今天我想跟你聊聊一种在特定场景下效率极高、堪称“救命稻草”的方案——基于USB的直接烧录。我手头这块全志T113-S3的开发板其内置的BootROM支持一种名为“FEL”的USB设备模式允许我们绕过所有外部存储介质直接通过USB线缆将固件“灌入”芯片的SRAM并执行进而完成对eMMC或SPI NAND的编程。这听起来是不是有点像给手机“线刷”原理上确实有相通之处。对于开发者而言这种“两步烧录法”的核心价值在于其极致的便捷性和强大的救砖能力。想象一下你的板子因为固件损坏无法启动TF卡槽接触不良或者你手头根本没有合适的存储卡时一根普通的USB Type-C线就成了唯一的希望。我经历过无数次在实验室深夜调试仅仅因为一个启动参数错误就导致板子“变砖”而USB烧录让我能在几分钟内恢复如初这种安全感是其他方式难以比拟的。它特别适合产品量产前的频繁测试、工厂生产烧录以及像我这样的个人开发者进行快速迭代。2. 核心原理与准备工作深入FEL模式的“心脏”在动手之前我们必须搞清楚“两步烧录”到底是怎么一回事。这不仅仅是插上线、点个按钮的简单操作其背后是全志BootROM设计精妙之处。2.1 FEL模式芯片的“安全模式”全志T113-S3芯片内部有一块固化的代码我们称之为BootROM。当芯片上电时它会按照一个既定的顺序如SD卡0、SPI NAND、eMMC去寻找可启动的固件通常是bootloader。如果所有预设的启动介质都失败了或者我们通过特定的引脚组合强制触发芯片就会进入FEL模式。此时芯片将自己枚举为一个USB设备VID: 1f3a, PID: efe8等待主机通过USB发送特定的命令和数据进行交互。你可以把FEL模式理解为芯片的“安全模式”或“急救模式”。在这个模式下芯片的核心CPU和DRAM控制器已经初始化一小块SRAM对于T113-S3通常是32KB或64KB可用。我们的目标就是通过USB向这片SRAM中下载一个名为“FEL烧录工具”的微型程序然后由这个工具来接管后续复杂的存储设备擦写工作。2.2 工具链准备选对“武器库”工欲善其事必先利其器。整个流程依赖两个核心工具它们通常包含在全志官方提供的“Tina Linux”SDK或社区维护的“Sunxi-tools”工具包中。sunxi-fel这是运行在主机你的Linux PC或虚拟机上的命令行工具。它是与开发板FEL模式通信的“指挥官”负责向SRAM中上传代码和数据并控制其执行。我强烈建议从源码编译最新版本以确保对T113-S3的完全兼容。git clone https://github.com/linux-sunxi/sunxi-tools.git cd sunxi-tools make sudo make install安装后执行sunxi-fel version确认工具就绪。sunxi-fel可执行的“payload”文件这是需要被下载到芯片SRAM中运行的程序。它本身是一个精简的二进制文件通常由全志提供或从SDK中编译得到。对于烧录eMMC这个文件可能是sunxi-fel工具内置了相关逻辑也可能是单独的fel-payload.bin。更常见的是我们需要一个功能更强大的引导程序比如uboot的SPLSecondary Program Loader部分。我们可以编译一个支持FEL和存储设备驱动的特殊版本U-Boot SPL用它作为“二级烧录器”。待烧录的固件这就是你最终要写入板载存储eMMC/SPI NAND的完整系统镜像通常是一个包含bootloader、内核、设备树、根文件系统的.img文件或者是由uboot的mkimage工具打包的uImage。注意不同版本的全志芯片、不同的存储介质eMMC vs SPI NAND所需的“payload”和命令参数可能有细微差别。务必确认你使用的工具链与T113-S3匹配。一个常见的坑是使用了旧版的sunxi-fel其可能不支持新芯片的DDR初始化参数导致后续步骤失败。2.3 硬件连接与进入FEL模式确保你的开发板有一个可用的USB OTG或Device接口通常是Type-C口并通过数据线连接到主机。让T113-S3进入FEL模式通常有以下几种方法上电自动进入如果板载存储是空的或者存储中的bootloader损坏上电后BootROM尝试所有启动设备失败会自动进入FEL模式。按键强制进入这是最可靠的方式。查阅你的开发板原理图找到“FEL”或“UBOOT”按键。在给开发板上电的瞬间或上电前按住这个按键不放持续2-3秒后再松开芯片即会被强制引导至FEL模式。软件触发在U-Boot命令行中可以执行fel命令来跳转到FEL模式但这要求你的系统已经能运行到U-Boot适用于切换模式而非救砖。连接好后在主机上执行lsusb命令如果看到Bus ... Device ...: ID 1f3a:efe8 Allwinner Technology的设备恭喜你板子已经成功进入FEL模式正等待你的指令。3. 两步烧录法详细实操解析所谓“两步”精髓在于第一步通过FEL模式将一个“烧录助手”程序通常是U-Boot SPL加载到芯片内存并运行第二步在这个“烧录助手”的运行环境下通过USB或网络等方式将完整的系统镜像写入板载存储。这里我们详细拆解最常用、最稳定的“FEL加载U-Boot SPL再通过U-Boot的fastboot协议烧录”的方案。3.1 第一步将U-Boot SPL“注入”内存并运行这一步的目标是让芯片从“被动”的FEL设备变成一个“主动”的、具备丰富驱动USB Gadget 存储设备的临时系统。准备U-Boot SPL镜像 你需要一个为T113-S3定制编译的U-Boot。在U-Boot的编译配置中确保启用了CONFIG_SPL_FEL和CONFIG_SPL_USB_GADGET等关键选项。编译完成后在输出目录如u-boot-sunxi-with-spl.bin中SPL部分通常位于文件开头。有时我们需要一个纯净的SPL镜像可以通过dd命令从合并文件中提取或者直接编译生成spl/sunxi-spl.bin。为了保险起见我通常直接使用u-boot-spl.bin如果单独生成或整个u-boot-sunxi-with-spl.binsunxi-fel工具能智能识别并只加载SPL部分。执行FEL加载与跳转 在主机终端进入存放镜像的目录执行核心命令sudo sunxi-fel -v spl u-boot-spl.bin-v启用详细输出方便查看加载过程强烈建议加上出问题时能提供关键信息。spl这是sunxi-fel的一个子命令专门用于加载并运行SPL镜像。它会计算好加载地址通常是SRAM的起始地址将二进制文件推送到芯片然后跳转到其入口点执行。u-boot-spl.bin你准备好的SPL镜像文件路径。如果成功你将看到类似如下的输出并且开发板上的串口调试终端如果你连接了会开始打印U-Boot的启动信息Verbose output enabled. Reading file u-boot-spl.bin... Loading SPL from 0x20000 (size 0x...) SPL loaded successfully. Jumping to 0x20000...此时板子上的程序已经从BootROM的FEL固件切换到了我们加载的U-Boot SPL。这个SPL会初始化更多的硬件特别是DDR内存并将自己重定位到DDR中运行为运行完整的U-Boot做准备。3.2 第二步利用U-Boot的fastboot进行固件烧录当U-Boot SPL运行起来后它会尝试加载并运行完整的U-Boot。我们可以在U-Boot启动的瞬间打断它通常串口按回车键进入U-Boot命令行。但现在有了更优雅的方式让SPL直接初始化USB Gadget功能将自己模拟成一个USB Fastboot设备。建立Fastboot连接 在第一步的sunxi-fel命令成功后不要断开USB线。U-Boot SPL或完整的U-Boot如果被加载如果配置正确会自动将USB接口切换到Gadget模式枚举为一个Fastboot设备。 在主机上另开一个终端运行sudo fastboot devices如果一切顺利你应该会看到一行输出例如abcdef12 fastboot这表示主机已经识别到了板子上的Fastboot设备。实操心得这里最容易出现的问题是USB设备枚举冲突。有时sunxi-fel程序退出后Linux系统可能没有彻底释放对USB设备的控制导致Fastboot设备无法被识别。如果fastboot devices没有输出可以尝试以下步骤物理上重新插拔一次USB线最有效。运行sudo usb_modeswitch -v 1f3a -p efe8 -R尝试重置USB设备模式需要安装usb-modeswitch。检查内核是否加载了必要的USB Gadget驱动模块如libcomposite,usb_f_fastboot。擦除与烧录分区 Fastboot协议的核心思想是通过命令将主机上的镜像文件“刷写”到设备的指定分区。你需要知道你的系统镜像布局。假设一个典型的Tina Linux布局如下boot分区存放内核(uImage)、设备树(dtb)。rootfs分区存放根文件系统。 那么烧录过程如下# 擦除旧分区非必须但建议 sudo fastboot erase boot sudo fastboot erase rootfs # 烧录boot分区镜像 sudo fastboot flash boot out/boot.img # 烧录根文件系统镜像 sudo fastboot flash rootfs out/rootfs.img # 如果你有一个包含所有分区的完整磁盘镜像也可以直接烧录 # sudo fastboot flash mmcblk0 out/sysimage-sdcard.img每条flash命令执行时都会显示传输进度和写入状态。这个过程的速度取决于USB2.0HS的带宽通常比通过TF卡复制要快。设置启动参数与重启 镜像烧写完成后我们可能还需要通过Fastboot设置一些U-Boot环境变量例如启动命令bootcmd。sudo fastboot oem setenv bootcmd mmc dev 0; fatload mmc 0:1 0x42000000 uImage; fatload mmc 0:1 0x43000000 dtb; bootm 0x42000000 - 0x43000000最后重启设备让它从新烧录的存储中启动sudo fastboot reboot开发板会重启此时它应该从eMMC或SPI NAND中正常启动你刚刚烧录的系统。串口终端将展示完整的启动日志。4. 替代方案与高级技巧除了上述主流的Fastboot方案根据你的工具链和习惯还有其他几种可行的“第二步”路径。4.1 方案B通过FEL直接烧录sunxi-fel write如果你的sunxi-fel工具版本较新且你有一个已知绝对地址的存储设备映射这需要深入了解芯片的内存映射理论上可以直接用sunxi-fel写存储。但这种方法非常危险容易因地址错误导致硬件损坏且不适用于带有坏块管理的NAND Flash。对于普通开发者我极度不推荐这种方式。它通常只在芯片厂商的底层测试中使用。4.2 方案C通过U-Boot命令行与tftp烧录这是一种更“传统”但非常灵活的网络烧录方式适合已连接以太网的开发环境。在第一步加载U-Boot SPL并进入U-Boot命令行后配置网络 setenv ipaddr 192.168.1.100 # 开发板IP setenv serverip 192.168.1.10 # 主机TFTP服务器IP setenv netmask 255.255.255.0使用TFTP将镜像下载到开发板的内存中 tftp 0x42000000 uImage # 将内核镜像加载到内存地址0x42000000 tftp 0x43000000 rootfs.img # 加载根文件系统镜像使用U-Boot的存储命令如mmc write,nand write将内存中的数据写入存储设备 mmc dev 0 # 切换到eMMC设备0 mmc write 0x42000000 0x800 0x2000 # 将内存0x42000000开始的数据写入eMMC从0x800扇区开始共0x2000个扇区这种方式要求你精确计算镜像大小对应的扇区数操作复杂但不受USB驱动兼容性问题影响。4.3 量产与自动化考量如果你需要为数十上百块板子烧录固件手动操作是不可接受的。这时可以将上述两步流程脚本化。编写脚本创建一个Shell脚本如flash_all.sh将sunxi-fel spl和fastboot flash命令按顺序写入并加入错误检测检查命令返回值、设备是否存在。自动进入FEL可以通过控制开发板电源的继电器并模拟“上电瞬间按FEL键”的时序来实现全自动化。或者使用一种特殊的“测试点”短接法在板子上电时自动拉低FEL引脚电平。使用专业工具全志官方为量产提供了“PhoenixSuit”或“LiveSuit”工具它们集成了驱动、烧录逻辑和UI通过USB进行一键烧录其底层原理与我们描述的两步法类似但封装得更易用。在Linux下也可以探索社区开发的sunxi-fel批量烧录脚本。5. 避坑指南与常见问题排查即使理解了原理和步骤实操中依然会遇到各种“坑”。下面是我在多次实践中总结的典型问题及解决方案。问题现象可能原因排查步骤与解决方案sudo sunxi-fel ver无输出或报错1. 板子未进入FEL模式。2. USB线缆或接口不良。3. 主机USB驱动问题。4. 权限不足Linux下。1. 确认FEL按键操作正确串口无其他输出。用lsusb检查是否有1f3a:efe8设备。2. 更换USB线缆尝试主机不同USB口。3. 在Linux下检查~/.xsunxi-fel文件是否存在旧缓存尝试删除。或运行sudo modprobe usbnet。4. 确保使用sudo或当前用户在plugdev组。sunxi-fel spl成功但fastboot devices无设备1. U-Boot SPL未启用或初始化USB Gadget失败。2. USB设备枚举冲突最常见。3. 主机fastboot程序问题。1. 确认编译的U-Boot SPL配置包含CONFIG_SPL_USB_GADGET和CONFIG_SPL_USB_GADGET_SDP。2.立即物理重插USB线。这是解决90%此类问题的最快方法。3. 运行sudo fastboot kill-server然后sudo fastboot start-server。尝试使用Android SDK中的fastboot。fastboot flash过程报错FAILED (remote: ‘unknown command’)1. 分区名称不对。2. 设备端的fastboot实现不支持该命令。1. 在U-Boot命令行下运行mmc part或nand info查看实际分区表使用正确的分区名如mmcblk0p1。2. 尝试基础的flash命令或通过fastboot getvar all查看设备支持的能力。烧录后系统无法启动1. 烧录的镜像不正确或损坏。2. 烧录地址/分区错误。3. U-Boot环境变量如bootcmd未正确设置。4. 存储设备本身有硬件问题。1. 在主机上校验镜像文件的MD5/SHA256。2. 核对烧录命令确认是烧到了boot分区而不是recovery分区等。3. 通过fastboot oem getenv bootcmd检查或进入U-Boot命令行手动设置。4. 尝试换用TF卡启动一个已知好的系统以排除主板其他问题。烧录速度极慢1. USB接口工作在低速LS或全速FS模式而非高速HS。2. 主机USB口或HUB带宽不足。1. 确保使用质量好的USB数据线。某些线缆仅支持充电数据传输引脚可能有问题。2. 将USB线直接插在主机背板的原生USB口上避免使用前置接口或扩展坞。最重要的心得保持串口日志始终开启。无论是进入FEL模式还是U-Boot启动亦或是内核加载串口终端都会打印最底层的调试信息。任何一步失败串口日志都是定位问题的第一手资料。养成“动手前先接好串口”的习惯能节省你大量的猜测时间。USB两步烧录法从本质上讲是利用了芯片底层预留的“后门”将复杂的存储设备编程任务转化为一个相对标准的、可通过USB高速通道完成的数据传输问题。它剥离了对额外硬件烧录器、SD卡的依赖将必备条件降到最低一根数据线一台电脑。掌握了它你就拥有了让开发板“起死回生”的终极能力。在无数次深夜调试和现场支持中正是这套看似简单的流程帮我稳住了阵脚高效地推进了项目。希望这份详细的拆解也能成为你工具箱里一件趁手的利器。