高通板卡部署备忘:Yocto 元数据、镜像构建与定制查询手册

阅读范围与版本

这份笔记从 Qualcomm Linux 功能 出发,结合同一本指南的概述、用户定制、调试,以及 Yocto 官方文档整理。目标是:以后拿到一块高通板,知道要查哪份配置、改哪一层、编译什么,以及拿什么证据判断部署是否正确。

项目 本文采用的边界
高通指南 80-70014-27Y,中文 Qualcomm Linux Yocto 指南
所给页面发布日期 页面末尾标注 2024-10-09,不是当前所有高通平台的最新统一说明
Yocto 版本 文档明确基于 Kirkstone,引用 Yocto 4.0.18
文档平台范围 概述列出 QCS6490/QCS5430;该代 qcm6490.conf 支持多个对应目标
当前板型 待确认。文中的 QCM6490/RB3 Gen 2 是官网例子,不表示我的实际板卡型号
核对日期 2026-09-08
验证状态 已核对文档与部分公开源码;未同步完整 BSP、未执行 BitBake 构建、未连接或刷写开发板

尤其注意:官网概述在这一本指南中允许 QCM6490/QCS6490 名称交替出现,这不是所有硬件都兼容的承诺。SoC 相同也不代表载板、摄像头 mezzanine、存储布局或设备树相同。平台说明

按问题直接查询

我现在想做什么 先看哪里
元数据到底是什么,和源码有什么区别? 构建的心智模型
meta-qcom-* 这么多层,应该改哪一个? 层与职责表
添加一个程序,为什么镜像里找不到? 配方、软件包与镜像
重新开终端后,自己的配置为什么没了? 环境初始化与可复现构建
:appendDEPENDSRDEPENDS 分不清? 变量与覆盖规则
怎样把自己的代码纳入 BSP? 最小自定义层示例
改了代码但不重新编译,怎么定位? 任务、缓存与 devtool
改内核、DTB、DTBO、实时配置? 内核与设备树
efi.binsystem.img、固件 ZIP 是什么? 构建产物与启动链
rootfs 只读,配置和日志放哪里? 板上文件系统与服务
应用用交叉编译还是 Docker? SDK 与应用部署
能不能直接刷进去? 上板前检查
报错后该先看哪条证据? 排错索引

1. 元数据是构建说明书,不是生成出来的业务数据

在 Yocto 语境里,metadata 是用来描述“如何构建软件与系统”的输入:下载地址、版本、补丁、依赖、编译任务、安装路径、打包规则以及硬件/发行版配置。

一个简化的关系是:

repo manifest:把哪些仓库的哪些版本同步到哪里

metadata layers:配方、类、配置、补丁
+ 上游源码/本地源码/预编译固件

BitBake:解析变量和依赖 → 生成任务图 → 执行任务/复用缓存

软件包 → rootfs/内核/设备树/固件打包 → 镜像集合
└→ SDK:给应用开发者使用的匹配工具链和 sysroot

这也解释了一个常见疑问:repo sync 完成后,为什么 bitbake 还在下载?前者主要同步 manifest 中的构建仓库;配方里的 SRC_URI 还可能指向其他源码、压缩包和预编译固件,后者在 do_fetch 阶段获取。Yocto 4.0.18:构建概念

1.1 分清元数据层与仓库清单

名称 本文怎样理解
Yocto metadata / meta-* layer 配方与配置的逻辑集合,是本文重点
repo manifest XML 仓库与 revision 的同步清单,不是 BitBake recipe

因此,“构建高通元数据”更准确地说,是使用高通及社区提供的元数据,构建面向指定硬件的系统镜像。不要看到 meta- 就认为目录内都是可执行源代码,更不要认为每个子系统固件都能在公开 Yocto 工作区中从源代码重建。

2. 从哪个 layer 开始找:职责比名字更重要

下面按官网列出的职责重新分组,而不是把目录结构原样抄一遍。

主要职责 实际查询场景
poky/meta OE-Core 核心配方、类与基础构建规则 工具链、libc、通用镜像和打包机制
meta-openembedded 的子层 扩充通用用户空间软件 查某个库、Python 包、网络服务的配方
meta-qcom Qualcomm 上游/开放源码 BSP 支持 查 QDL、QRTR、pd-mapper 等
meta-qcom-hwe Qualcomm 硬件使能、内核、固件整合及增值功能 查 machine、DTB、内核、预编译固件、UKI 类
meta-qcom-distro 参考发行版策略、镜像、packagegroup qcom-wayland、镜像应该包含什么
meta-qcom-realtime 实时内核配方与相关配置 准备 RT 内核,而非只改应用调度优先级
meta-qcom-extras 有相应权限时使用的可选层 整合自行构建的专有组件/固件,替代所选预编译输入
meta-qcom-qim-product-sdk QIM 多媒体与 AI 软件栈集成 GStreamer 插件、QNN/SNPE/TFLite 相关打包
meta-virtualization 容器/虚拟化的软件栈配方 Docker、Kubernetes 等的构建依赖
meta-selinux SELinux 构建支持 策略与安全功能集成

这是该版指南的层集合,不保证任意 release 的默认 manifest 都启用了每一层。meta-openembedded 也不能简单理解为“交叉编译器本身”;它主要扩展 OE-Core 之外的软件元数据。高通:元数据层概述

2.1 下载了一个 layer,为什么没有效果?

至少要走完三个关卡:

  1. 找得到:该目录存在,且有 conf/layer.conf
  2. 被解析:进入最终 BBLAYERS,兼容当前 Yocto 系列及其他依赖层。
  3. 被选择:其中的 recipe/配置影响了当前 target,相关软件包真的进入镜像依赖链。

