build: 删除 MDK-ARM/download.bat,烧录收敛到 stlink-flash skill

- test/run_all_suites.py 是唯一执行它的地方:DOWNLOAD_BAT 改为 STLINK_FLASH
  (.dsh/skills/stlink-flash/scripts/stlink_flash.py);直烧改
  [py, STLINK_FLASH, "flash"](原先把 .bat 包给命令行解释器执行);
  --flash-cmd 改由同一常量拼出,不再硬编码 .bat 路径
- 机制变化(须知晓):原 download.bat 走 UV4 -f(CMSIS-DAP),现走
  ST-LINK_CLI -P <hex> -Rst -Run —— 与 .serialtest/config.json 的
  flash_cmd、AGENTS.md 烧录铁律、回读 -CmpFile 要求同源;6.5s/1MB
  也快于 UV4 路径
- AGENTS.md / 环境与部署 3 篇 / ST-LINK_CLI 复位说明(原文写"正式流程仍以
  download.bat 为准",已反转)/ 自动化测试流程 / 串口助手设计说明 /
  链路延迟 / m2_data / README / MDK-ARM/README:引用改指 skill
- .gitignore:download_log.txt 条目保留并注明 legacy(他机残留物不变
  untracked);build 日志注释同步
- 保留 MDK-ARM/reset.bat:其 hard/halt/run 子命令是 skill 没有的
- 刻意未改:docs/问题记录/项目审查与优化建议报告.md 的 P2-15(史实)
- 验证:run_all_suites.py --dry-run 解析出 skill 路径;doc-links 123 通过
This commit is contained in:
2026-10-10 16:28:58 +08:00
parent 4f71947934
commit 5defabcabb
13 changed files with 28 additions and 71 deletions
+3 -1
View File
@@ -17,8 +17,10 @@
*.dep
.workbuddy-ai/
# Keil MDK - Build/download logs (regenerated by keil_build.py / download.bat)
# Keil MDK - Build log (regenerated by keil_build.py)
MDK-ARM/build_log.txt
# legacy: download.bat removed 2026-10-10; entry kept so stale leftovers on
# other machines do not surface as untracked files
MDK-ARM/download_log.txt
MDK-ARM/err.txt
MDK-ARM/out.txt
+1 -1
View File
@@ -16,7 +16,7 @@ STM32F407ZGTx @168MHz(HSE 8MHz → PLL M=4/N=168/P=2);**仅 Keil MDK-ARM v
## 构建与验证
- `@build` = **`keil-build` skill**:`& '.venv\Scripts\python.exe' .dsh\skills\keil-build\scripts\keil_build.py`(仓库根目录执行;纯标准库,任意 python3 亦可)。退出码 0 = 0 错误 0 警告(PASS)、1 = 构建失败(打印报错行)、2 = UV4 未找到/无效、3 = 用法错误。UV4 解析链 `--uv4` > `.serialtest/config.json` 的 `uv4` > `$DSH_KEIL_UV4` > `$DTU_KEIL_UV4` > PATH(**显式设了但无效 = 立即报错、不静默回退**);日志 `MDK-ARM/build_log.txt`。⚠ **原 `MDK-ARM/build.bat` 已于 2026-10-10 删除**(判定口径同款,但无超时保护、UV4 只认 `DTU_KEIL_UV4`、失败时 dump 整份日志);`test/run_all_suites.py` 已改调本 skill。换机必设 `DTU_KEIL_UV4`,见 `docs/环境与部署/本地工具路径环境变量方案.md`
- `@test` / `.dsh/skills/serial-boot-test/scripts/run_boot_test.py` 一键闭环(2026-09-20 起为纯 Python 标准库实现,替代 PowerShell 版;`& '.venv\Scripts\python.exe' .dsh/skills/serial-boot-test/scripts/run_boot_test.py`):开串口+清日志 → 烧录(`MDK-ARM/download.bat`,下载后 Reset&Run;快路径 `--flash-cmd "MDK-ARM\reset.bat flash"`)→ **固件身份戳**(从刚烧进去的 hex 里抠 `fw build: <DATE> <TIME>` 追加成 Required 标记)→ wait-idle(等 RX 静默 8s,超时 30s,首字节 12s 未到判 `no_data`)→ 提取日志 → **烧录回读校验**(`reset.bat cmp` = `-CmpFile`;不一致 = 本次运行作废 exit 2)→ `.dsh/skills/serial-boot-test/scripts/verify_log.py` 标记校验(含**启动锚点计数**:`reset cause:` 出现 0 次或 >1 次 = FAIL,`--max-boot-count` 调;Forbidden 命中**逐行打印行号+内容**;boot_log 每行带 `[+Nms]` daemon 毫秒时基 → 可查标记顺序 `--require-order` 与开机耗时 `--done-marker`/`--max-boot-ms`,实测 `net init: OK` = **+537ms**);退出码 0=PASS / 1=FAIL / 2=采集或烧录错误(含回读不一致)/ 3=用法/预检错误
- `@test` / `.dsh/skills/serial-boot-test/scripts/run_boot_test.py` 一键闭环(2026-09-20 起为纯 Python 标准库实现,替代 PowerShell 版;`& '.venv\Scripts\python.exe' .dsh/skills/serial-boot-test/scripts/run_boot_test.py`):开串口+清日志 → 烧录(**`stlink-flash` skill**:`stlink_flash.py flash` = `-P <hex> -Rst -Run`;`flash_cmd` 默认取 `.serialtest/config.json`,本仓库已指向本 skill)→ **固件身份戳**(从刚烧进去的 hex 里抠 `fw build: <DATE> <TIME>` 追加成 Required 标记)→ wait-idle(等 RX 静默 8s,超时 30s,首字节 12s 未到判 `no_data`)→ 提取日志 → **烧录回读校验**(`stlink_flash.py cmp` = `-CmpFile`;不一致 = 本次运行作废 exit 2)→ `.dsh/skills/serial-boot-test/scripts/verify_log.py` 标记校验(含**启动锚点计数**:`reset cause:` 出现 0 次或 >1 次 = FAIL,`--max-boot-count` 调;Forbidden 命中**逐行打印行号+内容**;boot_log 每行带 `[+Nms]` daemon 毫秒时基 → 可查标记顺序 `--require-order` 与开机耗时 `--done-marker`/`--max-boot-ms`,实测 `net init: OK` = **+537ms**);退出码 0=PASS / 1=FAIL / 2=采集或烧录错误(含回读不一致)/ 3=用法/预检错误
- 默认校验标记:Required `App init OK` / `Network Init` / `net init: OK` + **自动追加的固件身份戳 `fw build: <__DATE__> <__TIME__>`**(`App/app/app_main.c` 开机打印,`run_boot_test.py` 从待烧 hex 里抠出该串当 Required——此前所有标记都是固定串,**旧镜像/错镜像照样全中**,"反复重下载、芯片一直是旧镜像"在自动闭环里不可见,2026-10-10 补;`--no-fw-check` 关闭);Forbidden `FAIL` / `ERROR` / `HardFault` / `[ERR]`(**四个 Fault 的崩溃日志都以 `[ERR]` 开头 → 一律判 FAIL**,这是刻意的:出现 Fault 即本次运行不通过);按模块定制标记(网络/存储/RTC/ADC/RS485/UI)见 `docs/测试说明/自动化测试流程.md`
- ⚠️ 旧绝对路径 `D:\Code\DTU 程序\...` 出现即失效(仓库已搬迁),一律改用仓库相对路径
- **下载/烧录铁律(2026-09-20 实测)**:走 `& "MDK-ARM\reset.bat" flash [文件]`(= `ST-LINK_CLI -c SWD -P <文件> -Rst -Run`),烧后 `-Rst -Run` **不可省略**——裸 `-P` 会报 `Programming Complete`,但目标核处于死循环/异常状态时写入并不落地(芯片内容不变;这就是 09/19~09/20 "反复重下载、芯片一直是旧镜像、二分法失效" 的根因);`.hex`/`.bin` 均可直烧(1MB ≈ 6.5s,快于 UV4 路径);只重启不烧录用 `reset.bat` 无参(= `-c SWD -Rst -Run`,本机 3 线接线唯一复位手段:nRST 未接、`-HardRst`/`RM=` 不可用)
+1 -2
View File
@@ -10,8 +10,7 @@
| `STM32F407-Demo.uvprojx` | **Keil 工程文件**(源文件清单、编译选项、目标配置) |
| `STM32F407-Demo.uvoptx` | Keil 用户选项(调试器、断点等) |
| `startup_stm32f407xx.s` | 启动文件(**`Heap_Size EQU 0x200`(512B)在此限定**) |
| `download.bat` | 烧录(UV4 路径) |
| `reset.bat` | **复位/烧录**(`ST-LINK_CLI`,见下) |
| `reset.bat` | **复位/烧录/回读**(`ST-LINK_CLI` 封装,见下) |
## 构建与烧录
-45
View File
@@ -1,45 +0,0 @@
@echo off
setlocal
set PROJ=%~dp0STM32F407-Demo.uvprojx
set LOG=%~dp0download_log.txt
set TARGET=STM32F407-Demo
:: UV4 location: env var DTU_KEIL_UV4 = full path of UV4.exe (same contract
:: as keil_build.py (@build); required, no machine-default fallback).
if defined DTU_KEIL_UV4 goto uv4_set
echo DOWNLOAD_FAIL: environment variable DTU_KEIL_UV4 is not set
echo Set it to the full path of UV4.exe, e.g.:
echo [Environment]::SetEnvironmentVariable('DTU_KEIL_UV4', 'D:\Tools\Keil\UV4\UV4.exe', 'User')
exit /b 2
:uv4_set
if exist "%DTU_KEIL_UV4%" goto uv4_ok
echo ENV_ERROR: DTU_KEIL_UV4 is set but does not exist: "%DTU_KEIL_UV4%"
echo Fix the variable value. No fallback to another UV4 install is attempted.
exit /b 2
:uv4_ok
set UV4=%DTU_KEIL_UV4%
:: Remove stale log first: UV4 -o writes the log only when a download actually
:: runs. A leftover log would otherwise be misreported as this download's
:: result (same guard as keil_build.py).
if exist "%LOG%" del "%LOG%"
"%UV4%" -f "%PROJ%" -t%TARGET% -j0 -o "%LOG%"
if not exist "%LOG%" (
echo DOWNLOAD_FAIL: no download log produced - UV4 did not run or hung
exit /b 1
)
findstr /C:"Application running" "%LOG%" >nul
if %ERRORLEVEL% equ 0 (
echo DOWNLOAD_OK: flashed and running
exit /b 0
)
echo DOWNLOAD_FAIL: no application-running marker in log
type "%LOG%"
exit /b 1
+2 -3
View File
@@ -144,8 +144,7 @@ STM32F4-Base/
│ └── Third_Party/FreeRTOS/ # FreeRTOS 内核
├── MDK-ARM/ # Keil 工程
│ ├── STM32F407-Demo.uvprojx # 工程文件
│ ├── download.bat # 烧录脚本
│ ├── reset.bat # 复位 / 烧录(ST-LINK_CLI)
│ ├── reset.bat # 复位 / 烧录 / 回读(ST-LINK_CLI)
│ ├── *_probe.py # 台架探针(TCP 复连 / FTP 中止等)
│ └── startup_stm32f407xx.s # 启动文件
├── test/ # 测试代码与脚本
@@ -226,7 +225,7 @@ STM32F4-Base/
### 烧录
```bash
MDK-ARM\download.bat
& '.venv\Scripts\python.exe' .dsh\skills\stlink-flash\scripts\stlink_flash.py flash
```
### LVGL PC 模拟器
@@ -107,7 +107,7 @@ ST-LINK_CLI -c SWD -P "MDK-ARM\STM32F407-Demo\STM32F407-Demo.hex" -Rst -Run
- ⓞ **`.hex` 直接支持已实测**:1MB Intel HEX 编程耗时 **6.5s**,`Programming Complete`(远快于 UV4/CMSIS-DAP 路径);`.bin` 同理(`fromelf --bin` 可转,ARMCC 自带 `C:\Keil_v5\ARM\ARMCC\bin\fromelf.exe`);`.axf` 直读未测,无需。
- 加 `-V` 编程后校验、`-Q` 静默。
- 与 `download.bat`(`UV4 -f` 走 CMSIS-DAP)功能等价;脚本化场景用 CLI 更轻,两者并存。
- 与 `MDK-ARM/reset.bat flash` 同源(都走 ST-LINK_CLI)。原 `download.bat`(`UV4 -f` 走 CMSIS-DAP)**已于 2026-10-10 删除**,CLI 路径即唯一烧录路径。
- ⓞ **静默失败模式(2026-09-20 实测,代价最大的坑)**:省略结尾 `-Rst -Run` 的裸 `-c SWD -P <文件>` 仍报 `Memory programmed in 1s 906ms / Programming Complete`,但芯片 flash **不变**(回读向量表 = 旧镜像)——目标核处于死循环/异常状态时,"Normal 连接、不复位"的会话写入不落地;同文件改用完整 `-P <文件> -Rst -Run` 即正常落地(6.5s / 1MB)。**铁律:任何编程命令必须以 `-Rst -Run` 收尾;任何烧录之后必须 `-CmpFile` 全片回读校验**(详见 §10)。
### ⑥ 不扰目标连接(HOTPLUG,运行中板子的只读检查)✅ 本机可用
@@ -180,7 +180,7 @@ Get-Content .dsh\skills\serial-assistant\scripts\state\serial.log -Tail 100
2. **(已修,2026-10-10)旧版 `wait-idle` 在复位突发期会报 `daemon unresponsive after auto-start: timed out`**:CLI 把**超时**误判成"daemon 不可达",顺手拉起一个绑不上 HTTP 口的实例再把命令撞一次超时(数据其实已落盘)。现 CLI 超时按 `--max-ms` 自动推导、超时只快速失败不再误拉起实例;
3. **日志校验**:`.dsh/skills/serial-assistant/scripts/state/serial.log` 用 Read/Grep 直接查最直观;`serial_tool.py log --grep <标记>` 现已可作判定依据(2026-10-10 修:旧实现先 `--tail`(默认 50)后 grep,开机标记必然查不到——这就是当年"实测 0 命中、语义存疑"的真根因)。
**B. 完整烧写 + 运行**:`MDK-ARM\reset.bat flash [xxx.hex]`(= `-c SWD -P <hex> -Rst -Run`;09/19 实测 1MB ≈ 6.5s,09/20 复测 6.47s + 全片 `-CmpFile` 逐字节一致)。正式流程仍以 `download.bat`(`UV4 -f`)为准,CLI 路径作为脚本化/快速路径。
**B. 完整烧写 + 运行**:`stlink-flash` skill 的 `stlink_flash.py flash [xxx.hex]`(等价 `MDK-ARM\reset.bat flash`;= `-c SWD -P <hex> -Rst -Run`;09/19 实测 1MB ≈ 6.5s,09/20 复测 6.47s + 全片 `-CmpFile` 逐字节一致)。**2026-10-10 起 CLI 路径即唯一烧录路径**——原 `download.bat` 的 `UV4 -f` 已删除。
**B2. 回读校验**:`MDK-ARM\reset.bat cmp [xxx.hex]`(= `-c SWD -CmpFile <hex> 0x08000000`,2026-10-10 加;默认对最新构建 hex)。判定看输出行首的 `No difference found`(`This file is already downloaded` 是同义提示)。⚠ **连接即复位目标**:实测比对瞬间板子重打一遍开机日志 → 在自动化闭环里回读必须排在**日志采集之后**(`run_boot_test.py` 已按此顺序内置)。
+1 -1
View File
@@ -23,7 +23,7 @@
& '.venv\Scripts\python.exe' .dsh\skills\serial-assistant\scripts\serial_tool.py clear
& '.venv\Scripts\python.exe' test\latency_peer.py --host 192.168.1.100 --port 8080 `
--json "docs\测试说明\m2_data\m2_quiet_runNN.json" --wait 170 # 后台作业
& "MDK-ARM\download.bat"
& '.venv\Scripts\python.exe' .dsh\skills\stlink-flash\scripts\stlink_flash.py flash
& '.venv\Scripts\python.exe' .dsh\skills\serial-assistant\scripts\serial_tool.py wait-idle `
--timeout 120 --settle-ms 10000 --max-ms 110000
# 判定:Grep .dsh\skills\serial-assistant\scripts\state\serial.log
@@ -186,7 +186,7 @@ flowchart LR
```mermaid
flowchart LR
A["open(自动拉起 daemon;幂等)"] --> B["clear → gen=N"]
B --> C["MDK-ARM\download.bat(ST-Link 烧录+复位,端口全程打开)"]
B --> C["stlink-flash skill(stlink_flash.py flash:ST-Link 烧录+复位,端口全程打开)"]
C --> D["wait-idle:rx 静默 8s(-SettleMs)或超时 30s(-MaxWaitMs)"]
D --> E["提取本代际 [RX] 行,剥 [RX] 时间戳前缀 → boot txt"]
E --> F["verify_log.py(标记匹配)"]
+1 -1
View File
@@ -10,7 +10,7 @@
├─ Step 0 预检 .venv + serial_tool(selftest/ports 确认 COM)
├─ Step 1 构建验证 keil-build skill(keil_build.py) (0 错误 0 警告才继续)
├─ Step 2 烧录 + 采集(一条命令编排:开串口 + 清日志 → 烧录 → 固件身份戳 → wait-idle → 提取 → 回读校验)
│ .dsh/skills/serial-boot-test/scripts/run_boot_test.py (内置 serial_tool + download.bat + reset.bat cmp + verify_log.py)
│ .dsh/skills/serial-boot-test/scripts/run_boot_test.py (内置 serial_tool + stlink-flash skill 的 flash/cmp + verify_log.py)
├─ Step 3 判定:
│ PASS → 报告,结束
│ FAIL → 依据 [MISS]/[HIT] + 日志尾部,修改代码后回到 Step 1
@@ -261,7 +261,7 @@ DTU-RemoteLCD 客户端;输出每帧 `req2first / total / recv 批次到达时
& '.venv\Scripts\python.exe' test\latency_peer.py --host 192.168.1.100 --port 8080 `
--json "docs\测试说明\m2_data\m2_quiet.json" --wait 170 # 后台作业
# 2) 烧录(Reset&Run 不可省)
& "MDK-ARM\download.bat"
& '.venv\Scripts\python.exe' .dsh\skills\stlink-flash\scripts\stlink_flash.py flash
# 3) 等空闲:会话本身约 2s,但 peer 首连常因"芯片空闲超时 RST"失败一次并 2s 后重试
& '.venv\Scripts\python.exe' .dsh\skills\serial-assistant\scripts\serial_tool.py wait-idle `
--timeout 120 --settle-ms 10000 --max-ms 110000
@@ -283,7 +283,7 @@ DTU-RemoteLCD 客户端;输出每帧 `req2first / total / recv 批次到达时
# M3(生产路径,需要设备已烧 Phase 14 固件)
& '.venv\Scripts\python.exe' .dsh\skills\keil-build\scripts\keil_build.py # 0 错 0 警(Phase 14 构建)
& '.venv\Scripts\python.exe' .dsh\skills\serial-assistant\scripts\serial_tool.py clear
& "MDK-ARM\download.bat" # 先烧录,再起 peer(顺序不可反!)
& '.venv\Scripts\python.exe' .dsh\skills\stlink-flash\scripts\stlink_flash.py flash # 先烧录,再起 peer(顺序不可反!)
& '.venv\Scripts\python.exe' test\latency_peer.py --mode remo --host 192.168.1.100 --port 7003 `
--samples 45 --stress-from 15 --ftp-stress --json "docs\测试说明\m3_data\m3_dev_stress.json"
# 模拟器基线(Δ 的对照端)
@@ -9,7 +9,7 @@
| 变量 | 必需性 | 值的形态 | 使用者 | 默认/回退 |
|---|---|---|---|---|
| `DTU_KEIL_UV4` | MCU 构建/下载机必需 | UV4.exe 完整路径,例如 `D:\Tools\Keil\UV4\UV4.exe` | `keil_build.py`(`@build`)、`download.bat` | 不设即报错(exit 2);不从 C 盘旧路径猜测 |
| `DTU_KEIL_UV4` | MCU 构建机必需 | UV4.exe 完整路径,例如 `D:\Tools\Keil\UV4\UV4.exe` | `keil_build.py`(`@build`) | 不设即报错(exit 2);不从 C 盘旧路径猜测 |
| `DTU_STLINK_CLI` | 复位/烧录/回读机必需 | `ST-LINK_CLI.exe` 完整路径,例如 `C:\Program Files (x86)\STMicroelectronics\STM32 ST-LINK Utility\ST-LINK Utility\ST-LINK_CLI.exe` | `reset.bat` | 未设时回退 PATH(`where ST-LINK_CLI.exe` 首个命中);已设但无效 = 硬报错 |
| `DTU_PRECOMMIT_PYTHON` | 可选(覆盖用) | 含 `pre_commit` 模块的 `python.exe` 完整路径 | `ci_local.py` L0、CI `l0-gates` | 未设时按 §1.1 探测(当前解释器 → `.venv` → PATH);已设但无效 = 硬报错 |
| `DTU_GRAPHVIZ_DOT` | 可选(覆盖用) | `dot.exe` 完整路径 | `gen_refgraph.py` | 未设时只查 PATH;无 Graphviz 时降级为"生成 .dot/.json、跳过渲染" |
@@ -65,7 +65,7 @@ Graphviz / Cppcheck 的安装位置差异一律用 `DTU_*` 环境变量表达(
| 变量 | 必需性 | 值的形态 | 使用方 |
|---|---|---|---|
| `DTU_KEIL_UV4` | **必需**(MCU 构建/Keil 下载机) | UV4.exe 完整路径 | `keil_build.py`(`@build`)、`download.bat` |
| `DTU_KEIL_UV4` | **必需**(MCU 构建机) | UV4.exe 完整路径 | `keil_build.py`(`@build`) |
| `DTU_STLINK_CLI` | **必需**(用 ST-LINK CLI 的机器;已在 PATH 可不设) | ST-LINK_CLI.exe 完整路径 | `MDK-ARM/reset.bat`(烧录/复位/回读) |
| `DTU_PRECOMMIT_PYTHON` | 可选(pre-commit 不在 `.venv`/当前解释器时设;CI runner 建议必设) | 装有 pre-commit 的 python.exe 完整路径 | `scripts/ci_local.py`、CI L0/L0.5 |
| `DTU_CPPCHECK` | 可选(开发机入 PATH 即可;无 PATH 的 CI runner 建议设) | cppcheck.exe 完整路径 | pre-commit cppcheck 钩子、CI L0 |
@@ -91,11 +91,11 @@ Graphviz / Cppcheck 的安装位置差异一律用 `DTU_*` 环境变量表达(
| 项 | 要求 | 说明 |
|---|---|---|
| Keil MDK-ARM | **v5.x**(须含 ARMCC v5 编译器) | 工程锁定 `uAC6=0`(仅 ARMCC v5,**不支持 armclang**);仅支持此工具链,无其他工具链 |
| 安装路径 | **任意目录** | `keil_build.py` / `download.bat` / `reset.bat` 经 `DTU_*` 环境变量解析工具路径(§2.1.1);新机器装完后设置 `DTU_KEIL_UV4` / `DTU_STLINK_CLI` 即可,**无需修改仓库脚本** |
| 安装路径 | **任意目录** | `keil_build.py` / `reset.bat` 经 `DTU_*` 环境变量解析工具路径(§2.1.1);新机器装完后设置 `DTU_KEIL_UV4` / `DTU_STLINK_CLI` 即可,**无需修改仓库脚本** |
| 设备支持 | STM32F407ZGTx + CMSIS Flash 算法 | 工程引用 `STM32F4xx_1024.FLM`(1MB 片内 Flash,0x08000000),由 CMSIS STM32F4 设备包提供 |
| STM32CubeMX | **6.17.0**(工程 `STM32F407-Demo.ioc` 记录的版本) | 修改外设/引脚/时钟配置并再生成 CubeMX 文件;固件包须 **STM32Cube FW_F4 V1.28.3** |
| 命令行构建 | `& '.venv\Scripts\python.exe' .dsh\skills\keil-build\scripts\keil_build.py`(即 `@build`) | 退出码 0 = 0 错 0 警;失败看 `MDK-ARM/build_log.txt` |
| 命令行烧录 | `& "MDK-ARM\download.bat"`(即 `@download`) | flash + Reset & Run;日志出现 `Application running` 判成功 |
| 命令行烧录 | `& '.venv\Scripts\python.exe' .dsh\skills\stlink-flash\scripts\stlink_flash.py flash`(即 `@download`;原生入口 `MDK-ARM/reset.bat flash` 等价) | 烧后 `-Rst -Run`;判据 `Programming Complete` + 回读 `No difference found` |
> ⚠ **版本一致性关键**:.ioc 记录 `MxCube.Version=6.17.0` + `FirmwarePackage=STM32Cube FW_F4 V1.28.3`,
> 再生成代码必须用此组合——用更新版本的 CubeMX 会把仓库内 HAL 驱动升级、产生大量无关 diff(见 §六 速查)。
@@ -524,7 +524,7 @@ $env:DTU_KEIL_UV4 = 'D:\NotExist\UV4.exe' # 仅当前会话,不动用户级
| 项 | 说明 |
|---|---|
| 下载方式 | `& "MDK-ARM\download.bat"`(Keil 命令行:烧写 + Reset & Run) |
| 下载方式 | `& '.venv\Scripts\python.exe' .dsh\skills\stlink-flash\scripts\stlink_flash.py flash`(ST-LINK_CLI:烧写 + Reset & Run;等价 `MDK-ARM/reset.bat flash`) |
| 下载器 | 工程已配 `UL2CM3` 调试驱动 + `STM32F4xx_1024` Flash 算法;**物理下载器按现场选择**(本机为 ST-Link——不占 COM 口,可与串口调试并存);新机器在 Keil `Options for Target → Debug → Settings` 选择与硬件一致的驱动 |
| 调试日志 | USART1 115200;抓开机日志必须**先武装采集再复位**(`.dsh/skills/serial-boot-test/scripts/run_boot_test.py --flash-cmd` 已保证顺序) |
@@ -602,7 +602,7 @@ $env:DTU_KEIL_UV4 = 'D:\NotExist\UV4.exe' # 仅当前会话,不动用户级
| 现象 | 原因 | 处理 |
|---|---|---|
| `keil_build.py` / `download.bat` 报 `DTU_KEIL_UV4` 未设/无效 | `DTU_KEIL_UV4` 未设置或指向错误路径(**设完变量须重开终端**) | 设置/修正 `DTU_KEIL_UV4` 为 UV4.exe 完整路径(§2.1.1),重开终端重试 |
| `keil_build.py` 报 `DTU_KEIL_UV4` 未设/无效 | `DTU_KEIL_UV4` 未设置或指向错误路径(**设完变量须重开终端**) | 设置/修正 `DTU_KEIL_UV4` 为 UV4.exe 完整路径(§2.1.1),重开终端重试 |
| `reset.bat` 报 `ST-LINK_CLI.exe not found` / `ENV_ERROR: DTU_STLINK_CLI` | `DTU_STLINK_CLI` 未设且不在 PATH,或显式值无效 | 设置 `DTU_STLINK_CLI` 为 ST-LINK_CLI.exe 完整路径,或把其目录加入 PATH;显式值无效时**不会**回退,须修值 |
| Keil 编译报编译器不识别 | 新装 MDK 只有 armclang | 工程锁 `uAC6=0`,必须用带 **ARMCC v5** 的 MDK v5.x |
| CubeMX 再生成后出现大量 diff / 新告警 | 用了比工程记录更新的 CubeMX / 固件包版本 | 用 git 还原生成文件,按 **.ioc 记录的 CubeMX 6.17.0 + STM32Cube FW_F4 V1.28.3** 重新生成 |
+8 -6
View File
@@ -9,7 +9,7 @@
对每个套件:
1. 改 test_config.h 启用该套件(其它全注释)
2. @build(0 错 0 警,否则跳过该套件)
3. 烧录(MDK-ARM/download.bat,Reset & Run)
3. 烧录(stlink-flash skill:stlink_flash.py flash,Reset & Run)
4. @test 采集 + 判读(.dsh/skills/serial-boot-test 的 verify_log.py,含套件汇总行校验 T-2)
结束后:
5. **无条件还原 test_config.h**(try/finally,含异常/KeyboardInterrupt 路径)
@@ -54,7 +54,7 @@ from pathlib import Path
REPO_ROOT = Path(__file__).resolve().parent.parent
CONFIG = REPO_ROOT / "test" / "board" / "test_config.h"
KEIL_BUILD = REPO_ROOT / ".dsh" / "skills" / "keil-build" / "scripts" / "keil_build.py"
DOWNLOAD_BAT = REPO_ROOT / "MDK-ARM" / "download.bat"
STLINK_FLASH = REPO_ROOT / ".dsh" / "skills" / "stlink-flash" / "scripts" / "stlink_flash.py"
RUN_BOOT = REPO_ROOT / ".dsh" / "skills" / "serial-boot-test" / "scripts" / "run_boot_test.py"
# 套件 -> (宏名, verify_log 需要的汇总行名称, 该套件的 Required 标记, --forbidden 覆盖)
@@ -147,7 +147,7 @@ def main(argv=None):
return 2
# --check-build 不需要串口/烧录工具,故不强求 run_boot_test.py 存在
required = (CONFIG, KEIL_BUILD) if args.check_build else (CONFIG, KEIL_BUILD, DOWNLOAD_BAT, RUN_BOOT)
required = (CONFIG, KEIL_BUILD) if args.check_build else (CONFIG, KEIL_BUILD, STLINK_FLASH, RUN_BOOT)
for p in required:
if not p.is_file():
print("[ERROR] 缺文件:{}".format(p))
@@ -159,7 +159,7 @@ def main(argv=None):
print("套件:{}".format(", ".join(picked)))
print("构建:{}".format(KEIL_BUILD))
if not args.check_build:
print("烧录:{}".format(DOWNLOAD_BAT))
print("烧录:{}".format(STLINK_FLASH))
print("判读:{}".format(RUN_BOOT))
if args.dry_run:
print("[DRY-RUN] 仅打印计划,未改动任何文件。")
@@ -201,7 +201,7 @@ def main(argv=None):
# 2) 烧录
t0 = time.monotonic()
frc, fout = _run(["cmd", "/c", str(DOWNLOAD_BAT)], timeout=args.flash_timeout)
frc, fout = _run([py, str(STLINK_FLASH), "flash"], timeout=args.flash_timeout)
print("[FLASH] rc={} elapsed={:.1f}s".format(frc, time.monotonic() - t0))
if frc != 0:
print("\n".join(fout.strip().splitlines()[-6:]))
@@ -209,7 +209,9 @@ def main(argv=None):
print("[WARN] 烧录 rc={}(继续:板子可能已复位)".format(frc))
# 3) 采集 + 判读(含套件汇总行校验 T-2)
cmd = [py, str(RUN_BOOT), "--flash-cmd", "MDK-ARM\\download.bat"]
# 烧录统一走 stlink-flash skill(与 .serialtest/config.json 的 flash_cmd 同源)
flash_cmd = '"{}" "{}" flash'.format(py, STLINK_FLASH)
cmd = [py, str(RUN_BOOT), "--flash-cmd", flash_cmd]
if required:
cmd += ["--required", required]
if summary_name: