资料索引与基础说明

前言

最早接触到F1C100s是前两年的一个文章,里面使用F1C100s制作了一张可以运行Linux的名片,就是下图这个。下图上实际电路部分就占用角落一点点面积,当时觉得蛮有意思的的,可以跑Linux的开发板可以做这么小,成本和常见单片机最小系统板差不多,用来玩挺有意思的。

在这里文章里了解到 Sipeed Lichee Nano (荔枝派Nano),这个差不多可以当作F1C100s的最小系统板板用了,某宝一搜一大片,当时价格还不错,这两年因为疫情等各种原因价格上涨不少。

这篇文章将介绍下上手玩F1C100s需要的一些基础信息,方便回头查询使用。

资料来源

u-boot & linux

F1C100s玩的最多的就是拿来搞Linux玩,重要的是针对该芯片的uboot和linux的修改,这里收集了一些主要的项目:

u-boot

  • https://github.com/Icenowy/u-boot
    这个项目有 f1c100sf1c100s-spiflash 两个分支,后者更加新点;
    分支中有 licheepi_nano_defconfiglicheepi_nano_spiflash_defconfig 两个配置文件;
  • https://github.com/Lichee-Pi/u-boot
    这个项目包含荔枝派所有的u-boot,对于F1C100s而言则是在前面项目的 f1c100s-spiflash 分支基础上新增了 nano-lcd800480 分支,增加了对lcd的支持;

linux

基础特性

F1C100s是全志的一颗比较便宜的芯片,其功能框图如下:

典型应用如下:

  • F1C100s的内核是 ARM926EJ-S ,ARMv5架构,有MMU,没有硬件FPU,主频默认为408MHz;
  • F1C100s内置32MB DDR1内存;
  • F1C200s是F1C100s的兄弟型号,其它特性都相同,内存容量翻倍为64MB;

F1C100s和F1C200s价格便宜的时候可以在1~2刀左右,带有LCD、摄像头、音频、视频等接口,还内置几十兆内存,用来简单的点屏使用比单片机之类的好多了。所以经常可以看到用F1C100s来做行车记录仪或是复古游戏机等产品。

启动过程

F1C100s的启动过程在它流出的手册中并没有找到相关描述,在 全志V3sDataSheet4.2. Boot System 章节中倒是有相似描述,可以作为参考:

芯片上电启动后,芯片会先执行内部固化的程序(BROM),该程序会依次检查外部存储器是否可用,如果可用再从中加载第二阶段程序(SPL)并执行。如果前面过程失败了则会进入全志系列处理器内置的FEL模式。

对于F1C100s而言启动时寻找用户程序的位置顺序如下:

  • SDC0接口(PF0~PF5)上的SD(TF)卡;
  • SPI0接口(PC0~PC3)上的Nor Flash;
  • SPI0接口(PC0~PC3)上的Nand Flash;

对于SD(TF)卡而言在它上面的数据存储布局通常如下****:

start sector size usage
0KB 0 8KB Unused, available for an MBR or (limited) GPT partition table
8KB 16 32KB Initial SPL loader
—- —- ——— ——————
40KB 80 Max 984KB U-Boot
1MB 2048 - bootfs and rootfs

上面参数中SPL从8K位置开始不能动(这是由BROM决定的);文件系统可以根据需要来分区,boot分区在前,通常为FAT格式。

如果使用上文列出的那些 u-boot 项目,编译后会得到 u-boot-sunxi-with-spl.bin 这个文件会拼合 spl 和 u-boot ,直接把这个文件写入到 8KB 开始的位置就行了。

更多内容可以参考:https://linux-sunxi.org/Bootable_SD_card

对于SPI Flash而言其实和SD(TF)卡而言差不多,最关键的就是将 u-boot-sunxi-with-spl.bin 文件放在头部,即从0位置开始写入;其它内容根据需求而设置,只要对应的调整 u-boot 读取启动内核时相关位置参数就行。

需要注意的是默认情况下SPI Flash最大支持16M,更大就需要在程序中设置bank了。

FEL模式

上文中可以了解到F1C100s要是启动外部程序均失败的话就会进入FEL模式,用户可以通过USB和芯片进行交互 。在FEL模式你可以直接运行 u-boot 和 linux 等,也可以将数据写入spiflash中(可以用作烧录固件到设备中)。