高通这一代模板把层分成 BASELAYERSBSPLAYERSEXTRALAYERS,最后组合成 BBLAYERS。前面几个是模板的组织方式,最终有效的 BBLAYERS 才是关键证据

在已初始化的 Linux 构建 shell 内查询:

bitbake-layers show-layers
bitbake-layers show-recipes
bitbake-layers show-appends
bitbake -e qcom-multimedia-image | grep '^BBLAYERS='

这里的 qcom-multimedia-image 是官网目标示例;如果选择了自定义镜像,查询时也要使用自己的 target。高通:新增层排错Yocto:创建与启用 layer

3. .bb、packagegroup、image:不是一回事

3.1 文件类型速查

文件/目录 负责什么 典型入口
.bb 单个构建目标的配方 recipes-*/*/name_version.bb
.bbappend 追加或调整已有配方,名字需匹配 name_%.bbappend 或匹配版本的文件名
.bbclass 共享任务或构建逻辑 inherit cmakeinherit systemd
.inc 被其他元数据包含的公共片段 includerequire
.conf layer、machine、distro 或工作区配置 conf/machine/*.confconf/local.conf
patch、files/ 应用到源代码的补丁或待安装资源 通过 SRC_URI 和文件搜索路径引用

require 找不到文件会报错,include 找不到不一定终止;inherit 处理类。把文本放在某个目录下,不代表 BitBake 会自动采用它。BitBake 2.0:语法与操作符

3.2 一份 recipe 可以产生多个 package

例如一个程序配方可能拆出运行包、开发头文件包、调试符号包。bitbake robot-hello 是构建配方;IMAGE_INSTALLRDEPENDS 中通常填写软件包名,两者有时同名,但不能永远等同。

robot-hello_1.0.bb
├─ do_compile / do_install:编译并装入打包暂存区
└─ do_package:依据 PACKAGES、FILES 拆包
├─ robot-hello
├─ robot-hello-dbg(是否有内容取决于构建)
└─ ...

packagegroup-myrobot
└─ RDEPENDS → robot-hello、其他运行依赖

myrobot-image
└─ IMAGE_INSTALL → packagegroup-myrobot

单独配方构建成功,不会自动修改所有 rootfs。 必须让目标镜像选择对应软件包,再重新生成该镜像,并核对包清单。Yocto:编写配方

3.3 高通镜像选择表

该版镜像 用途 不要误认为
qcom-minimal-image 小型 rootfs、启动到 shell 的基础 天然就是去掉调试入口的量产镜像
qcom-console-image 在 minimal 基础上扩展控制台、包管理、SSH 等 与 multimedia 的软件集合完全相同
qcom-multimedia-image 多媒体相关软件集合,要求相应 Wayland distro feature 只要启用 Wayland 就包含所有相机硬件适配
qcom-multimedia-full-image multimedia 的扩展,含额外 GStreamer 支持 任意机器都支持所有插件/后端
qcom-multimedia-test-image 加入测试软件包 应直接作为最小产品交付版本
qcom-multimedia-crossesdk-image 文档中专用的 eSDK 相关目标 等同任意 image 的普通 rootfs

文档中的参考 minimal 配置含 debug-tweaks、调试工具和可选 ADB 等开发功能。以后面向产品交付,需要另外审查账号、认证、调试接口、签名和服务暴露面;“minimal”只描述选择目标,不能代替安全验收。高通:镜像与软件包组

4. 常用变量:先辨认它控制哪一层

变量 回答的问题 常见误用
MACHINE 为哪个 BSP 硬件配置构建? 直接填 SoC 商品名,不查实际 .conf
DISTRO 使用什么发行版策略? 把它当宿主 Ubuntu 版本
BBLAYERS 哪些 layer 被解析? 仅克隆仓库而未启用层
SRC_URISRCREV 源码/资源从哪来、Git 用哪个 revision? 固定 manifest 却保留配方的滚动 AUTOREV
SBD 源码目录/构建目录/打包安装暂存根目录 do_install 写成安装到宿主 /usr
DEPENDS 构建当前 recipe 需要什么依赖? 以为声明后整个依赖包一定装入目标 rootfs
RDEPENDS:${PN} 这个输出包运行时依赖什么包? 用配方名替代真实拆包后的运行包名
IMAGE_INSTALL 哪些包进入这个镜像? 写了 recipe 但没让镜像安装
DISTRO_FEATURES 发行版允许/启用哪些能力? 以为开启 feature 就一定装入全部相关软件
MACHINE_FEATURES BSP 声明硬件提供哪些能力? 把 feature 字符串当成驱动已正常工作
PACKAGECONFIG 某个配方如何选择编译功能? 只改全局 feature,不核对配方实际启用项
PREFERRED_PROVIDER_virtual/kernel 虚拟 kernel 目标由哪个配方提供? 以为 layer 加进来就必然换内核
DL_DIRSSTATE_DIR 下载缓存/共享任务结果缓存在哪里? 当成已经冻结版本的源代码归档
TMPDIRDEPLOY_DIR_IMAGE 工作产物/目标机镜像输出在哪里? 固定写死 tmptmp-glibc 到所有版本

对具体目标看最终展开值,而不是只看自己编辑的那一行:

bitbake -e qcom-multimedia-image | grep -E '^(MACHINE|DISTRO|DISTRO_FEATURES|IMAGE_INSTALL|TMPDIR|DEPLOY_DIR_IMAGE)='
bitbake -e virtual/kernel | grep -E '^(PN|PV|SRCREV|KERNEL_DEVICETREE)='

bitbake -e 输出中的变量历史注释也有助于追踪“最后是谁改了值”。不要随意将整份环境转储上传公共仓库,它可能包含内部源地址或私有构建配置。Yocto 变量表

4.1 覆盖语法最容易掉坑的地方

写法 含义/注意
A = "x" 赋值,变量引用通常在展开时求值
A := "${B}" 立即展开右边
A ?= "x" 当前尚未赋值时设置默认值
A ??= "x" 弱默认值;不能与 ?= 混为一谈
A += "x" 追加时自动加入空格,发生于解析阶段
A:append = " x" 覆盖式追加,不会自动补空格
A:prepend = "x " 覆盖式前置,同样自己处理空格
A:remove = "x" 从值中移除指定项,不是任意正则替换

Kirkstone 使用冒号形式的 overrides。迁移旧教程的 _append_remove 前,应先核对所用 BitBake 版本,不要盲目混写。

两个最常用的例子:

# 在镜像 recipe 的 bbappend 中添加运行包
IMAGE_INSTALL:append = " robot-hello"

# 在某个 bbappend 中添加本层的本地资源搜索路径
FILESEXTRAPATHS:prepend := "${THISDIR}/files:"
SRC_URI:append = " file://my-change.patch"

第二个例子的 := 保留当前 append 文件对应的目录,结尾冒号分隔路径。.bbappend 文件名也必须匹配目标,例如上游从 foo_1.0.bb 升级到 foo_2.0.bb,原来的 foo_1.0.bbappend 不会自动迁移。

BBFILE_PRIORITY 影响多个层提供同名配方时的优先关系,但不是“数值高就覆盖任何变量、任何 .conf、任何 class”的总开关。发生冲突时,结合 provider/version 选择、overrides、解析规则和 show-appends 排查。Yocto:层优先级与 appendBitBake:覆盖语法

5. 从 manifest 到镜像:先锁版本,再初始化

5.1 先记录五个选择

开始前至少明确:板卡/载板、BSP release、manifest 文件、MACHINEDISTRO/image 组合。不能从不同时间的网页中各取一个“看起来能用”的值拼起来。

官方编译指南还区分了获取路径:

情况 去哪里查询
未注册用户,使用公开工作流与预编译专有二进制 未注册用户 GitHub 工作流
已注册且有相应访问权限 编译指南简介 中的 QSC Launcher、QSC CLI 或注册用户 GitHub 路线
确认本次 release 的同步参数 对应 Release Notes 的 Build-critical release tags,而不是任意网页中的示例值

本次读到的未注册用户工作流标注 2024-08-07,其 Linux 示例要求 Ubuntu 22.04、16 GB RAM、300 GB 可用磁盘、超过 32 GB 的 swap,并提示虚拟机编译较慢。这些是该历史流程的容量与环境参考,不是后续所有 BSP 的统一最低要求;同时运行多个构建还需另估资源。它使用预编译专有输入,不能理解成“未注册也可以获取所有专有源码”。官方工作流与主机要求

官方仓库入口为 qcom-manifest。本次访问也会遇到迁移后的 qualcomm-linux 组织链接;记录实际仓库地址与 commit,避免只保留旧组织名。

这次实际读到的资料有三个不同层次:

证据 可以确认什么 不能据此确认什么
2024-10-09 的功能指南 使用 MACHINE=qcm6490 的历史示例 当前分支仍用同一个 machine 名称
公开 release 文件 qcom-6.6.17-QLI.1.0-Ver.1.4.xml 每个层的固定 revision 和工作区路径 它就是我尚未确定板卡的适用 release
本次读到的 qcom-linux-kirkstone README 示例已是 qcom-6.6.28-QLI.1.1-Ver.1.1.xml,搭配 qcs6490-rb3gen2-vision-kit 可以将新 machine 与旧 manifest 混用

例如,1.0 Ver.1.4 manifest 中,poky 固定为 54af8c5e80ebf63707ef4e51cc9d374f716da603meta-qcom-hwe 固定为 b33ec567fa7f4af85e86cd24de10c7e5e519a7cbmeta-qcom-distro 固定为 df08769a3044a33e903696acf2733d3b8babe20b。它还把 distro 仓库的 set_bb_env.sh 通过 linkfile 暴露成根目录 setup-environment。这说明 manifest 不只是一个版本名,还定义整个工作区如何拼装

上述 XML 文件本身仍通过分支 URL 引用;实际部署时也要记录 manifest 仓库的 commit,并保存 repo manifest -r 结果。不要把“XML 内部固定了 revision”误认为“引用 XML 的分支 URL 永远不变”。Kirkstone 分支 README

以下仅示意同步命令的形式,变量没有默认值,不可整段当成已确认板型的部署脚本

# 在已满足该 release 要求的 Linux 构建主机、独立工作区内
# 先为这些变量填入经过核对的值
: "${QCOM_MANIFEST_BRANCH:?填写匹配 BSP 的 manifest 分支}"
: "${QCOM_MANIFEST_FILE:?填写具体 release XML 文件名}"

repo init -u https://github.com/quic-yocto/qcom-manifest \
-b "$QCOM_MANIFEST_BRANCH" -m "$QCOM_MANIFEST_FILE"
repo sync

不要在现有网站仓库运行这些命令。宿主架构、Ubuntu 版本、磁盘空间、依赖和注册许可要求以对应 Qualcomm Linux 编译指南 为准。手头有一个 Ubuntu 22.04 容器,不等于已经有经过验证的高通 BSP 构建环境。

5.2 setup-environment 不是普通可执行程序

官网该代示例是:

# 在同步完成的 BSP 根目录;以下 machine 只是 2024 指南示例
export SHELL=/bin/bash
MACHINE=qcm6490 DISTRO=qcom-wayland source setup-environment

必须在兼容的 Bash shell 中运行。source 会改变当前 shell的环境和工作目录;改成 bash setup-environment,子进程退出后通常不能保留所需环境。export SHELL=/bin/bash 也不会把正在运行的 zsh 变成 Bash,需要先真正进入 Bash。

不同 release 的机器命名已经变化。只要源码里的 .conf 不支持当前 MACHINE,就应回到 release 文档,而不是改个近似名字反复尝试。

5.3 配置可能被重新生成

高通环境脚本不应直接套用“上游 oe-init-build-env 一定保留已有配置”的印象。本次成功读取的 Kirkstone 分支脚本 有两条路径:

调用条件 脚本处理
显式传入一个已有 build 目录,并且其中 conf/local.confconf/auto.confconf/bblayers.conf 三者都存在 初始化 OE 环境后提前返回,复用已有配置
无目录参数,或上述配置不完整 进入生成路径,重写 local.confbblayers.confauto.confsite.conf

因此,按已读分支脚本恢复环境的形式是:

# 在 BSP 工作区根目录;先备份并确认该目录的配置齐全
source setup-environment build-qcom-wayland

复用分支不会重新生成层列表,临时传入 EXTRALAYERS 也不等于自动加入新层;需要核对实际 BBLAYERS。这是本次读到的分支实现,不冒充所有 release 的保证;部署前仍须核对 manifest 固定 revision 对应的脚本。

操作原则:

  • 首次初始化后记录 pwd 和生成的 conf/ 内容。
  • 再次进入环境前,先看固定 release 的脚本是否支持显式传入已有 build 目录并复用配置。
  • auto.conf 若标注为自动生成,就不要把它作为持久定制入口。
  • 长期修改放在自己的 layer/受版本控制的配置模板中;对工作区配置保留差异和备份。
  • 初始化后再次核对 MACHINEDISTROBBLAYERS,不要只看终端提示符。

5.4 编译与产物确认

在已选择并确认的 build 环境中,文档示例构建:

bitbake qcom-multimedia-image

该代文档的典型输出为:

<workspace>/build-qcom-wayland/
conf/
tmp-glibc/
work/...
deploy/
images/<machine>/<image-name>/
sdk/...

真正找路径时优先查 TMPDIRDEPLOY_DIR_IMAGE 和部署类。高通 image-qcom-deploy.bbclass 还会组织 <image-name> 子目录。构建成功后要确认文件、大小、哈希和对应的 release,而不是只看最后一行 succeeded

6. 加自己的代码:维护一个小 layer

官网通过直接编辑高通 layer 展示定制点;长期维护时,我更倾向于保留 vendor 基线,用自己的 layer 放应用、配置、patch 和 .bbappend。这样 BSP 升级后可以清楚比较自己的增量。

下面是原创教学结构,未执行 BitBake 编译,不包含任何高通闭源代码:

layers/meta-myrobot/
conf/layer.conf
recipes-demo/robot-hello/
robot-hello_1.0.bb
files/hello.c
recipes-products/images/
qcom-multimedia-image.bbappend

在已经初始化、确认路径正确的 build 目录中,可以使用 Yocto 的创建工具生成 layer 骨架,再启用它:

# 假定 build 与 layers 是 BSP 根目录的同级子目录
bitbake-layers create-layer ../layers/meta-myrobot
bitbake-layers add-layer ../layers/meta-myrobot
bitbake-layers show-layers

命令会创建/修改文件;只应在自己的 BSP 工作区执行一次。如果目录已存在,先检查而不是覆盖。创建工具还可能生成示例 recipe;正式维护时整理为所需结构,并保留 layer 的 README、许可证与兼容系列声明。

6.1 应用、配方和镜像,三处各做一件事

hello.c 的教学内容:

/* SPDX-License-Identifier: MIT */
#include <stdio.h>

