简介

本章介绍如何使用 Ameba Yocto Linux SDK 编译固件。它描述了 Realtek Ameba 发布层和 Ameba 特定的使用方法。

Yocto 项目是一个专注于嵌入式 Linux 操作系统开发的开源协作项目。有关 Yocto 项目的更多信息,请参考 Yocto Project

Yocto 项目主页上的几份文档详细描述了如何使用该系统。要在没有 Realtek Ameba 发布层的情况下使用基础的 Yocto 项目,请按照《Yocto Project 快速入门》中的说明进行操作,具体在 Yocto Project Quick Build 中获取。

用于编译固件的文件存储在层中。层包含不同类型的自定义内容,并来自不同的来源。层中的一些文件被称为配方。Yocto 项目的配方包含了获取源代码、编译和打包组件的机制。

以下列表显示了此版本中使用的层。

  • Ameba 发布层:

    • meta-realtek

      • meta-realtek-bsp: Realtek BSP layer

      • meta-sdk: Realtek specific SDK customization

  • Yocto 项目社区层:

    • poky

主机设置

要编译 Ameba Yocto Linux SDK,你必须使用 Linux。目前不支持在 MacOS 或 Windows 下编译。你需要在编译主机上安装必要的主机软件包。以下命令是在 Ubuntu 发行版上安装主机软件包。

  • 基本工具 - 用于 SDK 编译的主机软件包。

    $sudo apt install chrpath diffstat lz4 liblz4-tool zstd mtd-utils python3 python3-dev python3-pip python3-pyelftools
    $sudo pip install python-mbedtls sslcrypto cryptography pycryptodome ecdsa
    

    或者,进入 SDK 的工具安装目录 <sdk>/sources/yocto/meta-realtek/tools ,执行其中的工具安装脚本。

    $cd <sdk>/sources/yocto/meta-realtek/tools
    $sudo ./install.sh
    
  • 将 shell 更改为 bash

    $sudo dpkg-reconfigure dash
    

工具链设置

Linux 系统

本节介绍了在用户需要使用 yocto 工具链来编译代码时,如何导出 yocto 工具链的步骤。

  1. 以产品 rtl8730elh-va7 为例。

    source envsetup.sh -m rtl8730elh-va7 -d ameba-generic
    
  2. 执行 bitbake 命令用于 meta-toolchain

    bitbake meta-toolchain
    
  3. 跳转到 sdk 目录。

    cd build_rtl8730elh-va7_ameba-generic/tmp/deploy/sdk
    
  4. 执行生成工具链的 shell 脚本文件。

    ./ameba-generic-glibc-x86_64-meta-toolchain-cortexa32hf-neon-rtl8730elh-va7-toolchain-4.0.7.sh -d <toolchain>
    

    其中 <toolchain> 是你用于存储目标工具链的自定义目录。

  5. 选择 Y

    工具链会在目录 <toolchain> 中生成。

  6. 跳转到 <toolchain>

    source environment-setup-cortexa32hf-neon-rtk-linux-gnueabi
    

    然后工具链便在此生成。

Windows 系统

本节介绍了准备工具链环境的步骤。

  1. 从 Realtek 获取工具链的压缩文件。

  1. 在路径 {MSYS2_path}\opt 下创建一个目录 rtk-toolchain

    其中 {MSYS2_path} 是你安装 MSYS2 的路径。

  2. 解压 asdk-10.3.x-mingw32-newlib-build-xxxx.zipvsdk-10.3.x-mingw32-newlib-build-xxxx.zip ,把工具链目录 (asdk-10.3.xvsdk-10.3.x) 放到由步骤 2 生成的 rtk-toolchain 目录下。

备注

  • 解压后的文件夹应与上述保持一致,不要更改它们,否则你需要在 makefile 中修改工具链目录以自定义路径。

  • 如果在编译项目时出现工具链错误,例如日志显示 “Error: No Toolchain in /opt/rtk-toolchain/vsdk-10.3.1/mingw32/newlib”,请检查你的工具链文件目录是否与日志中的目录不同。将工具链文件放置在正确的位置,然后重试。

固件编译

本节提供了编译固件的详细信息和流程。

设置环境

Ameba Yocto Linux SDK 提供了一个脚本 envsetup.sh,该脚本简化了为 Ameba 机器进行设置的过程。要使用该脚本,需要指定要编译的特定机器的名称以及其他参数,如发行版、编译目录等。该脚本会为指定的机器设置目录和配置文件。

envsetup.sh 脚本的语法如下所示:

$source envsetup.sh [-h] [-m machine] [-d distro] [-b build dir] [-j jobs] [-t tasks]

选项

用途

-h

显示脚本的帮助信息。

-m <machine>

设置要编译的目标机器。

-d <distro>