FEL模式其实也就是BROM上的一段程序,可以在 u-boot 命令行中使用 go 0xffff0020 跳转进入。另外也可以通过在SD(TF)卡写入下面数据来通过SD(TF)卡启动跳转:

1
2
3
4
# sdX 为SD(TF)卡,使用 sudo fdisk -l 查看
# 如果有自动挂载的分区则逐条使用 sudo umount /dev/sdXn 进行卸载
wget https://github.com/linux-sunxi/sunxi-tools/raw/master/bin/fel-sdboot.sunxi
sudo dd if=fel-sdboot.sunxi of=/dev/sdX bs=1024 seek=8

如果外接了SPI Flash,并且SPI Flash中有可运行的程序的话可以将F1C100s的 Pin60 - PC1 - SPI0_CS 即 SPI Flash 的 1 脚接地后进入FEL模式。

为了和FEL模式下的芯片交互我们还需要用到 sunxi-tools 工具包,针对运行程序或烧录等操作需要用到其中的 sunxi-fel 工具,工具包项目地址如下:
https://github.com/Icenowy/sunxi-tools

针对F1C100s的 sunxi-fel 工具可以使用下面方式下载、编译、安装:

1
2
3
4
5
6
7
8
9
10
11
sudo apt install pkg-config zlib1g-dev libusb-1.0-0-dev
git clone https://github.com/Icenowy/sunxi-tools.git -b f1c100s-spiflash
cd sunxi-tools
make
# 编译完成后可以使用下面方式安装到系统目录
# sudo make install
# 不过其实不推荐安装到系统目录,因为全志不同的芯片需要用不同分支的sunxi-tools
# 更加推荐使用时临时添加环境目录,比如下面这样
# export PATH=$PATH:sunxi-tools目录路径
# 这种方式使用时需要用下面方式
# sudo `which sunxi-fel` [-选项] 命令 参数

安装完成后可以使用 sudo sunxi-fel -l 列出所有处于FEL模式的设备、使用 sudo sunxi-fel ver 设备 BROM 信息:

可以使用 sudo sunxi-fel uboot /path/u-boot-sunxi-with-spl.bin 来直接运行u-boot程序;

可以使用 sudo sunxi-fel -p spiflash-write addr file (addr常用0)将数据写入spiflash(注意最大16M,再大可能需要改程序)。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
Usage: ./sunxi-fel [options] command arguments... [command...]
-v, --verbose Verbose logging
-p, --progress "write" transfers show a progress bar
-l, --list Enumerate all (USB) FEL devices and exit
-d, --dev bus:devnum Use specific USB bus and device number
--sid SID Select device by SID key (exact match)

spl file Load and execute U-Boot SPL
If file additionally contains a main U-Boot binary
(u-boot-sunxi-with-spl.bin), this command also transfers that
to memory (default address from image), but won't execute it.

uboot file-with-spl like "spl", but actually starts U-Boot
U-Boot execution will take place when the fel utility exits.
This allows combining "uboot" with further "write" commands
(to transfer other files needed for the boot).

hex[dump] address length Dumps memory region in hex
dump address length Binary memory dump
exe[cute] address Call function address
reset64 address RMR request for AArch64 warm boot
readl address Read 32-bit value from device memory
writel address value Write 32-bit value to device memory
read address length file Write memory contents into file
write address file Store file contents into memory
write-with-progress addr file "write" with progress bar
write-with-gauge addr file Output progress for "dialog --gauge"
write-with-xgauge addr file Extended gauge output (updates prompt)
multi[write] # addr file ... "write-with-progress" multiple files,
sharing a common progress status
multi[write]-with-gauge ... like their "write-with-*" counterpart,
multi[write]-with-xgauge ... but following the 'multi' syntax:
<#> addr file [addr file [...]]
echo-gauge "some text" Update prompt/caption for gauge output
ver[sion] Show BROM version
sid Retrieve and output 128-bit SID key
clear address length Clear memory
fill address length value Fill memory

对于Windows上装虚拟机来操作的话这之间还有一个坑:默认情况下FEL模式的USB设备Windows是无法识别的,这样就更没法传递给虚拟机使用了。这个问题可以使用 https://zadig.akeo.ie/ 这个工具来安装驱动解决(主要关注VID和PID就行):

除了 sunxi-fel ,也可以使用第三方的 XFEL 工具来进行FEL模式下的交互操作, XFEL 还有提供windows版本的可执行文件。项目地址如下:
https://github.com/xboot/xfel

