头图

前言

参考文章

其它参考

摘要

整体来说,大致的过程为,嵌入式设备上电后将执行 bootloader,对硬件进行硬件和堆栈初始化,然后搬运内核到 RAM 中并启动内核,紧接着挂载根文件系统。
  • 本文在 <font color=#F00>Ubuntu22.04</font> 的 Linux 上为 Cubieboard2 构建一个基于 armhf 的 Debian Linux,包括 SPL、U-BOOT、内核(Kernel)、根系统(ROOTFS)。

1 环境准备

mkdir -p ~/cubieboard2/chroot-armhf     # 创建目录
WORK_DIR=~/cubieboard2                  # 工作目录
ROOTFS_DIR=${WORK_DIR}/chroot-armhf     # 目标系统 rootfs 目录

1.1 下载必须的工具软件

sudo apt-get install build-essential libncurses5-dev u-boot-tools  \
                     qemu-user-static debootstrap git binfmt-support  \
                     libusb-1.0-0-dev pkg-config gcc-arm-linux-gnueabihf

1.2 下载源码

# 由于 github 仓库的网速过慢,这里使用 gitee 的同步仓库
cd $WORK_DIR

# 下载 lichee/内核
git clone https://gitee.com/luyaocf/linux-sunxi.git -b cubie/sunxi-3.4
tar -czvf linux-sunxi_cb2_`date +%Y%m%d_%H%M%S`.tar.gz linux-sunxi/

# 下载 uboot
git clone https://gitee.com/luyaocf/u-boot-sunxi.git -b cubie/sunxi
tar -czvf u-boot-sunxi_cb2_`date +%Y%m%d_%H%M%S`.tar.gz u-boot-sunxi/

# sunxi-tools master 分支
git clone https://gitee.com/luyaocf/sunxi-tools.git 
tar -czvf sunxi-tools_cb2_`date +%Y%m%d_%H%M%S`.tar.gz sunxi-tools/

# sunxi-boards master 分支
git clone https://gitee.com/luyaocf/sunxi-boards.git
tar -czvf sunxi-boards_cb2_`date +%Y%m%d_%H%M%S`.tar.gz sunxi-boards/
<font color=#F00>建议这里给虚拟机拍摄一个快照,因为接下来配置源需要多次尝试</font>

1.3 下载并配置 Debian 基础系统

cd $ROOTFS_DIR

##/ man debootstrap :
 # --no-check-gpg :Disables checking gpg signatures of retrieved Release files.
 # 从 man 的示例 “debootstrap stretch ./stretch-chroot http://deb.debian.org/debian” 可知:
 # 这里允许自定义下载源,官方的地址已经不支持 wheezy 版本,这里通过指定阿里源来指定 debian 版本为最新的 fullseye
 #/ 
debootstrap --foreign --no-check-gpg --arch armhf bullseye . http://mirrors.aliyun.com/debian/

cd $ROOTFS_DIR && sudo cp /usr/bin/qemu-arm-static usr/bin/

LC_ALL=C LANGUAGE=C LANG=C chroot . /debootstrap/debootstrap --second-stage

2 编译组件

2.1 编译 u-boot

这里使用 ubuntu 22.04 版本,其默认的 gcc-arm-linux-gnueabihf 版本为 11.2.0
# 卸载原来的工具链
apt-get remove gcc-arm-linux-gnueabi*

# 下载工具链
wget https://releases.linaro.org/components/toolchain/binaries/4.9-2016.02/arm-linux-gnueabihf/gcc-linaro-4.9-2016.02-x86_64_arm-linux-gnueabihf.tar.xz
# 解压
mkdir /usr/local/arm
tar -vxf gcc-linaro-4.9-2016.02-x86_64_arm-linux-gnueabihf.tar.xz -C /usr/local/arm
# 配置环境变量,在 /root/.bashrc 文件中添加:
export PATH=$PATH:/usr/local/arm/gcc-linaro-4.9-2016.02-x86_64_arm-linux-gnueabihf/bin
# 使生效
. ~/.bashrc

# 测试
-> arm-linux-gnueabihf-gcc -v
Using built-in specs.
COLLECT_GCC=arm-linux-gnueabihf-gcc
......
gcc version 4.9.4 20151028 (prerelease) (Linaro GCC 4.9-2016.02) 