int main(void) {
puts("robot-hello: application packaging check");
return 0;
}

robot-hello_1.0.bb 的结构:

SUMMARY = "Small application packaging exercise"
LICENSE = "MIT"
LIC_FILES_CHKSUM = "file://${COMMON_LICENSE_DIR}/MIT;md5=0835ade698e0bcf8506ecda2f7b4f302"

SRC_URI = "file://hello.c"
S = "${WORKDIR}"

do_compile() {
${CC} ${CPPFLAGS} ${CFLAGS} ${S}/hello.c ${LDFLAGS} -o robot-hello
}

do_install() {
install -d ${D}${bindir}
install -m 0755 robot-hello ${D}${bindir}/robot-hello
}

这个本地单文件示例使用 Kirkstone 的 WORKDIR 布局。示例校验值已对照 Poky Kirkstone 的公共 MIT 文件 计算核对;实际项目要声明真实许可证并检查文件校验值,不能给专有代码随便贴 MIT。${CC} 和相关 flags 来自目标工具链;${D} 是打包暂存根目录,不能删掉它把文件安装到构建主机。

随后在 qcom-multimedia-image.bbappend 中写:

IMAGE_INSTALL:append = " robot-hello"

最后分别确认“配方可构建”和“镜像会安装”:

bitbake robot-hello
bitbake-layers show-appends
bitbake -e qcom-multimedia-image | grep '^IMAGE_INSTALL='
bitbake qcom-multimedia-image