关于FEL模式的更多内容可以参考下面链接:
https://linux-sunxi.org/FEL
https://linux-sunxi.org/FEL/USBBoot

电路设计

电路设计上主要有下面一些注意点:

  • SD(TF)卡连接在SDC0
    Pin53 - PF5 - SDC0_D2
    Pin54 - PF4 - SDC0_D3
    Pin55 - PF3 - SDC0_CMD
    Pin56 - PF2 - SDC0_CLK
    Pin57 - PF1 - SDC0_D0
    Pin58 - PF0 - SDC0_D1
  • SPI Flash连接在SPI0
    Pin59 - PC0 - SPI0_CLK
    Pin60 - PC1 - SPI0_CS
    Pin61 - PC2 - SPI0_MISO
    Pin62 - PC3 - SPI0_MOSI
  • FEL模式通过USB通讯
    Pin68 - USB-DM
    Pin69 - USB-DP
  • 控制台交互通过UART0
    Pin48 - PE1 - UART0_TX
    Pin49 - PE0 - UART0_RX
  • 供电
    VCC-CORE - 1.0~1.2V
    VCC-DRAM - 2.3~2.7V SVREF - 通过电阻将VCC-DRAM分压成一半
    AVCC - 2.5~3.1V
    VCC-IO / UVCC / HPVCC / TV_VCC - 2.5~3.1V

电路设计上可以参考 荔枝派Nano 的原理图(可以点击查看大图):

如果对电路功能上没啥需求,只需要跑个Linux玩的话可以参考 Business Card 的原理图(可以点击查看大图):

u-boot & linux & rootfs 编译与烧录测试(基于SD卡)

基础准备

硬件准备

测试用开发板可以参考上面文章中电路绘制,或者也可以直接购买荔枝派Nano进行测试。

开发环境

下载安装Ubuntu Desktop(使用版本为20.04):
https://ubuntu.com/download/desktop

安装完成后进行基础环境安装与设置:

1
2
3
4
5
6
7
8
9
10
11
12
sudo apt update

sudo apt install -y build-essential
sudo apt install -y libusb-1.0-0-dev zlib1g-dev
sudo apt install -y pkg-config
sudo apt install -y python python3 python-dev python3-dev
sudo apt install -y swig
sudo apt install -y libncurses-dev libncurses5-dev
sudo apt install -y libssl-dev
sudo apt install -y kpartx
sudo apt install -y mtd-utils

因为需要从GitHub下载项目所以还要安装git:

1
2
3
4
5
sudo apt install -y git
# git使用时可能需要设置用户名和邮箱
# git config --global user.name "naisu"
# git config --global user.email naisu@example.com

建立工作目录并进入:

1
2
3
4
5
# 本文将工作目录设置在用户目录($HOME)下的f1c100s-sdk文件夹中
# cd ~
mkdir f1c100s-sdk
cd f1c100s-sdk/

制作toolchain和rootfs

为了方便这里使用buildroot来制作rootfs,这里有个坑。这里如果使用linaro等组织提供的现成的交叉编译工具链来编译buildroot项目生成rootfs,在使用时系统启动过程中可能会出现 Kernel panic - not syncing: Attempted to kill init! exitcode=0x0000000b ,而使用buildroot自己生成的编译工具链就不会出现这个问题了。所以我们这里统一使用buildroot生成的编译工具链。

下载、解压与配置:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# cd ~/f1c100s-sdk/
wget https://buildroot.org/downloads/buildroot-2022.02.tar.xz
tar -xJf buildroot-2022.02.tar.xz

# 进入buildroot-2022.02目录
cd buildroot-2022.02/

# 进行配置
# 这里做测试使用,只要配置下目标和工具链即可,详见后面截图
make menuconfig

# 编译
make

编译完成后 output 目录下的 host 目录中就是交叉编译工具链(toolchain); output 目录下的 images 目录中的 rootfs.tar 就是生成的根文件系统。

设置编译工具链

注意PATH使用自己的路径,每次打开终端都需要重新设置:

1
2
3
4
export ARCH=arm
export CROSS_COMPILE=arm-buildroot-linux-gnueabi-
export PATH=$PATH:/home/nx/f1c100s-sdk/buildroot-2022.02/output/host/bin

u-boot & linux编译

u-boot