2.1.1 u-boot-sunxi 分支

# git branch -a
cubie/sunxi             # make 过程报错
lichee-dev              # 无 cubieboard2
lichee-dev-a20          # 无 cubieboard2
lichee/lichee-dev       # 无 cubieboard2
lichee/lichee-dev-ICS   # 无 cubieboard2
lichee/lichee-dev-mmc   # 无 cubieboard2
old/sunxi-current       # make 过程报错
sunxi                   # make 过程报错
wip/a20                 # make 过程报错

# git checkout cubie/sunxi
# 这里选择 cubie/sunxi 分支

2.1.2 编译 U-boot

cd $WORK_DIR/u-boot-sunxi

# 清空
sudo make distclean CROSS_COMPILE=arm-linux-gnueabihf-
# 编译
sudo make cubieboard2 CROSS_COMPILE=arm-linux-gnueabihf-
  • 错误 1:<font color=#F00>arm-linux-gnueabihf-gcc: error: unrecognized -march target: armv5</font>

    • 通过 grep -rn "armv5" 找到所有包含 “armv5” 的地方,其中 arch/arm/cpu/armv7/config.mk:11 处有如下内容,说明这里可以把 armv5 修改为 armv7-a

      # If armv7-a is not supported by GCC fall-back to armv5, which is
      # supported by more tool-chains
      PF_CPPFLAGS_ARMV7 := $(call cc-option, -march=armv7-a, -march=armv5)
    • 通过查找,cubieboard2 的 CPU 架构确实是 “ARMv7 Cortex-A7”

  • 错误2:<font color=#F00>compiler-gcc.h:93:1: fatal error: linux/compiler-gcc11.h: 没有那个文件或目录</font>

    # 这里将内核文件夹 include/linux 下的 compiler-gcc3.h 或 compiler-gcc4.h 拷贝为 compiler-gcc11.h
    cp include/linux/compiler-gcc3.h include/linux/compiler-gcc11.h

2.2 编译 sunxi-tools

  • sunxi-tools 提供了 fexc、nand-part 等工具,在系统安装、定制的过程中可能会用到,所以可以先编译它们。
  • 因为这些工具常常在宿主系统上(x86-64 Ubuntu Linux)来针对目标设备、目标系统运行,所以可以把它们编译为x86-64的可执行文件。
  • 编译:

    cd $WORK_DIR/sunxi-tools
    make

2.3 配置、编译内核

2.3.1 拷贝预设内核配置文件

# 切换到内核代码目录
cd $WORK_DIR/linux-sunxi/

# 复制配置文件
cp arch/arm/configs/sun7i_defconfig .config

2.3.2 配置内核

  • 打开配置图形化界面:

    cp .config bak1_orig.config
    make ARCH=arm menuconfig
    cp .config bak2_soloforce.config
  • 具体配置项:

    • *,表示该驱动将作为内核的一部分被编译进内核映像中。
    • M,则表示该驱动将作为一个独立的模块编译,并且可以在需要时通过 insmod 或 modprobe 加载。
    • 推荐除自定义模块外,所有项前面需要修改为选中 <*>

| <div style="width: 40pt;">说明 |<div style="width: 60pt;"> 第一级 | 第二级 | 第三级 | 第四级 | 第五级 |
| - | - | - | - | - | - |
| 无线网络 | Networking support | Wireless | Generic IEEE 802.11 Networking Stack (mac80211)
| SATA | Device Drivers | Serial ATA and Parallel ATA drivers | SoftWinner Platform AHCI SATA support
| Tun/Tap | Device Drivers | Network device support | Universal TUN/TAP device driver support
| USB 网卡 | Device Drivers | Network device support | Wireless LAN (NEW) | Ralink driver support
| 红外线 | Device Drivers | Input device support | Keyboards (NEW) | sunxi IR support (NEW)
| GPIO | Device Drivers | GPIO Support | GPIO Support for sunxi platform
| 错误 | Device Drivers | Hardware Monitoring support
| 摄像头 | Device Drivers | Multimedia support | Video capture adapters (NEW) | V4L USB devices (NEW) | USB Video Class (UVC)
| HDMI | Device Drivers | Graphics support | Support for frame buffer devices | HDMI Driver Support(sunxi)
| USB串口 | Device Drivers | USB support(NEW) | USB Serial Converter support | USB Prolific 2303 Single Port Serial Driver

