简介
本章介绍如何使用 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 工具链的步骤。
以产品 rtl8730elh-va7 为例。
source envsetup.sh -m rtl8730elh-va7 -d ameba-generic
执行
bitbake
命令用于 meta-toolchain。bitbake meta-toolchain
跳转到 sdk 目录。
cd build_rtl8730elh-va7_ameba-generic/tmp/deploy/sdk
执行生成工具链的 shell 脚本文件。
./ameba-generic-glibc-x86_64-meta-toolchain-cortexa32hf-neon-rtl8730elh-va7-toolchain-4.0.7.sh -d <toolchain>
其中
<toolchain>
是你用于存储目标工具链的自定义目录。选择
Y
。工具链会在目录
<toolchain>
中生成。跳转到
<toolchain>
。source environment-setup-cortexa32hf-neon-rtk-linux-gnueabi
然后工具链便在此生成。
Windows 系统
本节介绍了准备工具链环境的步骤。
从 Realtek 获取工具链的压缩文件。
在路径
{MSYS2_path}\opt
下创建一个目录rtk-toolchain
。其中
{MSYS2_path}
是你安装 MSYS2 的路径。解压
asdk-10.3.x-mingw32-newlib-build-xxxx.zip
与vsdk-10.3.x-mingw32-newlib-build-xxxx.zip
,把工具链目录 (asdk-10.3.x
与vsdk-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.conf
和 local.conf
文件的 conf 文件夹将被创建。
<builddir>/conf/bblayers.conf
文件包含 Ameba Yocto Linux SDK 发行版中使用的所有元层。local.conf
文件包含机器和发行版的规范:MACHINE ??= "rtl8730elh-va8" DISTRO ?= "ameba-generic"
如果需要,可以通过编辑此文件来更改 MACHINE
和 DISTRO
配置。
在 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:
参考 Image Tool 获取 Ameba 固件工具的常用操作。
参考 Flash layout。
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 来说都是相同的。