下载、配置、编译:

1
2
3
4
5
6
7
8
9
10
11
12
# cd ~/f1c100s-sdk/
git clone -b nano-lcd800480 --depth=1 https://github.com/Lichee-Pi/u-boot.git

# 进入u-boot目录
cd u-boot/

# 加载配置文件
make licheepi_nano_defconfig

# 修改默认bootcmd
gedit include/configs/suniv.h

需要修改为:

1
#define CONFIG_BOOTCOMMAND "run distro_bootcmd"

然后就可以编译了:

1
2
# 根据电脑配置使用make -jx等加快编译速度
make

编译后当前目录下的 u-boot-sunxi-with-spl.bin 文件就是我们需要的。

boot.scr

根据上面对bootcmd的修改,u-boot启动时会从第一分区读取 boot.scr 文件,并执行其中的脚本。我们可以通过这个来设置要传递给linux内核的参数、来加载内核和设备树、来启动内核。

在uboot目录下新建boot.cmd文件,向其中写入u-boot要执行的脚本:

1
2
3
# cd ~/f1c100s-sdk/u-boot/
touch boot.cmd
gedit boot.cmd

写入以下内容:

1
2
3
4
5
6
7
# 设置传递给内核的bootargs参数
# 读取内核镜像和设备树到内存中指定位置
# 启动内核程序
setenv bootargs console=tty0 console=ttyS0,115200 panic=5 rootwait root=/dev/mmcblk0p2 rw
load mmc 0:1 0x80008000 zImage
load mmc 0:1 0x80C00000 suniv-f1c100s-licheepi-nano.dtb
bootz 0x80008000 - 0x80C00000

使用u-boot编译后tools目录下的 mkimage 工具可以将boot.cmd文件生成为 boot.scr 文件,通过下面命令:

1
2
# arm架构;不压缩;script文件;输入boot.cmd文件;输出boot.scr文件
tools/mkimage -A arm -C none -T script -d boot.cmd boot.scr

生成的 boot.scr 文件就在当前目录下。

linux

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# cd ~/f1c100s-sdk/
git clone -b nano-4.14-exp --depth=1 https://github.com/Lichee-Pi/linux.git

# 进入linux目录
cd linux/

# 下载使用荔枝派Nano的linux配置文件
wget https://dl.sipeed.com/fileList/LICHEE/Nano/SDK/config
cp config .config

# 根据需要配置,没有需要的话直接按两下Esc保存退出
make menuconfig

# 编译
# 根据电脑配置使用make -jx等加快编译速度
# 过程中如果出现需要设置的选项全部选n
make

编译后在 arch/arm/boot/ 目录下的 zImage 文件就是压缩后的内核程序;在 arch/arm/boot/dts/ 目录下的 suniv-f1c100s-licheepi-nano.dtbsuniv-f1c100s-licheepi-nano-with-lcd.dtb 文件就是编译后的设备树文件。

测试程序

嵌入式linux开发最终是需要在系统上运行应用程序来实现特定的功能需求,这里编写个基础的应用程序用于测试:

1
2
3
4
5
6
7
8
9
# cd ~/f1c100s-sdk/
# 建立程序文件夹并进入
mkdir helloworld
cd helloworld/

# 建立程序文件并编写程序
touch helloworld.c
gedit helloworld.c

写入以下内容:

1
2
3
4
5
6
#include <stdio.h>

int main(void)
{
printf("Hello, world!\n");
}

编译生成可执行文件:

1
arm-buildroot-linux-gnueabi-gcc helloworld.c -o helloworld

生成的 helloworld 就是我们需要的可执行文件了。

文件烧录

前面编译生成的内容可以分块分别烧录进SD卡进行测试,也可以将 u-boot & linux & rootfs 整块打包烧录进SD卡进行测试,其实本质上是一样的,这里先进行分块测试的介绍,打包烧录介绍将在后面的章节说明。

1
2
3
# 先将SD卡插入Ubuntu中
# 使用 lsblk 查看SD卡设备号sdX
# 我这里显示为sdb,下面均以此进行说明

分区设置

准备SD卡并按要求分区,空间划分参考本文开头的给出的文章,下面是在Ubuntu终端中进行分区划分示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 如果已经分过区了那么Ubuntu可能会自动挂载
# 逐条使用 sudo umount /dev/sdbn 进行卸载