核对生成镜像的 package manifest,确认包含 robot-hello;以后上板再执行它确认目标架构、动态库和安装路径。本文没有把这些预期动作写成实测成功日志。Yocto:新配方

6.2 加服务、加依赖、裁剪功能时怎么扩展

变化 优先使用的元数据入口
程序编译时需要某个库的头文件/链接文件 recipe 的 DEPENDS
运行时调用外部命令或解释器 输出包的 RDEPENDS:${PN},同时核对自动依赖
安装 systemd 服务 recipe 安装 unit 并 inherit systemd;设置对应 SYSTEMD_SERVICE,明确是否自启动
一组机器人应用一起安装 自己的 packagegroup,定义运行依赖,再由 image 选择
裁剪显示/蓝牙 定位引用它的 packagegroup,使用自己 layer 的 append;再检查是否有其他依赖重新引入
保留自定义机器/发行版配置 自己 layer 的 conf/machineconf/distro,按实际 BSP 继承关系组织

注意,原始 image 最终可能不仅靠 IMAGE_INSTALL,还使用 CORE_IMAGE_* 和 packagegroup 等机制;删除某一处引用后,应看最终包清单,不把编辑成功当成裁剪成功。

7. 任务与缓存:每条命令究竟做什么

典型源码配方可以按下面的链条理解,实际 DAG 会包含依赖和额外任务:

do_fetch → do_unpack → do_patch → do_configure → do_compile
→ do_install → do_package → do_package_write_*
→ 镜像依赖装配 do_rootfs → do_image* → 部署相关任务

qprebuilt 一类配方可能使用预编译输入,并不按普通源码程序那样完成编译。任务列表和 bitbake -e 的最终函数才是证据。

命令 用途/副作用
bitbake -c listtasks robot-hello 查看任务名称
bitbake -e robot-hello 解析元数据、查看展开值,不是编译验收
bitbake -c fetch robot-hello 获取资源,会发生下载和缓存写入
bitbake -c compile robot-hello 请求 compile 及依赖任务,不保证打包进最终镜像
bitbake robot-hello 运行配方的默认构建目标
bitbake -g robot-hello 生成依赖图文件,适合追踪依赖
bitbake -c clean robot-hello 清理该配方工作输出,不等于删除全部 sstate
bitbake -c cleansstate robot-hello 进一步清理该配方本地共享状态;共享缓存环境下要协调
bitbake -c cleanall robot-hello 还可能清除下载输入,不作为普通排错第一步

缓存不是简单判断“文件夹存在就不再编译”。任务签名与输入变化决定重建/复用;直接改 tmp*/work 下临时展开源码,可能被重新解包覆盖,也可能没有按希望触发重建。

7.1 定位日志,不手猜路径

bitbake -e robot-hello | grep -E '^(WORKDIR|S|B|T)='

在输出的任务日志目录查看 log.do_fetchlog.do_configurelog.do_compilelog.do_installlog.do_package_qa 等;实际失败在哪个 task,就先检查该 task 的日志。run.do_* 还可帮助理解实际执行命令,具体后缀以目录中内容为准。

7.2 devtool 用于开发,完成后要保存回 layer

以官网已有的 Weston 目标为例,在适用 BSP 内:

devtool modify weston
# 编辑 devtool 报告的源代码目录,记录修改并按工作流提交补丁
devtool build weston
devtool build-image qcom-multimedia-image

长期保存时,再按该版 devtool finish --help 将修改归入自己的 layer,并核对生成的补丁/append。workspace/sources 是开发工作区,不是最终可移植构建说明书。不要在尚未保存改动时随意 reset 或清理工作区。

官网用户定制的 QDL 段落出现“修改 QDL 却 devtool build weston”,Weston 段落也出现 pulseaudio 输出路径,明显存在拷贝痕迹。修改哪个 recipe,就围绕该 recipe 验证,不能照抄示例中的不一致名称。 QDL 还区分 target 与 qdl-native 等宿主构建变体,要先明确需要的是刷机主机上的工具。高通:用户定制

8. 内核、设备树和 RT:硬件支持的三条线

8.1 内核与配置入口

该版指南使用 6.6 LTS 的 linux-kernel-qcom 配方;实时扩展由 meta-qcom-realtimelinux-kernel-qcom-rt 提供。文档中的核心配置包括:

入口 用途
qcom_defconfig 基础配置
qcom_addons.config Qualcomm 下游增补
qcom_debug.configqcom_addons_debug.config 调试变体的增补
KERNEL_DEFCONFIGKERNEL_CONFIG_FRAGMENTS 指定基础 defconfig 与配置片段
KERNEL_MODULE_AUTOLOAD 指定需要自动加载的模块名
KERNEL_CMDLINE_EXTRA 添加内核启动参数,不等同编译 Kconfig

DEBUG_BUILDPERFORMANCE_BUILD 是该 BSP 定义的控制项,不是通用 Yocto 开关。官网说明 DEBUG_BUILD=1 优先;性能启动模式可能移除 UART console。首次 bring-up 时丢掉串口输出,会让定位启动失败更困难。

8.2 DTB 和 DTBO 为什么还要跟 package 依赖配合

KERNEL_DEVICETREE 选择基础 DTB;该 BSP 的 KERNEL_TECH_DTBOS 为指定基础设备树关联技术模块 overlay。生成 DTBO 的包还需要进入相应依赖,例如 MACHINE_EXTRA_RDEPENDS