2.3.3 编译内核

# 备份
cp .config bak_`date +%Y%m%d_%H%M%S`.config
# 编译
make -j12 ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- uImage modules
  • 编译完成后,得到内核文件:

    ll arch/arm/boot/uImage

2.3.4 发掘更多的可用内存

3 建立 ROOTFS

3.1 ROOTFS 配置

cd $WORK_DIR/chroot-armhf
chroot . passwd

echo "Cubieboard2" > etc/hostname && cat etc/hostname

echo "127.0.0.1 Cubieboard2" >> etc/hosts && cat etc/hosts

# 安装内核镜像
cp ../linux-sunxi/arch/arm/boot/uImage boot/
make -C ../linux-sunxi INSTALL_MOD_PATH=. ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- modules_install

# 初始化 inittab 文件
echo T0:2345:respawn:/sbin/getty -L ttyS0 115200 vt100 >> etc/inittab && cat etc/inittab

# 初始化 sources.list 文件
vi etc/apt/sources.list
cat etc/apt/sources.list

chroot . apt-get update
chroot . apt-get upgrade
chroot . apt-get install openssh-server locales wireless-tools wpasupplicant vim lrzsz net-tools firmware-ralink 
echo "en_US.UTF-8 UTF-8" > etc/locale.gen
echo "zh_CN.UTF-8 UTF-8" >> etc/locale.gen
chroot . locale-gen

# 到此为止,Debian 基础系统已经配置好了;现在可以把 $ROOTFS_DIR 保存为一个压缩包,以备日后之用。
cd ../ && sudo tar -czvf chroot-armhf_cb2_`date +%Y%m%d_%H%M%S`.tar.gz chroot-armhf/

3.2 更新为阿里源

deb http://mirrors.aliyun.com/debian/ bullseye main non-free contrib
deb-src http://mirrors.aliyun.com/debian/ bullseye main non-free contrib
deb http://mirrors.aliyun.com/debian-security/ bullseye-security main
deb-src http://mirrors.aliyun.com/debian-security/ bullseye-security main
deb http://mirrors.aliyun.com/debian/ bullseye-updates main non-free contrib
deb-src http://mirrors.aliyun.com/debian/ bullseye-updates main non-free contrib
deb http://mirrors.aliyun.com/debian/ bullseye-backports main non-free contrib
deb-src http://mirrors.aliyun.com/debian/ bullseye-backports main non-free contrib

3.3 etc/inittab 文件内容

# /etc/inittab: init(8) configuration.
# $Id: inittab,v 1.91 2002/01/25 13:35:21 miquels Exp $
# The default runlevel.
id:2:initdefault:
# Boot-time system configuration/initialization script.
# This is run first except when booting in emergency (-b) mode.
si::sysinit:/etc/init.d/rcS

# What to do in single-user mode.
~~:S:wait:/sbin/sulogin

# /etc/init.d executes the S and K scripts upon change
# of runlevel.
#
# Runlevel 0 is halt.
# Runlevel 1 is single-user.
# Runlevels 2-5 are multi-user.
# Runlevel 6 is reboot.

l0:0:wait:/etc/init.d/rc 0
l1:1:wait:/etc/init.d/rc 1
l2:2:wait:/etc/init.d/rc 2
l3:3:wait:/etc/init.d/rc 3
l4:4:wait:/etc/init.d/rc 4
l5:5:wait:/etc/init.d/rc 5
l6:6:wait:/etc/init.d/rc 6
# Normally not reached, but fallthrough in case of emergency.
z6:6:respawn:/sbin/sulogin

# What to do when CTRL-ALT-DEL is pressed.
ca:12345:ctrlaltdel:/sbin/shutdown -t1 -a -r now

# Action on special keypress (ALT-UpArrow).
#kb::kbrequest:/bin/echo "Keyboard Request--edit /etc/inittab to let this work."

# What to do when the power fails/returns.
pf::powerwait:/etc/init.d/powerfail start
pn::powerfailnow:/etc/init.d/powerfail now
po::powerokwait:/etc/init.d/powerfail stop