# 对SD(TF)卡进行分区
sudo fdisk /dev/sdb
# 如果有分区的话可以输入 d 回车依次删除
# 输入 n 新建分区,分区大小根据需要设置即可
# 下面是我新建的两个分区的输入情况
# n回车 回车(p) 回车(1) 回车(2048) +32M回车 (如果有额外提示则Y回车)
# n回车 回车(p) 回车(2) 回车(67584) +200M回车 (如果有额外提示则Y回车)
# 输入 w 回车保存退出,输入使用 lsblk 查看分区情况

# 格式化分区建立文件系统
sudo mkfs.vfat /dev/sdb1
sudo mkfs.ext4 /dev/sdb2

分块烧录

u-boot
u-boot-sunxi-with-spl.bin 文件需要放置在SD卡8k开始的位置上:

1
2
# cd ~/f1c100s-sdk/u-boot/
sudo dd if=u-boot-sunxi-with-spl.bin of=/dev/sdb bs=1024 seek=8

linux & dtb & boot.scr
这三个放在刚才新建的第一个分区里(sdb1):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 如果分区已挂载到别的地方先进行卸载
# sudo umount /dev/sdb1
# 将分区挂载到 /mnt
sudo mount /dev/sdb1 /mnt

# 拷贝linux和dtb
# cd ~/f1c100s-sdk/linux/
sudo cp arch/arm/boot/zImage /mnt/
sudo cp arch/arm/boot/dts/suniv-f1c100s-licheepi-nano.dtb /mnt/

# 拷贝boot.scr
# cd ~/f1c100s-sdk/u-boot/
sudo cp boot.scr /mnt/

# 保存退出
# sync
# sudo umount /dev/sdb1

rootfs
这个放在刚才新建的第二个分区里(sdb2):

1
2
3
4
5
6
7
8
9
10
11
12
# 如果分区已挂载到别的地方先进行卸载
# sudo umount /dev/sdb2
# 将分区挂载到 /mnt
sudo mount /dev/sdb2 /mnt

# 解压并拷贝rootfs
# cd ~/f1c100s-sdk/buildroot-2022.02/
sudo tar -xf output/images/rootfs.tar -C /mnt/

# 保存退出
# sync
# sudo umount /dev/sdb2

测试程序

1
2
3
4
5
6
7
8
9
10
11
12
13
# 如果分区已挂载到别的地方先进行卸载
# sudo umount /dev/sdb2
# 将分区挂载到 /mnt
sudo mount /dev/sdb2 /mnt

# 拷贝helloworld
# cd ~/f1c100s-sdk/helloworld/
sudo cp helloworld /mnt/root/

# 保存退出
# sync
# sudo umount /dev/sdb2

上电测试

上电打印信息与应用程序测试结果与关键日志如下:

默认通过UART0 PE0-RX PE1-TX 波特率115200
我这里使用的是F1C200s,所以内存显示为 64 MiB
前面生成的rootfs登陆用户名为root,无密码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
U-Boot SPL 2018.01-gd83b2fe-dirty (Mar 15 2022 - 15:52:58)
DRAM: 64 MiB
Trying to boot from MMC1


U-Boot 2018.01-gd83b2fe-dirty (Mar 15 2022 - 15:52:58 +0800) Allwinner Technology

CPU: Allwinner F Series (SUNIV)
Model: Lichee Pi Nano
DRAM: 64 MiB
MMC: SUNXI SD/MMC: 0

省略若干内容……

mmc0 is current device
Scanning mmc 0:1...
Found U-Boot script /boot.scr
reading /boot.scr
279 bytes read in 14 ms (18.6 KiB/s)
## Executing script at 80c50000
reading zImage
3841152 bytes read in 200 ms (18.3 MiB/s)
reading suniv-f1c100s-licheepi-nano.dtb
7464 bytes read in 25 ms (291 KiB/s)
## Flattened Device Tree blob at 80c00000
Booting using the fdt blob at 0x80c00000
Loading Device Tree to 816fb000, end 816ffd27 ... OK

Starting kernel ...

[ 0.000000] Booting Linux on physical CPU 0x0
[ 0.000000] Linux version 4.14.0-licheepi-nano+ (nx@nx-ubuntu) (gcc version 10.3.0 (Buildroot 2022.02)) #1 Tue Mar 15 16:07:52 CST 2022
[ 0.000000] CPU: ARM926EJ-S [41069265] revision 5 (ARMv5TEJ), cr=0005317f

