115 lines
9.3 KiB
Markdown
115 lines
9.3 KiB
Markdown
# PSP 组包与设备验证
|
||
|
||
## EMX2.1 固定打包契约
|
||
|
||
PSP 的日常开发仓库位于 `~/work/project/EMX2.1/AppTeam/Psp/<项目名>/`。需要验证时,把同一个 candidate commit 作为独立 `psp` 子仓库加入用户指定的 EMX2.1 应用工程;打包身份是 `<应用工程>/psp` 的精确 Git commit,不是一次无版本拷贝。
|
||
|
||
应用工程、脚本和输出位置固定为:
|
||
|
||
```text
|
||
<应用工程>/
|
||
├── psp/ # 当前 candidate 的独立 PSP 子仓库
|
||
├── scripts/
|
||
│ ├── product.py
|
||
│ └── release.py
|
||
└── output/<版本>/ # 本轮组包生成的版本目录
|
||
```
|
||
|
||
打包机器契约准确记录 `project_root`、`project_root/psp`、`project_root/scripts`、`project_root/output`、适用芯片、成功退出码以及下面三条允许命令。该契约只描述稳定接口,保存在 PSP 仓库外;Skill 不解析、重构或修改工程打包框架。
|
||
|
||
```text
|
||
./product.py
|
||
./release.py 0
|
||
./release.py 1
|
||
```
|
||
|
||
用户给出应用工程路径后,使用 `record_packaging_result.py contract --project-root <应用工程> --chip <芯片> --output <仓库外契约文件>` 按上述固定规则生成契约,不再要求用户手写 JSON 或重复说明命令。候选提交前允许工程内 `psp/` 尚未加入,此时只对 staging 做准备检查;正式组包前 `psp/` 必须存在并锁定候选 commit。工程路径不一致或脚本不完整时停止;不得猜测替代命令、标记 `packaged` 或交付烧录包。
|
||
|
||
## 参数 `0/1` 的选择
|
||
|
||
`./release.py 0` 是自动执行的默认值:PSP 资源或项目配置变化,且未改变应用源码、编译配置、工具链、依赖或会使增量结果失效的输入时使用,优先保留增量构建效率。
|
||
|
||
只有下列情况使用 `./release.py 1`:应用/公共源码有较大修改,CMake/编译选项/工具链/依赖发生变化,增量产物疑似陈旧或已失败,用户明确要求 clean rebuild,或本轮无法证明增量结果可靠。它会清理已有编译状态,执行前必须向用户展示精确工程和命令并取得当次确认;不能仅凭“更稳妥”自动选择。
|
||
|
||
## 打包前检查
|
||
|
||
打包准备检查分两次执行。第一次在 staging 适配完成、候选提交创建前执行,用 `preflight --psp-source <staging>` 提前发现 PSP 自身问题;第二次在候选提交已集成到应用工程后执行,用 `preflight --psp-commit <完整 SHA> --formal` 锁定实际组包输入。
|
||
|
||
`preflight` 至少检查:
|
||
|
||
- `scripts/product.py`、`scripts/release.py` 和 `psp.json` 是普通文件;
|
||
- `EmxResToProduct` 每个 `src` 都有明确且存在的来源,`dst` 是安全的工程内相对路径且不重复;
|
||
- `data` 分区有 `file`,`release.py` 使用 DATA 组包时,`mkAiData.py` 和 `data_ubinize.cfg` 都由 PSP 显式映射,不能依赖应用工作区里的旧文件;
|
||
- `mkAiData.py` 的容量参数按 `参数 × UBI LEB` 换算实际请求空间,并加上明确的 PEB 保留量后不超过 `data` 分区;默认基线是 LEB=126976、PEB=131072、至少保留 8 PEB,项目工具参数不允许沿用无来源的固定常数;
|
||
- PSP 的 kernel/rootfs 分区名称、文件和容量与 `metadata/bsp.lock.json` 中已经通过的 BSP 分区证据一致,余量仍不少于 512 KiB;
|
||
- PSP 是预期 commit 且工作区干净。
|
||
|
||
工具能证明的是静态关系。还要只读检查 `product.py` 使用的 Media、AIPlugin、运行库和驱动清单;空目录、空列表以及“脚本打印错误但退出码仍为 0”的路径都要在执行前说明。该问题属于应用打包框架时,未经明确授权不得修改应用脚本。
|
||
|
||
分区发生变化时,先运行 `validate_partition_closure.py --psp-json <PSP/psp.json> --boot-default <PSP内实际生效Default> --release-py <应用/scripts/release.py>`。报告必须证明每个分区的推导 offset/size 与 Boot/Default 一致,以及 DATA 请求空间加保留块后仍可容纳。`release.py` 属于应用工程;工具只读校验,修改仍需要应用侧授权,不能因为 PSP 分区变化就越界改脚本。
|
||
|
||
完成上述检查后自动继续:
|
||
|
||
1. 从项目已有规则读取“哪个文件是实际烧录包”的精确相对路径。无法唯一发现时视为异常,先请用户指定;`output/<版本>/` 可能包含多个 `.bin`,不能按扩展名或修改时间自行挑选。
|
||
2. 在命令前运行 `record_packaging_result.py snapshot --contract <契约> --state <PSP 仓库外证据路径>`,锁定契约 hash、PSP commit、应用工程状态和既有 `output` 版本目录。不得为了方便删除旧版本目录。
|
||
3. 命令日志写入 PSP 仓库外的受限证据目录。日志可能包含账号、口令或内部地址;不得把原始日志提交到 PSP、复制到文档或 Etunel 消息。证据只保存日志绝对路径、大小、SHA-256,以及失败/警告行号和行 hash。
|
||
|
||
## 精确执行顺序
|
||
|
||
执行目录必须是 `<应用工程>/scripts`,顺序不能颠倒或合并为无法区分结果的一条命令:
|
||
|
||
1. 自动运行 `./product.py`,记录真实退出码和独立日志。该步骤拷贝 PSP 配置/资源到工程使用位置。
|
||
2. 退出码为契约成功码后,仍要检查日志和复制结果。已知脚本中的报错打印不一定都转成非零退出码,因此只看 `$?` 不足以通过;出现红色错误输出、Traceback、明确复制/校验失败或资源缺失时停止,不运行 `release.py`。
|
||
3. `product.py` 无错误后自动运行 `./release.py 0`,记录独立退出码和日志。只有需要 clean rebuild 时才停止并请用户确认 `./release.py 1`。
|
||
4. 用 `record_packaging_result.py record` 同时提交两条命令、两个退出码、两个日志和用户/项目指定的烧录包绝对路径;工具不执行命令,只验证证据。
|
||
|
||
若实际流程未按顺序执行、两阶段日志无法区分,或在 `product.py` 已失败后仍运行 `release.py`,本轮不得标记 packaged。需要重试时重新快照并生成新的不可覆盖证据文件。
|
||
|
||
## `output` 结果判定
|
||
|
||
成功退出码不单独证明 packaged。完成后必须同时满足:
|
||
|
||
- 相对打包前快照,`<应用工程>/output/` 恰好新增一个直接子版本目录;
|
||
- 既有版本目录没有被删除或修改;
|
||
- 新版本目录内全部普通文件可枚举并记录路径、大小和 SHA-256,且不含软链接;
|
||
- 用户/项目指定的唯一烧录包是该新版本目录内的非空普通文件;
|
||
- PSP 在打包前后均为同一个完整 commit 且 worktree 干净;
|
||
- `product.py` 和 `release.py` 的退出码、日志、命令及执行目录均与契约一致。
|
||
|
||
不得选择目录中的“最新”版本。没有新目录、同时新增多个目录、复写旧目录、烧录包不在本轮目录、输出文件无法唯一确认或 hash 无法计算时均失败。最终记录既包含本轮 `output/<版本>/` 绝对路径,也包含精确烧录包路径/hash,供设备验证和后续 PSP→应用交接使用。
|
||
|
||
打包失败只收集证据并判断归属:指向 PSP 时在 staging 修正并重新生成候选提交;指向应用工程、框架、BSP 或公共库时交对应所有者处理。不得为绕过失败而放宽契约。
|
||
|
||
出现异常后不自动修改、提交或重试。先展示失败证据、归属和建议处理方式,由用户确认下一步。问题修正并重新通过 `preflight` 后,恢复正常自动流程:创建新的候选提交,再执行 `./product.py` 和 `./release.py 0`。Git 上传、Etunel 发送、设备和发布仍单独确认。
|
||
|
||
## 当前人工烧录
|
||
|
||
PSP skill 不执行烧录。packaged 后向用户展示烧录包绝对路径、SHA-256、`output/<版本>/` 路径、PSP commit、BSP build ID 和项目检查项。用户手工烧录后,记录:
|
||
|
||
- 板卡型号和硬件 revision;
|
||
- 实际烧录包路径/hash 和 PSP commit;
|
||
- 启动是否成功;
|
||
- 内存/分区、关键 GPIO、Sensor、媒体、用户更新的 ISP/PQ、AIPlugin 和异常日志;
|
||
- N/A、未执行项、异常现象、结论和确认时间;
|
||
- `evidence_source: USER_REPORTED`。
|
||
|
||
通用模板不替代项目功能清单。模糊的“正常”不能自动覆盖所有适用项;缺少反馈时保持 packaged,适用检查未执行时为 PARTIAL。
|
||
|
||
## 状态和证据失效
|
||
|
||
```text
|
||
candidate -> packaged -> device_verified
|
||
-> app_integrated
|
||
同一 commit 两项均通过 -> accepted
|
||
```
|
||
|
||
`accepted` 需要静态检查、固定工程打包、目标设备验证、目标应用集成、底层负责人确认、应用负责人确认和阻塞问题关闭。它不替代独立整机测试、产品验收或发布。
|
||
|
||
`psp.json`、GPIO、Sensor、Media、AIPlugin、脚本、小型资源、BSP 路径/build/hash 任一有效变化,使 packaged、device_verified、app_integrated 失效。ISP/PQ 由用户更新;一旦其内容变化,同样必须重打包并重新验证对应图像项。纯文档/注释变化经差异证明和负责人确认可复用技术证据,但新 commit 仍需独立 accepted 状态。
|
||
|
||
每轮烧录对应一个不可变 candidate 和烧录包 hash。失败后修正产生新 commit/新镜像;不得覆盖已验证基线。
|
||
|
||
## 后续串口能力
|
||
|
||
首版不创建串口工具或依赖。后续在取得串口设备、波特率、登录方式、启动特征、参数查询命令和设备授权规则后,单独实现启动日志采集和只读参数分析。默认不自动烧录、重启或发送改变设备状态的命令。
|