设置要编译的发行版。

-b <build dir>

设置项目编译文件夹的非默认路径。

-j <jobs>

设置在编译阶段由 make 生成的任务数。

-t <tasks>

设置可以并行执行的 BitBake 任务数。

-p <download dir>

设置 DL_DIR 的非默认路径。

-c <sstate dir>

设置 SSTATE_DIR 的非默认路径。

脚本运行后,将由脚本创建工作目录,可以通过 -b 选项指定,如果未指定 -b 选项,则使用默认名称。一个包含 bblayers.conflocal.conf 文件的 conf 文件夹将被创建。

  • <builddir>/conf/bblayers.conf 文件包含 Ameba Yocto Linux SDK 发行版中使用的所有元层。

  • local.conf 文件包含机器和发行版的规范:

    MACHINE ??= "rtl8730elh-va8"
    DISTRO ?= "ameba-generic"
    

如果需要,可以通过编辑此文件来更改 MACHINEDISTRO 配置。

meta-realtek` 层中,可以选择以下 Ameba 机器和发行版配置。请查看发行说明或机器和发行版目录以获取最新添加的信息。

机器

目标版本

配置路径

rtl8730eah-va6

RTL8730EAH-VA6 芯片的机器配置。

sources/yocto/meta-realtek/meta-realtek-bsp/conf/machine/rtl8730eah-va6.conf

rtl8730elh-va7

RTL8730ELH-VA7 芯片的机器配置。

sources/yocto/meta-realtek/meta-realtek-bsp/conf/machine/rtl8730elh-va7.conf

rtl8730elh-va8

RTL8730ELH-VA8 芯片的机器配置。

sources/yocto/meta-realtek/meta-realtek-bsp/conf/machine/rtl8730elh-va8.conf

rtl8730elh-recovery

编译 recovery 固件的机器配置。

sources/yocto/meta-realtek/meta-realtek-bsp/conf/machine/rtl8730elh-recovery.conf

发行版

目标版本

配置路径

ameba-generic

发行版包含基本功能。

sources/yocto/meta-realtek/meta-sdk/conf/distro/ameba-generic.conf

ameba-full

发行版包含完整的演示功能。

sources/yocto/meta-realtek/meta-sdk/conf/distro/ameba-full.conf

备注

RTL8730EAH-VA6 专用于 NOR flash。

加速编译

在编译之前,用户可以提前下载编译加速包,该包通常包括下载文件和 sstate-cache。请联系 Realtek 获取此包。假设下载后已将它们存储在路径 <packages> 中。在执行 envsetup.sh 后,为它们在指定的 build-<machine> 目录中创建软链接。通过这种方式,可以节省编译过程中的下载时间。

cd build-<machine>
ln -s <packages>/downloads .
ln -s <packages>/sstate-cache .

如果用户之前成功编译了 SDK,他们还可以将之前编译过程中下载的软件包单独保存,然后在新的 SDK 编译过程中创建指向它们的软链接。假设之前的编译目录是 build-<machine>-1,当前的编译目录是 build-<machine>-2

cd build-<machine>-2
ln -s build-<machine>-1/downloads .
ln -s build-<machine>-1/sstate-cache .

编译固件

SDK 为 Ameba 机器提供了两种编译固件的方法:快速命令和手动编译命令。

快速命令是通过脚本 envsetup.sh 添加的便捷命令。执行 envsetup.sh 后,以下功能会被添加到 shell 环境中。

命令

描述

m

为 Ameba 机器编译所有 Linux 固件,包括 boot.img、kernel.img、rootfs.img、userdata.img 和 dtb。

m clean

清理所有编译输出。

mfw

编译 firmware 启动与固件。

mfw mp

编译量产 firmware 启动与固件。

mfw clean

清理编译 firmware 的输出文件。

mfw menuconfig

设置编译 firmware 的参数。

mrecovery

编译 linux recovery 固件。

mkernel

编译 kernel 固件。

要编译所有需刷写的固件,请运行如下命令:

$source envsetup.sh -m rtl8730elh-va8
$m
$mfw

Yocto 项目的编译使用 bitbake 命令。例如,bitbake <component> 用于编译指定的组件。每个组件的编译都有多个任务,如获取、配置、编译、打包和部署到目标根文件系统。bitbake 固件编译会收集固件所需的所有组件,并按照每个任务的依赖顺序进行编译。

下面的命令是编译一份固件的示例:

$bitbake ameba-image-core

在 meta-realtek 层,你可以选择以下固件配方进行编译。

产品名称

描述

ameba-image-core

核心固件包含基本功能。

ameba-image-userdata

用作用户数据文件系统的固件。

ameba-image-recovery

用于恢复系统的小型固件。

Bitbake 选项

用于编译固件的 bitbake 命令是 bitbake <image name>。可以使用附加参数来进行下文描述的特定活动。Bitbake 提供了多种有用的选项来开发单个组件。

bitbake <parameter> <component>

其中 <component> 是期望编译的包。

下表提供了部分 Bitbake 的选项。

Bitbake 参数

描述

-c fetch

如果下载状态未标记为完成,则获取。

-c cleanall

清理整个组件编译目录。编译目录中的所有更改都会丢失。组件的 rootfs 和状态也会被清除。该组件也会从下载目录中移除。

-c deploy

将固件、组件部署到 rootfs。

-c compile -f

不建议直接更改临时目录下的源代码,但如果进行了更改,Yocto 项目可能不会重建它,除非使用此选项。

在固件部署后使用此选项以强制重新编译。

-c menuconfig

如果组件支持,执行 make menuconfig 针对特定组件。

-e <component>

显示组件的编译环境。

-g

列出固件、组件的依赖关系树。

-k

即使出现编译中断,仍继续编译组件。

-DDD

开启三级深度的调试。每增加一个“D”就增加一级调试等级。

固件部署

最终要编辑的固件被部署在 <build directory>/tmp/deploy/images

该固件特定于环境设置中设定的机器。成功编译后,将生成以下 Linux 固件。

  • boot.img

  • kernel.img

  • rootfs.img

  • userdata.img

  • linux device tree images

这些设备树固件都有各自的名称。例如,用于机器 rtl8730elh-va7-generic 的固件名称是 rtl8730elh-va7-generic.dtb

firmware 启动固件和应用固件是通过 mfw 快速命令生成的:

  • km4_boot_all.bin

  • km0_km4_app.bin

下载固件到 flash

为了下载固件到 flash:

Docker 容器

Docker 是一个开源平台,旨在自动化应用程序在容器中的部署、扩展和管理。容器是轻量级、可移植且自给自足的单元,其中包含运行软件所需的一切,如代码、运行环境、库和系统工具。

  • Docker 利用容器化技术将应用程序及其依赖项打包到一个单独的容器中。这确保了在不同环境(如开发、测试和生产)中的一致行为。

  • 容器几乎可以在任何地方运行,无论是在开发人员的机器上,还是在数据中心的物理或虚拟机上,亦或是在云中运行,并且无需改动。

  • 容器共享主机系统的内核,使其比传统的虚拟机更轻量化,后者在每个实例中都包含一个完整的操作系统。

影像

制作影像

在制作新的 Docker 影像之前,你需要在计算机上安装 Docker。安装 Docker 的步骤请参考 Docker 首页

你可以在 Windows、Linux、MacOS 等系统上运行 Docker。这里我们介绍在 Linux 上的安装步骤,其他操作系统上的步骤与 Linux 相同。

首先,你的工作目录中应该有一个名为 Dockerfile 的文件。

下面是一个 Dockerfile 的内容的示例:

# Set the base system.
FROM ubuntu:20.04

# Set environment variables.
ENV DEBIAN_FRONTEND=noninteractive

# Update.
RUN apt-get update

# Install some tools.
RUN apt-get install -y sudo
RUN apt-get install -y make
RUN apt-get install -y make-guile
RUN apt-get install -y build-essential
RUN apt-get install -y gcc
RUN apt-get install -y g++
# Any other tools you need to install # ……

# Add toolchain.
ADD rtk-toolchain.tar.gz /opt

# Create a normal user named "ameba", with password "ameba".
RUN useradd -m -s /bin/bash ameba && echo "ameba:ameba" | chpasswd && adduser ameba sudo
RUN echo "ameba ALL=(ALL) NOPASSWD: ALL" >> /etc/sudoers
USER ameba

# Set work directory.
WORKDIR /home/ameba

# RUN shell command.
CMD ["/bin/bash"]

然后,你可以执行 docker build 命令来制作你的影像。

sudo docker build -t <image_name>:<image_tag> .

这里 <image_name> 表示 docker 影像的名字,<image_tag> 是可选的,用于标记 docker 影像的不同版本,如果没有它,则默认其为 latest

制作成功之后,你可以用 docker images 命令查看你的主机中是否存在这个影像。

sudo docker images

你可以假设参数 -a 来展示包括隐藏层在内的所有影像。

sudo docker images -a

然后,所有影像及其名称、标签和 ID 都会被显示出来。

你可以给一个影像添加新的名字、标签。

sudo docker tag <image_id> <new_image_name>:<new_image_tag>

载入影像

我们为客户提供即用型的 Docker 影像。请联系 Realtek 获取用于编译 SDK 的基础影像版本。

例如,当你获取到名为 rtk_ameba_sdk_build_v1.1.tar 的影像时,你可以在你的主机上通过命令 docker load 来载入它。

sudo docker load -i rtk_ameba_sdk_build_v1.1.tar

然后你可以使用 docker images 命令来检查这个影像是否在你的主机上。

sudo docker images

如果你不再需要某个影像,你可以通过名字和标签删除它。

sudo docker rmi <image_name>:<image_tag>

一个 <image_id> 可能对应一个或多个 <image_name>:<image_tag> ,当你给一个 <image_id> 标记多个 <image_name>:<image_tag> 时,上面这个命令不会删除掉对应的 <image_id> ,因为还有其它的 <image_name>:<image_tag> 存在。

你可以通过 ID 来删除影像,在这种情况下,所有对应于这个 <image_id><image_name>:<image_tag> 都会被同时删除。

sudo docker rmi <image_id>

容器

Docker 容器是 Docker 影像的一个实例。它是一个可执行的软件单元,将应用程序与其在任何环境中一致运行所需的所有内容打包在一起。

  • 容器在隔离的环境中运行,利用操作系统级别的虚拟化共享主机系统的内核,与传统虚拟机相比,确保了最低的开销。

  • 默认情况下,容器是无状态和临时的,这意味着在执行期间所做的任何更改在停止后不会保存,除非进行了明确的配置。

运行容器

在制作新的 Docker 影像或加载现成的 Docker 影像后,您可以根据该影像的名称运行一个新的容器。

sudo docker run --name <container_name> -it <image_name>:<image_tag>

或者,基于这个影像的 ID。

sudo docker run --name <container_name> -it <image_id>

这里 <container_name> 必须区别于已有的其它容器的名字,如果没有这个参数,docker 会自动分配一个唯一性的名字给这个容器。

此外,如果您想在此容器上挂载主机上的目录,可以添加参数 -v

sudo docker run --name <container_name> -v <host_dir>:<container_dir> -it <image_name>:<image_tag>
sudo docker run --name <container_name> -v <host_dir>:<container_dir> -it <image_id>

这里 <host_dir> 是您主机上的一个目录,它应该是已经存在的。 <container_dir> 是容器内的一个目录,如果不存在,容器可以自动创建它。

在成功挂载目录后,用户可以同时在主机和容器中操作该目录。

在容器中,你可以执行 exit 来退回到主机。

exit

然后你可以使用 docker ps 命令来查看容器是否在运行。

sudo docker ps

如果你想要查看所有的容器,包括运行的和不在运行的,你可以添加参数 -a

sudo docker ps -a

如果某个容器不再需要了,你可以通过 <container_name> 或者 <container_id> 来删除它。

sudo docker rm <container_name>
sudo docker rm <container_id>

运行已有的容器

如果您想执行一个未运行的容器,应首先通过容器名称或 ID 启动它。

sudo docker start <container_name>
sudo docker start <container_id>

然后,执行 docker exec 命令来通过容器名字或 ID 进入容器。

sudo docker exec -it <container_name> /bin/bash
sudo docker exec -it <container_id> /bin/bash

在退出容器之后,你可以通过容器名字或 ID 来停止容器。

sudo docker stop <container_name>
sudo docker stop <container_id>

此外,您还可以直接使用以下带有参数 -ia 的命令来启动一个已存在的容器:

sudo docker start -ia <container_name>
sudo docker start -ia <container_id>

然后运行 exit 来直接退出容器,退出的同时容器也会停止。

exit

在容器内编译 SDK

对于 Realtek 发布的影像,环境已配置好,您可以直接编译 SDK。

如果您将主机的目录挂载到容器上,可以将 SDK 放入该目录,然后它也会同步出现在容器内,您可以直接编译代码。

如果您没有挂载主机的目录,可以使用命令 docker cp 在主机和容器之间复制文件或目录。

从主机复制文件或目录到容器。

sudo docker cp <host_directory>/<files_or_directory> <container_name>:<container_directory>
sudo docker cp <host_directory>/<files_or_directory> <container_id>:<container_directory>

在成功编译 SDK 之后,您可以将文件或目录从容器复制到主机。

sudo docker cp <container_name>:<container_directory_or_files> <host_directory>
sudo docker cp <container_id>:<container_directory_or_files> <host_directory>

您也可以在容器中从 GitHub 获取 SDK,操作步骤与在主机上相同。

使用 Podman 替代

Podman 也可以像 Docker 一样处理影像和容器。用户可以从 Podman 首页 获取 podman。

Podman 和 Docker 的命令格式几乎相同,您可以直接将前缀 docker 替换为 podman 来使用。例如,您可以使用 podman build 代替 docker build ,使用 podman images 代替 docker images ,使用 podman ps 代替 docker ps ,等等。处理影像和容器的所有过程对于 podman 和 docker 来说都是相同的。