省略若干内容……

[ 1.331930] Waiting for root device /dev/mmcblk0p2...
[ 1.375977] mmc0: host does not support reading read-only switch, assuming write-enable
[ 1.390277] mmc0: new high speed SDHC card at address aaaa
[ 1.396880] mmcblk0: mmc0:aaaa SC16G 14.8 GiB
[ 1.407742] mmcblk0: p1 p2

省略若干内容……

Starting syslogd: OK
Starting klogd: OK
Running sysctl: OK

省略若干内容……

Welcome to Buildroot
buildroot login: root
# ls
helloworld
# ./helloworld
Hello, world!
#

系统镜像

前面分块烧录在测试的时候用用还行,但是如果是要批量生产或是交给他人使用就不方便了,这个时候可以制作系统成单个系统镜像文件来处理。

前面讲了对SD卡分区等操作,其实不管是分区还是数据拷贝等,最终在SD卡上无非就是一片按照一定顺序存储的数据。把这段数据原模原样的拷贝成一个文件,这就是系统镜像文件,使用的时候只要把这个文件内容拷贝到SD卡上就可以了。

制作镜像文件

从已有SD卡制作镜像文件
如果有已经烧录完成所有内容的SD卡的话直接使用 dd 命令将SD卡内容复制到一个文件即可得到系统镜像文件。比如针对前面流程下的SD卡可以使用下面方式:

1
2
3
4
5
6
7
8
9
10
11
12
13
# cd ~/f1c100s-sdk/

# 如果分区已挂载到别的地方先进行卸载
# sudo umount /dev/sdb1
# sudo umount /dev/sdb2

# 创建系统镜像文件
touch f1c100s-system-image.bin
# 将SD卡中有用的数据保存镜像文件中
# 大小为 1M(uboot) + 32M(bootfs) + 200M(rootfs) + 2M(多拷贝点,防止不明意外)
# 数据比较大会花点时间
dd if=/dev/sdb of=f1c100s-system-image.bin bs=1M count=235

从编译生成的文件制作
如果还没有烧录好的SD卡也可以直接从编译生成的文件制作

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
# cd ~/f1c100s-sdk/
# rm f1c100s-system-image.bin

# 创建系统镜像文件
touch f1c100s-system-image.bin
# 向镜像文件写入空数据固定大小
dd if=/dev/zero of=f1c100s-system-image.bin bs=1M count=235

# 查看可用的设备挂载点
sudo losetup -f
# 我这里显示 /dev/loop13,接下来都以此进行说明
# 将镜像文件挂载到 /dev/loop13
sudo losetup /dev/loop13 f1c100s-system-image.bin

# 对挂载的设备进行分区
sudo fdisk /dev/loop13
# 下面是我新建的两个分区的输入情况
# n回车 回车(p) 回车(1) 回车(2048) +32M回车 (如果有额外提示则Y回车)
# n回车 回车(p) 回车(2) 回车(67584) +200M回车 (如果有额外提示则Y回车)
# 接着 a回车 1回车 (将分区1设置为可启动)
# 输入 w 回车保存退出,会有点问题提示不用管

# 更新分区表
sudo kpartx -av /dev/loop13

# 格式化分区建立文件系统
sudo mkfs.vfat /dev/mapper/loop13p1
sudo mkfs.ext4 /dev/mapper/loop13p2

# 挂载第一个分区向里拷贝linux、dtb、boot.scr
sudo mount /dev/mapper/loop13p1 /mnt
sudo cp linux/arch/arm/boot/zImage /mnt/
sudo cp linux/arch/arm/boot/dts/suniv-f1c100s-licheepi-nano.dtb /mnt/
sudo cp u-boot/boot.scr /mnt/
sync
sudo umount /dev/mapper/loop13p1

# 挂载第二个分区向里解压并拷贝rootfs
sudo mount /dev/mapper/loop13p2 /mnt
sudo tar -xf buildroot-2022.02/output/images/rootfs.tar -C /mnt/
# 根据需求也可以拷贝应用程序进去
# sudo cp helloworld/helloworld /mnt/root/
sync
sudo umount /dev/mapper/loop13p2

# 卸载设备
sudo kpartx -d /dev/loop13
sudo losetup -d /dev/loop13

