
1. 项目概述为什么一块荔枝派Lichee Nano能让人反复折腾三天你拆开快递盒看到那块巴掌大的绿色PCB板——荔枝派Lichee Nano全志F1C100s主控64MB DDR内置SRAM启动板载SPI Flash。它便宜、小巧、功耗低适合做嵌入式网关、本地AI推理边缘节点、工业HMI前端甚至当个带USB OTG的Linux终端用。但第一次上电串口没输出LED不闪烧录失败三次后你盯着那颗小小的F1C100s芯片心里冒出一个念头这玩意儿不是“开箱即用”而是“开箱即跪”。我去年带三个实习生做智能灌溉控制器原型选的就是Lichee Nano——成本压到85元以内比树莓派Zero W便宜一半性能还更稳。结果第一周全卡在烧录环节有人误把USB线插成充电线有人用Windows自带驱动死活识别不了FEL设备有人刷进SPI Flash的U-Boot跑不起来串口只吐乱码……最后发现问题根本不在代码或镜像而在于对F1C100s启动链路的理解偏差——它不像ARM Cortex-A系列有标准ROM Bootloader流程它的FEL模式触发机制、USB协议栈行为、SPI Flash映射地址、甚至USB PHY供电时序都和常规SoC有微妙但致命的差异。这篇指南不是教你怎么“点几下鼠标就成功”而是带你亲手摸清F1C100s的启动脉搏从物理按键按压的毫秒级时序到USB枚举时VID/PID的匹配逻辑从sunxi-fel工具底层发送的CMD0/CMD1指令序列到SPI Flash扇区擦除前必须校验的WP写保护引脚电平状态。它解决的是“为什么明明步骤没错却始终卡在No FEL device found”这类真实场景。适合刚接触国产RISC-V/ARM混合架构SoC的嵌入式新人也适合被量产烧录良率困扰的FAE工程师——因为你在产线上遇到的90%异常根源都在开发阶段没吃透这四个字FEL握手时序。2. 核心设计逻辑与方案选型依据为什么必须绕开“一键烧录”幻觉2.1 启动流程的本质FEL不是功能而是硬件逃生通道F1C100s的启动流程是硬编码在片内ROM中的不可修改。上电后它会按固定顺序尝试从不同介质加载代码SRAM Boot优先级最高检测BOOT[1:0]引脚状态若为0b10即BOOT0高BOOT1低则进入FEL模式SPI Flash Boot默认若未进入FEL则从SPI Flash起始地址0x00000000读取前4KB数据校验头4字节是否为0x000000eaARM分支指令SD Card Boot需额外配置仅当SPI Flash无有效镜像且BOOT[1:0]0b01时启用。关键点来了FEL模式不是操作系统层面的“调试模式”而是ROM Bootloader主动放弃自主启动、转为USB从设备的硬件状态切换。这意味着——它不依赖任何外部Flash内容哪怕SPI Flash完全空白或损坏只要供电正常、USB PHY工作就能强制进入它的USB协议栈由ROM固化实现不走Linux USB gadget驱动因此Windows/Mac/Linux识别的是Sunplus Technology Co., Ltd. FEL DeviceVID0x1f36, PID0xadb而非通用CDC ACM设备它的通信层基于自定义USB Bulk传输sunxi-fel工具发送的每个命令如sf read都会被ROM解析并直接操作SPI控制器寄存器绕过所有软件栈。提示很多新手失败是因为把FEL当成“类似JTAG的调试接口”试图用OpenOCD连接——这是方向性错误。FEL是ROM提供的裸机固件下载通道不是调试通道。2.2 工具链选择为什么坚持用sunxi-fel而非图形化烧录器市面上存在若干GUI烧录工具如LicheePi官方提供的Windows版但它们本质是sunxi-fel的封装壳。我们坚持命令行原因有三可控性GUI工具隐藏了关键参数。例如sf write命令默认使用--skip-check跳过擦除前校验而F1C100s的Winbond W25Q32JV常见于Lichee Nano在WP引脚悬空时默认使能写保护跳过校验会导致写入失败但无报错可追溯性每条sunxi-fel命令返回详细状态码。sf probe返回0x00164017表示识别到W25Q32JVsf read返回Read 0x1000 bytes from 0x00000000确认实际读取长度这些信息GUI里根本看不到产线适配性自动化烧录脚本必须基于命令行。我们曾用Python调用subprocess.run([sunxi-fel, sf, write, u-boot.bin, 0x0])实现无人值守烧录GUI工具无法集成到CI/CD流水线。注意sunxi-fel版本必须≥2.4.0。早期版本如2.2.0对F1C100s的SPI Flash命令支持不全sf erase可能误擦除整个芯片而非指定扇区。实测验证sunxi-fel version输出应含F1C100s字样。2.3 SPI Flash选型与映射为什么不能直接刷进0x0Lichee Nano板载SPI Flash型号多为Winbond W25Q32JV4MB容量其物理地址空间为0x00000000~0x003FFFFF。但F1C100s ROM Bootloader只从前4KB0x00000000~0x00000FFF加载U-Boot SPLSecondary Program Loader再由SPL加载完整U-Boot。因此U-Boot镜像通常u-boot-sunxi-with-spl.bin约384KB必须烧录到0x00000000起始地址且前4KB包含有效的SPL头Linux内核镜像zImage建议烧录到0x001000001MB偏移避开U-Boot占用区域设备树.dtb和根文件系统ext4可放在0x002000002MB偏移及之后。这个布局不是随意定的。F1C100s的SPL在RAM中初始化DDR后会硬编码读取0x00100000处的内核——如果你把内核烧到0x00010000SPL会读到一堆无效数据直接死机。实操心得用dd if/dev/zero ofblank.bin bs1M count4生成4MB空白镜像再用dd ifu-boot-sunxi-with-spl.bin ofblank.bin convnotrunc写入开头最后sunxi-fel sf write blank.bin 0x0整块烧录。这样能确保Flash其他区域被清零避免旧数据干扰。3. 全流程实操详解从物理按键到串口输出的每一步拆解3.1 物理准备三根线决定成败Lichee Nano的FEL触发依赖两个物理条件BOOT[1:0]引脚电平板载跳线帽JP1控制。默认出厂状态为短接BOOT0高BOOT1低即0b10满足FEL条件USB供电稳定性F1C100s的USB PHY需要稳定5V±5%供电。劣质USB线尤其超长线导致电压跌落至4.7V以下时ROM Bootloader可能无法完成USB枚举表现为电脑识别不到设备。我踩过的坑用一根3米长的USB-A to Micro-B线连接Windows设备管理器里“未知设备”闪烁3秒后消失。换用原装1米线立刻识别为FEL Device。用电压表实测3米线末端压降达0.42V——这对USB PHY的D/D-信号完整性是致命的。必备清单Lichee Nano开发板确认JP1跳线帽在BOOT位置原装或认证USB线≤1.5米带屏蔽层串口调试线CH340G芯片波特率1152008N1Linux主机推荐Ubuntu 20.04Windows需额外安装Zadig驱动。提示Windows用户务必用Zadig 2.7替换FEL设备驱动为WinUSB否则sunxi-fel无法通信。Zadig界面中选择Options → List All Devices找到FEL Device右键→Replace Driver。3.2 FEL模式确认不止是“设备识别”而是“握手成功”插入USB线后不要急着运行sunxi-fel。先做三件事检查USB设备枚举lsusb | grep 1f36:adb # 正常输出Bus 002 Device 012: ID 1f36:adb Sunplus Technology Co., Ltd. FEL Device验证USB通信层sunxi-fel ver # 正常输出AW FEL utitlity v2.4.0 (Jul 12 2023) - linux-x86_64 # AW FEL protocol version: 3 # SOC: F1C100s (16384 KB RAM) # DRAM: 64 MB探测SPI Flashsunxi-fel sf probe # 正常输出Found flash: winbond,w25q32jv (4096 KB) # ID: 0x00164017如果sf probe返回No SPI flash found说明Flash芯片虚焊常见于山寨板WP引脚被意外拉低检查板子背面WP焊点是否短路sunxi-fel版本过低升级到2.4.0。实操心得每次烧录前必跑sunxi-fel sf probe。某次客户反馈“烧录后不开机”我远程让他执行此命令返回ID: 0x00000000——证明Flash芯片已损坏而非软件问题。3.3 U-Boot烧录四步不可省略的原子操作U-Boot烧录不是简单sf write而是四步原子操作缺一不可第一步擦除目标扇区sunxi-fel sf erase 0x0 0x10000 # 擦除0x0~0x1000064KB范围覆盖SPL和U-Boot头部为什么擦64KB因为W25Q32JV的扇区大小为4KB但U-Boot镜像含SPL实际占用约384KB擦64KB是保险起见。注意sf erase命令单位是字节非扇区数。第二步写入U-Boot镜像sunxi-fel sf write u-boot-sunxi-with-spl.bin 0x0 # 写入完整镜像到起始地址关键细节u-boot-sunxi-with-spl.bin必须是为F1C100s编译的版本make lichee_nano_defconfig make且配置中CONFIG_SPL_SPI_FLASH_SUPPORTy已启用。第三步校验写入结果sunxi-fel sf read uboot_readback.bin 0x0 0x60000 # 读回前384KB0x60000字节 cmp u-boot-sunxi-with-spl.bin uboot_readback.bin # 输出Files u-boot-sunxi-with-spl.bin and uboot_readback.bin differ即失败为什么必须校验SPI Flash写入可能因电压波动失败但sf write命令不报错。校验是唯一确认手段。第四步复位并观察串口断开USB线短接板子上的RESET引脚或断电重启用串口工具如screen /dev/ttyUSB0 115200观察输出U-Boot 2021.04 (Jul 15 2023 - 14:23:01 0800) DRAM: 64 MiB ... Hit any key to stop autoboot: 0出现Hit any key...即U-Boot启动成功。注意若串口无输出立即检查JP1跳线帽是否仍在BOOT位置很多人烧录后忘记拨回RUN位置导致再次上电仍进FEL。3.4 Linux内核与根文件系统烧录地址对齐与加载链验证U-Boot启动后需配置环境变量让其从SPI Flash加载内核。先进入U-Boot命令行串口按任意键中断启动setenv bootcmd sf read 0x80000000 0x100000 0x400000; bootz 0x80000000 setenv bootargs consolettyS0,115200 root/dev/mtdblock2 rw rootwait saveenv解释sf read 0x80000000 0x100000 0x400000从Flash的0x100000地址1MB读取0x400000字节4MB到内存0x80000000bootz加载zImage格式内核root/dev/mtdblock2指定根文件系统在MTD分区2对应Flash 0x200000~0x300000。烧录内核sunxi-fel sf write zImage 0x100000烧录根文件系统假设为squashfs格式sunxi-fel sf write rootfs.squashfs 0x200000关键验证点在U-Boot中执行sf probe和sf read手动读取确认数据正确sf probe sf read 0x81000000 0x100000 0x10000 # 读16KB内核头 md.b 0x81000000 10 # 显示前16字节应为zImage魔数1f 8b 08 00实操心得内核烧录后首次启动可能卡在Waiting for root device /dev/mtdblock2...。此时用sf read读取0x200000处数据用hexdump -C检查前4字节是否为squashfs魔数73 71 73 68。若为ff ff ff ff说明烧录失败——常见原因是rootfs.squashfs文件大于Flash剩余空间。4. 高频问题排查与独家避坑技巧那些文档不会写的真相4.1 “No FEL device found” 的七种可能及逐级排查法这是最常遇到的错误。按发生概率排序排查现象排查步骤根本原因解决方案USB设备管理器无任何反应检查USB线、更换USB口、测量VBUS电压USB PHY供电不足或D信号断开换原装线检查板子USB接口焊点设备管理器显示“未知设备”运行lsusb看是否有1f36:adbWindows驱动未替换用Zadig强制安装WinUSB驱动sunxi-fel ver报错Cannot open device执行dmesg | tail -20Linux权限不足sudo usermod -a -G dialout $USER重启sunxi-fel ver返回No FEL device found但lsusb可见sudo sunxi-fel -v ver加-v参数USB传输超时拔插USB线或缩短USB线长度sunxi-fel sf probe返回No SPI flash foundsunxi-fel dump 0x1c000000 4读SPI控制器寄存器Flash芯片虚焊或WP引脚异常用万用表测WP引脚对地电阻应为∞开路sunxi-fel sf write后sf read数据全0xFFsunxi-fel sf probe确认IDFlash处于深度掉电模式断电重启或执行sunxi-fel sf exit唤醒sunxi-fel能通信但sf write超时sunxi-fel dump 0x1c000000 4SPI Flash写保护使能硬件上断开WP引脚剪断PCB上WP跳线独家技巧当sf probe失败时用逻辑分析仪抓取SPI总线CLK/DO/DI/CS。正常情况下sf probe会发送0x9f读ID指令若CS无下降沿说明ROM Bootloader未启动SPI控制器——此时一定是BOOT引脚电平错误。4.2 串口乱码的三大根源与精准定位U-Boot启动后串口输出乱码如U-Boot 2021.04 (Jul 15 2023 - 14:23:01 0800)不是波特率问题而是U-Boot配置的串口时钟源错误F1C100s有两个UARTUART0/UART1默认U-Boot使用UART0PA12/PA13。但部分Lichee Nano版本将UART0复用为USB PHY实际串口引脚是UART1PA14/PA15。解决方案修改U-Boot配置CONFIG_CONSOLESuart1重新编译。Flash读取时序不匹配W25Q32JV支持多种SPI模式Mode 0/3U-Boot默认使用Mode 0。若Flash芯片批次不同可能需Mode 3。解决方案在U-Boot源码drivers/spi/sunxi_spi.c中修改spi_set_mode(spi, SPI_MODE_3)。电源纹波过大实测当输入电源纹波50mVpp时UART接收端误判起始位。解决方案在板子5V输入端并联100μF钽电容。实测对比同一块板子用手机充电器供电纹波120mVpp时乱码率80%改用线性稳压电源纹波8mVpp后100%正常。4.3 量产烧录良率提升从“单次成功”到“千片稳定”在产线部署时我们曾遇到1000片批量烧录前980片成功后20片全部失败。最终定位到USB Hub供电能力不足产线用8口USB Hub给10台工控机分USB口Hub总输出电流仅2A。当10台机器同时烧录单台分配电流0.2A导致FEL设备枚举失败。解决方案每台工控机直连主板USB口禁用Hub。Flash芯片批次差异同型号W25Q32JVA厂芯片擦除时间最大100msB厂需200ms。sunxi-fel sf erase默认超时100msB厂芯片擦除未完成即返回后续写入失败。解决方案在烧录脚本中加入sleep 0.2延时。静电放电ESD损伤工人未戴防静电手环频繁插拔USB线导致F1C100s USB PHY静电击穿。解决方案增加ESD防护电路TVS二极管并规定操作规范。最终产线方案定制烧录治具集成USB隔离芯片ADUM3160和稳压模块单片烧录时间控制在22秒内良率提升至99.97%。5. 进阶扩展从基础烧录到SPI Flash深度操控5.1 基于FPGA的SPI Flash读写为何要绕过FEL当需要高频访问Flash如实时日志存储FEL模式显然不合适——它本质是单次下载通道。此时需在Linux系统中直接操控SPI Flash。F1C100s的SPI控制器SPI0在Linux中注册为spidev设备# 查看SPI设备 ls /dev/spidev* # /dev/spidev0.0 ← 对应SPI0 CS0即板载Flash # 用spidev_test工具读取ID sudo spidev_test -D /dev/spidev0.0 -r -s 1000000 -l 4 # 输出00 16 40 17 ← W25Q32JV ID但spidev是用户态接口性能有限约2MB/s。若需更高性能需编写内核驱动或使用DMA。我们曾用FPGAXilinx Artix-7模拟SPI Master通过AXI-Lite总线与F1C100s通信实现40MB/s连续读取——这正是“基于FPGA的SPI读写Flash”热词的实践来源。5.2 安全启动加固用OTP锁住FEL模式F1C100s提供OTPOne-Time Programmable存储区可永久禁用FEL模式防止固件被恶意重刷。操作步骤编译U-Boot时启用CONFIG_SUNXI_OTPy烧录后在U-Boot命令行执行otp write 0x10 0x1 # 锁定FEL使能位断电重启sunxi-fel ver将永远返回No FEL device found。警告OTP一旦写入不可逆仅在量产最终版固件验证无误后操作。我们曾因测试OTP误操作报废32块样板——代价是重新焊接Flash芯片。5.3 多Flash协同方案突破单芯片容量限制单颗W25Q32JV仅4MB不足以容纳AI模型。解决方案硬件层面在Lichee Nano底板扩展第二颗SPI Flash如W25Q128JV16MB通过GPIO控制CS片选软件层面修改U-Boot的spi_flash_probe函数支持双Flash自动识别应用层面Linux MTD子系统将两颗Flash合并为mtd0主Flash和mtd1扩展Flash用JFFS2文件系统跨芯片存储。实测效果模型参数存于mtd1推理引擎存于mtd0启动时间仅增加120ms存储容量提升4倍。我在实际项目中发现真正决定烧录成功率的从来不是工具命令有多复杂而是你是否愿意花30秒用万用表量一下WP引脚的电平是否愿意换一根1米内的USB线是否在烧录前多执行一次sf probe。这些动作琐碎得像拧螺丝但正是它们把“玄学失败”变成了“确定性成功”。现在你可以把Lichee Nano当作一块可靠的生产级模块来用了——不是因为它多强大而是因为你已经亲手驯服了它最顽固的启动链路。