1. 编译 Linux4.19 固件

1.1. 编译环境搭建

本章介绍 Linux SDK 的编译环境搭建

注意:

(1)推荐在 X86_64 Ubuntu 18.04 系统环境下进行开发,若使用其它系统版本,可能需要对编译环境做相应调整。

(2)使用普通用户进行编译,不要使用 root 用户权限进行编译。

1.1.1. 获取 SDK

首先准备一个空文件夹用于存放 SDK,建议在 home 目录下,本文以~/proj为例

不要在虚拟机共享文件夹以及非英文目录存放、解压SDK,避免产生不必要的错误

获取 SDK 需要先安装:

sudo apt update
sudo apt install -y repo git python
  • 方法一(推荐)

由于 Firefly_Linux_SDK 源码包比较大,部分用户电脑不支持4G以上文件或单个文件网络传输较慢, 所以我们采用分卷压缩的方法来打包 SDK。用户可以通过如下方式获取 Firefly_Linux_SDK 源码包:Firefly_Linux_SDK源码包

下载完成后先验证一下 MD5 码:

$ md5sum rk356x_linux_release_v1.3.0b_20221213_split_dir/*firefly_split*
409b81a9ed3bb9a7d6af91223836cad5  rk356x_linux_release_v1.3.0b_20221213_split_dir/rk356x_linux_release_v1.3.0b_20221213_firefly_split.file00
75cef82f2bf91052a7d3c6f0b8405a89  rk356x_linux_release_v1.3.0b_20221213_split_dir/rk356x_linux_release_v1.3.0b_20221213_firefly_split.file01
6f20f62e9652f8f999692587a2ac4b79  rk356x_linux_release_v1.3.0b_20221213_split_dir/rk356x_linux_release_v1.3.0b_20221213_firefly_split.file02
113acbbcd18d3abe0552ef296e983a3f  rk356x_linux_release_v1.3.0b_20221213_split_dir/rk356x_linux_release_v1.3.0b_20221213_firefly_split.file03
624c88a4da2eaa4a48f380783b126d00  rk356x_linux_release_v1.3.0b_20221213_split_dir/rk356x_linux_release_v1.3.0b_20221213_firefly_split.file04
1cf861afb0b36c9ebcf26a7d6effb260  rk356x_linux_release_v1.3.0b_20221213_split_dir/rk356x_linux_release_v1.3.0b_20221213_firefly_split.file05
3009e46fc14481e77fe7ec143e217de4  rk356x_linux_release_v1.3.0b_20221213_split_dir/rk356x_linux_release_v1.3.0b_20221213_firefly_split.file06
5e1cc90b99e34f20b75fb506d3e9bcd7  rk356x_linux_release_v1.3.0b_20221213_split_dir/rk356x_linux_release_v1.3.0b_20221213_firefly_split.file07
1a512fa7c9e2fd1a0781f8d40e228402  rk356x_linux_release_v1.3.0b_20221213_split_dir/rk356x_linux_release_v1.3.0b_20221213_firefly_split.file08

确认无误后,就可以解压:

# 解压
mkdir ~/proj/
cd ~/proj/
cat path/to/rk356x_linux_release_v1.3.0b_20221213_split_dir/*firefly_split* | tar -xzv

# 导出数据
.repo/repo/repo sync -l
  • 方法二

通过 repo 拉取代码,此方法对网络要求较高,有条件可以使用

可选择获取完整 SDK 或者 BSP:

mkdir ~/proj/rk356x_linux_release_v1.3.0b_20221213/
cd ~/proj/rk356x_linux_release_v1.3.0b_20221213/

## 完整 SDK
repo init --no-clone-bundle --repo-url https://gitlab.com/firefly-linux/git-repo.git --no-repo-verify -u https://gitlab.com/firefly-linux/manifests.git -b master -m rk356x_linux_release.xml

## BSP ( 只包含基础仓库和编译工具 )
## BSP 包括 device/rockchip 、docs 、 kernel 、 u-boot 、 rkbin 、 tools 和交叉编译链
repo init --no-clone-bundle --repo-url https://gitlab.com/firefly-linux/git-repo.git --no-repo-verify -u https://gitlab.com/firefly-linux/manifests.git -b master -m rk356x_linux_bsp_release.xml

1.1.2. 同步代码

执行如下命令同步代码:

# 进入 SDK 根目录
cd ~/proj/rk356x_linux_release_v1.3.0b_20221213/

# 同步
.repo/repo/repo sync -c --no-tags
.repo/repo/repo start firefly --all

后续可以使用以下命令更新 SDK:

.repo/repo/repo sync -c --no-tags

因为网络环境等原因,.repo/repo/repo sync -c --no-tags 命令更新代码可能会失败,可多次反复执行。

1.1.3. 目录结构

.
├── app
├── buildroot														# Buildroot 根文件系统编译目录
├── build.sh -> device/rockchip/common/build.sh					# 编译脚本
├── debian															# Debian 根文件系统编译目录
├── device															# 编译相关配置文件
├── docs															# 文档
├── envsetup.sh -> buildroot/build/envsetup.sh
├── external
├── kernel															# Kernel
├── Makefile -> buildroot/build/Makefile
├── mkfirmware.sh -> device/rockchip/common/mkfirmware.sh	# 链接脚本
├── prebuilts														# 交叉编译工具链
├── rkbin
├── rkflash.sh -> device/rockchip/common/rkflash.sh				# 烧写脚本
├── tools															# 工具目录
└── u-boot															# U-Boot

1.1.4. 安装依赖

  • 方法一:

在 PC 中自行安装环境:

sudo apt-get install repo git ssh make gcc libssl-dev liblz4-tool \
expect g++ patchelf chrpath gawk texinfo chrpath diffstat binfmt-support \
qemu-user-static live-build bison flex fakeroot cmake \
unzip device-tree-compiler python-pip ncurses-dev python-pyelftools
  • 方法二:使用 Docker

使用 dockerfile 创建容器,在容器中进行编译,完美解决编译环境问题,并且与主机环境隔离,互不影响。

首先在主机中安装 docker,请参考:安装教程

创建一个目录作为 docker 工作目录,例如~/docker/,在其中创建文件dockerfile,内容如下:

FROM ubuntu:18.04
MAINTAINER firefly "service@t-firefly.com"

ENV DEBIAN_FRONTEND=noninteractive

RUN cp -a /etc/apt/sources.list /etc/apt/sources.list.bak
RUN sed -i 's@http://.*ubuntu.com@http://repo.huaweicloud.com@g' /etc/apt/sources.list

RUN apt update

RUN apt install -y build-essential crossbuild-essential-arm64 \
	bash-completion vim sudo locales time rsync bc python

RUN apt install -y repo git ssh libssl-dev liblz4-tool lib32stdc++6 \
	expect patchelf chrpath gawk texinfo diffstat binfmt-support \
	qemu-user-static live-build bison flex fakeroot cmake \
	unzip device-tree-compiler python-pip ncurses-dev python-pyelftools \
	subversion asciidoc w3m dblatex graphviz python-matplotlib cpio \
	libparse-yapp-perl default-jre patchutils swig expect-dev u-boot-tools

RUN apt update && apt install -y -f

# language support
RUN locale-gen en_US.UTF-8
ENV LANG en_US.UTF-8

# switch to a no-root user
RUN useradd -c 'firefly user' -m -d /home/firefly -s /bin/bash firefly
RUN sed -i -e '/\%sudo/ c \%sudo ALL=(ALL) NOPASSWD: ALL' /etc/sudoers
RUN usermod -a -G sudo firefly

USER firefly
WORKDIR /home/firefly

创建镜像

cd ~/docker
docker build -t sdkcompiler .
# sdkcompiler 是镜像名称,可随意更改,注意命令最后有一个‘.’
# 此过程需要一段时间,请耐心等待

镜像创建完毕后,创建容器并启动

# 此处将主机内 SDK 所在文件夹挂载到容器内,这样容器内就能访问主机中的 SDK 了
# source= 填 SDK 所在目录;target= 填容器内的一个目录,必须是空目录
# ubuntu18 是容器名,firefly 是容器 hostname,均可随意更改
# sdkcompiler 是上一步的镜像名
docker run --privileged --mount type=bind,source=/home/fierfly/proj,target=/home/firefly/proj --name="ubuntu18" -h firefly -it sdkcompiler

现在就可以在容器中进行 SDK 的编译了。

退出容器、重启容器的方法:

# 在容器内输入 exit 即可退出

# 查看所有容器(包括已退出的)
docker ps -a

# 重启一个退出的容器并连接
docker start ubuntu18 # 容器名
docker attach ubuntu18

1.2. 编译 Ubuntu 固件

本章介绍 Ubuntu 固件的编译流程,推荐在 Ubuntu 18.04 系统环境下进行开发,若使用其它系统版本,可能需要对编译环境做相应调整。

1.2.2. 编译 SDK

1.2.2.1. 编译前配置

不同板型的配置文件存放在device/rockchip/rk356x/目录下

回到 SDK 根目录执行build.sh选择配置文件:

./build.sh aio-3566-jd4-ubuntu.mk

配置文件会链接到 device/rockchip/.BoardConfig.mk,检查该文件可以验证是否配置成功。

相关配置介绍:

# Target arch
export RK_ARCH=arm64 # 64位 ARM 架构
# Uboot defconfig
export RK_UBOOT_DEFCONFIG=firefly-rk3566 # u-boot 配置文件
# Kernel defconfig
export RK_KERNEL_DEFCONFIG=firefly_linux_defconfig # kernel 配置文件
# Kernel dts
export RK_KERNEL_DTS=rk3566-firefly-aiojd4 # dts 文件
# parameter for GPT table
export RK_PARAMETER=parameter-ubuntu-fit.txt # 分区表
# rootfs image path
export RK_ROOTFS_IMG=ubuntu_rootfs/rk356x_ubuntu_rootfs.img # 根文件系统路径

1.2.2.2. 选择编译配件

device/rockchip/rk356x/ 目录下,除了aio-3566-jd4-ubuntu.mk之外,还有其他不同配件搭配的配置文件

配置文件的名称中会标明所使用的屏幕和摄像头。如果没有标明屏幕,说明使用的是默认 HDMI 显示;如果没有标明摄像头,说明使用的是默认单目摄像头

# 例如:
xxxx-ubuntu.mk                      # 使用 HDMI + 单目摄像头
xxxx-2cam-ubuntu.mk                 # 使用 HDMI + 双目摄像头
xxxx-mipi-ubuntu.mk                 # 使用 mipi + 单目摄像头
xxxx-mipi-2cam-ubuntu.mk            # 使用 mipi + 双目摄像头
xxxx-tf-hdmi-mipi-rk628-ubuntu.mk   # 使用 HDMI + HDMI TO MIPI_CSI(RK628D)

选择好配置文件后,执行build.sh来使其生效:

# 例如:
./build.sh xxxx-mipi-2cam-ubuntu.mk

1.2.2.3. 下载 Ubuntu 根文件系统

7z x ubuntu-aarch64-rootfs.7z
  • 将根文件系统放到 ubuntu_rootfs/ 目录下

mkdir ubuntu_rootfs
mv ubuntu-aarch64-rootfs.img ubuntu_rootfs/rk356x_ubuntu_rootfs.img

1.2.2.4. 全自动编译

全自动编译会执行所有编译、打包操作,直接生成 RK 固件。

./build.sh

1.2.2.5. 部分编译

  • 编译 u-boot

./build.sh uboot
  • 编译 kernel

注意:Firefly kernel 没有开启全部的内核功能,有需求请查看Kernel 使用

./build.sh kernel

Linux SDK v1.2.4a 及之后版本采用了 extboot, 编译内核请执行./build.sh extboot

生成的文件为 SDK/kernel/extboot.img,取代之前的 boot.img

如何查看版本:

  1. 版本格式为 vx.x.xx,例如 v1.2.4a

  2. 固件文件名称中存在版本号(…_vx.x.xx_日期.img)

  3. Buildroot 使用cat /etc/version获取版本(rk356x_linux_release_日期_vx.x.xx.xml)

  4. Ubuntu 使用ffgo version获取版本(rk356x_linux_release_日期_vx.x.xx.xml)

  5. SDK 中可以在 SDK 根目录通过命令查看:ls -l .repo/manifests/rk356x_linux_release.xml

  6. 如果上述方法找不到格式为 vx.x.xx 的版本,说明是旧版本,不支持 extboot

不要将 extboot.img 烧录进旧版本固件!

除此之外,extboot ubuntu 还支持以安装包的形式更新内核,详情查看Ubuntu 使用手册

  • 编译 recovery

./build.sh recovery

1.2.2.6. 更新链接

更新各部分镜像链接到 rockdev/ 目录:

./mkfirmware.sh

1.2.2.7. 打包固件

打包固件,生成的完整固件会保存到 rockdev/pack/ 目录。

1.2.2.7.1. RK 固件

RK 固件,是以 Rockchip 专有格式打包的固件,使用 Rockchip 提供的工具可以烧写到 eMMC 或者 SD 卡中(:若无特殊说明,WIKI 上提及的固件默认为 RK 固件)。

# 打包 RK 固件
./build.sh updateimg
1.2.2.7.2. RAW 固件

RAW 固件,是一种能以逐位复制的方式烧写到存储设备的固件,是存储设备的原始映像。不同于 RK 固件,目前仅支持通过 Etcher 工具烧写至 SD 卡启动。

Etcher 官方下载链接

# 打包 RAW 固件
./build.sh rawimg

1.2.3. 分区说明

1.2.3.1. parameter 分区表

parameter.txt 文件中包含了固件的分区信息,以 parameter-ubuntu-fit.txt 为例:

路径:device/rockchip/rk356x/parameter-ubuntu-fit.txt

FIRMWARE_VER: 1.0
MACHINE_MODEL: RK3568
MACHINE_ID: 007
MANUFACTURER: RK3568
MAGIC: 0x5041524B
ATAG: 0x00200800
MACHINE: 0xffffffff
CHECK_MASK: 0x80
PWR_HLD: 0,0,A,0,1
TYPE: GPT
CMDLINE: mtdparts=rk29xxnand:0x00002000@0x00004000(uboot),0x00002000@0x00006000(misc),0x00010000@0x00008000(boot),0x00010000@0x00018000(recovery),0x00010000@0x00028000(backup),0x00c00000@0x00038000(rootfs),-@0x00c38000(userdata:grow)
uuid:rootfs=614e0000-0000-4b53-8000-1d28000054a9

CMDLINE 属性是我们关注的地方,以 uboot 为例, 0x00002000@0x00004000(uboot) 中 0x00004000 为uboot 分区的起始位置,0x00002000 为分区的大小,以此类推。

1.2.3.2. package-file

package-file 文件用于打包固件时确定需要的分区镜像和镜像路径,同时它需要与 parameter.txt 文件保持一致。

路径:tools/linux/Linux_Pack_Firmware/rockdev/rk356x-ubuntu-package-file

# NAME          Relative path
#
#HWDEF          HWDEF
package-file    package-file
bootloader      Image/MiniLoaderAll.bin
parameter       Image/parameter.txt
uboot           Image/uboot.img
misc            Image/misc.img
boot            Image/boot.img
recovery        Image/recovery.img
rootfs          Image/rootfs.img
userdata        RESERVED
backup          RESERVED

1.3. 编译 Debian 固件

本章介绍 Debian 固件的编译流程,推荐在 Ubuntu 18.04 系统环境下进行开发,若使用其它系统版本,可能需要对编译环境做相应调整。

1.3.1. 编译

Debian 固件的编译方法和 Ubuntu 的唯一区别是使用的文件系统不一样,其他步骤包括配置文件完全一致

因此请参考 编译 Ubuntu 固件

下面只介绍不同点,文件系统的替换

1.3.1.1. 下载 Debian 根文件系统

7z x Debian10-xxxx_RK3568_xxxx.7z
  • 将根文件系统放到 ubuntu_rootfs/ 目录下

mkdir ubuntu_rootfs
mv Debian10-xxxx_RK3568_xxxx.img ubuntu_rootfs/
  • 创建一个链接将文件系统链接到 rk356x_ubuntu_rootfs.img

cd ubuntu_rootfs
ln -sf Debian10-xxxx_RK3568_xxxx.img rk356x_ubuntu_rootfs.img

之后按照正常编译 Ubuntu 固件的步骤执行即可

1.4. 编译 Buildroot 固件

本章介绍 Buildroot 固件的编译流程,推荐在 Ubuntu 18.04 系统环境下进行开发,若使用其它系统版本,可能需要对编译环境做相应调整。

1.4.1. 编译 SDK

1.4.1.1. 编译前配置

不同板型的配置文件存放在device/rockchip/rk356x/目录下

回到 SDK 根目录执行build.sh选择配置文件:

./build.sh aio-3566-jd4-buildroot.mk

配置文件会链接到 device/rockchip/.BoardConfig.mk,检查该文件可以验证是否配置成功。

相关配置介绍:

# Target arch
export RK_ARCH=arm64 # 64位 ARM 架构
# Uboot defconfig
export RK_UBOOT_DEFCONFIG=firefly-rk3566 # u-boot 配置文件
# Kernel defconfig
export RK_KERNEL_DEFCONFIG=firefly_linux_defconfig # kernel 配置文件
# Kernel dts
export RK_KERNEL_DTS=rk3566-firefly-aiojd4 # dts 文件
# Buildroot config
export RK_CFG_BUILDROOT=rockchip_rk3566 # Buildroot 配置
# Recovery config
export RK_CFG_RECOVERY=rockchip_rk356x_recovery # recovery 配置
# parameter for GPT table
export RK_PARAMETER=parameter-buildroot-fit.txt # 分区表
# rootfs image path
export RK_ROOTFS_IMG=rockdev/rootfs.${RK_ROOTFS_TYPE} # 根文件系统路径

1.4.1.2. 选择编译配件

device/rockchip/rk356x/ 目录下,除了aio-3566-jd4-buildroot.mk之外,还有其他不同配件搭配的配置文件

配置文件的名称中会标明所使用的屏幕和摄像头。如果没有标明屏幕,说明使用的是默认 HDMI 显示;如果没有标明摄像头,说明使用的是默认单目摄像头

# 例如:
xxxx-buildroot.mk              # 使用 HDMI + 单目摄像头
xxxx-2cam-buildroot.mk         # 使用 HDMI + 双目摄像头
xxxx-mipi-buildroot.mk         # 使用 mipi + 单目摄像头
xxxx-mipi-2cam-buildroot.mk    # 使用 mipi + 双目摄像头

选择好配置文件后,执行build.sh来使其生效:

# 例如:
./build.sh xxxx-mipi-2cam-buildroot.mk

1.4.1.3. 全自动编译

全自动编译会执行所有编译、打包操作,生成完整固件。

./build.sh

1.4.1.4. 部分编译

  • 编译 u-boot

./build.sh uboot
  • 编译 kernel

注意:Firefly kernel 没有开启全部的内核功能,有需求请查看Kernel 使用

./build.sh kernel
  • 编译 recovery

./build.sh recovery
  • 编译 Buildroot 根文件系统

编译 Buildroot 根文件系统,将会在 buildroot/output 生成编译输出目录:

./build.sh buildroot

# 注:确保作为普通用户编译 Buildroot 根文件系统,避免不必要的错误。

1.4.1.5. 打包固件

更新各部分镜像链接到 rockdev/ 目录:

./mkfirmware.sh

打包固件,生成的完整固件会保存到 rockdev/pack/ 目录。

./build.sh updateimg

1.4.2. 分区说明

1.4.2.1. parameter 分区表

parameter.txt 文件中包含了固件的分区信息,以 parameter-buildroot-fit.txt 为例:

路径:device/rockchip/rk356x/parameter-buildroot-fit.txt

FIRMWARE_VER: 1.0
MACHINE_MODEL: RK3568
MACHINE_ID: 007
MANUFACTURER: RK3568
MAGIC: 0x5041524B
ATAG: 0x00200800
MACHINE: 0xffffffff
CHECK_MASK: 0x80
PWR_HLD: 0,0,A,0,1
TYPE: GPT
CMDLINE: mtdparts=rk29xxnand:0x00002000@0x00004000(uboot),0x00002000@0x00006000(misc),0x00010000@0x00008000(boot),0x00010000@0x00018000(recovery),0x00010000@0x00028000(backup),0x00040000@0x00038000(oem),0x00c00000@0x00078000(rootfs),-@0x00c78000(userdata:grow)
uuid:rootfs=614e0000-0000-4b53-8000-1d28000054a9

CMDLINE 属性是我们关注的地方,以 uboot 为例, 0x00002000@0x00004000(uboot) 中 0x00004000 为uboot 分区的起始位置,0x00002000 为分区的大小,以此类推。

1.4.2.2. package-file

package-file 文件用于打包固件时确定需要的分区镜像和镜像路径,同时它需要与 parameter.txt 文件保持一致。

路径:tools/linux/Linux_Pack_Firmware/rockdev/rk356x-package-file

package-file    package-file
bootloader      Image/MiniLoaderAll.bin
parameter       Image/parameter.txt
uboot           Image/uboot.img
misc            Image/misc.img
boot            Image/boot.img
recovery        Image/recovery.img
rootfs          Image/rootfs.img
oem             Image/oem.img
userdata        Image/userdata.img
backup          RESERVED