因此“在变量里填了一个 .dtbo 文件名”并不保证文件已经被构建并进入镜像。还要检查:源文件/配方是否存在、依赖是否生效、打包产物是否存在、启动时是否选中了适配实际载板的设备树。

这也是不能只凭 MACHINE=qcm6490 就判断 camera mezzanine 可用的原因。该代平台支持组合多个 DTB,UEFI 依据硬件选择对应项;基础板与视觉扩展板的选择要匹配。

本次也读到了上述旧 manifest 固定的 qcm6490.conf(b33ec567…)KERNEL_DEVICETREE 同时列出 QCS5430 不同变体与 QCS6490 RB3 Gen 2 的基础板、video/vision mezzanine 等 DTB;KERNEL_TECH_DTBOS[...] 按基础板条目关联 overlay,MACHINE_EXTRA_RDEPENDS 再拉入 firmware packagegroup 与 graphics/display/camera/WLAN/BT 设备树包。这是“同一个 machine 文件覆盖多个具体设备树目标”的实际例子,不是各载板可以混用镜像的保证。

8.3 模块签名与实时性

指南说明 BSP 强制模块签名,并通过 qmodule.bbclass 处理部分树外模块签名。自编模块加载失败时,应检查内核版本/配置、vermagic、签名和信任链,不要首先关闭强制校验。

同理,加入 meta-qcom-realtime 只解决 RT 内核构建的一部分。对机器人控制,应实测调度延迟、驱动和中断行为、负载下的周期抖动与 deadline miss;它不是一条让整机自动满足硬实时的开关。高通:内核、RT 与设备树

9. 输出文件怎么认:rootfs 不等于整机固件

9.1 三种固件输入

该代配方/输入 放到哪里、用来做什么
firmware-qcom-bootbinsQCM6490_bootbinaries.zip 关键启动二进制,部署到对应镜像集合供刷写
firmware-qcom-hlosfwQCM6490_fw.zip aDSP、cDSP、Modem、WLAN 等子系统固件,安装到 rootfs 的相关固件目录
firmware-qcom-dspsoQCM6490_dspso.zip 被用户空间使用链路引用的 DSP 库,按配方放入 rootfs

默认 meta-qcom-hwe 路径可以获取预编译固件;在拥有相应源码和权限时,meta-qcom-extras 可通过 FWZIP_PATH 接入自行生成的匹配 ZIP。公开 layer 能被 clone,不意味着闭源固件源码和分发许可也自动开放。

9.2 启动与打包关系

启动固件/UEFI

EFI 系统分区 efi.bin
├─ bootaa64.efi:启动管理器
└─ uki.efi:kernel + initramfs + cmdline + OS 元数据等

dtb.bin
└─ 对应硬件的设备树/该 BSP 的组合 DTB

system.img
└─ 目标 rootfs:库、程序、服务、部分子系统固件

分区描述 → gen_partition → partition.xml → Ptool
└─ GPT 二进制 + rawprogram XML + patch XML

该代的 uki.bbclassimage-efi.bbclass 负责相应封装,image-qcom-deploy.bbclass 组织交付文件。只替换 Linux Image 文件,未必就替换了设备实际启动的 UKI/EFI 分区内容。

9.3 刷写输入是成套契约

prog_firehose_*.elf 是与目标平台相关的刷写 programmer;rawprogram*.xml 描述写入内容和位置;patch*.xml 与 GPT 等负责对应布局调整。它们必须与板型、存储介质、容量、分区方案和安全状态匹配。

文档使用 UFS 示例,不能直接推到 eMMC。也不要从不同版本目录各取一个 programmer、rootfs 和 XML 拼在一起。没有确认这些条件前,本笔记不提供可直接执行的通用刷写命令。高通:固件、分区与 QDL

10. 板上文件系统与服务:为什么“重启还在”和“刷机还在”不同

10.1 rootfs、overlay、persist

区域 该版设计中的用途 后续部署注意
基础 rootfs 系统与预装软件,推荐只读 临时改动不应代替 recipe
overlay /etc/var/opt 等提供可写上层 实际挂载点按板上 findmntmount 确认;不要猜分区号
persist,挂到 /var/persist BSP 跨重启所需的持久性数据 不能当成通用清理空间,更不能随意格式化

“放在 overlay 重启后还在”不等于“更新整个分区后还在”。反过来,旧 overlay 上层文件也可能遮住新 rootfs 中更新后的同名配置;出现“镜像明明改了但运行还是旧内容”,应检查挂载层与升级策略。后一点是基于 overlay 工作方式的部署推论,不是本文已经在板上复现的故障。

目标板只读查询示例:

cat /etc/os-release
uname -m
uname -r
findmnt /
findmnt /etc
findmnt /var
findmnt /opt
findmnt /var/persist
lsblk -o NAME,SIZE,FSTYPE,LABEL,PARTLABEL,MOUNTPOINTS

不同目标镜像可能未安装完整 util-linux 命令,可先用 mount 查看,不要因为工具缺失就假定分区不存在。指南出现的 /dev/sda10/dev/sda11 只是示例,不应硬编码进部署脚本。

10.2 需要认识的服务

服务/配置 查询用途
mnt-overlay.mountvar-persist.mount 确认可写层与持久分区是否按预期挂载
pd-mapper.service、QRTR 相关组件 排查应用与远端子系统相关的基础通信支持
property-vault.servicepersist-property-vault.service 该 BSP 的属性服务及持久属性初始化
android-tools-adbd.service 检查开发调试接口是否启用,不默认视为所有镜像必有
rsyslog.service、logrotate 配置 系统/应用日志收集与滚动
systemctl --failed --no-pager
systemctl status property-vault.service --no-pager
journalctl -b -u property-vault.service --no-pager

