阅读范围与版本
这份笔记从 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-* 这么多层,应该改哪一个? |
层与职责表 |
| 添加一个程序,为什么镜像里找不到? | 配方、软件包与镜像 |
| 重新开终端后,自己的配置为什么没了? | 环境初始化与可复现构建 |
:append、DEPENDS、RDEPENDS 分不清? |
变量与覆盖规则 |
| 怎样把自己的代码纳入 BSP? | 最小自定义层示例 |
| 改了代码但不重新编译,怎么定位? | 任务、缓存与 devtool |
| 改内核、DTB、DTBO、实时配置? | 内核与设备树 |
efi.bin、system.img、固件 ZIP 是什么? |
构建产物与启动链 |
| rootfs 只读,配置和日志放哪里? | 板上文件系统与服务 |
| 应用用交叉编译还是 Docker? | SDK 与应用部署 |
| 能不能直接刷进去? | 上板前检查 |
| 报错后该先看哪条证据? | 排错索引 |
1. 元数据是构建说明书,不是生成出来的业务数据
在 Yocto 语境里,metadata 是用来描述“如何构建软件与系统”的输入:下载地址、版本、补丁、依赖、编译任务、安装路径、打包规则以及硬件/发行版配置。
一个简化的关系是:
repo manifest:把哪些仓库的哪些版本同步到哪里 |
这也解释了一个常见疑问: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,为什么没有效果?
至少要走完三个关卡:
- 找得到:该目录存在,且有
conf/layer.conf。 - 被解析:进入最终
BBLAYERS,兼容当前 Yocto 系列及其他依赖层。 - 被选择:其中的 recipe/配置影响了当前 target,相关软件包真的进入镜像依赖链。
高通这一代模板把层分成 BASELAYERS、BSPLAYERS、EXTRALAYERS,最后组合成 BBLAYERS。前面几个是模板的组织方式,最终有效的 BBLAYERS 才是关键证据。
在已初始化的 Linux 构建 shell 内查询:
bitbake-layers show-layers |
这里的 qcom-multimedia-image 是官网目标示例;如果选择了自定义镜像,查询时也要使用自己的 target。高通:新增层排错、Yocto:创建与启用 layer
3. .bb、packagegroup、image:不是一回事
3.1 文件类型速查
| 文件/目录 | 负责什么 | 典型入口 |
|---|---|---|
.bb |
单个构建目标的配方 | recipes-*/*/name_version.bb |
.bbappend |
追加或调整已有配方,名字需匹配 | name_%.bbappend 或匹配版本的文件名 |
.bbclass |
共享任务或构建逻辑 | inherit cmake、inherit systemd |
.inc |
被其他元数据包含的公共片段 | include/require |
.conf |
layer、machine、distro 或工作区配置 | conf/machine/*.conf、conf/local.conf |
patch、files/ |
应用到源代码的补丁或待安装资源 | 通过 SRC_URI 和文件搜索路径引用 |
require 找不到文件会报错,include 找不到不一定终止;inherit 处理类。把文本放在某个目录下,不代表 BitBake 会自动采用它。BitBake 2.0:语法与操作符
3.2 一份 recipe 可以产生多个 package
例如一个程序配方可能拆出运行包、开发头文件包、调试符号包。bitbake robot-hello 是构建配方;IMAGE_INSTALL/RDEPENDS 中通常填写软件包名,两者有时同名,但不能永远等同。
robot-hello_1.0.bb |
单独配方构建成功,不会自动修改所有 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_URI/SRCREV |
源码/资源从哪来、Git 用哪个 revision? | 固定 manifest 却保留配方的滚动 AUTOREV |
S/B/D |
源码目录/构建目录/打包安装暂存根目录 | 将 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_DIR/SSTATE_DIR |
下载缓存/共享任务结果缓存在哪里? | 当成已经冻结版本的源代码归档 |
TMPDIR/DEPLOY_DIR_IMAGE |
工作产物/目标机镜像输出在哪里? | 固定写死 tmp 或 tmp-glibc 到所有版本 |
对具体目标看最终展开值,而不是只看自己编辑的那一行:
bitbake -e qcom-multimedia-image | grep -E '^(MACHINE|DISTRO|DISTRO_FEATURES|IMAGE_INSTALL|TMPDIR|DEPLOY_DIR_IMAGE)=' |
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 中添加运行包 |
第二个例子的 := 保留当前 append 文件对应的目录,结尾冒号分隔路径。.bbappend 文件名也必须匹配目标,例如上游从 foo_1.0.bb 升级到 foo_2.0.bb,原来的 foo_1.0.bbappend 不会自动迁移。
BBFILE_PRIORITY 影响多个层提供同名配方时的优先关系,但不是“数值高就覆盖任何变量、任何 .conf、任何 class”的总开关。发生冲突时,结合 provider/version 选择、overrides、解析规则和 show-appends 排查。Yocto:层优先级与 append、BitBake:覆盖语法
5. 从 manifest 到镜像:先锁版本,再初始化
5.1 先记录五个选择
开始前至少明确:板卡/载板、BSP release、manifest 文件、MACHINE、DISTRO/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 固定为 54af8c5e80ebf63707ef4e51cc9d374f716da603,meta-qcom-hwe 固定为 b33ec567fa7f4af85e86cd24de10c7e5e519a7cb,meta-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 构建主机、独立工作区内 |
不要在现有网站仓库运行这些命令。宿主架构、Ubuntu 版本、磁盘空间、依赖和注册许可要求以对应 Qualcomm Linux 编译指南 为准。手头有一个 Ubuntu 22.04 容器,不等于已经有经过验证的高通 BSP 构建环境。
5.2 setup-environment 不是普通可执行程序
官网该代示例是:
# 在同步完成的 BSP 根目录;以下 machine 只是 2024 指南示例 |
必须在兼容的 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.conf、conf/auto.conf、conf/bblayers.conf 三者都存在 |
初始化 OE 环境后提前返回,复用已有配置 |
| 无目录参数,或上述配置不完整 | 进入生成路径,重写 local.conf、bblayers.conf、auto.conf、site.conf |
因此,按已读分支脚本恢复环境的形式是:
# 在 BSP 工作区根目录;先备份并确认该目录的配置齐全 |
复用分支不会重新生成层列表,临时传入 EXTRALAYERS 也不等于自动加入新层;需要核对实际 BBLAYERS。这是本次读到的分支实现,不冒充所有 release 的保证;部署前仍须核对 manifest 固定 revision 对应的脚本。
操作原则:
- 首次初始化后记录
pwd和生成的conf/内容。 - 再次进入环境前,先看固定 release 的脚本是否支持显式传入已有 build 目录并复用配置。
auto.conf若标注为自动生成,就不要把它作为持久定制入口。- 长期修改放在自己的 layer/受版本控制的配置模板中;对工作区配置保留差异和备份。
- 初始化后再次核对
MACHINE、DISTRO、BBLAYERS,不要只看终端提示符。
5.4 编译与产物确认
在已选择并确认的 build 环境中,文档示例构建:
bitbake qcom-multimedia-image |
该代文档的典型输出为:
<workspace>/build-qcom-wayland/ |
真正找路径时优先查 TMPDIR、DEPLOY_DIR_IMAGE 和部署类。高通 image-qcom-deploy.bbclass 还会组织 <image-name> 子目录。构建成功后要确认文件、大小、哈希和对应的 release,而不是只看最后一行 succeeded。
6. 加自己的代码:维护一个小 layer
官网通过直接编辑高通 layer 展示定制点;长期维护时,我更倾向于保留 vendor 基线,用自己的 layer 放应用、配置、patch 和 .bbappend。这样 BSP 升级后可以清楚比较自己的增量。
下面是原创教学结构,未执行 BitBake 编译,不包含任何高通闭源代码:
layers/meta-myrobot/ |
在已经初始化、确认路径正确的 build 目录中,可以使用 Yocto 的创建工具生成 layer 骨架,再启用它:
# 假定 build 与 layers 是 BSP 根目录的同级子目录 |
命令会创建/修改文件;只应在自己的 BSP 工作区执行一次。如果目录已存在,先检查而不是覆盖。创建工具还可能生成示例 recipe;正式维护时整理为所需结构,并保留 layer 的 README、许可证与兼容系列声明。
6.1 应用、配方和镜像,三处各做一件事
hello.c 的教学内容:
/* SPDX-License-Identifier: MIT */ |
robot-hello_1.0.bb 的结构:
SUMMARY = "Small application packaging exercise" |
这个本地单文件示例使用 Kirkstone 的 WORKDIR 布局。示例校验值已对照 Poky Kirkstone 的公共 MIT 文件 计算核对;实际项目要声明真实许可证并检查文件校验值,不能给专有代码随便贴 MIT。${CC} 和相关 flags 来自目标工具链;${D} 是打包暂存根目录,不能删掉它把文件安装到构建主机。
随后在 qcom-multimedia-image.bbappend 中写:
IMAGE_INSTALL:append = " robot-hello" |
最后分别确认“配方可构建”和“镜像会安装”:
bitbake robot-hello |
核对生成镜像的 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/machine/conf/distro,按实际 BSP 继承关系组织 |
注意,原始 image 最终可能不仅靠 IMAGE_INSTALL,还使用 CORE_IMAGE_* 和 packagegroup 等机制;删除某一处引用后,应看最终包清单,不把编辑成功当成裁剪成功。
7. 任务与缓存:每条命令究竟做什么
典型源码配方可以按下面的链条理解,实际 DAG 会包含依赖和额外任务:
do_fetch → do_unpack → do_patch → do_configure → do_compile |
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_fetch、log.do_configure、log.do_compile、log.do_install、log.do_package_qa 等;实际失败在哪个 task,就先检查该 task 的日志。run.do_* 还可帮助理解实际执行命令,具体后缀以目录中内容为准。
7.2 devtool 用于开发,完成后要保存回 layer
以官网已有的 Weston 目标为例,在适用 BSP 内:
devtool modify weston |
长期保存时,再按该版 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-realtime 的 linux-kernel-qcom-rt 提供。文档中的核心配置包括:
| 入口 | 用途 |
|---|---|
qcom_defconfig |
基础配置 |
qcom_addons.config |
Qualcomm 下游增补 |
qcom_debug.config、qcom_addons_debug.config |
调试变体的增补 |
KERNEL_DEFCONFIG/KERNEL_CONFIG_FRAGMENTS |
指定基础 defconfig 与配置片段 |
KERNEL_MODULE_AUTOLOAD |
指定需要自动加载的模块名 |
KERNEL_CMDLINE_EXTRA |
添加内核启动参数,不等同编译 Kconfig |
DEBUG_BUILD、PERFORMANCE_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-bootbins/QCM6490_bootbinaries.zip |
关键启动二进制,部署到对应镜像集合供刷写 |
firmware-qcom-hlosfw/QCM6490_fw.zip |
aDSP、cDSP、Modem、WLAN 等子系统固件,安装到 rootfs 的相关固件目录 |
firmware-qcom-dspso/QCM6490_dspso.zip |
被用户空间使用链路引用的 DSP 库,按配方放入 rootfs |
默认 meta-qcom-hwe 路径可以获取预编译固件;在拥有相应源码和权限时,meta-qcom-extras 可通过 FWZIP_PATH 接入自行生成的匹配 ZIP。公开 layer 能被 clone,不意味着闭源固件源码和分发许可也自动开放。
9.2 启动与打包关系
启动固件/UEFI |
该代的 uki.bbclass 与 image-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 等提供可写上层 |
实际挂载点按板上 findmnt/mount 确认;不要猜分区号 |
persist,挂到 /var/persist |
BSP 跨重启所需的持久性数据 | 不能当成通用清理空间,更不能随意格式化 |
“放在 overlay 重启后还在”不等于“更新整个分区后还在”。反过来,旧 overlay 上层文件也可能遮住新 rootfs 中更新后的同名配置;出现“镜像明明改了但运行还是旧内容”,应检查挂载层与升级策略。后一点是基于 overlay 工作方式的部署推论,不是本文已经在板上复现的故障。
目标板只读查询示例:
cat /etc/os-release |
不同目标镜像可能未安装完整 util-linux 命令,可先用 mount 查看,不要因为工具缺失就假定分区不存在。指南出现的 /dev/sda10、/dev/sda11 只是示例,不应硬编码进部署脚本。
10.2 需要认识的服务
| 服务/配置 | 查询用途 |
|---|---|
mnt-overlay.mount、var-persist.mount |
确认可写层与持久分区是否按预期挂载 |
pd-mapper.service、QRTR 相关组件 |
排查应用与远端子系统相关的基础通信支持 |
property-vault.service、persist-property-vault.service |
该 BSP 的属性服务及持久属性初始化 |
android-tools-adbd.service |
检查开发调试接口是否启用,不默认视为所有镜像必有 |
rsyslog.service、logrotate 配置 |
系统/应用日志收集与滚动 |
systemctl --failed --no-pager |
getprop/setprop 在本文是高通 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-virtualization、packagegroup-container、相关内核配置以及 multimedia packagegroup 集成 Docker/Compose/Kubernetes。它说明这套 BSP 的集成路径,不是当前所有镜像都已开启这些能力。
部署前只读核对:
docker version |
官网某些示例包含广泛的设备映射、--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-layers、show-recipes、名称、兼容系列、provider 选择 |
| 新 layer 没有效果 | 最终 BBLAYERS;环境脚本是否重写配置 |
.bbappend 没生效/dangling append |
上游 recipe 文件名与版本;show-appends |
| 配方编译成功但 rootfs 没程序 | 输出包名、PACKAGES/FILES、镜像依赖链与 package manifest |
do_fetch 失败 |
SRC_URI/revision、网络代理、镜像源、许可证或访问权限;不要靠关闭校验掩盖问题 |
| 修改后仍像旧版本 | 实际被选中的 recipe/源码、SRCREV、devtool workspace、任务日志和最终产物 |
| 内核模块无法加载 | 目标内核版本、配置、vermagic、签名/信任链、依赖模块 |
| 相机/显示设备不出现 | 实际载板 DTB/DTBO、对应生成包、驱动、固件和服务 |
文件存在却报 No such file or directory |
file/readelf 检查 ELF 架构、动态链接器及库,不只是检查文件是否存在 |
| 从 BSP 输出目录复制 QDL 后无法启动 | 可能依赖构建工作区的 uninative loader;工具是否与刷机主机架构匹配 |
| QDL 通信异常 | USB 枚举、线缆、权限、programmer、ModemManager 争用;先保留错误日志 |
| 新镜像配置没有体现 | 是否刷到实际启动分区;overlay 上层是否遮蔽新基础文件 |
| 开机无 UART 日志 | 接线/波特率/设备节点,以及 debug/performance 与内核 console 设置 |
| Docker/K8s 不工作 | 镜像中是否打包、内核能力、服务实际状态、存储驱动/cgroup,而非只看文档列表 |
QDL 与 ModemManager 的具体诊断入口见 高通:调试。如果为了刷机临时停止服务,应记录原状态并在完成后恢复,不能不加区分地永久禁用。
14. 官网旧例子中,不应原样带进部署脚本的内容
| 看到的表述 | 这份笔记的处理 |
|---|---|
deploy/image 与 deploy/images 混用 |
查询实际变量与部署类;本文将官网示例目录写为 deploy/images |
单独编译 QDL 示例里 git https://... |
原命令缺少子命令;不当成可执行命令复制 |
| QDL/Weston 的 devtool 示例对象不一致 | 根据被修改的 recipe 核对,不伪造成功输出 |
conf/layers.conf/bblayer.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 配置确认,不能仅凭页面末尾日期决定命令正确性 |
这些差异不否定官网提供的架构信息,但提醒我:知识可以按概念整理,命令必须按具体版本验证。
原始资料与相关笔记
- Qualcomm Linux Yocto 指南:概述。
- 用户提供的入口:Qualcomm Linux 功能。
- 同版指南:用户定制、调试。
- Qualcomm Linux 编译指南入口:实际 BSP 构建/刷写应回到对应 release。
- Yocto 4.0.18 文档、BitBake 2.0 语法。
- 本站:Docker:镜像、容器与可复现环境、Linux 进程诊断工具。
- 分类:系统与开发环境 → Linux 与终端。
最后用一句话记:manifest 固定源码入口,layer 组织构建知识,machine 定义硬件目标,distro 定义系统策略,image 决定交付内容;真正部署时还要核对固件、分区、工具链和安全状态。