全志芯片开发必备:编译sunxi-tools与FEL模式实战指南
1. 为什么我们需要自己编译 sunxi-tools?
如果你玩过全志(Allwinner)方案的开发板,比如大名鼎鼎的香橙派(Orange Pi)、荔枝派(Lichee Pi),或者一些早期的平板、电视盒子,那你大概率听说过或者用过sunxi-tools这个工具集。它可以说是全志芯片玩家的“瑞士军刀”,其中最核心的功能就是FEL 模式。
FEL 模式是什么?简单说,它是全志芯片内置的一种特殊的 USB 启动/烧录模式。当你的开发板变砖了,或者你想绕过 eMMC/SD 卡里的 Bootloader 直接向内存里加载程序进行调试,FEL 模式就是你的救命稻草。通过一根 USB 线连接电脑和板子的 OTG 口,你就能像操作一个 USB 设备一样,直接读写芯片的内存、SPI Flash,甚至直接启动代码。sunxi-tools里的sunxi-fel命令,就是电脑端与这个模式通信的客户端。
那么问题来了,既然很多 Linux 发行版的软件仓库里都有sunxi-tools这个包,为什么还要费劲自己编译“最新版本”呢?我踩过几次坑,总结下来主要有三个原因:
- 官方仓库版本滞后:Ubuntu 的
apt仓库为了稳定性,软件版本更新往往比较慢。你apt install sunxi-tools装上的,可能是一两年前甚至更老的版本。而全志的芯片和生态在持续演进,新版本的工具可能增加了对新款芯片(比如 D1、H616)的支持,修复了老版本中某些芯片的通信 Bug,或者增加了新的实用命令(比如对 SPI NAND 的支持)。用老工具去操作新硬件,轻则功能缺失,重则直接失败。 - 功能阉割与依赖问题:有些发行版打包的
sunxi-tools可能没有开启所有编译选项。比如,对 NAND Flash 操作的支持、详细的调试信息输出等,可能在打包时被默认禁用。自己编译可以确保所有功能都被开启。另外,编译过程本身会解决所有动态库依赖,生成的就是最适合你当前系统的二进制文件。 - 开发与调试需求:如果你是开发者,或者遇到了一个非常诡异的、仅在特定版本出现的 FEL 通信问题,你可能需要查看源码、添加调试打印、甚至打补丁。这时候,有一个本地的、可修改的源码树并进行编译,是排查问题的唯一途径。
所以,自己编译最新版的sunxi-tools,不是为了炫技,而是一个追求稳定、兼容性和深度使用的全志玩家/开发者的基本操作。接下来,我就带你走一遍在 Ubuntu 下从零开始编译的全过程,并分享几个我实际使用中总结出来的关键技巧和避坑点。
2. 编译前的环境准备:不仅仅是apt install
编译任何开源项目,第一步永远是准备好构建环境。对于sunxi-tools这种偏底层的工具,依赖项不多,但每一个都很关键。
2.1 安装必备的编译工具链和库
打开终端,我们首先更新软件源并安装核心的编译工具:
sudo apt update sudo apt install -y build-essential pkg-configbuild-essential:包含了gcc,g++,make等最基础的编译工具。pkg-config:一个用来帮助编译器在编译时找到正确的头文件和链接库的工具,后面配置libusb时会用到。
接下来是sunxi-tools的核心依赖:libusb-1.0。它提供了用户态访问 USB 设备的统一接口。
sudo apt install -y libusb-1.0-0-dev请注意,这里必须安装-dev版本(libusb-1.0-0-dev),它包含了编译所需的头文件(.h)和链接库文件(.so)。如果只安装libusb-1.0-0(运行时库),编译时会因为找不到头文件而失败。这是新手最容易踩的第一个坑。
2.2 获取最新源代码:Git 是唯一推荐的方式
sunxi-tools的官方仓库托管在 GitHub 上。我们使用git来克隆,这能确保我们拿到的是最新的、包含所有提交历史的代码。
# 安装 git(如果尚未安装) sudo apt install -y git # 克隆 sunxi-tools 仓库到当前目录 git clone https://github.com/linux-sunxi/sunxi-tools.git # 进入源码目录 cd sunxi-tools使用git clone而非直接下载压缩包的好处是,你可以随时通过git pull拉取最新的更新,也可以方便地切换分支、查看提交历史来定位问题。
进入目录后,我建议先看一眼README.md文件,了解当前版本的一些基本信息和可能的编译选项。
注意:网络环境可能会影响克隆 GitHub 仓库的速度。如果遇到问题,可以考虑配置 Git 代理或使用国内镜像源,但务必确保源码来源的可靠性。
3. 编译与安装的详细步骤及原理剖析
环境准备好,源码也拉下来了,现在进入核心的编译环节。这个过程不仅仅是执行几条命令,理解每一步在做什么,能让你在遇到问题时更快地定位。
3.1 理解 Makefile 与编译流程
sunxi-tools使用经典的make工具来管理编译。它的根目录下有一个Makefile文件。我们不需要手动修改它,但可以通过向make命令传递参数来影响编译行为。
标准的编译安装流程是三步:
make sudo make install但让我们拆开看,并加入一些有用的参数。
首先,直接运行make,它会:
- 读取
Makefile。 - 根据
Makefile中的规则,调用gcc编译器,将.c源文件编译成.o目标文件。 - 将目标文件与
libusb-1.0等库链接,生成最终的可执行文件(如sunxi-fel,sunxi-nand-part等)。
在make之前,我们通常不需要运行./configure脚本(像很多大型项目那样),因为sunxi-tools的Makefile已经足够智能,能通过pkg-config自动检测libusb的路径。
3.2 执行编译并启用关键特性
我推荐在第一次编译时,加上-j参数来利用多核 CPU 并行编译,加快速度。你可以用nproc命令查看你的 CPU 核心数。
# 使用所有CPU核心进行并行编译 make -j$(nproc)编译完成后,你会在当前目录下看到生成的可执行文件。使用ls -lh sunxi-fel可以查看其大小和属性。
一个重要技巧:开启调试符号。如果你未来可能需要调试sunxi-fel的行为(比如它为什么无法识别你的设备),可以在编译时启用调试信息。虽然这会使二进制文件稍大,但非常有用。
# 清理之前的编译结果(如果已编译过) make clean # 带上调试信息重新编译 make -j$(nproc) CFLAGS="-g -O2"CFLAGS="-g -O2":这是传递给gcc的编译选项。-g:生成调试信息,这样你可以用gdb工具来调试程序。-O2:启用编译器优化级别2,在保持生成代码较小的同时进行较好的优化。这是性能和安全性的一个平衡点,通常比默认的-O0(不优化)或-Os(优化大小)更适合发布。
3.3 安装到系统路径
编译生成的二进制文件还在源码目录里。为了能在任何地方直接使用sunxi-fel命令,我们需要将其安装到系统的标准路径下,比如/usr/local/bin。
sudo make install这条命令会:
- 将
sunxi-fel、sunxi-nand-part等工具复制到/usr/local/bin/。 - 将一些脚本(如
bin2fex、fex2bin)也复制到相应位置。 - 将头文件(如果需要开发)和 man 手册页安装到
/usr/local/include/和/usr/local/share/man/。
安装完成后,你可以打开一个新的终端,直接输入sunxi-fel version来验证是否安装成功。如果成功,它会输出当前工具的版本信息。
注意:
/usr/local/bin默认在系统的PATH环境变量中。如果安装后命令仍找不到,可以尝试执行source ~/.bashrc或重新打开终端。
4. 权限配置:解决 “Cannot open USB device” 错误
这是编译安装后,实际操作时几乎百分百会遇到的第一个,也是最重要的一个坑。当你兴冲冲地连接板子进入 FEL 模式,然后运行sunxi-fel ver想查看芯片信息时,很可能会看到这样的错误:
ERROR: Unable to claim USB device (Cannot open USB device)或者
ERROR: Could not find a FEL device“找不到设备”和“无法打开设备”有时是同一个权限问题导致的。这是因为在 Linux 系统下,普通用户默认没有权限直接访问 USB 设备文件(通常是/dev/bus/usb/00x/00y这样的路径)。libusb需要以 root 身份(通过sudo)才能打开这些设备。
每次都加sudo固然可以,但麻烦且不安全(因为sunxi-fel脚本可能会被恶意利用)。最好的方法是创建一个USB 设备访问规则,让特定的用户组(比如plugdev)获得访问全志 FEL 设备的权限。
4.1 创建 udev 规则文件
Linux 使用udev系统来管理设备节点。我们通过添加一个规则文件来永久解决权限问题。
使用
lsusb命令找到你的全志设备在 FEL 模式下的 USB 厂商ID(Vendor ID)和产品ID(Product ID)。连接板子并进入 FEL 模式(通常需要按住某个按键上电或短接测试点),然后在终端运行:lsusb在输出列表中,寻找类似
Allwinner字样的设备。例如,你可能会看到:Bus 003 Device 007: ID 1f3a:efe8 Onda (unverified) V972 tablet in flashing mode或者更标准的:
Bus 001 Device 005: ID 1f3a:efe8这里的
1f3a:efe8就是VendorID:ProductID。对于大多数全志芯片,FEL 模式的 PID 通常是efe8,VID 可能是1f3a(昂达)或18d1(Google,某些芯片使用)。最通用的做法是匹配PID=0xefe8。创建一个新的 udev 规则文件。规则文件通常放在
/etc/udev/rules.d/目录下,以.rules结尾,数字越小优先级越高。sudo nano /etc/udev/rules.d/10-sunxi-fel.rules(你也可以使用
vim或gedit代替nano)。在文件中添加以下规则内容:
# 全志 FEL 模式设备访问规则 SUBSYSTEM=="usb", ATTR{idVendor}=="1f3a", ATTR{idProduct}=="efe8", MODE="0660", GROUP="plugdev", TAG+="uaccess" SUBSYSTEM=="usb", ATTR{idVendor}=="18d1", ATTR{idProduct}=="efe8", MODE="0660", GROUP="plugdev", TAG+="uaccess"SUBSYSTEM=="usb":规则针对 USB 子系统。ATTR{idVendor}=="..."和ATTR{idProduct}=="...":匹配设备的厂商ID和产品ID。这里我添加了两条,覆盖了两种常见的 VID。MODE="0660":设置设备文件的权限为rw-rw----(所有者和管理员可读写)。GROUP="plugdev":将设备文件的所有组设置为plugdev。你需要确保你的用户在这个组里。TAG+="uaccess":这是一个现代系统(使用systemd和logind)的补充规则,确保用户会话也能获得访问权限,更加可靠。
4.2 应用规则并验证
保存并退出编辑器后,需要让udev重新加载规则并触发重新识别设备。
# 重新加载 udev 规则 sudo udevadm control --reload-rules sudo udevadm trigger # 将当前用户添加到 plugdev 组(如果尚未加入) sudo usermod -a -G plugdev $USER非常重要:usermod命令修改组信息后,需要注销当前用户并重新登录,或者开启一个新的登录会话(比如另一个终端窗口或图形界面会话),组变更才会生效。
完成以上步骤后,拔掉 USB 线,再重新连接板子进入 FEL 模式。此时,你应该可以不使用sudo,直接运行sunxi-fel ver并成功看到芯片信息了。
如果仍然不行,请检查:
- 你的用户是否真的在
plugdev组中(运行groups命令查看)。 - 是否已经重新登录。
- 使用
ls -l /dev/bus/usb/00x/00y(设备路径根据lsusb输出确定)查看设备文件的权限和所属组是否已变为plugdev。
5. 核心工具 sunxi-fel 的实战应用与排坑指南
工具装好了,权限也通了,现在才是真正发挥威力的时候。sunxi-fel命令功能很多,这里我挑几个最常用、也最容易出问题的场景,结合我的实战经验来讲。
5.1 基础设备交互与信息获取
首先,任何时候都要先确认设备是否连接正确。
# 查看已连接的 FEL 设备列表(新版工具支持) sunxi-fel list # 查看芯片信息(最常用的验证命令) sunxi-fel versunxi-fel ver会返回类似如下的信息:
AWUSBFEX soc=00001663(H3) 00000001 ver=0001 44 08 scratchpad=00007e00 00000000 00000000这告诉你,连接的是一个全志 H3 芯片,FEL 协议版本是 0x01。不同芯片的soc代码不同,这是识别芯片型号的关键。
5.2 内存操作:加载与运行代码
这是 FEL 模式最核心的功能之一。你可以将一段二进制程序(比如一个裸机程序、一个 Bootloader)直接加载到芯片的内存中并执行。
# 将 boot.bin 文件加载到内存地址 0x40000000 处 sunxi-fel write 0x40000000 boot.bin # 从内存地址 0x40000000 开始执行代码 sunxi-fel exec 0x40000000关键点与避坑:
- 地址选择:
0x40000000是全志很多芯片的默认 SRAM A1 地址,大小约32KB,是上电后最早可用的内存。对于更大的程序(如 U-Boot),你需要将其加载到 DRAM 地址(如0x40000000或0x42000000,具体看芯片内存映射)。加载到错误的地址会导致程序无法运行或芯片无响应。务必查阅你所用芯片的官方数据手册或相关的开源 Bootloader(如 U-Boot)的链接脚本。 - 文件格式:
sunxi-fel write写入的是纯二进制文件(*.bin)。如果你编译生成的是 ELF 文件(如u-boot),需要先用交叉编译工具链里的objcopy命令进行转换:arm-linux-gnueabihf-objcopy -O binary u-boot u-boot.bin - 执行后状态:
fel exec执行后,程序就开始在芯片上跑了。如果是裸机程序,它可能会控制硬件,此时 FEL 连接可能会中断(因为 USB 控制器被程序接管了)。如果是跳转到了 U-Boot,你通常可以通过串口看到 U-Boot 的输出。此时不要再尝试通过sunxi-fel与芯片通信,除非程序主动退出或复位芯片重新进入 FEL 模式。
5.3 SPI Flash 烧录:救砖与量产
对于使用 SPI Nor Flash 作为存储介质的设备(很多电视盒子、小开发板),sunxi-fel可以直接烧录整个固件,这是救砖的终极手段。
# 假设你的 SPI Flash 在系统中识别为 spiflash # 将固件镜像 flash.bin 烧录到 SPI Flash 的起始位置 sunxi-fel spiflash-write 0 flash.bin重大避坑指南:
- 速度极慢:通过 USB 2.0 烧录 SPI Flash,速度可能只有 50-100 KB/s。一个 16MB 的镜像需要好几分钟。这是正常的,请耐心等待,切勿中断!中断可能导致 Flash 数据不完整,彻底变砖。
- 芯片支持:并非所有全志芯片的 FEL 模式都支持
spiflash-write命令。较新的芯片和sunxi-tools版本支持较好。如果不支持,命令会报错。此时你可能需要先通过fel write和fel exec加载一个专门的 SPI 烧录程序到内存,再通过它来烧写。 - Flash 型号识别:有些版本需要先探测 Flash。可以尝试
sunxi-fel spiflash-info。 - 备用方案:如果
spiflash-write不可用,传统的救砖方法是:先用fel write和fel exec启动一个能运行在 SRAM 中的微型 Bootloader(比如sunxi-fel项目里可能提供的spl镜像),然后通过这个 Bootloader 的 USB 或串口协议来接收并烧写更大的固件。这个过程更复杂,需要寻找对应你芯片的专用“FEL 烧录工具链”。
5.4 常见问题排查思路
即使一切步骤都正确,你还是可能会遇到问题。下面是我的排查清单:
sunxi-fel完全没反应,不报错也不输出:- 检查板子是否真的进入了 FEL 模式。对于不同板子,进入方式不同:可能是按住
FEL键或UBOOT键上电;可能是短接SPI芯片的某些引脚;也可能是通过串口发送特定命令。最可靠的确认方法是观察lsusb命令的输出,看是否有新的全志设备出现。 - 尝试使用
sudo sunxi-fel ver。如果加了sudo能工作,说明还是 udev 权限规则没生效,回头检查第4章的内容。
- 检查板子是否真的进入了 FEL 模式。对于不同板子,进入方式不同:可能是按住
ERROR: Could not find a FEL device:- 驱动问题(仅限Windows):在 Linux 下很少见,因为
libusb是通用驱动。如果在 Windows 下,需要安装zadig替换驱动。 - USB 线或端口问题:换一根质量好的、带数据传输功能的USB 线,并尝试电脑上不同的 USB 端口(最好是主板原生接口,而非机箱前面板或扩展坞)。
- 芯片未进入 FEL:同上,确认进入模式的操作。
- 驱动问题(仅限Windows):在 Linux 下很少见,因为
ERROR: Timeout waiting for header或通信超时:- 这通常发生在
fel write或fel exec过程中。可能的原因:- 加载的二进制文件损坏或格式不对。
- 加载的内存地址错误,导致程序跑飞,芯片死机。
- 电源问题:这是非常常见但又容易被忽略的一点!有些开发板在 FEL 模式下,仅靠 USB 的 5V/500mA 供电可能不足,尤其是接了外设时。尝试给板子单独提供稳定的 5V 电源(注意共地)。
- 解决方法:重新检查二进制文件,确认加载地址,加强电源供应,然后重启板子重新进入 FEL 模式。
- 这通常发生在
命令执行成功但板子没反应:
- 最可能的原因是,你加载并运行的程序,其输出是通过串口(UART)进行的,而不是 USB。你必须连接串口调试线(USB to TTL)到板子的 UART 引脚,并在电脑上用串口终端软件(如
minicom,picocom,PuTTY)查看输出。这是调试 Bootloader 和内核的标配,FEL 只是加载工具,不是调试控制台。
- 最可能的原因是,你加载并运行的程序,其输出是通过串口(UART)进行的,而不是 USB。你必须连接串口调试线(USB to TTL)到板子的 UART 引脚,并在电脑上用串口终端软件(如
6. 进阶:探索 sunxi-tools 的其他实用工具
除了sunxi-fel,这个工具集里还有其他几个宝藏工具,在处理全志平台的镜像时非常有用。
6.1 bin2fex 与 fex2bin:处理 legacy 脚本配置
全志老一代的芯片(A10, A20, A31s 等)使用一种名为FEX(全志配置文件)的文本格式来定义系统硬件参数(如 GPIO、LCD、摄像头配置)。最终的二进制固件里包含的是它的二进制形式BIN。
bin2fex:从一个完整的固件镜像(如sunxi-*.img)中,提取出sys_config.bin并将其反编译成可读的sys_config.fex文本文件,方便你修改。bin2fex sunxi.img > sys_config.fexfex2bin:将你修改好的sys_config.fex文本文件,编译回sys_config.bin,然后再用其他工具(如dd)打包回固件镜像。fex2bin sys_config.fex sys_config.bin
注意:新一代的芯片(H3、H5、H6、F1Cxx 等)已经转向使用 Device Tree(*.dts)作为硬件描述文件,FEX系统逐渐被淘汰。但如果你在折腾一些老设备或特定的定制固件,这两个工具依然是必不可少的。
6.2 sunxi-nand-part:处理 NAND Flash 分区
对于使用 NAND Flash 的设备(如很多平板),这个工具可以帮助你分析 NAND 镜像的分区表信息。
# 查看一个 NAND 镜像文件的分区信息 sunxi-nand-part image.bin它会输出每个分区的名称、起始偏移、大小等。在从设备备份全盘镜像或制作恢复包时,这个信息至关重要。
6.3 编译其他可选工具
在sunxi-tools源码目录下,执行make默认会编译所有工具。但有些工具可能有额外的依赖。你可以查看Makefile来了解。例如,sunxi-pio(用于操作 GPIO)可能需要额外的库。如果你只需要sunxi-fel,也可以单独编译它:
make sunxi-fel sudo cp sunxi-fel /usr/local/bin/自己编译sunxi-tools的过程,本质上是一个与硬件底层打交道的标准化流程。从解决依赖、处理权限,到理解每个命令背后的内存地址和硬件行为,每一步都需要清晰的逻辑和对细节的把控。我强烈建议你在自己的 Ubuntu 系统上完整走一遍这个过程,成功运行起sunxi-fel ver的那一刻,你就掌握了与全志芯片“直接对话”的钥匙。以后无论是救砖、刷机还是底层开发,这套工具链和排查思路都会是你的得力助手。遇到问题多查芯片的数据手册、多看看sunxi-tools的 GitHub Issues 页面,社区里有很多前人留下的宝贵经验。
