由于我们项目的需求十分的简单,但是因为涉及到图像分析,所以又需要一个linux作为载体,这样软件编写简单,开发难度小,于是乎,构建一个成本最低的linux的平台,就成为了我们的迫切所需。
目前我们选定使用榴莲派的f1c100s作为基本开发平台,计划先从flash入手,系统系统的flash是16MB,我们经过评估,希望将其裁剪到4MB的样子。这样可以节省成本,由于系统内存是32MB的,并且不可更换,所以我们可以尽量地利用内存,以使得在现有的成本之上榨干性能。
整体的计划如下:
1.编译所有镜像,并且构建原生的系统。以熟悉其系统的开发功能
2.裁剪每一个部分,其中uboot最好在200k内,内核在1.8m内,文件系统在1.8m内,
3.移植busybox文件系统,以使得整个根文件系统更小!!!!!
首先。编译下载所有镜像
1.编译下载uboot
git clone https://gitee.com/monke/u-boot.git
cd u-boot
git checkout master
配置:make ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- liulianpi_f1c100s_norflash_defconfig
编译:make ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- -j8
此时:u-boot-sunxi-with-spl.bin:448K
2.编译下载内核
git clone https://gitee.com/monke/linux-5.4.77.git
cd linux-5.4.77
git checkout master
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- liulianpi_defconfig
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- -j8
此时: arch/arm/boot/zImage:3.4M
3.编译文件系统
wget https://buildroot.org/downloads/buildroot-2023.02.3.tar.gz
tar xvf buildroot-2023.02.3.tar.gz
cd buildroot-2023.02.3/
make menuconfig
做如下配置:
Target options —->
Target Architecture (ARM (little endian)) —-> // ARM架构,little endian模式
Target Architecture Variant (arm926t) —-> // arm926ejs架构
Enable VFP extension support // 不要勾选!F1C100S 没有 VFP单元,勾选会导致某些应用无法运行
Target ABI (EABI) —->
Floating point strategy (Soft float) —-> // 软浮点
Toolchain —->
Toolchain Type (Buildroot toolchain) —-> // 这里使用buildroot内部编译链
External toolchain C library (musl) —-> // 可以选择自己希望使用的库:这里的musl可以使得整体的系统减小
Kernel Headers (Linux 5.4.x kernel headers) —-> // 内核版本,这里是指当前目标板系统的版本
tar -xvf rootfs.tar -C output
mkfs.jffs2 -s 0x100 -e 0x10000 -X zlib -d output/ -o rootfs.jffs2
此时: rootfs.jffs2:2016K
那么为了将其放入到4MB的flash中,就需要进行一些精简。
目前大小:
| 文件 | 大小 |
|---|---|
| u-boot-sunxi-with-spl.bin | 448K |
| suniv-f1c100s-liulianpi-spinor.dtb | 16K |
| arch/arm/boot/zImage | 3404K |
| rootfs.jffs2 | 2016K |
后面的优化方向:
1.uboot:想办法将其优化到20k以内,可能最好是spl就可以直接执行。
2.内核:优化到2M以内。
3.rootfs:最好是1500K左右
具体优化步骤:
uboot
内核
目标是2m以下:
修改了内核的compressmode为xz(genenal setup,kernel compress mode)用空间换时间。
arch/arm/boot/zImage,变成了2.5M
经过各种config的删除,文件系统的删除,devicedriver的删除
zImage:1997960
rootfs
1.buildroot下面执行make busybox-menuconfig.然后setting,build options,里面选定build static,然后执行后解压rootfs.tar 通过命令:readelf -d busybox | grep NEEDED确定busybox已经是静态链接的了(大小是1.1M)
或者:
file busybox
busybox: ELF 32-bit LSB executable, ARM, EABI5 version 1 (SYSV), statically linked, stripped
然后删除lib里面的文件后继续执行制作filesystem的命令:
# 当前设置
mkfs.jffs2 -s 0x100 -e 0x10000 -X zlib -d output/ -o rootfs_zlib.jffs2
# 改成 2KB 页,看差异
mkfs.jffs2 -s 0x800 -e 0x10000 -X zlib -d output/ -o rootfs_zlib_2k.jffs2
# 再换成 lzo 算法
mkfs.jffs2 -s 0x800 -e 0x10000 -X lzo -d output/ -o rootfs_lzo_2k.jffs2
结果是:
output/ → 解开的目录(真实文件内容)
output.tgz → 589 KB (tar + gzip 压缩,很紧凑)
rootfs.tar → 2.49 MB (纯 tar,无压缩)
rootfs.jffs2 → 1.31 MB (参数 -s 0x100 -e 0x10000 -X zlib)
rootfs_lzo_2k → 856 KB (参数 -s 0x800 -e 0x10000 -X lzo)
rootfs_zlib_2k → 784 KB (参数 -s 0x800 -e 0x10000 -X zlib)
后面选择
mkfs.jffs2 -s 0x800 -e 0x10000 -d output/ -o rootfs_2k.jffs2即使不压缩,仍旧可以得到784KB大小的文件系统
加入了我们的目标app:
1576 rootfs_2k.jffs2
1032 rootfs_2k_nolib.jffs2
我们暂定给到的rootfs分区1600K,后续如果kernel优化的不明显,则选择1032版本。
经过思考后:
第一个版本,保证4MB可以跑的起来,最小化风险。
1.针对rootfs,先修改busybox的static library,然后将目标可执行文件拷贝并删除文件系统库通过命令生成jffs2的文件系统,
mkfs.jffs2 -s 0x800 -e 0x10000 -d output/ -o rootfs_2k.jffs2
得到的结果是:1032 rootfs_2k.jffs2,那么我们为其分区是1056KB(32KB对齐)
2.针对内核。我们仅仅修改压缩方式测试下,general setup->compress kernel :XZ.得到的内核大小是2460KB(2464),dtb的大小是16K,这样uboot的空间是充足的!
| 镜像 | 实际大小 | 分区大小 | 地址范围 |
|---|---|---|---|
| u-boot-sunxi-with-spl.bin | 457676 | 15*32=480KB | 0 - 0x7 7FFF |
| suniv-f1c100s-liulianpi-spinor.dtb | 15109 | 32KB | 0x7 8000 - 0x7 FFFF |
| zImage | 2515496 | 77*32 = 2464KB | 0x8 0000 - 0x2E 7FFF |
| rootfs_2k.jffs2 | 1055004 | 35*32=1120KB | 0x2E 8000 - 0x40 0000 |
此时我们需要根据上表修改uboot和内核的分区表后再次编译
uboot:
CONFIG_BOOTCOMMAND="sf probe 0 50000000; sf read 0x80C00000 0x78000 0x4000; sf read 0x80008000 0x80000 0x268000; bootz 0x80008000 - 0x80C00000"
内核:arch/arm/boot/dts/suniv-f1c100s-liulianpi-spinor.dts
partition@0 {
label = "u-boot";
reg = <0x000000 0x78000>;
read-only;
};
partition78000 {
label = "dtb";
reg = <0x78000 0x8000>;
read-only;
};
partition@80000 {
label = "kernel";
reg = <0x80000 0x268000>;
read-only;
};
partition@2E8000 {
label = "rootfs";
reg = <0x2E8000 0x118000>;
};
打包脚本package.sh
#!/bin/sh
dd if=/dev/zero of=f1c100s_spiflash_4M.bin bs=1M count=4 &&\
dd if=u-boot-sunxi-with-spl.bin of=f1c100s_spiflash_4M.bin bs=1K conv=notrunc &&\
dd if=suniv-f1c100s-liulianpi-spinor.dtb of=f1c100s_spiflash_4M.bin bs=1K seek=480 conv=notrunc &&\
dd if=zImage of=f1c100s_spiflash_4M.bin bs=1K seek=512 conv=notrunc &&\
dd if=rootfs_2k.jffs2 of=f1c100s_spiflash_4M.bin bs=1k seek=2976 conv=notrunc &&\
sync
最后生成了f1c100s_spiflash_4M.bin
只等东西到了烧写测试下
后续极端优化步骤:
1.rootfs只有基本的busybox,再使用squash压缩文件系统,控制在500kb以内
2.内核控制在1MB以内。内核最大可以1400kb
3.dtb还是会16k。就算极致也只能到8k
4.uboot最好是使用spl,这样可以控制在100kb以内。
2099

被折叠的 条评论
为什么被折叠?



