首先是荔枝派的官方文档,写的不是很细,应当说我们必须明确几点: 出厂时 SPI Flash 自带了一个 U-Boot+Linux Kernel(出厂的时候可能烧过了),可直接拿来用。如果希望自己烧固件,才需要后续步骤必须使用移植版的 sunxi-tools 工具,而非官方版必须使用移植版的 U-Boot 工具,而非官方版可以使用最新的主线 Linux 内核荔枝派 Nano 没有 reset 按钮,且使用的是片内 DDR1 DRAM,大小为 32MB,外部 SPI Flash 为 16MB
编译 U-Boot
据说是因为 Winbond 涨价了,所以板子上的 SPI Flash 换成了大陆产 xt25f128,需要修改 U-Boot 的 arch/arm/dts/suniv-f1c100s-licheepi-nano.dts:
&spi0 {pinctrl-names = "default";pinctrl-0 = ;status = "okay";flash@0 {#address-cells = <1>;#size-cells = <1>;compatible = "winbond,xt25f128", "jedec,spi-nor";reg = <0>;spi-max-frequency = <40000000>;};};1234567891011121312345678910111213
然后修改 drivers/mtd/spi/spi_flash_ids.c,在 Winbond 节加入: {"xt25f128", INFO(0x0b4018, 0x0, 64*1024, 256, RD_FULL | WR_QPP | SECT_4K) },11 移植版的 U-Boot 没有做这个步骤,也没有任何说明,这不是故意坑么?
编译 Busybox
参考 用BusyBox制作Linux最小系统,然后要创建 jffs2 文件系统,因为我使用 initramfs,所以就不做这一步。
编译 Linux
我选用主线 Linux。需要启用如下选项(不会吧,你该不会不知道可以用 / 键进行搜索吧?): CONFIG_ARCH_MULTI_V5:选择 ARM v5,选择了这个以后才能选 F1C100sCONFIG_ARCH_SUNXI:选择全志 SoCsCONFIG_MACH_SUNIV:选择了这个以后才能选 F1C100sCONFIG_AEABI:如果出现错误 Kernel panic - not syncing: Attempted to kill init! exitcode=0x00000004 就是因为这个没有选中CONFIG_LOCALVERSION:这个选项用来设置内核启动时显示的额外版本信息,你可以设置为你的名字,看上去像是你的专用版 LinuxCONFIG_BLK_DEV_INITRD:启用 initrd/initramfs,这样就可以先不弄 jffs2,而是使用 ramfsCONFIG_INITRAMFS_SOURCE:指向 busybox 生成的目录CONFIG_SPI:启用 SPICONFIG_MTD:启用 MTDCONFIG_MTD_SPI_NOR:启用 SPI NOR FlashCONFIG_MTD_SPI_NOR_USE_4K_SECTORS:启用 4K 扇区CONFIG_MISC_FILESYSTEMS:启用 JFFS2CONFIG_JFFS2_FS:启用 JFFS2
其他选项不知道就默认就行。编译的时候记得加 -j8 启用 8 线程编译加速。
烧录
烧录 U-Boot 到 SPI Flash 是必须的,至于引导 Linux,可以把 Linux 映像放到 SD、TF 卡中,也可以直接烧到 SPI Flash 中。这里我采用后者。为此,我们准备一个打包脚本(因为我这里使用 initramfs,所以就不需要额外 rootfs 了):
dd if
=/dev/zero of
=firmware.bin bs
=1M count
=16 2
>/dev/null
printf
"create firmware.bin, size 0x%04x\n" $
[1024*1024*16
]
echo
"+======================+"
echo
"| Bootloader: 1MB"
echo
"+----------------------+"
echo
"| dtb: 32KB"
echo
"+----------------------+"
echo
"| zImage: 8MB"
echo
"+----------------------+"
echo
"| rootfs: .MB"
echo
"+======================+"
dd if
=u-boot/u-boot-sunxi-with-spl.bin of
=firmware.bin bs
=1k conv
=notrunc 2
>/dev/null
printf
"uboot: 0x0000, size 0x%04x\n" $
[1024*1024
]
dd if
=linux/arch/arm/boot/dts/suniv-f1c100s-licheepi-nano.dtb of
=firmware.bin bs
=1k seek
=1024 conv
=notrunc 2
>/dev/null
printf
"dtb: 0x%04x, size 0x%04x\n" $
[1024*1024
] $
[32*1024
]
dd if
=linux/arch/arm/boot/zImage of
=firmware.bin bs
=1k seek
=$
[1024+32
] conv
=notrunc 2
>/dev/null
printf
"zImage: 0x%04x, size 0x%04x\n" $
[1024*
(1024+32
)
] $
[1024*1024*8
]
#dd if=jffs2.img of=firmware.bin bs=1K seek=$((1024+32+8192)) conv=notrunc 2>/dev/null
printf
"rootfs: 0x%04x, size 0x%04x\n" $
[1024*
(1024+32+1024*8
)
] $
[1024*
(1024*16 - 1024*9 - 32
)
]
echo
"sf probe 0 50000000 0; sf erase 0 0x1000000; reset"
echo
"sudo sunxi-fel -p spiflash-write 0 firmware.bin"123456789101112131415161718192021222324252627123456789101112131415161718192021222324252627
注意这个 dtb 文件应该使用 linux 编译目标 dtbs 生成,而不应该使用 U-Boot 所生成的 dtb 文件。
然后烧录。根据官方的文档,先把 SPI Flash 的 CS 脚拉低,然后芯片进入 FEL 模式后进行操作。测试发现,sunxi-tools 的烧录命令似乎没有进行 erase,导致我后面烧录的时候,里面的数据根本没有变化。
因此我们在烧新的 U-Boot 前,应该先进入出厂时的 U-Boot ,用以下命令清空 SPI Flash 的 16MB 空间(注意 0 和 50000000之间没有冒号,别被官方文档骗了): sf probe 0 50000000 0sf erase 0 0x1000000reset123123
重新上电,由于没有 SPL 头部,芯片会自动进入 FEL 模式。然后就可以使用 sunxi-tools 来烧写了。 这么隐蔽的坑,那感觉,谁试谁知道
引导 Kernel
重新上电,在 U-Boot 中执行:
setenv bootargs "console=tty0 console=ttyS0,115200n8"sf probe 0 50000000 0sf read 0x80C00000 0x100000 0x8000sf read 0x80008000 0x108000 0x800000bootz 0x80008000 - 0x80C000001234512345
如果你的内核映像在 SD 卡中: setenv bootargs "console=tty0 console=ttyS0,115200n8"load mmc 0:1 0x80C00000 suniv-f1c100s-licheepi-nano.dtbload mmc 0:1 0x80008000 zImagebootz 0x80008000 - 0x80C0000012341234
最终效果 就是在用户登录那里总是有问题,明明已经关闭密码了却还提示密码错误,设置一个有效密码仍然是密码错误,见鬼。最后索性不需要登录了。