getpropsetprop 在本文是高通 property-vault 提供的能力,不应据此推断目标系统就是 Android。持久属性与普通临时属性不同;不要把属性服务当成放密码、密钥的安全存储。高通:文件系统、初始化与属性

11. 后续应用部署:交叉 SDK、原生包和 Docker 各管一层

11.1 “SDK”在这里至少有两种意思

名称 内容/用途
Yocto 标准 SDK/eSDK 匹配构建产物的交叉工具链、sysroot、应用开发工具;eSDK 进一步支持开发工作流
QIM/AI 产品 SDK 多媒体插件、AI runtime、接口库及相关集成包

有 QIM layer 不代表已经生成应用交叉 SDK;有交叉工具链也不代表设备上存在对应 NPU/DSP runtime。

应用和第三方 C++ 库需要作为可追溯制品复用时,可继续看 Conan:制品身份、依赖锁定与 Yocto SDK 对接。其中区分 build/host profile、工具链与 sysroot 的配置归属,以及为什么换一个 SDK 路径不一定会改变 Conan 的 package ID。该节仍是待板卡验证的集成方案,不表示本文 BSP 已经接入 Conan。

对支持标准 SDK 的 image,Yocto 通用入口为:

bitbake qcom-multimedia-image -c populate_sdk

安装器通常位于 ${TMPDIR}/deploy/sdk,实际文件名以生成结果为准。不要从别的 BSP 随便拿一个同为 aarch64 的 SDK:glibc、C++ ABI、头文件、驱动用户态接口和库版本都需要匹配。Yocto 4.0.18:获取 SDK

11.2 哪种部署方式适合什么阶段

方式 适用场景 需要保留的证据
SDK 编译后复制程序 首次验证、快速定位依赖 工具链/sysroot 版本、目标架构、动态链接器、所需库
recipe 纳入镜像或受控包源 系统级正式集成与重建 layer commit、配方依赖、包清单、镜像哈希
板上运行应用容器 用户空间服务隔离、可复现应用环境 linux/arm64 镜像摘要、设备/库映射、宿主 BSP 契约

应用容器共享目标板的宿主内核。容器不能替代 BSP 驱动、设备树、子系统固件或签名链。把本站现有 ONNX/MuJoCo Docker 镜像搬过去,也不能自动获得高通 NPU 加速;应分别核对 CPU 架构、实际推理 provider、模型算子、runtime 与驱动匹配。

11.3 官网容器能力说明应怎样使用

该代文档通过 meta-virtualizationpackagegroup-container、相关内核配置以及 multimedia packagegroup 集成 Docker/Compose/Kubernetes。它说明这套 BSP 的集成路径,不是当前所有镜像都已开启这些能力。

部署前只读核对:

docker version
docker info
systemctl status docker --no-pager
systemctl status kubelet --no-pager

官网某些示例包含广泛的设备映射、--privileged、忽略 Kubernetes preflight 检查等开发设置。它们不作为本文默认的产品部署策略;后续按所需设备、权限、网络和安全策略最小化配置。Compose v1 的 docker-compose 与插件形式 docker compose 也应按目标实际版本区分。

12. 上板前检查:先留下一份可追溯记录

12.1 部署记录模板

可下载 部署检查表 YAML。这是人工记录模板,不是会执行刷机的配置文件

必填项 为什么需要
SoC、板卡、载板、硬件 revision、mezzanine 确认 machine/DTB 真正匹配
UFS/eMMC、容量、分区方案 programmer 与 XML 不能只凭名字匹配
BSP release、manifest 文件与 commit 避免浮动分支重建出不同版本
各 layer revision、自己的补丁 commit 解释本次构建与官方基线的差别
image、distro、machine、debug/RT 等设置 定义实际构建目标
固件 ZIP 来源、版本、哈希与使用权限 避免混用未配套固件
主机 OS/架构、SDK、构建工具版本 定位宿主和工具链差异
镜像包清单、产物 SHA-256、构建日志 确认上板的是验收过的那一份
当前设备可用版本、备份、恢复入口 失败时可以回到已知可用状态

repo manifest -r 可用于导出解析后的仓库 revision;但它不会自动保存未提交补丁、外部 SRC_URI 下载物、许可证授权或所有环境配置。应按团队允许的存储范围归档这些证据,不把凭据和专有软件上传公开网站。

12.2 哪些操作必须单独确认

  • 刷写/重新分区会写设备存储,可能覆盖系统和数据;先确认串口、恢复模式和对应板卡官方流程。
  • persist 不能作为普通缓存删除;备份范围也要考虑校准、设备身份等实际 BSP 数据用途。
  • UFS OTP、--finalize-provisioning、熔丝、密钥烧录、Secure Boot 状态变更可能不可逆,不属于普通尝鲜步骤。
  • 不把关闭 SELinux、关闭模块签名、启用宽松调试账号当成通用解决方法。
  • 看到 USB 05c6:9008 只说明相关下载模式枚举,不证明 programmer、容量和安全状态匹配。

这轮只整理知识,没有连接硬件,也没有执行这些操作。刷写细节必须等实际板型与 BSP release 确认后再形成单独的、可审核的操作单。

12.3 验收不要只停在“能开机”

建议逐层确认:启动/串口 → 系统版本和挂载 → 驱动/设备树 → 固件与服务 → 应用依赖 → 功能输入输出 → 重启持久性 → 长时运行与资源占用 → 更新回滚。

