1. 全志V3s与NOR Flash开发板简介第一次拿到全志V3s开发板时我注意到板子上那颗不起眼的XT25F128B NOR Flash芯片。这种16MB容量的存储介质在嵌入式领域非常典型——价格低廉但性能有限就像给跑车装了个小油箱。与常见的NAND Flash不同NOR Flash允许直接执行代码XIP但写入速度较慢且容量较小。这种特性决定了我们必须精打细算地规划存储空间。荔枝派Zero开发板的硬件布局很紧凑SPI接口的NOR Flash直接连接在V3s的SPI0控制器上。实测发现这颗XT25F128B的擦除块大小是64KB这意味着我们所有的分区设计都必须以64KB为最小单位对齐。就像装修时要考虑瓷砖尺寸一样不当的分区规划会导致大量存储空间浪费。2. 嵌入式Linux四大件与存储妥协2.1 系统必备组件在NOR Flash上部署Linux系统就像玩俄罗斯方块需要巧妙安排几个关键组件U-Boot系统引导程序我通常预留1MB空间设备树(dtb)硬件描述文件64KB足够Linux内核经过裁剪后4MB空间绰绰有余根文件系统剩下的约10.9MB空间全部分配给它2.2 NOR Flash的特殊考量由于NOR Flash的特性我们必须做出一些妥协文件系统必须选择JFFS2这种专为Flash设计的类型内核需要特别配置MTD和SPI-NOR驱动支持U-Boot环境变量必须放在前1MB空间内所有分区起始地址必须按擦除块大小对齐我曾尝试使用ext4文件系统结果系统启动时直接卡死。后来发现是因为ext4的日志特性会频繁擦写Flash导致寿命急剧下降。3. U-Boot编译与配置实战3.1 获取特殊版本U-Boot全志芯片的SPI驱动尚未合并到主线U-Boot需要克隆实验分支git clone -b v3s-spi-experimental https://github.com/Lichee-Pi/u-boot.git cd u-boot3.2 Flash型号配置技巧执行menuconfig时有个坑要注意make ARCHarm menuconfig进入Device Drivers SPI Flash Support后虽然列表里没有芯天下的选项但实测选择Macronix的驱动可以兼容XT25F128B。如果Flash容量大于16MB记得勾选CONFIG_SPI_FLASH_BAR选项。3.3 环境变量关键配置在include/configs/sun8i.h中添加启动参数时一定要在包含sunxi-common.h之前添加#define CONFIG_BOOTCOMMAND sf probe 0; \ sf read 0x41800000 0x100000 0x10000; \ sf read 0x41000000 0x110000 0x400000; \ bootz 0x41000000 - 0x41800000 #define CONFIG_BOOTARGS consolettyS0,115200 earlyprintk panic5 rootwait \ mtdpartsspi32766.0:1M(uboot)ro,64k(dtb)ro,4M(kernel)ro,-(rootfs) root31:03 rw rootfstypejffs2这里有几个关键点root31:03表示使用mtdblock3作为根文件系统rootfstypejffs2指定文件系统类型内存地址0x41000000用于加载内核0x41800000用于设备树4. Linux内核定制化编译4.1 获取适配内核源码使用Lichee Pi维护的内核分支更稳定git clone https://github.com/Lichee-Pi/linux.git cd linux git checkout zero-4.13.y4.2 内核关键配置项必须确保以下选项启用make ARCHarm menuconfig路径Device Drivers Memory Technology Device (MTD) support Command line partition table parsingDevice Drivers Memory Technology Device (MTD) support SPI-NOR device supportFile systems Miscellaneous filesystems Journalling Flash File System v2 (JFFS2) support4.3 设备树修改要点在arch/arm/boot/dts/sun8i-v3s-licheepi-zero.dts中添加SPI节点spi0 { status okay; xt25f128b: xt25f128b0 { compatible jedec,spi-nor; reg 0; spi-max-frequency 50000000; #address-cells 1; #size-cells 1; }; };注意Flash型号必须在内核支持的m25p_ids[]列表中否则无法识别。如果型号不在列表中可以尝试使用通用的spi-nor兼容性标签。5. 文件系统与镜像打包5.1 JFFS2镜像生成首先安装制作工具sudo apt-get install mtd-utils假设已有rootfs目录计算JFFS2分区大小16MB(总空间) - 1MB(uboot) - 64KB(dtb) - 4MB(kernel) 0xAF0000(10.9MB)生成镜像命令mkfs.jffs2 -s 0x100 -e 0x10000 -p 0xAF0000 -d rootfs/ -o jffs2.img参数说明-s 0x100页大小256字节-e 0x10000擦除块大小64KB-p 0xAF0000分区总空间5.2 完整镜像打包脚本创建打包脚本package.sh#!/bin/sh dd if/dev/zero offlashimg.bin bs1M count16 dd ifu-boot-sunxi-with-spl.bin offlashimg.bin bs1K convnotrunc dd ifsun8i-v3s-licheepi-zero.dtb offlashimg.bin bs1K seek1024 convnotrunc dd ifzImage offlashimg.bin bs1K seek1088 convnotrunc dd ifjffs2.img offlashimg.bin bs1K seek5184 convnotrunc执行后会生成16MB的flashimg.bin文件包含所有系统组件。这种打包方式就像制作多层蛋糕每层食材必须精确放置在指定位置。6. 烧录与启动技巧6.1 进入FEL模式的方法全志芯片的FEL模式有三种进入方式不插SD卡且Flash为空使用特殊SD卡启动镜像上电时将SPI_MISO引脚拉低最可靠的方法是先清空Flash然后通过USB连接电脑sudo sunxi-fel version正常连接会显示类似AWUSBFEX soc00001681(V3s)的信息。6.2 镜像烧录命令全盘烧录最简单sudo sunxi-fel -p spiflash-write 0 flashimg.bin如果想单独更新某个组件比如只更新内核sudo sunxi-fel -p spiflash-write 0x110000 zImage烧录完成后复位开发板通过串口可以看到启动日志。如果遇到问题建议先检查U-Boot是否能正确识别Flash内核启动参数中的root参数是否正确JFFS2镜像是否完整无误在实际项目中我发现NOR Flash的写入速度较慢频繁烧录会降低开发效率。因此建议先在SD卡上调试系统稳定后再移植到NOR Flash。