[Tiny4412] 搭建 Linux3.5 开发环境

前言

最近在学习 V4L2 编程,刚好自己手头上有一块 Tiny4412 的板子和一个免驱的摄像头。因此想在 Tiny4412 的板子上做实验,在实践中学习。
本文做为第一篇文章,在 Tiny4412 板子上搭建 Linux 系统。

一 配置编译烧写 u-boot

1.1 获取 uboot 源码和交叉工具链

uboot 源码和交叉工具链可以在 Tiny4412 附赠的光盘中获取,没有光盘的小伙伴可以访问我的 github 仓库获取。

获取交叉工具链

user@vmware:~/tiny4412$ git clone git@github.com:tiny4412/FriendlyARM.tool.chain.git

获取 uboot 源码

user@vmware:~/tiny4412$ git clone git@github.com:tiny4412/FriendlyARM.source.code.git

这里我是直接从光盘中拷贝的,放在 ~/tiny4412 目录下。

user@vmware:~/tiny4412$ ls
arm-linux-gcc-4.5.1-v6-vfp-20120301.tgz   uboot_tiny4412-20130729.tgz

1.2 创建仓库管理 uboot 源码

在 github 上创建一个名为 FriendlyARM.uboot-2010.12 的空仓库,克隆到本地

user@vmware:~/tiny4412$ git clone git@github.com:tiny4412/FriendlyARM.uboot-2010.12.git
Cloning into 'FriendlyARM.uboot-2010.12'...
Warning: Permanently added the RSA host key for IP address '192.30.253.112' to the list of known hosts.
warning: You appear to have cloned an empty repository.
Checking connectivity... done.

解压 uboot 源码,并将源码移动到仓库目录中进行管理

