最近画了一个Linux板子,主控是全志的F1C100S,自带了32M RAM,不是很大,但是可以学习下;
板子图片:
| 板子正面 | 板子反面 | UBoot启动 |
|---|---|---|
![]() |
![]() |
![]() |
FLASH下载工具使用
1、通过命令 sudo sunxi-fel ver 来确认有无成功进入fel模式;
1 | sudo sunxi-fel ver |
2、短接FLASH1和4脚,可以进入fel模式,其实就是CS引脚拉低;
3、单次运行(下载到RAM中):
1 | sunxi-fel uboot /your/path/to/u-boot-sunxi-with-spl.bin |
4、烧进 spi-flash (开机自启)
1 | sunxi-fel -p spiflash-write 0 /your/path/to/u-boot-sunxi-with-spl.bin |
其中0是烧录偏移地址;
Uboot编译
1 | sudo apt-get install git |
1 | git clone -b nano-lcd800480 --depth=1 https://github.com/Lichee-Pi/u-boot.git |
只需要u-boot-sunxi-with-spl.bin即可;
boot.scr
根据上面对
bootcmd的修改,u-boot启动时会从第一分区读取boot.scr文件,并执行其中的脚本。我们可以通过这个来设置要传递给linux内核的参数、来加载内核和设备树、来启动内核。
在uboot目录下新建boot.cmd文件,向其中写入u-boot要执行的脚本:
1 | cd ~/f1c100s-sdk/u-boot/ |
写入以下内容:
1 | #设置传递给内核的bootargs参数 |
使用u-boot编译后tools目录下的 mkimage 工具可以将boot.cmd文件生成为 boot.scr 文件,通过下面命令:
1 | #arm架构;不压缩;script文件;输入boot.cmd文件;输出boot.scr文件 |
生成的 boot.scr 文件就在当前目录下;
Linux编译
1、Linux下载
1 | git clone https://gitee.com/LicheePiNano/Linux.git |
2、Linux编译
1 | make ARCH=arm f1c100s_nano_linux_defconfig |
编译成功后,生成文件所在位置:
- 内核img文件:
./arch/arm/boot/zImage - 设备树dtb文件:
./arch/arm/boot/dts/suniv-f1c100s-licheepi-nano.dtb - modules文件夹:
./out/lib/modules
buildrooft构建根文件系统
buildroot可用于构建小型的linux根文件系统。
大小最小可低至2M,与内核一起可以放入最小8M的spi flash中。
buildroot中可以方便地加入第三方软件包(其实已经内置了很多),省去了手工交叉编译的烦恼。
下载安装
首先安装一些依赖,比如linux头文件:
1 | apt-get install linux-headers-$(uname -r) |
然后下载安装:
1 | wget https://buildroot.org/downloads/buildroot-2021.02.4.tar.gz |
配置
1 | make menuconfig |
一些配置的简单说明
1 | Target options ---> |
编译
1 | make |
编译的过程如果带上下载软件包的时间比较漫长,很适合喝杯茶睡个午觉;(buildroot不能进行多线程编译)
编译完成的镜像包,是buildroot-2021.02.4/output/images/rootfs.tar;
测试程序
嵌入式linux开发最终是需要在系统上运行应用程序来实现特定的功能需求,这里编写个基础的应用程序用于测试:
建立程序文件夹并进入
1 | mkdir helloworld |
建立程序文件并编写程序
1 | touch helloworld.c |
写入以下内容:
1 |
|
编译生成可执行文件:
1 | arm-linux-gnueabi-gcc -static helloworld.c -o helloworld |
生成的 helloworld 就是我们需要的可执行文件了。
需要静态编译;
系统烧录(SD卡)
在SD卡中放了以下文件:
1 | ├── boot.cmd |
带星号的是加载进SD卡中的;
分别是U-boot、rootfs、Linux、boot.scr、测试程序;
关于boot.scr:
修改默认bootcmd:
1 gedit include/configs/suniv.h需要修改为:
1然后就可以编译了:
根据上面对bootcmd的修改,u-boot启动时会从第一分区读取 boot.scr 文件,并执行其中的脚本。我们可以通过这个来设置要传递给linux内核的参数、来加载内核和设备树、来启动内核。
也可以使用Uboot中的boot命令:
boot 命令也是用来启动 Linux 系统的,只是
boot会读取环境变量bootcmd来启动 Linux 系
统,bootcmd是一个很重要的环境变量!其名字分为“boot”和“cmd”,也就是“引导”和“命
令”,说明这个环境变量保存着引导命令,其实就是启动的命令集合,具体的引导命令内容是可
以修改的。比如我们要想使用 tftp 命令从网络启动 Linux 那么就可以设置bootcmd为“tftp 80800000 zImage; tftp 83000000 imx6ull-14x14-emmc-7-1024x600-c.dtb; bootz 80800000 -83000000”,然后使用saveenv将bootcmd保存起来。然后直接输入 boot 命令即可从网络启动Linux 系统,命令如下:
1
2
3 $:setenv bootcmd 'tftp 80800000 zImage; tftp 83000000 imx6ull-14x14-emmc-7-1024x600-c.dtb;bootz 80800000 - 83000000'
$:saveenv
$:bootboot命令使用如下所示:
1
2
3 $:setenv bootcmd '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'
$:saveenv
$:boot最后输入boot,启动linux系统,并且重启后仍会自动跳转进入linux系统;
得到了需要的所有文件,接下来是烧录到SD卡中;
文件烧录:
前面编译生成的内容可以分块分别烧录进SD卡进行测试,也可以将 u-boot & linux & rootfs 整块打包烧录进SD卡进行测试,其实本质上是一样的,这里先进行分块测试的介绍,打包烧录介绍将在后面的章节说明。
- 先将SD卡插入Ubuntu中;
- 使用 lsblk 查看SD卡设备号sdX;
我这里显示为sdb,下面均以此进行说明;
分区设置:
准备SD卡并按要求分区,空间划分参考下表:
| 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 |
下面是在Ubuntu终端中进行分区划分示例:
如果已经分过区了那么Ubuntu可能会自动挂载;
逐条使用 sudo umount /dev/sdbn 进行卸载;
对SD(TF)卡进行分区:
1 | sudo fdisk /dev/sdb |
格式化分区建立文件系统:
1 | sudo mkfs.vfat /dev/sdb1 |
分块烧录:
u-boot:
u-boot-sunxi-with-spl.bin 文件需要放置在SD卡8k开始的位置上:
1 | cd ~/f1c100s-sdk/u-boot/ |
linux & dtb & boot.scr
这三个放在刚才新建的第一个分区里(sdb1):
1 | #如果分区已挂载到别的地方先进行卸载 |
rootfs:
这个放在刚才新建的第二个分区里(sdb2):
1 | #如果分区已挂载到别的地方先进行卸载 |
测试程序:
1 | #如果分区已挂载到别的地方先进行卸载 |
系统烧录(SPI FLASH 16M)
Flash分区:
| 分区序号 | 分区大小 | 分区作用 | 地址空间及分区名 |
|---|---|---|---|
| mtd0 | 1MB | spl+uboot | 0x0000000-0x0100000 : “uboot” |
| mtd2 | 64KB | dtb文件 | 0x0100000-0x0110000: “dtb” |
| mtd2 | 4MB | linux内核 | 0x0110000-0x0510000 : “kernel” |
| mtd3 | 剩余 | 根文件系统 | 0x0510000-0x0c00000 : “rootfs” |
| mtd4 | 剩余 | 用户区 | 0x0c00000-0x1000000 : “user” |
烧录前要进入fel模式,然后进行程序下载;
烧录文件准备:
只有根文件系统烧录文件与TF卡的不同,其他文件均相同;
准备根文件系统,生成rootfs.img镜像文件:
1、新建一个目录make_rootfs(这个目录随便找一个路径放就可以了),拷贝rootfs.tar到make_rootfs目录下。
2、使用命令解压:
1 | tar -xf rootfs.tar |
然后删除压缩包:
1 | rm -rf rootfs.tar |
3、回到上级目录make_rootfs:
1 | cd ../ |
4、然后使用命令生成rootfs.img:
1 | mkfs.jffs2 -s 0x100 -e 0x10000 -p 0x6F0000 -d rootfs/ -o rootfs.img |
说明:(0x10000:块擦除大小),(0x6F0000:分区的大小);
5、mtd-utils安装:
此步骤是上一步制作根文件系统的命令没有的前提下进行的;
安装mkfs.jffs2工具:
1 | sudo apt-get install mtd-utils |
烧录命令:
清空flash,进入FEL模式:
1 | sf probe 0 |
烧录u-boot
1 | sudo sunxi-fel -p spiflash-write 0 ./u-boot-sunxi-with-spl.bin |
烧录kernel
1 | sudo sunxi-fel -p spiflash-write 0x0110000 ./zImage |
烧录dtb
1 | sudo sunxi-fel -p spiflash-write 0x0100000 ./suniv-f1c100s-licheepi-nano.dtb |
烧录rootfs
1 | sudo sunxi-fel -p spiflash-write 0x0510000 ./rootfs.img |
烧录userfs
说明:这个是个人创建的文件系统,该分区如果不需要可以不烧了;
1 | sudo sunxi-fel -p spiflash-write 0x0c00000 userfs.img |
U-boot中启动系统:
1 | sf probe 0 50000000 |
1 | setenv bootcmd 'sf probe 0 50000000; sf read 0x80C00000 0x100000 0x10000; sf read 0x80008000 0x110000 0x400000; bootz 0x80008000 - 0x80C00000' |
U-boot中sf命令用法:
- sf read用来读取flash数据到内存;
- sf write写内存数据到flash;
- sf erase 擦除指定位置,指定长度的flash内容, 在进行写flash的时候一定要先进行擦除,否则会失败,因为flash只能从1变为0;
具体用法:
1 | sf - SPI flash sub-system |
示例:
连接flash:
1 | sf probe 0 |
在使用sf的其他命令之前必须先进行此操作进行连接flash;
写flash:
1 | sf write 0x82000000 0x8000 0x20000 |
把内存0x8200 0000处的数据, 写入flash的偏移0x80000, 写入数据长度为0x20000(128KB), 操作偏移和长度最小单位是Byte;
读flash:
1 | sf read 0x82000000 0x10000 0x20000 |
把flash偏移0x10000(64KB)处, 长度为0x20000(128KB)的数据, 写入到内存0x82000000, 操作偏移和长度最小单位是Byte;
擦除flash:
1 | sf erase 0x0 0x10000 |
擦除偏移0x0处, 到0x10000之间的擦除块, 擦除操作是以erase block为单位的, 要求offset和len参数必须是erase block对齐的;
sunxi-fel工具的使用:
安装:
1 | git clone -b f1c100s-spiflash https://github.com/Icenowy/sunxi-tools.git |
用法:
1 | Usage: ./sunxi-fel [options] command arguments... [command...] |
示例:
烧录文件到FLASH:
1 | sudo sunxi-fel -p spiflash-write 0 Your-Flash-BIN |
烧录到RAM中:
1 | sudo sunxi-fel uboot u-boot-sunxi-with-spl.bin |
检测usb设备:
1 | $: sudo sunxi-fel -l |
列出设备信息:
1 | $: |
F1C100S GPIO操作:
1 | #使用sysfs操作GPIO的例子: |
引脚计算规则:
在Linux中,GPIO 使用0~MAX_INT之间的整数标识。
对于32位CPU,每组GPIO 32个,引脚号就是按顺序排列。
从PA0开始gpio是0,那么PE3对应是32*4+3=131,经试验已验证;
这个板子是PE12引脚为LED引脚,故:
故点灯的脚本如下:
1 | echo "out" > /sys/class/gpio/gpio140/direction #设置为输出 |
Linux取消开机登录输入账户密码:
找到 /etc/inittab 文件的:
1 | console::respawn:/sbin/getty -L console 0 vt100 # GENERIC_SERIAL |
修改为:
1 | console::respawn:-/bin/sh |
重启后就没有恼人的 login 提示了;