# /sbin/getty invocations for the runlevels.
#
# The "id" field MUST be the same as the last
# characters of the device (after "tty").
#
# Format:
#  <id>:<runlevels>:<action>:<process>
#
# Note that on most Debian systems tty7 is used by the X Window System,
# so if you want to add more getty's go ahead but skip tty7 if you run X.
#
1:2345:respawn:/sbin/getty 38400 tty1
2:23:respawn:/sbin/getty 38400 tty2
3:23:respawn:/sbin/getty 38400 tty3
4:23:respawn:/sbin/getty 38400 tty4
5:23:respawn:/sbin/getty 38400 tty5
6:23:respawn:/sbin/getty 38400 tty6

# Example how to put a getty on a serial line (for a terminal)
#
#T0:23:respawn:/sbin/getty -L ttyS0 9600 vt100
#T1:23:respawn:/sbin/getty -L ttyS1 9600 vt100

# Example how to put a getty on a modem line.
#
#T3:23:respawn:/sbin/mgetty -x0 -s 57600 ttyS3

4 烧录

4.1 准备工作

  • 1)工作目录

    WORK_DIR=~/cubieboard2                 
    ROOTFS_DIR=${WORK_DIR}/chroot-armhf  
  • 2)准备工具

  • (1)uboot
    $WORK_DIR/u-boot-sunxi/u-boot-sunxi-with-spl.bin
  • (2)kernel
    $WORK_DIR/linux-sunxi/arch/arm/boot/uImage
  • (3)boot.scr
    $WORK_DIR/boot.scr
  • (4)script.bin
    $WORK_DIR/sunxi-boards/sys_config/a20/script.bin
  • (5)rootfs
    $WORK_DIR/chroot-armhf.tar.gz

4.2 烧写

4.2.1 分区

ll /dev/sd*         # 查看分区名称,一般为 sdb
card=/dev/sdb
dd if=/dev/zero of=${card} bs=1M count=1    # dd if=<输入文件> of=<输出文件> bs=<块大小> count=<块数>
sfdisk -r ${card}   # 分区排序
fdisk ${card}       # 操作分区

d                   # 删除旧分区

n [Enter] [Enter] [Enter] +64M      # 创建分区 1

n [Enter] [Enter] [Enter] [Enter]   # 创建分区 2

t 1 c w             # 指定分区类型

# 格式化分区 1、2
mkfs.vfat ${card}1
mkfs.ext4 ${card}2

4.2.2 写入 bootloader

cd $WORK_DIR/u-boot-sunxi
dd if=u-boot-sunxi-with-spl.bin of=$card bs=1024 seek=8

4.2.3 烧写其它内容

  • 1)分区 1 中写入内核 uImage、script.bin、boot.scr:

    mount ${card}1 /mnt 
    mkdir /mnt/boot
    
    # 安装内核 uImage
    cp $WORK_DIR/linux-sunxi/arch/arm/boot/uImage /mnt/boot 
    # 安装 script.bin
    cp $WORK_DIR/sunxi-boards/sys_config/a20/script.bin /mnt/boot
    # 安装 boot.scr
    cp $WORK_DIR/boot.scr /mnt/
    
    sync && umount /mnt
  • 2)分区 2 中写入文件系统:

    # 安装 rootfs
    mount ${card}2 /mnt
    
    cp $WORK_DIR/chroot-armhf.tar.gz /mnt/
    tar -zxvf chroot-armhf.tar.gz
    
    sync && umount /mnt

4.2.4 烧写结果

lsb_release -a          # 查看 ubuntu 版本
cat /etc/issue          # 查看 ubuntu 版本
cat /etc/debian_version # ubuntu 下查看 debian 版本   
cat /etc/os-release     # 查看系统详情

后记

于 2022-08-07:
重试了多次,上述过程无法正常启动系统。
最终,使用官方的 uboot 与 内核,只将根文件系统 chroot-armhf.tar.gz 解压到 /dev/sdb2 下后成功,且系统为 debian 11。

送南阳马生序
7 声望3 粉丝

余之业有不精、德有不成,非天质之卑,则心不若他之专耳,岂他人之过哉!