STM32MP257 OpenSTLinux Yocto:meta 层独立重构 + OP‑TEE 启动 panic 踩坑全记录
前言
本文基于正点原子 ATK‑MP257(STM32MP257,2GB DDR、eMMC 启动)完整工程实践,记录整套 BSP 开发三大核心问题:
- 自定义 BSP 与 ST 官方层混用,多构建目录之间
DL_DIR/SSTATE_DIR缓存互相污染,构建结果不可控; - 固件烧录后 OP‑TEE 安全世界 panic,TF‑A→OP‑TEE 阶段卡死,无法进入 U‑Boot 与 Linux 系统;
- 将 repo 检出的 OpenSTLinux 整套构建树转为 Git 快照仓库,遇到 gitlink 空目录、顶层目录改名路径连锁报错。
硬件:ALIENTEK ATK‑MP257 核心板(STM32MP257,2GB DDR eMMC) 软件版本:
openstlinux‑6.6‑yocto‑scarthgap‑mpu‑v26.06.10,OpenSTLinux v6.2.1 / Yocto Scarthgap / OE‑core 5.x 启动链:TF‑A (BL2) → OP‑TEE (BL32) → U‑Boot (BL33) → Linux 适配方式:OpenSTLinuxexternal‑dt外部设备树注入 工程仓库:atk‑mp257,为 repo 环境的快照仓库,克隆即编译,不依赖 repo 工具
原始 repo 检出目录结构:
Distribution‑Package/
├─ .repo/ # repo元数据目录
├─ layers/
│ ├─ meta‑atk‑mp257/ # 待重构板级BSP层
│ ├─ meta‑st/ # ST官方BSP集合层
│ ├─ meta‑openembedded/
│ └─ openembedded‑core/
├─ build‑openstlinuxweston‑stm32mp257‑atk/
└─ build‑openstlinuxweston‑stm32mp2/
一、meta‑atk‑mp257 集合层 fork 重构(参考米尔 meta‑myir 方案)
原始方案将板级 dts、bbappend 全部放在单薄的meta‑atk‑mp257薄层,编译依赖外部meta‑st,不同机器共用下载与 sstate 缓存。
设计思路:完整 fork meta‑st下面三套子层封装为独立集合层;保留原有BBFILE_COLLECTIONS、LAYERDEPENDS名称不修改,仅修改文件路径;板级 machine、设备树、bbappend 迁移到 fork 后的 BSP 子层,实现编译环境完全隔离。
1.1 备份原有板级资源
mkdir -p /tmp/atk-orig/conf/machine \
/tmp/atk-orig/recipes-kernel/linux/linux-stm32mp \
/tmp/atk-orig/recipes-extended/external-dt/external-dt/{optee,tf-a,u-boot}
cd /home/ubuntu/Distribution-Package/layers/meta-atk-mp257
cp conf/machine/stm32mp257-atk.conf /tmp/atk-orig/conf/machine/
cp recipes-kernel/linux/linux-stm32mp_%.bbappend /tmp/atk-orig/recipes-kernel/linux/
cp recipes-kernel/linux/linux-stm32mp/stm32mp257d-atk-ddr-2GB*.dts* \
recipes-kernel/linux/linux-stm32mp/stm32mp25-pinctrl-atk-ddr-2GB.dtsi \
/tmp/atk-orig/recipes-kernel/linux/linux-stm32mp/
cp recipes-extended/external-dt/external-dt_%.bbappend \
/tmp/atk-orig/recipes-extended/external-dt/
cp recipes-extended/external-dt/external-dt/optee/* \
recipes-extended/external-dt/external-dt/tf-a/* \
recipes-extended/external-dt/external-dt/u-boot/* \
/tmp/atk-orig/recipes-extended/external-dt/external-dt/
1.2 fork ST 官方层
复制脚本与 BSP 三层,过滤.git、.repo版本控制文件
cd /home/ubuntu/Distribution-Package/layers
rm -rf meta-atk-mp257
mkdir -p meta-atk-mp257
rsync -a --exclude='.git' --exclude='.repo' \
meta-st/scripts/ meta-atk-mp257/scripts/
rsync -a --exclude='.git' --exclude='.repo' \
meta-st/meta-st-stm32mp/ meta-atk-mp257/meta-atk-mp257-stm32mp/
rsync -a --exclude='.git' --exclude='.repo' \
meta-st/meta-st-stm32mp-addons/ meta-atk-mp257/meta-atk-mp257-stm32mp-addons/
rsync -a --exclude='.git' --exclude='.repo' \
meta-st/meta-st-openstlinux/ meta-atk-mp257/meta-atk-mp257-openstlinux/
find meta-atk-mp257 -name '.git*' -exec rm -rf {} + 2>/dev/null
1.3 迁移板级配置、设备树到 fork 后的 BSP 子层
cd /home/ubuntu/Distribution-Package/layers/meta-atk-mp257
BSP=meta-atk-mp257-stm32mp
cp /tmp/atk-orig/conf/machine/stm32mp257-atk.conf $BSP/conf/machine/
ln -sf ST_EULA_SLA $BSP/conf/eula/stm32mp257-atk
mkdir -p $BSP/recipes-kernel/linux/linux-stm32mp
cp /tmp/atk-orig/recipes-kernel/linux/linux-stm32mp_%.bbappend $BSP/recipes-kernel/linux/
cp /tmp/atk-orig/recipes-kernel/linux/linux-stm32mp/* $BSP/recipes-kernel/linux/linux-stm32mp/
mkdir -p $BSP/recipes-extended/external-dt/external-dt/{optee,tf-a,u-boot}
cp /tmp/atk-orig/recipes-extended/external-dt/external-dt_%.bbappend \
$BSP/recipes-extended/external-dt/
cp /tmp/atk-orig/recipes-extended/external-dt/external-dt/optee/* \
$BSP/recipes-extended/external-dt/external-dt/optee/
cp /tmp/atk-orig/recipes-extended/external-dt/external-dt/tf-a/* \
$BSP/recipes-extended/external-dt/external-dt/tf-a/
cp /tmp/atk-orig/recipes-extended/external-dt/external-dt/u-boot/* \
$BSP/recipes-extended/external-dt/external-dt/u-boot/
1.4 修改 envsetup.sh(关键)
修改集合层根路径:
sed -i 's|_META_LAYER_ROOT=layers/meta-st|_META_LAYER_ROOT=layers/meta-atk-mp257|' \
layers/meta-atk-mp257/scripts/envsetup.sh
1.5 修改 bblayers.conf.sample 模板
路径:layers/meta‑atk‑mp257/meta‑atk‑mp257‑openstlinux/conf/templates/default/bblayers.conf.sample
BSPLAYER ?= " \
${@'${OEROOT}/layers/meta-atk-mp257/meta-atk-mp257-stm32mp' if os.path.isfile('${OEROOT}/layers/meta-atk-mp257/meta-atk-mp257-stm32mp/conf/layer.conf') else ''} \
"
ADDONSLAYERS += "${@'${OEROOT}/layers/meta-atk-mp257/meta-atk-mp257-stm32mp-addons' if os.path.isfile('${OEROOT}/layers/meta-atk-mp257/meta-atk-mp257-stm32mp-addons/conf/layer.conf') else ''}"
FRAMEWORKLAYERS += "${@'${OEROOT}/layers/meta-atk-mp257/meta-atk-mp257-openstlinux' if os.path.isfile('${OEROOT}/layers/meta-atk-mp257/meta-atk-mp257-openstlinux/conf/layer.conf') else ''}"
重要:fork 子层内部
layer.conf中BBFILE_COLLECTIONS、LAYERDEPENDS保持 ST 原版,不要修改,否则 Yocto 层依赖校验直接失败。
1.6 重构后目录结构(layers 阶段)
layers/meta-atk-mp257/
├─ scripts/
├─ meta-atk-mp257-stm32mp/ # BSP主层,存放atk板级machine、dts、bbappend
│ ├─ conf/machine/stm32mp257-atk.conf
│ ├─ conf/eula/stm32mp257-atk -> ST_EULA_SLA
│ ├─ recipes-kernel/linux/linux-stm32mp/
│ └─ recipes-extended/external-dt/
├─ meta-atk-mp257-stm32mp-addons/
└─ meta-atk-mp257-openstlinux/
关键点:
meta‑atk‑mp257此时是集合容器目录,本身没有 layer.conf,真正 BSP 层是内部子目录。旧 build 配置中如果直接引用容器目录会报找不到 layer.conf 错误。
1.7 生成独立编译构建目录,隔离缓存
cd /home/ubuntu/Distribution-Package
DISTRO=openstlinux-weston \
MACHINE=stm32mp257-atk \
BUILD_DIR=build-openstlinuxweston-stm32mp257-atk \
EULA_stm32mp257atk=1 \
source layers/meta-atk-mp257/scripts/envsetup.sh --no-ui
在build‑openstlinuxweston‑stm32mp257‑atk/conf/site.conf配置本地缓存,和其他构建完全隔离:
DL_DIR = "/home/ubuntu/Distribution-Package/build-openstlinuxweston-stm32mp257-atk/downloads"
SSTATE_DIR = "/home/ubuntu/Distribution-Package/build-openstlinuxweston-stm32mp257-atk/sstate-cache"
1.8 解析验证(不编译,快速校验)
source layers/openembedded-core/oe-init-build-env build-openstlinuxweston-stm32mp257-atk
bitbake -p
bitbake -e | grep -E '^MACHINE=|^DISTRO=|^ACCEPT_EULA_stm32mp257-atk='
首次完整编译提示:无共享 sstate 缓存,需要下载约 10GB 源码,编译耗时较长,产物、缓存全部存放在当前 build 目录。
二、OP‑TEE 启动阶段 panic 两大踩坑实录
注意:OP‑TEE 设备树与 Linux 内核设备树是两套完全独立 DTS;使用
external‑dt注入 boot 链设备树,修改后必须优先编译 external‑dt。
错误一:PMIC stpmic2 探测失败 panic
报错日志:
E/TC:0 0 probe_driver_node:565 Failed to probe stm32_pmic2 on node stpmic2@33: 0xffff0008
E/TC:0 0 print_probe_list:518 |- Driver stm32_pmic2 on node stpmic2@33 failed
E/TC:0 0 Panic at ... core/kernel/dt_driver.c:904 <probe_dt_drivers>
0xffff0008 = TEE_ERROR_ITEM_NOT_FOUND
根因
- OP‑TEE 开启
CFG_STM32_PWR_IRQ=y,PMIC 驱动需要读取中断属性; - 移植沿用 STM32MP1 旧属性
st,wakeup‑pin-number / wakeup‑parent,STM32MP2 不再支持; - EXTI1 line52 的 RIF 权限配置为
RIF_NSEC,OP‑TEE 安全域无权访问该中断资源。
修改文件路径: layers/meta‑atk‑mp257/meta‑atk‑mp257‑stm32mp/recipes‑extended/external‑dt/external‑dt/optee/stm32mp257d‑atk‑ddr‑2GB.dts
#include <dt-bindings/clock/stm32mp25-clksrc.h>
#include <dt-bindings/interrupt-controller/irq.h>
#include <dt-bindings/mfd/st,stpmic2.h>
pmic2: stpmic2@33 {
compatible = "st,stpmic2";
reg = <0x33>;
interrupts-extended = <&exti1 52 IRQ_TYPE_EDGE_FALLING>;
wakeup-source;
st,pmic-it-id = <IT_PKEY_FA IT_PKEY_RI>;
st,notif-it-id = <0 1>;
status = "okay";
};
RIF 权限修改文件:stm32mp257d‑atk‑ddr‑2GB‑ca35tdcid‑rif.dtsi
RIFPROT(RIF_EXTI1_RESOURCE(52), RIF_UNUSED, RIF_UNLOCK, RIF_SEC, RIF_PRIV, RIF_CID1, RIF_SEM_DIS, RIF_CFEN)
错误二:GPU OPP 初始化 panic(修复 PMIC 之后复现)
报错日志:
E/TC:0 0 clk_stm32_pll3_set_rate:2877 OPP for 800000000 rate not found
E/TC:0 0 set_opp:70 set rate failed
E/TC:0 0 Panic at .../core/drivers/stm32_gpu_opp.c:339 <stm32_gpu_init>
根因:OP‑TEE GPU 驱动初始化读取&rcc {st,clk_opp}下st,ck_gpu时钟 OPP 配置;板级 dts 缺失该节点,查找 OPP 失败直接 panic。
dts 修改片段:
&rcc {
st,c1msrd = <2>;
st,clk_opp {
st,ck_cpu1 {
cfg_1 { hz = <1500000000>; st,pll = <&pll1_cfg_1500Mhz>; };
cfg_2 { hz = <1200000000>; st,pll = <&pll1_cfg_1200Mhz>; };
};
st,ck_gpu {
cfg_1 {
hz = <800000000>;
st,pll = <&pll3_cfg_800Mhz>;
};
cfg_2 {
hz = <900000000>;
st,pll = <&pll3_cfg_900Mhz>;
};
};
};
};
OP‑TEE 内嵌 DTB 提取验证技巧
不要只看源码 dts,直接从编译输出 bin 镜像提取内嵌 dtb,确认真正编译进固件的设备树。
python3 -c "
import struct
data=open('tee-pager_v2-stm32mp257d-atk-ddr-2GB-optee.bin','rb').read()
i=data.find(b'\xd0\x0d\xfe\xed')
sz=struct.unpack('>I',data[i+4:i+8])[0]
open('/tmp/atk-optee.dtb','wb').write(data[i:i+sz])
"
dtc -I dtb -O dts /tmp/atk-optee.dtb -o /tmp/atk-optee.dts
grep -n -A5 "stpmic2@33" /tmp/atk-optee.dts
grep -n -A10 "st,ck_gpu" /tmp/atk-optee.dts
修改 dts 后快速重编 boot 链
编译顺序硬性约束:
external‑dt → optee‑os‑stm32mp → fip‑stm32mp
source layers/openembedded-core/oe-init-build-env build-openstlinuxweston-stm32mp257-atk
bitbake external-dt -c cleansstate
bitbake external-dt
bitbake optee-os-stm32mp
bitbake fip-stm32mp
产物路径:build‑openstlinuxweston‑stm32mp257‑atk/tmp‑glibc/deploy/images/stm32mp257‑atk/fip/,使用 DFU 烧录分区 0x03。
三、整套 OpenSTLinux 转为 Git 快照仓库(atk‑mp257)
重构完成后,将layers整套构建树转为 Git 快照仓库,脱离 repo 工具,实现克隆即编译。
仓库克隆后顶层目录固定为
atk‑mp257,envsetup 脚本对顶层目录名存在硬依赖,请勿随意改名。
快照仓库目录总览:
atk-mp257/
├─ README.md
├─ meta-atk-mp257/ # 项目定制层集合
│ ├─ scripts/
│ ├─ meta-atk-mp257-stm32mp/
│ ├─ meta-atk-mp257-stm32mp-addons/
│ └─ meta-atk-mp257-openstlinux/
├─ meta-st/ # ST官方层,纳入git快照
├─ meta-openembedded/ # meta‑oe / meta‑python
└─ openembedded-core/ # OE‑core,无poky
坑 1:git push 远端目录为空(gitlink 子模块指针)
现象:git push 提交成功,GitHub 上除自己开发的meta‑atk‑mp257之外,meta‑st、meta‑openembedded、openembedded‑core目录显示灰色无法点开。
根因:repo 检出工程每个子目录内部存在.git符号链接,指向.repo/projects真实仓库。Git 识别嵌套 git 仓库,生成权限位160000的gitlink(子模块指针),仓库只保存 commit hash,不会上传实际源码文件。
快照展平操作(适合本项目一次性快照):
cd layers
# 删除所有嵌套的.git符号链接,保留顶层git仓库
find . -mindepth 2 -name .git -type l -delete
# 清除git索引中的gitlink引用
git rm -r --cached meta-openembedded meta-st openembedded-core
# 以普通文件重新跟踪所有代码
git add -A
# 校验:输出0代表无gitlink残留
git ls-files -s | grep 160000 | wc -l
git commit -m "track layer contents as regular files"
代价:快照仓库脱离 repo 上游;后续如需同步 ST 上游版本,需要手动替换对应层目录;如需保留上游更新能力,使用 gitmodules 配置正式子模块方案。
坑 2:顶层 layers 重命名为 atk‑mp257,批量路径替换
仓库希望 clone 后顶层目录为atk‑mp257,仅执行mv layers atk‑mp257会大量路径报错,Yocto 多处硬编码layers/字符串。
需要修改的点位清单
表格
| 分类 | 文件位置 | 影响 |
|---|---|---|
| 运行编译 | build 目录bblayers.conf、templateconf.cfg | 不改直接编译失败 |
| 配置模板 | bblayers.conf.sample | envsetup --reset 重新生成配置会沿用旧路径 |
| INIT 初始化 | machine conf 中#@NEEDED_BSPLAYERS | meta‑oe、meta‑python 自动追加路径错误 |
| 环境脚本 | envsetup.sh(atk fork 版本 + meta‑st 原版) | source 后无法定位 meta 层根目录 |
注意:
openembedded‑core内部 SDK 相关layers字符串不要修改,属于 SDK 安装之后的内部布局,和源码顶层目录无关。
执行改名与批量替换:
mv layers atk-mp257
# 替换OEROOT变量引用路径
git grep -l '\${OEROOT}/layers/' | xargs sed -i 's|${OEROOT}/layers/|${OEROOT}/atk-mp257/|g'
# 替换NEEDED_BSPLAYERS路径
git grep -l 'NEEDED_BSPLAYERS: layers/' | xargs sed -i 's|NEEDED_BSPLAYERS: layers/|NEEDED_BSPLAYERS: atk-mp257/|g'
# 更新两份envsetup脚本内部META_LAYER_ROOT
sed -i 's|_META_LAYER_ROOT=layers/meta-st|_META_LAYER_ROOT=atk-mp257/meta-st|' atk-mp257/meta-st/scripts/envsetup.sh
sed -i 's|layers/openembedded-core|atk-mp257/openembedded-core|g' atk-mp257/meta-st/scripts/envsetup.sh
sed -i 's|_META_LAYER_ROOT=layers/meta-atk-mp257|_META_LAYER_ROOT=atk-mp257/meta-atk-mp257|' atk-mp257/meta-atk-mp257/scripts/envsetup.sh
sed -i 's|layers/openembedded-core|atk-mp257/openembedded-core|g' atk-mp257/meta-atk-mp257/scripts/envsetup.sh
# build目录不在git仓库,单独替换路径
sed -i 's|${OEROOT}/layers/|${OEROOT}/atk-mp257/|g' \
build-openstlinuxweston-stm32mp257-atk/conf/bblayers.conf \
build-openstlinuxweston-stm32mp2/conf/bblayers.conf
sed -i 's|../../layers/|../../atk-mp257/|g' build-*/conf/templateconf.cfg
改名暴露的历史遗留 bug(层重构遗留)
stm32mp2 的bblayers.conf残留无效配置行:
BBLAYERS =+ ".../meta‑atk‑mp257"
重构之后meta‑atk‑mp257只是容器目录,没有 layer.conf,bitbake 解析直接报FileNotFoundError。
重要:fork 集合层的
BBFILE_COLLECTIONS集合名与原版 meta‑st 重名,两套 BSP 集合不能共用同一个 build 目录。 解决办法:直接删除 stm32mp2 build 的 bblayers.conf 中这一行,恢复 ST 原版纯净构建。
改名后完整验证流程
# 验证atk‑mp257工程
source atk-mp257/meta-atk-mp257/scripts/envsetup.sh build-openstlinuxweston-stm32mp257-atk
bitbake -p
bitbake st-image-weston
# 验证原生stm32mp2编译不受破坏
source atk-mp257/meta-st/scripts/envsetup.sh build-openstlinuxweston-stm32mp2
bitbake -p
atk‑mp257 快照仓库构建命令(README 摘录)
主机环境 Ubuntu20.04/22.04/24.04,禁止 root 用户操作。
# 交互式初始化
source atk-mp257/meta-atk-mp257/scripts/envsetup.sh build-openstlinuxweston-stm32mp257-atk
# 非交互式首次初始化(预接受EULA)
DISTRO=openstlinux-weston \
MACHINE=stm32mp257-atk \
BUILD_DIR=build-openstlinuxweston-stm32mp257-atk \
EULA_stm32mp257atk=1 \
source atk-mp257/meta-atk-mp257/scripts/envsetup.sh --no-ui
# 完整编译镜像
bitbake st-image-weston
# 仅重编译boot链
source atk-mp257/openembedded-core/oe-init-build-env build-openstlinuxweston-stm32mp257-atk
bitbake external-dt -c cleansstate
bitbake external-dt
bitbake optee-os-stm32mp
bitbake fip-stm32mp
编译产物:build‑openstlinuxweston‑stm32mp257‑atk/tmp‑glibc/deploy/images/stm32mp257‑atk/
四、工程踩坑经验总结
- meta 集合 fork 重构要点:完整复制 ST 子层,layer.conf 中 BBFILE_COLLECTIONS 集合名称严禁修改,仅改动文件路径;配置独立
DL_DIR、SSTATE_DIR实现编译环境隔离;重构后顶层meta‑atk‑mp257是容器目录,BSP 实际在子目录,旧配置不要直接引用容器目录。 - STM32MP2 OP‑TEE 高频踩坑:STM32MP1 的 PMIC 中断设备树写法不能直接复用至 MP2;RIF 安全权限、GPU OPP 时钟配置极易引发 panic;OP‑TEE DTS 独立于 Linux 内核 DTS;修改 external‑dt 之后编译顺序必须严格遵守:
external‑dt → optee‑os‑stm32mp → fip‑stm32mp;可以从 bin 镜像提取 dtb 反编译确认固件内真实设备树。 - repo 工程转 Git 快照:repo 检出目录下
.git是软链接,直接 git add 会生成 gitlink 子模块指针,远端仓库只有 hash 没有实际源码;快照托管需要清除嵌套.git 符号链接。 - Yocto 顶层目录改名不是简单 mv,
bblayers.conf、bblayers.conf.sample、machine 的#@NEEDED_BSPLAYERS、envsetup.sh、build 目录templateconf.cfg全部同步替换路径;优先执行bitbake -p解析校验,不需要完整编译即可定位绝大多数路径错误。 - 区分改动引入 bug 和历史遗留 bug,本次目录改名暴露了 meta 层重构阶段遗留的无效配置行;排查问题建议对照版本修改时间线定位。
- atk‑mp257 快照仓库约束:克隆后顶层目录名必须为
atk‑mp257,envsetup 脚本对目录名硬依赖;仓库已经脱离 repo,上游更新需要手动替换层目录;GPU 多媒体 EULA 受限特性需要ACCEPT_EULA_stm32mp257‑atk = "1"。
五、相关资源
- 本工程仓库:<https://github.com/2022102437/atk-mp257>
- OpenSTLinux 官方文档:<https://wiki.st.com/stm32mpu>
标签:
#STM32MP257#OpenSTLinux#Yocto#OP‑TEE#external‑dt#meta层重构
更多推荐



所有评论(0)