分区规划
本文以licheepi_nano为例,参考官方的flash分区规划,可以得到Flash空间的分区表。
| 分区编号 | 分区作用 | 分区大小 | 地址空间 |
|---|---|---|---|
| mtd0 | spl+u-boot | 1MB(0x100000) | 0x0 ~ 0x100000 |
| mtd1 | dtb | 64KB(0x1000) | 0x100000 ~ 0x110000 |
| mtd2 | kernel | 4MB(0x400000) | 0x110000 ~ 0x510000 |
| mtd3 | rootfs | 剩余空间(0xAF000) | 0x510000 ~ 0x1000000 |
编译spl+U-BOOT
首先要拉取并编译荔枝派官方u-boot,详情可以参考licheepi_nano官方教程文档: 前言 - Sipeed Wiki 或者直接执行下列命令进入配置界面。
git clone https://gitee.com/LicheePiNano/u-boot.git -b nano-v2018.01 && cd u-boot
make licheepi_nano_spiflash_defconfig
make menuconfig
在配置菜单中找到下列选项,并做到对应的配置。
# 对应 `CONFIG_BOOTCMD` 的宏定义
[*] Enable a default value for bootcmd
(sf probe 0 50000000; sf read 0x80C00000 0x100000 0x4000; sf read 0x80008000 0x110000 0x400000; bootz 0x80008000 - 0x80C00000) bootcmd value
# 对应 `CONFIG_BOOTARGS` 的宏定义
[*] Enable boot arguments
(console=ttyS0,115200 earlyprintk panic=5 rootwait mtdparts=spi32766.0:1M(uboot)ro,64k(dtb)ro,4M(kernel)ro,-(rootfs) root=/dev/mtdblock3 rw rootfstype=jffs2) Boot arguments
bootcmd中的sf指令:
sf 命令专门用于访问 SPI NOR flash,在uboot命令行界面下输入help sf可以得到使用说明:
sf probe [[bus:]cs] [hz] [mode]:
sf probe用于初始化flash,sf probe 0 50000000表示初始化SPI0上的flash设备,速度为50MHz。
sf read addr offset|partition len
sf read用于读flash,sf read 0x80C00000 0x100000 0x4000表示读取0x4000长度的字节从flash设备最开始0x100000偏移地址起,到内存0x80C0000处。
sf write addr offset|partition len
sf write用于写flash,sf write 0x80C00000 0x100000 0x4000表示将内存0x80C00000开始0x4000字节长度写入flash设备最开始偏移地址0x100000处。
sf erase offset|partition [+]len
sf erase用于擦除flash设备内容,sf erase 0x100000 0x400000表示擦除0x400000字节内容,从flash设备最开始0x100000偏移处开始。
bootcmd参数详解
console=ttyS0,115200即使用ttyS0作为控制台输出,buadrate=115200
earlyprintk表示内核在启动过程中打印信息到界面上。
panic=5代表内核在无响应5s后进入“恐慌”
rootwait指内核在挂载到根文件系统之前,将一直处于等待
mtdparts=spi32766.0:1M(uboot)ro,64k(dtb)ro,4M(kernel)ro,-(rootfs)表示分区信息,要想使该参数生效,需要在编译kernel时打开MTD(Memerory Technology Device Support)选项。spi32766.0指具体设备,为什么是32766.0可以参考以下文章为什么是spi32766.0-CSDN,后面的内容则是具体的分区大小和分区名称
root=/dev/mtdblock3 rw指明了根文件系统位于的分区,并允许读写
rootfstype=jffs2代表根文件系统类型为jffs2
编译完成后我们就得到了u-boot-sunxi-with-spl.bin,将其保存到新建的Image目录下,该文件夹存放带烧录的镜像文件
编译kernel + dtb
详细的编译流程可以参考Licheepi_nano的官方教程主线Linux编译 - Sipeed Wiki
在make前最好先检查一遍配置信息,并将下列重要选项勾选。
File systems --->
[*] Miscellaneous filesystems --->
<*> Journalling Flash File System v2 (JFFS2) support # 打开jffs2的文件系统支持
(0) JFFS2 debugging verbosity (0 = quiet, 2 = noisy)
[*] JFFS2 write-buffering support
[ ] JFFS2 summary support
[ ] JFFS2 XATTR support
[ ] Advanced compression options for JFFS2
Device Drivers --->
<*> Memory Technology Device (MTD) support --->
<*> Command line partition table parsing # 勾选,用来解析uboot传递过来的flash分区信息。
<*> Caching block device access to MTD devices # 勾选,读写块设备用户模块
<*> SPI-NOR device support --->
编译完成后将得到的ZImage文件和suniv-f1c100s-licheepi-nano.dtb文件,拷贝到刚才创建的Image文件夹下。
编译rootfs,并生成镜像
运行menuconfig后可以进行如下配置,具体配置看个人喜好。
Target options --->
Target Architecture (ARM (little endian)) --->
Target Architecture Variant (arm926t) --->
Toolchain --->
C library (musl) --->
System configuration --->
(ender) System hostname #
(Welcome to my linux) System banner
[*] Enable root login with password (NEW)
(root) Root password
[*] remount root filesystem read-write during boot (NEW)
[*] Install timezone info
(asia) timezone list
(Asia/Shanghai) default local time
Target packages --->
System tools --->
[*] util-linux --->
[*] mount/umount
完成后执行make,这个过程比较慢,可耐心等待10来分钟。不出意外的话会在/out/image目录下生成rootfs.tar文件,将该文件通过以下命令解压到新文件夹。
mkdir rootfs && sudo tar -xvf rootfs.tar -C ./rootfs
制作根文件系统镜像
由于要烧录的目标为Norflash,因此需要先安装mtd-utils工具,可以使用如下命令来安装。
sudo apt-get install mtd-utils
安装完毕后就可以进行镜像制作了,使用以下命令进行分区镜像制作。
sudo mkfs.jffs2 -s 0x100 -e 0x10000 --pad=0xAF0000 -d rootfs/ -o rootfs.img
其中-e指定块大小,-s指定页大小,-e指定擦除块大小,--pad用于指定制作的镜像大小,-d指定要制作的文件目录,-o指定镜像输出文件名称。完成后即可得到名为rootfs.img的根文件系统镜像,将其拷贝至Image文件夹下。至此,系统启动的3块拼图都已经集齐,接下来就是如何将他们整合成一个整体的镜像文件,并烧录进入板子上的nor-flash。
系统镜像的制作
切换到之前我们创建的Image目录,这里存放着文件有我们刚刚编译好的u-boot-sunxi-with-spl.bin,suniv-f1c100s-licheepi-nano.dtb,ZImage,rootfs.img。此时我们可以在该目录下新建一个shell脚本,并在里面添加以下内容:
#bin/sh
dd if=/dev/zero of=download_flash.img bs=1M count=16
dd if=u-boot-sunxi-with-spl.bin of=download_flash.img conv=notrunc
dd if=suniv-f1c100s-licheepi-nano.dtb of=download_flash.img bs=1M seek=1 conv=notrunc
dd if=zImage of=download_flash.img bs=1K seek=1088 conv=notrunc
dd if=rootfs.img of=download_flash.img bs=1K seek=5184 conv=notrunc
这样就将uboot、dtb、kernel、rootfs分别写入了一个空的二进制文件中,从而形成了所谓的系统镜像。而这个download_flash.img就是我们要烧入flash中的最终系统镜像文件。
烧录
为了烧录该镜像,我们需要使用sunxi-fel工具,在使F1C100S/F1C200S上电进入FEL模式后,可以执行以下命令进行烧录
sudo sunxi-fel -p spiflash-write 0x0 download_flash.img
以下是笔者在烧录过程中遇到的一些问题,特在此处记录,以免忘记。
问题一:No package 'libusb-1.0' found
No package 'libusb-1.0' found
fel_lib.c:26:10: fatal error: libusb.h: 没有那个文件或目录
#include <libusb.h>
^~~~~~~~~~
compilation terminated.
Makefile:129: recipe for target 'sunxi-fel' failed
make: *** [sunxi-fel] Error 1
解决:这是因为没有安装libusb-1.0-0-dev,手动安装即可。
sudo apt-get install libusb-1.0-0-dev
问题二:usb_bulk_recv() ERROR:-7:Operation time out
在虚拟机中烧录到一半,进度条卡住不动,并提示usb_bulk_recv() ERROR:-7:Operation time out
解决:可能是在虚拟机环境下造成的,换成windows环境下进行烧录即可,以下提出在windows下使用sunxi-fel的办法
1.下载工具包,链接:链接:pan.baidu.com/s/1ojHNVRY6… 提取码:6w9f
2.接入开发板,使其进入FEL模式
3.解压后运行zadig-2.5.exe,并点击Options选项下的List All Device
4.在列表中选择刚才插入的FEL设备(USB ID:1f3a efe8),选择完毕后点击Reinstall Driver。
5.安装完毕后即可在windows下使用sunxi-fel工具。注意:该工具需要在命令行下运行。不熟悉cmd的可以在windows下装一个git工具来使用。
当烧写完成后,即可重启开发板,可以看到系统成功起来了,至此整个镜像的制作、烧录流程结束。