对后续四足控制部署,还应另外记录控制频率、端到端时延、deadline miss、通信中断行为、watchdog 和故障恢复;“成功启动一个 ONNX session”不能替代控制闭环验收。

13. 排错索引:先看证据,再改配置

症状 优先检查
Nothing PROVIDES/找不到 recipe show-layersshow-recipes、名称、兼容系列、provider 选择
新 layer 没有效果 最终 BBLAYERS;环境脚本是否重写配置
.bbappend 没生效/dangling append 上游 recipe 文件名与版本;show-appends
配方编译成功但 rootfs 没程序 输出包名、PACKAGESFILES、镜像依赖链与 package manifest
do_fetch 失败 SRC_URI/revision、网络代理、镜像源、许可证或访问权限;不要靠关闭校验掩盖问题
修改后仍像旧版本 实际被选中的 recipe/源码、SRCREV、devtool workspace、任务日志和最终产物
内核模块无法加载 目标内核版本、配置、vermagic、签名/信任链、依赖模块
相机/显示设备不出现 实际载板 DTB/DTBO、对应生成包、驱动、固件和服务
文件存在却报 No such file or directory filereadelf 检查 ELF 架构、动态链接器及库,不只是检查文件是否存在
从 BSP 输出目录复制 QDL 后无法启动 可能依赖构建工作区的 uninative loader;工具是否与刷机主机架构匹配
QDL 通信异常 USB 枚举、线缆、权限、programmer、ModemManager 争用;先保留错误日志
新镜像配置没有体现 是否刷到实际启动分区;overlay 上层是否遮蔽新基础文件
开机无 UART 日志 接线/波特率/设备节点,以及 debug/performance 与内核 console 设置
Docker/K8s 不工作 镜像中是否打包、内核能力、服务实际状态、存储驱动/cgroup,而非只看文档列表

QDL 与 ModemManager 的具体诊断入口见 高通:调试。如果为了刷机临时停止服务,应记录原状态并在完成后恢复,不能不加区分地永久禁用。

14. 官网旧例子中,不应原样带进部署脚本的内容

看到的表述 这份笔记的处理
deploy/imagedeploy/images 混用 查询实际变量与部署类;本文将官网示例目录写为 deploy/images
单独编译 QDL 示例里 git https://... 原命令缺少子命令;不当成可执行命令复制
QDL/Weston 的 devtool 示例对象不一致 根据被修改的 recipe 核对,不伪造成功输出
conf/layers.confbblayer.conf 等拼写 layer 描述是 conf/layer.conf,构建层列表是 conf/bblayers.conf
分区概览称 JSON,后文却展示 .conf 行式选项 以该 release 实际 gen_partition 输入格式为准,不自行改成 JSON
ARM64 UKI 表格中出现 linuxx64.efi.stub 架构必须由实际构建检查,不能把表格中的名字当成目标板要求
容器服务状态表/开发特权示例 以目标机运行结果与当前版本文档为准,不据此默认扩大权限
旧页面引用指向浮动 kirkstone 分支 记录实际 manifest 中的 commit,不把网页日期当成分支冻结日期
未注册用户工作流示例仍写 qcm6490,Kirkstone README 却已写 qcs6490-rb3gen2-vision-kit 两处均为实际读到的资料差异;按目标 release 的 tags 与同步后 machine 配置确认,不能仅凭页面末尾日期决定命令正确性

这些差异不否定官网提供的架构信息,但提醒我:知识可以按概念整理,命令必须按具体版本验证。

原始资料与相关笔记

最后用一句话记:manifest 固定源码入口,layer 组织构建知识,machine 定义硬件目标,distro 定义系统策略,image 决定交付内容;真正部署时还要核对固件、分区、工具链和安全状态。

3d打印 actor-critic adaptive sampling ai辅助设计 algorithm algorithms anymal apriltag ardupilot async atlas attention automation axis-angle bang-bang belief encoder bitbake blender bode bsp c++ cadquery calibration camera calibration camera-intrinsics cargo chrome cmake cmakelists cnn colcon computer-vision conan control controller_manager cpp cpu d435i dagger data_struct db depth camera depth-camera design-pattern diagnostics direct collocation dots dtof economics eigen elevation map elf embedded linux executor factory-pattern fcpx ffi fiducial marker figure finance forge fourier fov freecad gae gazebo gdb geometry git gnu gru guitar hardware humanoid ibus imu interest isaac gym isaac lab isaaclab kdl laplace latent variable latex launch learning-notes legged locomotion legged robotics legged-robot legged_gym life linux linux-kernel linux-tools mac math matlab matrix memory mixture of experts mlp money motion imitation motion-control motor moveit mpc mujoco music-theory network neural mapping ocs2 ode onnx openscad operator optimal algorithm optimal-control perceptive locomotion perf performance personal-finance piano pinhole-camera pinocchio pixhawk pixhawk 6c point-cloud policy distillation ppo privileged learning profiling px4 python qgroundcontrol qos quadrotor qualcomm realsense reinforcement learning representation learning reward tuning rnn robogauge robot robot parkour robotics ros ros2 ros2_control rsl_rl rtb rust security sensor-fusion shell signal-processing sim-to-real simulation socket soft dynamics constraints spot ssh stairs stl stm32 systems-programming tcp-ip teacher policy teacher student teacher-student temporal convolution terrain reconstruction thread tools tron1 twist ubuntu uml uncertainty unitree unitree g1 urdf vae valgrind vcxsrv velocity vim web wifi wiring work workflow wsl yocto z-transform zero-shot transfer 中文输入 交叉编译 人形机器人
知识共享许可协议