user@vmware:~/tiny4412$ tar zxvf uboot_tiny4412-20130729.tgz
user@vmware:~/tiny4412$ mv uboot_tiny4412/* FriendlyARM.uboot-2010.12/

提交第一笔提交,记录最原始的 uboot 源码状态

user@vmware:~/tiny4412$ cd FriendlyARM.uboot-2010.12/
user@vmware:~/tiny4412/FriendlyARM.uboot-2010.12$ make clean
user@vmware:~/tiny4412/FriendlyARM.uboot-2010.12$ make distclean
user@vmware:~/tiny4412/FriendlyARM.uboot-2010.12$ git add --all
user@vmware:~/tiny4412/FriendlyARM.uboot-2010.12$ git commit -m "init: get the u-boot source code by friendly arm"
user@vmware:~/tiny4412/FriendlyARM.uboot-2010.12$ git push origin -u master

1.3 安装交叉编译器

这里其实也没有什么安装一说,就是将交叉编译器解压出来,后续编译 uboot 的时候,修改 uboot 编译 Makefile 指定交叉编译器用我们现在解压的这个而已

user@vmware:~/tiny4412$ tar zxvf arm-linux-gcc-4.5.1-v6-vfp-20120301.tgz

1.4 指定 uboot 使用的交叉编译器

通过修改 arch/arm/config.mk 指定交叉编译器

user@vmware:~/tiny4412/FriendlyARM.uboot-2010.12$ git diff
diff --git a/arch/arm/config.mk b/arch/arm/config.mk
index 24f8982..a454343 100644
--- a/arch/arm/config.mk
+++ b/arch/arm/config.mk
@@ -21,7 +21,7 @@
 # MA 02111-1307 USA
 #

-CROSS_COMPILE ?= arm-linux-
+CROSS_COMPILE ?= /home/user/tiny4412/opt/FriendlyARM/toolschain/4.5.1/bin/arm-linux-

 ifeq ($(BOARD),omap2420h4)
 STANDALONE_LOAD_ADDR = 0x80300000
user@vmware:~/tiny4412/FriendlyARM.uboot-2010.12$ git add --all
user@vmware:~/tiny4412/FriendlyARM.uboot-2010.12$ git commit -m "conf: modify the cross compiler"
user@vmware:~/tiny4412/FriendlyARM.uboot-2010.12$ git push origin

1.5 配置编译 uboot

配置 uboot

user@vmware:~/tiny4412/FriendlyARM.uboot-2010.12$ make tiny4412_config
Configuring for tiny4412 board...

编译 uboot

user@vmware:~/tiny4412/FriendlyARM.uboot-2010.12$ make

确认到 u-boot.bin 镜像成功生成

user@vmware:~/tiny4412/FriendlyARM.uboot-2010.12$ ls -l u-boot.bin
-rw-rw-r-- 1 user user 276932 9月  23 22:36 u-boot.bin

1.6 给 u-boot 添加 .gitignore 文件

查看发现全是编译的中间文件,这些文件根本不需使用版本库进行管理,因此我们要忽略它们。随便找一个 kernel 源码中拷贝一个 kernel 默认的忽略规则过来就好。这里我拷贝的是 mini2440 用到的 linux-2.6.22.6 中的忽略规则。

user@vmware:~/tiny4412/FriendlyARM.uboot-2010.12$ cp ../../mini2440/linux-2.6.22.6/.gitignore ./

将 kernel 默认的忽略文件拷贝到 u-boot 源码中,很好,大部分的中间文件都成功忽略了,但是通过 git st 查看还是有部分中间文件没有被忽略。因此将剩余的中间文件都追加到 .gitignore 文件中。
需要追加的列表有:

# don't ignore the .gitignore file
!.gitignore
arch/arm/include/asm/arch
arch/arm/include/asm/proc
examples/standalone/hello_world
examples/standalone/hello_world.bin
examples/standalone/hello_world.srec
include/autoconf.mk
include/autoconf.mk.dep
include/config.h
include/config.mk
include/generated/
include/timestamp_autogenerated.h
include/version_autogenerated.h
tools/gen_eth_addr
tools/img2srec
tools/mkimage
u-boot
u-boot.bin
u-boot.lds
u-boot.map
u-boot.srec

将忽略规则提交

user@vmware:~/tiny4412/FriendlyARM.uboot-2010.12$ git add --all
user@vmware:~/tiny4412/FriendlyARM.uboot-2010.12$ git commit -m "conf: add the gitignore rule"
user@vmware:~/tiny4412/FriendlyARM.uboot-2010.12$ git push origin

1.7 烧写 uboot

通过 uboot 中提供的脚本可以将 uboot 烧写到 sd 卡中,之后便可以通过 sd 卡启动 uboot。
另外由于我是在虚拟机上编译的 uboot,因此,sd 卡接在 windows 上,需要在虚拟机右下角找到 sd 卡设备,断开其 windows 主机的连接,让其连接到虚拟机中。
sd 卡在虚拟机中正确识别后,在 /dev 目录下将会自动创建对应的设备节点

sd 卡未接入

user@vmware:~/tiny4412/FriendlyARM.uboot-2010.12/sd_fuse/tiny4412$ ls /dev/sd*
/dev/sda  /dev/sda1  /dev/sda2  /dev/sda5

sd 卡接入后

user@vmware:~/tiny4412/FriendlyARM.uboot-2010.12/sd_fuse/tiny4412$ ls /dev/sd*
/dev/sda  /dev/sda1  /dev/sda2  /dev/sda5  /dev/sdb  /dev/sdb1

确认到 sd 卡是 /dev/sdb 节点后,就可以开始用脚本烧写了,但是烧写依赖 mkbl2 镜像,因此要先生成它。

user@vmware:~/tiny4412/FriendlyARM.uboot-2010.12$ cd sd_fuse/
user@vmware:~/tiny4412/FriendlyARM.uboot-2010.12/sd_fuse$ ls
Makefile  sd_fdisk.c  tiny4412  V310-EVT1-mkbl2.c
user@vmware:~/tiny4412/FriendlyARM.uboot-2010.12/sd_fuse$ make
gcc -o    mkbl2 V310-EVT1-mkbl2.c
gcc -o    sd_fdisk sd_fdisk.c
user@vmware:~/tiny4412/FriendlyARM.uboot-2010.12/sd_fuse$ ls
Makefile  mkbl2  sd_fdisk  sd_fdisk.c  tiny4412  V310-EVT1-mkbl2.c

执行烧写脚本烧写 uboot,使用方法为 ./sd_fusing.sh /dev/sdb,值得注意的是,需要加 sudo 添超级权限才可以读写 sdb。

user@vmware:~/tiny4412/FriendlyARM.uboot-2010.12/sd_fuse$ cd tiny4412/
user@vmware:~/tiny4412/FriendlyARM.uboot-2010.12/sd_fuse/tiny4412$ ls
E4412_N.bl1.bin  E4412_tzsw.bin  fast_fuse.sh  sd_fusing.sh
user@vmware:~/tiny4412/FriendlyARM.uboot-2010.12/sd_fuse/tiny4412$ sudo ./sd_fusing.sh /dev/sdb
/dev/sdb reader is identified.
---------------------------------------
BL1 fusing
16+0 records in
16+0 records out
8192 bytes (8.2 kB, 8.0 KiB) copied, 0.203274 s, 40.3 kB/s
---------------------------------------
BL2 fusing
28+0 records in
28+0 records out
14336 bytes (14 kB, 14 KiB) copied, 0.444371 s, 32.3 kB/s
---------------------------------------
u-boot fusing
541+1 records in
541+1 records out
276996 bytes (277 kB, 271 KiB) copied, 1.9351 s, 143 kB/s
---------------------------------------
TrustZone S/W fusing
184+0 records in
184+0 records out
94208 bytes (94 kB, 92 KiB) copied, 0.721558 s, 131 kB/s
---------------------------------------
U-boot image is fused successfully.
Eject SD card and insert it again.

1.8 用 sd 卡启动验证是否烧录成功

将 SD 卡插入板子中,使用 SD 卡启动,出现如下打印,说明编译烧写成功,如不成功,请仔细 check 上述每一个步骤

OK

U-Boot 2010.12-00000-gcfd8b91 (Sep 23 2018 - 22:36:26) for TINY4412


CPU:    S5PC220 [Samsung SOC on SMP Platform Base on ARM CortexA9]
    APLL = 1400MHz, MPLL = 800MHz

Board:    TINY4412
DRAM:    1023 MiB

vdd_arm: 1.2
vdd_int: 1.0
vdd_mif: 1.1

BL1 version:  N/A (TrustZone Enabled BSP)


Checking Boot Mode ... SDMMC
REVISION: 1.1
MMC Device 0: 7460 MB
MMC Device 1: 3728 MB
MMC Device 2: N/A
*** Warning - using default environment

Net:    No ethernet found.
Hit any key to stop autoboot:  0
TINY4412 #
TINY4412 #
TINY4412 #
TINY4412 #

二 配置编译烧写 linux 内核

2.1 获取 linux 源码

linux 源码可以在 Tiny4412 附赠的光盘中获取,没有光盘的小伙伴可以访问我的 github 仓库获取。

user@vmware:~/tiny4412$ git clone git@github.com:tiny4412/FriendlyARM.source.code.git

这里我是直接从光盘中拷贝的,放在 ~/tiny4412 目录下。

user@vmware:~/tiny4412$ ls
FriendlyARM.source.code  FriendlyARM.tool.chain  FriendlyARM.uboot-2010.12  linux-3.5-20150929.tgz  opt

2.2 创建仓库管理 linux 源码

在 github 上创建一个名为 FriendlyARM.linux-3.5 的空仓库,克隆到本地

user@vmware:~/tiny4412$ git clone git@github.com:tiny4412/FriendlyARM.linux-3.5.git
Cloning into 'FriendlyARM.linux-3.5'...
warning: You appear to have cloned an empty repository.
Checking connectivity... done.

解压 linux 源码,并将源码移动到仓库目录中进行管理

user@vmware:~/tiny4412$ tar zxf linux-3.5-20150929.tgz
user@vmware:~/tiny4412$ mv linux-3.5/* FriendlyARM.linux-3.5/

提交第一笔提交,记录最原始的 linux 源码状态

user@vmware:~/tiny4412$ cd FriendlyARM.linux-3.5/
user@vmware:~/tiny4412/FriendlyARM.linux-3.5$ make clean
user@vmware:~/tiny4412/FriendlyARM.linux-3.5$ make distclean
user@vmware:~/tiny4412/FriendlyARM.linux-3.5$ git add --all
user@vmware:~/tiny4412/FriendlyARM.linux-3.5$ git commit -m "init: get the linux source code by friendly arm"
user@vmware:~/tiny4412/FriendlyARM.linux-3.5$ git push origin -u master

2.3 指定 linux 使用的交叉编译器

通过修改顶层 Makefile 指定交叉编译器

user@vmware:~/tiny4412/FriendlyARM.linux-3.5$ git diff
diff --git a/Makefile b/Makefile
old mode 100644
new mode 100755
index 371e0e4..053f911
--- a/Makefile
+++ b/Makefile
@@ -194,7 +194,7 @@ SUBARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ \
 export KBUILD_BUILDHOST := $(SUBARCH)
 #ARCH          ?= $(SUBARCH)
 ARCH           ?= arm
-CROSS_COMPILE  ?= $(CONFIG_CROSS_COMPILE:"%"=%)
+CROSS_COMPILE  ?= /home/user/tiny4412/opt/FriendlyARM/toolschain/4.5.1/bin/arm-linux-

 # Architecture as present in compile.h
 UTS_MACHINE    := $(ARCH)
user@vmware:~/tiny4412/FriendlyARM.linux-3.5$ git add --all
user@vmware:~/tiny4412/FriendlyARM.linux-3.5$ git commit -m "conf: modify the cross compiler"
user@vmware:~/tiny4412/FriendlyARM.linux-3.5$ git push origin

2.4 配置内核

修改友善之臂官网提供的配置文件,关闭 trustzone 功能

user@vmware:~/tiny4412/FriendlyARM.linux-3.5$ git diff
diff --git a/tiny4412_linux_defconfig b/tiny4412_linux_defconfig
old mode 100644
new mode 100755
index 8da9719..c2b29bd
--- a/tiny4412_linux_defconfig
+++ b/tiny4412_linux_defconfig
@@ -482,7 +482,7 @@ CONFIG_CPU_CP15_MMU=y
 #
 # Processor Features
 #
-CONFIG_ARM_TRUSTZONE=y
+# CONFIG_ARM_TRUSTZONE is not set
 # CONFIG_ARM_LPAE is not set
 # CONFIG_ARCH_PHYS_ADDR_T_64BIT is not set
 CONFIG_ARM_THUMB=y
user@vmware:~/tiny4412/FriendlyARM.linux-3.5$ git add --all
user@vmware:~/tiny4412/FriendlyARM.linux-3.5$ git commit -m "conf: disable the trustzone"
user@vmware:~/tiny4412/FriendlyARM.linux-3.5$ git push origin

使用友善之臂提供的配置文件来配置内核

user@vmware:~/tiny4412/FriendlyARM.linux-3.5$ cp tiny4412_linux_defconfig .config

2.5 编译内核

内核配置好后,直接执行 make 开始编译即可

user@vmware:~/tiny4412/FriendlyARM.linux-3.5$ make
... ...
  TIMEC   kernel/timeconst.h
Can't use 'defined(@array)' (Maybe you should just omit the defined()?) at kernel/timeconst.pl line 373.
/home/user/tiny4412/FriendlyARM.linux-3.5/kernel/Makefile:133: recipe for target 'kernel/timeconst.h' failed
make[1]: *** [kernel/timeconst.h] Error 255
Makefile:776: recipe for target 'kernel' failed
make: *** [kernel] Error 2

报错了,不慌,百度了解到需要做如下修改

user@vmware:~/tiny4412/FriendlyARM.linux-3.5$ git add kernel/timeconst.pl
user@vmware:~/tiny4412/FriendlyARM.linux-3.5$ git diff --cached
diff --git a/kernel/timeconst.pl b/kernel/timeconst.pl
old mode 100644
new mode 100755
index eb51d76..0461239
--- a/kernel/timeconst.pl
+++ b/kernel/timeconst.pl
@@ -370,7 +370,7 @@ if ($hz eq '--can') {
        }

        @val = @{$canned_values{$hz}};
-       if (!defined(@val)) {
+       if (!@val) {
                @val = compute_values($hz);
        }
        output($hz, @val);user@vmware:~/tiny4412/FriendlyARM.linux-3.5$ git diff --cached
diff --git a/kernel/timeconst.pl b/kernel/timeconst.pl
old mode 100644
new mode 100755
index eb51d76..0461239
--- a/kernel/timeconst.pl
+++ b/kernel/timeconst.pl
@@ -370,7 +370,7 @@ if ($hz eq '--can') {
        }

        @val = @{$canned_values{$hz}};
-       if (!defined(@val)) {
+       if (!@val) {
                @val = compute_values($hz);
        }
        output($hz, @val);

修改好后重新 make 成功了,确认到成功生成内核镜像

user@vmware:~/tiny4412/FriendlyARM.linux-3.5$ ls -l arch/arm/boot/zImage
-rwxrwxr-x 1 user user 4783472 9月  24 16:32 arch/arm/boot/zImage

2.6 给 linux 添加 .gitignore 文件

原本内核都是自带 ,gitignore 文件的,但是友善之臂提供的内核却没有,因此我们需要手动添加下忽略规则。

user@vmware:~/tiny4412/FriendlyARM.linux-3.5$ cp ../FriendlyARM.uboot-2010.12/.gitignore ./

同样,参考 uboot 中修改 ignore 规则一样,还是有部分中间文件没有被忽略。因此将剩余的中间文件都追加到 .gitignore 文件中。并将忽略规则提交

user@vmware:~/tiny4412/FriendlyARM.linux-3.5$ git add --all
user@vmware:~/tiny4412/FriendlyARM.linux-3.5$ git commit -m "conf: add the gitignore rule"
user@vmware:~/tiny4412/FriendlyARM.linux-3.5$ git push origin

2.7 烧写内核

通过 dd 命令将内核烧写到 SD 卡中,dd 使用格式为:

dd iflag=dsync oflag=dsync if=<烧写的文件名称> of=<指定烧写的设备> seek=<跳过块数量>

UBOOT默认情况下是从SD卡的1057块开始读取内核映像。
位置可以随意写,但是不能将前面的UBOOT代码覆盖掉。

user@vmware:~/tiny4412/FriendlyARM.linux-3.5$ sudo dd iflag=dsync oflag=dsync if=arch/arm/boot/zImage of=/dev/sdb seek=1057
[sudo] password for user:
9342+1 records in
9342+1 records out
4783472 bytes (4.8 MB, 4.6 MiB) copied, 42.1633 s, 113 kB/s

2.8 用 sd 卡启动验证是否烧录成功

将 SD 卡插入板子中,使用 SD 卡启动,出现如下打印,说明编译烧写成功,如不成功,请仔细 check 上述每一个步骤

OK

U-Boot 2010.12-00000-gbf8103b-dirty (Sep 24 2018 - 09:19:16) for TINY4412


CPU:    S5PC220 [Samsung SOC on SMP Platform Base on ARM CortexA9]
    APLL = 1400MHz, MPLL = 800MHz

Board:    TINY4412
DRAM:    1023 MiB

vdd_arm: 1.2
vdd_int: 1.0
vdd_mif: 1.1

BL1 version:  N/A (TrustZone Enabled BSP)


Checking Boot Mode ... SDMMC
REVISION: 1.1
MMC Device 0: 7460 MB
MMC Device 1: 3728 MB
MMC Device 2: N/A
*** Warning - using default environment

Net:    No ethernet found.
Hit any key to stop autoboot:  0
reading kernel..device 0 Start 1057, Count 12288
MMC read: dev # 0, block # 1057, count 12288 ... 12288 blocks read: OK
completed
reading RFS..device 0 Count 13345, Start 2048
MMC read: dev # 0, block # 13345, count 2048 ... 2048 blocks read: OK
completed
Boot with zImage
Wrong Ramdisk Image Format
[err] boot_get_ramdisk

Starting kernel ...

Uncompressing Linux... done, booting the kernel.
[    0.000000] Booting Linux on physical CPU 0
[    0.000000] Initializing cgroup subsys cpu
[    0.000000] Linux version 3.5.0-FriendlyARM-gd4bb223-dirty (user@vmware) (gcc version 4.5.1 (ctng-1.8.1-FA) ) #1 SMP PREEMPT Mon Sep 24 16:31:49 CST 2018

如果此时接了屏幕的话,还可以看到屏幕上出现企鹅图标。

三 构建根文件系统

我们知道 linux 中一切皆文件,linux 的运行少不了文件文件系统中的系统文件的支持,就好比 windows 电脑如果没有 c 盘中的 windows 系统文件,windows 系统也是无法运行起来的。因此要让我们自己编译的 linux 系统运行起来,必须提供系统需要的对应的系统文件,这些系统文件包括常用的可执行程序,如 ls、cd 等我们常用的命令的其他 linux 系统服务需要用到的配置文件。

这里我们要用到 busybox 工具去生成我们自己的 linux 系统需要需要到的工具,以及通过拷贝我们使用的 ubuntu 主机上的配置文件作为我们班子上 linux 的配置文件,

3.1 获取 busybox

可以从官网下载最新版本,也可以从我的 github 仓库中获取我本文使用的 busybox-1.23.2

user@vmware:~/tiny4412$ git clone git@github.com:tiny4412/FriendlyARM.tool.chain.git

解压得到 busybox 源码

user@vmware:~/tiny4412$ tar -jxvf busybox-1.23.2.tar.bz2
user@vmware:~/tiny4412$ ls
busybox-1.23.2          FriendlyARM.uboot-2010.12  FriendlyARM.tool.chain  opt
busybox-1.23.2.tar.bz2  FriendlyARM.source.code    FriendlyARM.linux-3.5

3.2 创建仓库管理根文件系统

在 github 上创建一个名为 FriendlyARM.rootfs 的空仓库,克隆到本地

user@vmware:~/tiny4412$ git clone git@github.com:tiny4412/FriendlyARM.rootfs.git
Cloning into 'FriendlyARM.rootfs'...
warning: You appear to have cloned an empty repository.
Checking connectivity... done.

3.3 配置编译 busybox

先配置 busybox,进入到解压目录下。敲 make menuconfig 命令进入图形配置菜单

user@vmware:~/tiny4412/busybox-1.23.2$ make menuconfig

分别进行以下配置:

  • 配置 busybox 的编译器为 /home/user/tiny4412/opt/FriendlyARM/toolschain/4.5.1/bin/arm-linux-

    Busybox Settings -->
        Build Options -->
            (/home/user/tiny4412/opt/FriendlyARM/toolschain/4.5.1/bin/arm-linux-) Cross Compiler prefix
    
  • 配置 busybox 编译安装的目录为 /home/user/tiny4412/FriendlyARM.rootfs

    Busybox Settings -->
        Installation Options ("make install" behavior) -->
            (/home/user/tiny4412/FriendlyARM.rootfs) BusyBox installation prefix
    

我在配置的时候,遇到 BusyBox installation prefix 无法编辑的情况,就是可以进入编辑框,但是无法删除原来的配置,退格键没有用。遇到这种情况的话,可以先执行 make menuconfig 生成 .config 配置文件,然后用文本编辑器手动修改下面两个宏为对应的值效果也是一样的。

user@vmware:~/tiny4412/busybox-1.23.2$ cat .config | grep tiny4412
CONFIG_CROSS_COMPILER_PREFIX="/home/user/tiny4412/opt/FriendlyARM/toolschain/4.5.1/bin/arm-linux-"
CONFIG_PREFIX="/home/user/tiny4412/FriendlyARM.rootfs"

配置好后,开始编译安装 busybox

user@vmware:~/tiny4412/busybox-1.23.2$ make
user@vmware:~/tiny4412/busybox-1.23.2$ make install

安装好后,将会在安装目标目录,也就是 make menuconfig 中指定的 FriendlyARM.rootfs 目录中生产以下文件

user@vmware:~/tiny4412/busybox-1.23.2$ cd ../FriendlyARM.rootfs/
user@vmware:~/tiny4412/FriendlyARM.rootfs$ ls
bin  linuxrc  sbin  usr

使用 ls -l 查看下,不难看出,这些生成的可执行文件都是到 busybox 的链接

ls -l bin/* sbin/* usr/* linuxrc
lrwxrwxrwx 1 user user      7 9月  24 22:02 bin/cat -> busybox
lrwxrwxrwx 1 user user      7 9月  24 22:02 bin/chmod -> busybox
lrwxrwxrwx 1 user user      7 9月  24 22:02 bin/conspy -> busybox
lrwxrwxrwx 1 user user      7 9月  24 22:02 bin/cp -> busybox
lrwxrwxrwx 1 user user      7 9月  24 22:02 bin/dmesg -> busybox
lrwxrwxrwx 1 user user      7 9月  24 22:02 bin/echo -> busybox
lrwxrwxrwx 1 user user      7 9月  24 22:02 bin/grep -> busybox
lrwxrwxrwx 1 user user      7 9月  24 22:02 bin/gunzip -> busybox
lrwxrwxrwx 1 user user      7 9月  24 22:02 bin/gzip -> busybox
lrwxrwxrwx 1 user user      7 9月  24 22:02 bin/ln -> busybox
lrwxrwxrwx 1 user user      7 9月  24 22:02 bin/ls -> busybox
lrwxrwxrwx 1 user user      7 9月  24 22:02 bin/mv -> busybox
lrwxrwxrwx 1 user user      7 9月  24 22:02 bin/ping -> busybox
lrwxrwxrwx 1 user user     11 9月  24 22:02 linuxrc -> bin/busybox

3.4 制作根文件系统

  1. 完善 linux 系统根目录下的目录

    user@vmware:~/tiny4412/FriendlyARM.rootfs$ mkdir -p lib dev etc/init.d home proc sys root opt tmp var mnt
    user@vmware:~/tiny4412/FriendlyARM.rootfs$ ls
    bin  dev  etc  home  lib  linuxrc  mnt  opt  proc  root  sbin  sys  tmp  usr  var
    
  2. 拷贝共享库到 rootfs/lib 目录下

    user@vmware:~/tiny4412/FriendlyARM.rootfs$ cp -rfdv ../opt/FriendlyARM/toolschain/4.5.1/arm-none-linux-gnueabi/lib/* lib/
    
  3. 拷贝分组和密码文件到 rootfs/etc 目录下

    user@vmware:~/tiny4412/FriendlyARM.rootfs$ cp /etc/group etc/
    user@vmware:~/tiny4412/FriendlyARM.rootfs$ cp /etc/passwd etc/
    
  4. 创建 fstab 文件

    user@vmware:~/tiny4412/FriendlyARM.rootfs$ cp /etc/fstab etc/
    
  5. 创建 inittab 文件

    user@vmware:~/tiny4412/FriendlyARM.rootfs$ vim etc/inittab
    user@vmware:~/tiny4412/FriendlyARM.rootfs$ cat etc/inittab 
    ::sysinit:/etc/init.d/rcS
    console::respawn:-/bin/sh
    ::ctrlaltdel:/sbin/reboot
    ::shutdown:/bin/umount -a -r
    

    解释以上代码:

    ::sysinit:/etc/init.d/rcS        # 定义系统上电执行的初始化文件。
    console::respawn:-/bin/sh        # 指定控制台的脚本解释器和进入控制台的模式。可选的模式有
                                     #     1. askfirst 进入命令行需要按回车键确认
                                     #     2. respawn  进入命令行不需要按回车键确认
    ::ctrlaltdel:/sbin/reboot        # 指定系统重启命令。
    ::shutdown:/bin/umount -a -r     # 指定系统关机前执行的命令
    
  6. 创建 etc/init.d/rcS 文件

    user@vmware:~/tiny4412/FriendlyARM.rootfs$ vim etc/init.d/rcS
    user@vmware:~/tiny4412/FriendlyARM.rootfs$ cat etc/init.d/rcS 
    #!/bin/sh
    mount -a
    mkdir /dev/pts
    mount -t devpts devpts /dev/pts
    echo /sbin/mdev > /proc/sys/kernel/hotplug
    mdev -s
    /bin/hostname Maziot
    

    注意, rcS 文件是一个脚本文件,必须有可执行权限

    user@vmware:~/tiny4412/FriendlyARM.rootfs$ chmod 777 etc/init.d/rcS 
    user@vmware:~/tiny4412/FriendlyARM.rootfs$ ll etc/init.d/rcS 
    -rwxrwxrwx 1 user user 130 10月  5 19:49 etc/init.d/rcS*
    

    其中 mdev -s 命令会根据安装的驱动自动在 dev 目录下创建设备节点

  7. 创建 etc/profile 文件

    user@vmware:~/tiny4412/FriendlyARM.rootfs$ vim etc/profile
    user@vmware:~/tiny4412/FriendlyARM.rootfs$ cat etc/profile
    USER="id-un"
    LOGNAME=$USER
    PS1='[\u@\h \w]\# '
    PATH=$PATH
    HOSTNAME='/bin/hostname'
    export USER LOGNAME PS1 PATH
    

    其中 PS1 环境变量保存的是当前命令行终端提示符显示的格式

3.5 将制作好的文件系统上传到 github 管理

由于 git 默认不管理空目录,但是文件系统中一些的特定的目录结构是需要存在的,因此需要将空目录也提交的 github 上。参考立体风的博客了解到,如要想要提交空目录 mnt 到 github 上,只需要在该目录下创建 .gitkeep 文件即可。

user@vmware:~/tiny4412/FriendlyARM.rootfs$ touch dev/.gitkeep home/.gitkeep opt/.gitkeep proc/.gitkeep sys/.gitkeep tmp/.gitkeep var/.gitkeep mnt/.gitkeep
user@vmware:~/tiny4412/FriendlyARM.rootfs$ git add --all
user@vmware:~/tiny4412/FriendlyARM.rootfs$ git commit -m "conf: create the root file system"
user@vmware:~/tiny4412/FriendlyARM.rootfs$ git push origin

3.6 配置 nfs 共享目录

编辑 nfs 服务的配置文件,将 /home/user/tiny4412/FriendlyARM.rootfs 目录加入共享目录

user@vmware:~/tiny4412/FriendlyARM.rootfs$ sudo vim /etc/exports 
user@vmware:~/tiny4412/FriendlyARM.rootfs$ cat /etc/exports 
# /etc/exports: the access control list for filesystems which may be exported
#       to NFS clients.  See exports(5).
#
# Example for NFSv2 and NFSv3:
# /srv/homes       hostname1(rw,sync,no_subtree_check) hostname2(ro,sync,no_subtree_check)
#
# Example for NFSv4:
# /srv/nfs4        gss/krb5i(rw,sync,fsid=0,crossmnt,no_subtree_check)
# /srv/nfs4/homes  gss/krb5i(rw,sync,no_subtree_check)
#
/home/user/board/ *(rw,sync,no_root_squash)
/home/user/tiny4412/rootfs *(rw,no_root_squash,sync)
/home/user/tiny4412/FriendlyARM.rootfs *(rw,sync,no_root_squash)

加入后重启 nfs 服务

user@vmware:~/tiny4412/FriendlyARM.rootfs$ sudo /etc/init.d/nfs-kernel-server restart
[ ok ] Restarting nfs-kernel-server (via systemctl): nfs-kernel-server.service.

重启 nfs 服务后,本地验证下 nfs 配置是否生效

user@vmware:~/tiny4412$ sudo mount -t nfs 192.168.31.178:/home/user/tiny4412/FriendlyARM.rootfs /mnt -o nolock
user@vmware:~/tiny4412$ cd /mnt/
user@vmware:/mnt$ ls
bin  dev  etc  home  lib  linuxrc  opt  proc  root  sbin  sys  tmp  usr  var
user@vmware:/mnt$ touch fs1
user@vmware:/mnt$ cd -
/home/user/tiny4412
user@vmware:~/tiny4412$ cd FriendlyARM.rootfs/
user@vmware:~/tiny4412/FriendlyARM.rootfs$ ls
bin  dev  etc  fs1  home  lib  linuxrc  opt  proc  root  sbin  sys  tmp  usr  var
user@vmware:~/tiny4412/FriendlyARM.rootfs$ rm -rf fs1

确认到配置是没问题的

3.7 设置 uboot 启动参数

从 sd 启动,开机倒数计时按下 enter 进入 uboot 命令行,重新设置 bootargs 环境变量,设置为 nfs 方式挂载文件系统

Checking Boot Mode ... SDMMC
REVISION: 1.1
MMC Device 0: 7460 MB
MMC Device 1: 3728 MB
MMC Device 2: N/A
Net:    No ethernet found.
Hit any key to stop autoboot:  0 
TINY4412 # 
TINY4412 # setenv bootargs root=/dev/nfs nfsroot=192.168.31.178:/home/user/tiny4412/FriendlyARM.rootfs ip=192.168.31.199:192.168.31.178:192.168.31.1:255.255.255.0::eth0:off init=/linuxrc console=ttySAC0
TINY4412 # 
TINY4412 # saveenv
Saving Environment to SMDK bootable device...
done

nfsroot 语法格式为:

<服务器IP地址>:<服务器上的文件目录> ip=<开发板IP地址>:<服务器IP地址>:<网关>:<子网掩码>::eth0:off

3.8 挂载文件系统启动 linux

重启开发板,此时应该可以正常启动内核,正常情况下最后一段 log 为:

... ...
[    7.325000] link_reset() speed: 10 duplex: 0
[    7.335000] IP-Config: Complete:
[    7.335000]      device=eth0, addr=192.168.31.199, mask=255.255.255.0, gw=192.168.31.1
[    7.335000]      host=192.168.31.199, domain=, nis-domain=(none)
[    7.335000]      bootserver=192.168.31.178, rootserver=192.168.31.178, rootpath=
[    7.335000] hotplug_policy_init: intialised with policy : DVFS_NR_BASED_HOTPLUG
[    7.345000] ALSA device list:
[    7.345000]   No soundcards found.
[    7.365000] VFS: Mounted root (nfs filesystem) on device 0:10.
[    7.365000] Freeing init memory: 212K
[root@Maziot /]#

但是有的时候会出现问题

  • 情况1:卡死在 No soundcards found 这里,没有成功挂载到 nfs 文件系统
    这样情况需要重点检查 nfs 服务这块,nfs 服务配置是否正确,uboot 中 bootargs 是否设置正确

  • 情况2:卡死在 Freeing init memory: 212K 成功 mount 了文件系统,但是没有进入终端
    说实话,我也不清除具体的原因,这里我的排查方法是用同学做好的,可以正常启动的文件系统包做交叉实验,找到自己文件系统中哪些文件配置的不对

同学做好的正常的文件系统我也放了一份到 https://github.com/tiny4412/FriendlyARM.source.code.git 仓库中,克隆下来将会得到 rootfs-huangweizhong.tar.gz 文件。先试试这个文件系统能否正常挂载

user@vmware:~/tiny4412$ tar zxvf rootfs-huangweizhong.tar.gz
user@vmware:~/tiny4412$ cd rootfs/
user@vmware:~/tiny4412/rootfs$ pwd
/home/user/tiny4412/rootfs

设置 uboot 中 bootargs 以及 nfs 共享的目录

setenv bootargs root=/dev/nfs nfsroot=192.168.31.178:/home/user/tiny4412/FriendlyARM.rootfs ip=192.168.31.199:192.168.31.178:192.168.31.1:255.255.255.0::eth0:off init=/linuxrc console=ttySAC0

确认到可以正常挂载,接下来就是找不同,看看具体是哪个配置的区别导致我自己做的文件系统挂载不上。
我在制作本文文件系统中就是遇到情况2的问题,卡死在 Freeing init memory: 212K 位置,最后通过交叉实验,确认到是 fstab 的问题。需要将 fstab 修改为:

user@vmware:~/tiny4412/FriendlyARM.rootfs$ cat etc/fstab 
#
# /etc/fstab
#
# Accessible filesystems, by reference, are maintained under '/dev/disk'
# See man pages fstab(5), findfs(8), mount(8) and/or blkid(8) for more info
#
/dev/mapper/VolGroup-lv_root                /           ext4    defaults        1 1
UUID=1d8cfac6-27f4-464f-9296-04d5bad1d7b2   /boot       ext4    defaults        1 2
/dev/mapper/VolGroup-lv_home                /home       ext4    defaults        1 2
/dev/mapper/VolGroup-lv_swap                swap        swap    defaults        0 0
tmpfs                                       /dev/shm    tmpfs   defaults        0 0
devpts                                      /dev/pts    devpts  gid=5,mode=620  0 0
sysfs                                       /sys        sysfs   defaults        0 0
proc                                        /proc       proc    defaults        0 0

四 产品发布

前面提到的在 tiny4412 上搭建 linux 环境基本已经可以运行了,使用的是 SD 启动挂载 nfs 网络文件系统,这样的方式好处是可以很方便的在 ubuntu 和 tiny4412 之前传输文件,但是我们最终的产品是要卖给用户的。我们不能强制用户要求插上启动用的 SD 卡,以及网线挂载网络文件系统。因此,最终,我们要将 uboot、kernel、fs 都要烧写到 EMMC 中,并在 EMMC 引导他们启动。

4.1 将 uboot 和内核从 SD 卡中拷贝到 EMMC 中

注意:SD 中有第 0 块不可用,EMMC 第 0 块是可用的,因此从 SD 到 EMMC 中烧的任何代码都需要减去 1
SD 卡是从第一个块开始的, EMMC 是从第0个块开始的

坚持原创技术分享,您的支持将鼓励我继续创作!