# 向头部写入uboot,注意conv=notrunc选项参数一定不能漏
sudo dd if=u-boot/u-boot-sunxi-with-spl.bin of=f1c100s-system-image.bin bs=1024 seek=8 conv=notrunc

压缩系统镜像
前面生成的系统镜像比较大,不适合存储,可以对镜像镜像压缩:

1
2
3
# cd ~/f1c100s-sdk/
# 将系统镜像以zip方式镜像压缩
zip f1c100s-system-image.zip f1c100s-system-image.bin

使用镜像文件

在Linux上可以直接使用 *dd* 命令将镜像文件写入SD卡中

1
2
3
4
5
6
7
8
9
10
# cd ~/f1c100s-sdk/
# rm f1c100s-system-image.bin
# 如果分区已挂载到别的地方先进行卸载
# sudo umount /dev/sdb1
# sudo umount /dev/sdb2

# 解压镜像文件压缩包
unzip f1c100s-system-image.zip
# 将镜像文件写入SD卡,写入可能较慢
sudo dd if=f1c100s-system-image.bin of=/dev/sdb bs=1M

当然我更加推荐使用工具来烧录,这里推荐使用 BalenaEtcher 工具 ,这个工具支持windos、macos、linux,其官方页面和项目地址分别如下:
https://www.balena.io/etcher/
https://github.com/balena-io/etcher
下面是用这个工具进行烧录的演示:

上面演示了使用BalenaEtcher工具进行烧录和启动测试,其中有两点值得注意的:

  • 原始的.bin后缀名的系统进行经过压缩后变得非常小(235MB > 5.98MB),可见压缩非常有用;
  • BalenaEtcher可以直接使用压缩包进行烧录(比如我上面演示中);

可能会遇到的问题

  • buildroot编译过程中下载文件慢
    buildroot编译过程中会下载很多文件,有可能会下着下着就不动了,或是下载缓慢。首先可以尝试使用 ctrl + c 终止当前工作后再 make ,会从终止的步骤重新开始;
    如果上面的方式不行,那自行查看编译输出信息,其中有文件下载地址的,手动用下载工具进行下载,把下载的内容压缩包或解压后内容放到buildroot的 dl 目录下,然后重复前面步骤;
  • 编译过程中因为缺少文件报错
    百度、必应等查找Ubuntu下安装这些文件的方法;
  • 编译或使用中其它不明的问题
    使用 make clean 或者 make distclean 后重复配置编译过程;

SDK数据包

鉴于整个过程中有很多东西需要下载,部分内容可能下载缓慢,所以将本文中出现的主要的几个项目内容进行了打包,方便将来使用。下载链接如下:

链接:https://pan.baidu.com/s/1BJPKuZJQmczxh82JJOGG_g
提取码:ezrw

下载下来是个zip格式压缩包,解压后得到下面内容(Ubuntu上可以使用 unzip 进行解压):

各个文件说明如下:

文件 说明
helloworld 内部含有helloworld.c文件
buildroot-2022.02.tar.xz 使用 wget https://buildroot.org/downloads/buildroot-2022.02.tar.xz 下载得到的压缩包
buildroot-2022.02-with-dl.tar.xz 根据上面项目 make menuconfig > make > make clean 后的文件夹进行重新打包压缩 其dl文件夹中包含了所有make时需要下载的东西
linux.tar.xz 使用 git clone -b nano-4.14-exp –depth=1 https://github.com/Lichee-Pi/linux.git 下载 得到的linux文件夹中放入使用 wget https://dl.sipeed.com/fileList/LICHEE/Nano/SDK/config 下载的config文件
然后对linux文件夹重新打包
sunxi-tools.tar.xz 使用 git clone -b f1c100s-spiflash –depth=1 https://github.com/Icenowy/sunxi-tools.git 下载 得到的sunxi-tools文件夹重新打包
u-boot.tar.xz 使用 git clone -b nano-lcd800480 –depth=1 https://github.com/Lichee-Pi/u-boot.git 下载 到的u-boot文件夹重新打包

总结

本文基于现有的一些项目,详细记录 u-boot & linux & rootfs 编译与烧录测试( 基于SD卡) 整个流程内容,可以作为进一步的移植、开发与使用的基础。


相关链接(侵删)

  1. 资料索引与基础说明
  2. u-boot & linux & rootfs 编译与烧录测试(基于SD卡)

=================我是分割线=================

欢迎到公众号来唠嗑: