From b80f59cc5d4e2956fbbe70c6af68957354ffea89 Mon Sep 17 00:00:00 2001 From: Wanderingss <1624155937@qq.com> Date: Sat, 10 Oct 2026 15:46:21 +0800 Subject: [PATCH] =?UTF-8?q?fix(bench):=20ST-LINK=5FCLI=20=E5=AD=90?= =?UTF-8?q?=E8=BF=9B=E7=A8=8B=E5=8A=A0=20stdin=3DDEVNULL=EF=BC=8C=E9=97=AD?= =?UTF-8?q?=E7=8E=AF=E4=B8=8D=E5=86=8D=E6=8C=82=E6=AD=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - stlink_flash.py::run_cli 与 run_boot_test.py::_run_cmd 调 subprocess.run 时未给 stdin=DEVNULL:ST-LINK_CLI 编程完成后停在 "run application to exit" 等 stdin,stdin 是未关闭管道即永久挂起(编程其实已成功、板子已 复位运行)→ 闭环误判 flash rc=-1(180s 超时) - 归档 ADC 1kHz 台架证据 boot_log_data/20261010_prod_adc_tim6_boot_log.txt 并在 README 清单登记 - 同步 ADC采样节拍设计说明(状态→通过台架验收、新增 §7.1 实测) 与 继电保护功能复现规划 L1-1 --- .../serial-boot-test/scripts/run_boot_test.py | 10 ++- .../stlink-flash/scripts/stlink_flash.py | 6 +- docs/子系统设计/ADC采样节拍设计说明.md | 27 ++++++- .../20261010_prod_adc_tim6_boot_log.txt | 72 +++++++++++++++++++ docs/测试说明/boot_log_data/README.md | 2 +- docs/算法/继电保护功能复现规划.md | 2 +- 6 files changed, 112 insertions(+), 7 deletions(-) create mode 100644 docs/测试说明/boot_log_data/20261010_prod_adc_tim6_boot_log.txt diff --git a/.dsh/skills/serial-boot-test/scripts/run_boot_test.py b/.dsh/skills/serial-boot-test/scripts/run_boot_test.py index f99f0333..ac40c2b0 100644 --- a/.dsh/skills/serial-boot-test/scripts/run_boot_test.py +++ b/.dsh/skills/serial-boot-test/scripts/run_boot_test.py @@ -145,9 +145,15 @@ def _split_cmd(cmd_str): def _run_cmd(argv, timeout): - """跑一条外部命令,按字节取回输出并显式 UTF-8 解码(不受控制台代码页影响)。""" + """跑一条外部命令,按字节取回输出并显式 UTF-8 解码(不受控制台代码页影响)。 + + stdin=DEVNULL 必须:烧录/回读走 ST-LINK_CLI,它编程完成后会停在 + "run application to exit" 等按键——stdin 若是未关闭的管道会永久挂起 + (2026-10-10 台架实测:编程成功但 CLI 180s 不退 → 误判 flash rc=-1)。 + """ try: - proc = subprocess.run(argv, capture_output=True, timeout=timeout) + proc = subprocess.run(argv, capture_output=True, timeout=timeout, + stdin=subprocess.DEVNULL) rc = proc.returncode raw = (proc.stdout or b"") + (proc.stderr or b"") except subprocess.TimeoutExpired as e: diff --git a/.dsh/skills/stlink-flash/scripts/stlink_flash.py b/.dsh/skills/stlink-flash/scripts/stlink_flash.py index 747ddcb3..ef44c9b7 100644 --- a/.dsh/skills/stlink-flash/scripts/stlink_flash.py +++ b/.dsh/skills/stlink-flash/scripts/stlink_flash.py @@ -80,7 +80,11 @@ def find_cli(cli_arg, cfg): def run_cli(cli, args, timeout): t0 = time.monotonic() try: - proc = subprocess.run([str(cli)] + args, capture_output=True, timeout=timeout) + # stdin=DEVNULL 必须:ST-LINK_CLI 编程完成后会停在 "run application to exit" + # 等按键,若 stdin 是未关闭的管道/控制台会**永久挂起**(2026-10-10 台架实测: + # 编程已成功、板子已复位运行,CLI 却 180s 不退 → 闭环误判 flash rc=-1)。 + proc = subprocess.run([str(cli)] + args, capture_output=True, timeout=timeout, + stdin=subprocess.DEVNULL) rc = proc.returncode raw = (proc.stdout or b"") + (proc.stderr or b"") except subprocess.TimeoutExpired as e: diff --git a/docs/子系统设计/ADC采样节拍设计说明.md b/docs/子系统设计/ADC采样节拍设计说明.md index 1eeafd38..9d2a8fc8 100644 --- a/docs/子系统设计/ADC采样节拍设计说明.md +++ b/docs/子系统设计/ADC采样节拍设计说明.md @@ -1,7 +1,9 @@ # ADC 采样节拍设计说明(1 kHz 硬件定时器触发) -> **状态**:**已实现(2026-10-10)**——TIM6 更新中断(1 kHz)触发已落地(`Src/main.c` 回调 + -> `app_main.c` 启动 + `adc_task.c` 退化为纯消费者),`@build` 0 错 0 警;**台架 `@test` 验收(§7)待做**。 +> **状态**:**已实现并通过台架验收(2026-10-10)**——TIM6 更新中断(1 kHz)触发已落地 +> (`Src/main.c` 回调 + `app_main.c` 启动 + `adc_task.c` 退化为纯消费者),`@build` 0 错 0 警; +> 台架 `@test` **PASS**(`frame_seq` 每 10 s 精确 +10000 = 1000.0 Hz、`frst_err=0`、回读一致; +> 实测见 §7.1)。 > **上位需求**:`docs/算法/继电保护功能复现规划.md` §3.2 L1-1(周期 CONVST 重触发 1000 Hz, > 与保护节拍同源)。**驱动契约**:`Drivers/BSP/TPAFE5160/README.md`。 > **背景**:B1(2026-10-10)已把 `adc_task` 由空桩改为真实消费者,但采样节拍是 @@ -181,6 +183,26 @@ t=1000 µs 下一个 TIM6 更新事件 | 6 | 开机日志时间戳正常(TIM7 时基未坏) | 串口日志 | | 7 | 无 HardFault / `[ERR]` / 看门狗复位 | `@test` Forbidden 判定 | +### 7.1 台架实测结果(2026-10-10,`@test` PASS) + +证据:`docs/测试说明/boot_log_data/20261010_prod_adc_tim6_boot_log.txt`(`fw build: Oct 10 2026 15:21:20`)。 + +| # | 判据 | 实测 | +|---|---|---| +| 1 | `@build` 0 错 0 警 + 镜像时效 | ✅ 0 错 0 警;无源文件新于 hex | +| 2 | CONVST 1.000 kHz | ✅ 以 `frame_seq` 速率替代(无示波器):`seq` 10005→20005→30005,**每 10 s 精确 +10000 = 1000.0 Hz** | +| 3 | BUSY 每周期一脉冲 | ✅ 以 `frst_err=0` 替代:全程无"FRSTDATA 无跳变"帧(BUSY EXTI 每周期都在读帧) | +| 4 | `frame_seq` 严格递增 | ✅ 见 #2,严格单调 | +| 5 | `frst_err=0`、`idle` 基本为 0 | ✅ `frst_err=0`;⚠ `idle` 每 10 s +5(≈0.05%,见下) | +| 6 | 开机时间戳正常 | ✅ 日志带墙钟时间戳,`net init: OK` 在 +530 ms | +| 7 | 无 HardFault / `[ERR]` / 看门狗复位 | ✅ 零 `[ERR]`/HardFault;`reset cause:` 仅 1 次(调试器软复位) | + +**关于 `idle`(不是缺陷,是轮询消费的固有抖动)**:生产端(TIM6)与消费端(`adcTask` 1 ms 轮询) +同为 1000 Hz(TIM6 与 FreeRTOS tick 源 TIM7 参数一致,均 84 MHz/84/1000),但二者无显式同步 → +偶发 ±1 帧的相位抖动:每 10 s 约 5 次"两次轮询落在同一生产间隔"(`idle` +5)配 5 次"一次轮询跨两个 +生产间隔"(`frames` 少 5,即 9995/10000 ≈ 99.95% 取数)。要彻底消除需把消费端改为**帧就绪事件驱动** +(在 BUSY EXTI 读帧完成时通知 `adcTask`)——与 §8 等周波调频的消费端改造是同一件事,留待该阶段一并做。 + --- ## 8. 后续:等周波调频(不在本项范围) @@ -201,3 +223,4 @@ t=1000 µs 下一个 TIM6 更新事件 |---|---|---| | 2026-10-10 | 建立本文档 | B1(ADC 采集链路)遗留项"精确 1 kHz 硬件定时器触发"的规划:方案选型(A/B)、CubeMX 配置规格、代码改造清单、时序与优先级分析、风险与验收判据、等周波调频预留 | | 2026-10-10 | **实现(方案 A)** | CubeMX 加 TIM6(PSC=83 / ARR=999 / ARR 预装载 / NVIC 抢占优先级 6);`Src/main.c` 回调加 TIM6 分支触发 CONVST;`app_main.c` 用 `HAL_TIM_Base_Start_IT(&htim6)` 启动节拍;`adc_task.c` 退化为纯消费者。`@build` 0 错 0 警;台架 `@test` 验收待做 | +| 2026-10-10 | **台架 `@test` 验收 PASS** | 真机闭环:`seq` 10005→20005→30005(每 10 s +10000 = 1000.0 Hz)、`frst_err=0`、`idle` 每 10 s +5(0.05%,轮询抖动)、回读 `No difference found`、零 `[ERR]`/HardFault、`reset cause` 仅 1 次。证据 `boot_log_data/20261010_prod_adc_tim6_boot_log.txt` | diff --git a/docs/测试说明/boot_log_data/20261010_prod_adc_tim6_boot_log.txt b/docs/测试说明/boot_log_data/20261010_prod_adc_tim6_boot_log.txt new file mode 100644 index 00000000..21e16e40 --- /dev/null +++ b/docs/测试说明/boot_log_data/20261010_prod_adc_tim6_boot_log.txt @@ -0,0 +1,72 @@ +[+0ms] [----/--/-- --:--:--][APP] boot: syslog init OK +[+0ms] [----/--/-- --:--:--][APP] fw build: Oct 10 2026 15:21:20 +[+10ms] [----/--/-- --:--:--][APP] reset cause: software (NVIC_SystemReset) (CSR=0x14000000) +[+20ms] PREVRUN seg=2 seq=1910016719 t=9345 +[+20ms] TICKRUN uw=9385 n=9385 duw=40 +[+31ms] [----/--/-- --:--:--][RTC] sd2506_init: OK +[+31ms] [----/--/-- --:--:--][APP] SD2506 init: OK (ret=0) +[+31ms] [2026-10-10 07:44:17][CLK] sys_clock_init: RTC initial time 2026-10-10 07:44:17 +[+42ms] [2026-10-10 07:44:17][CLK] sys_clock_init: wall clock base = unix 1791618257, base_tick=136 +[+52ms] [2026-10-10 07:44:17][APP] RS485 init: OK (UART4, DE=PA15) +[+73ms] [2026-10-10 07:44:17][NAND] Resetting NAND... +[+83ms] [2026-10-10 07:44:17][NAND] Reading NAND ID... +[+83ms] [2026-10-10 07:44:17][NAND] NAND ID: MID=0xC8, DID=0x52 +[+96ms] [2026-10-10 07:44:17][NAND] Scanning bad blocks... +[+225ms] [2026-10-10 07:44:17][NAND] BBT scan: 0 bad blocks found +[+225ms] [2026-10-10 07:44:17][NAND] Enabling ECC... +[+235ms] [2026-10-10 07:44:17][NAND] Unlocking block protection... +[+246ms] [2026-10-10 07:44:17][NAND] Locating BBT pool... +[+246ms] [2026-10-10 07:44:17][NAND] Loading persisted BBT... +[+258ms] [2026-10-10 07:44:17][NAND] NAND init OK +[+258ms] [2026-10-10 07:44:17][APP] NAND init: OK +[+258ms] [2026-10-10 07:44:17][ADC] Init OK +[+258ms] [2026-10-10 07:44:17][APP] ADC init: OK +[+269ms] [2026-10-10 07:44:17][APP] SD2506 ID: 2512153425482405 +[+279ms] [2026-10-10 07:44:17][APP] SD2506 time: 2026-10-10 07:44:17 (week 2) +[+279ms] [2026-10-10 07:44:17][APP] SD2506 temp: 29 C +[+279ms] [2026-10-10 07:44:17][APP] SD2506 battery: 3.12 V +[+290ms] [2026-10-10 07:44:17][APP] App init OK +[+300ms] [2026-10-10 07:44:17][NAND_FTL] Initializing NAND FTL... +[+321ms] [2026-10-10 07:44:17][NAND_FTL] Map resumed: 14094/97504 sectors used +[+332ms] [2026-10-10 07:44:17][NAND_FTL] Map head=108784 tail=86214 epoch=1 +[+332ms] [2026-10-10 07:44:17][NAND_FTL] NAND FTL ready (capacity: 97504 pages = 190 MB) +[+415ms] [2026-10-10 07:44:17] [FS] FATFS mounted +[+457ms] [2026-10-10 07:44:17][SYSLOG] runlog boot entry: reboot +[+467ms] [2026-10-10 07:44:17][CFG] register: section 'network' (4 keys) +[+478ms] [2026-10-10 07:44:17][CFG] load: OK (523B, heap free 15240B) +[+478ms] [2026-10-10 07:44:17][NET_CFG] load: OK ip=192.168.1.100 +[+509ms] [2026-10-10 07:44:17][NET_TASK] === Network Init === +[+520ms] [2026-10-10 07:44:17][ADC_TASK] first frame: UA=11428 UN=11454 IA=11451 +[+530ms] [2026-10-10 07:44:17][NET_TASK] net init: OK +[+530ms] [2026-10-10 07:44:17][NET_TASK] MAC: 3C:AB:72:53:2B:12 +[+541ms] [2026-10-10 07:44:17][NET_TASK] IP_INF: IP=192.168.1.100 GW=192.168.1.1 MASK=255.255.255.0 +[+551ms] MISS start snap=0x00000067 req=0x00000077 t=649 +[+551ms] [2026-10-10 07:44:17][WD] [WD] armed: timeout ~2498ms (worst ~1701ms), miss_tol=800ms +[+562ms] [2026-10-10 07:44:17][UI_TASK] UI task: started, wait net ready +[+2533ms] [2026-10-10 07:44:19][NET_TASK] PHY: 100M FULL +[+2544ms] [2026-10-10 07:44:19][NET_TASK] netTask: started (single-socket mode) +[+2576ms] [2026-10-10 07:44:19] [FTP] waiting for connection... +[+2617ms] [2026-10-10 07:44:19][TIME_SYNC] time_sync: TCP listen on :8888 (sock=1) +[+2627ms] [2026-10-10 07:44:19][UI_TASK] UI task: net ready, init port +[+2627ms] [2026-10-10 07:44:19][UI_TASK] UI task: ui_port_init enter +[+2638ms] [2026-10-10 07:44:19][UI_PORT] theme: mono dark_bg=true applied +[+2638ms] [2026-10-10 07:44:19][UI_TASK] UI port init: OK +[+2648ms] [2026-10-10 07:44:19][UI_TASK] UI task: ui_menu_init enter +[+2648ms] [2026-10-10 07:44:19][UI_MENU] menu build start: total=39408 free=36572 big=36572 +[+2659ms] [2026-10-10 07:44:19][UI_MENU_VIEW] view init: root frame w=66 h=107 +[+2669ms] [2026-10-10 07:44:19][UI_MENU] menu build done: total=39292 free=35708 big=35696 used=3584 +[+2679ms] [2026-10-10 07:44:19][UI_TASK] UI menu init: OK +[+2679ms] [2026-10-10 07:44:19][UI_STANDBY] standby: ready (idle=60000ms) +[+2690ms] MISS start snap=0x00000067 req=0x00000077 t=2789 +[+2690ms] [2026-10-10 07:44:19][UI_TASK] UI standby: ready (idle=60s) +[+2742ms] [2026-10-10 07:44:19][UI_TASK] UI net sink: started (port 7003) +[+5294ms] [2026-10-10 07:44:22] [STACK] default peak_used=2164/4096 free_min=1932 (47%) +[+5305ms] [2026-10-10 07:44:22] [STACK] net peak_used=920/3840 free_min=2920 (76%) +[+5305ms] [2026-10-10 07:44:22] [STACK] ftp peak_used=740/4096 free_min=3356 (81%) +[+5315ms] [2026-10-10 07:44:22] [STACK] ui peak_used=4016/16384 free_min=12368 (75%) +[+5326ms] [2026-10-10 07:44:22] [STACK] timesync peak_used=616/2048 free_min=1432 (69%) +[+5326ms] [2026-10-10 07:44:22] [STACK] adc peak_used=528/2048 free_min=1520 (74%) +[+5336ms] [2026-10-10 07:44:22] [STACK] heap free=15088 min_ever=7152 +[+10297ms] [2026-10-10 07:44:27][ADC_TASK] frames=9961 idle=40 seq=10005 frst_err=0 +[+20294ms] [2026-10-10 07:44:37][ADC_TASK] frames=19956 idle=45 seq=20005 frst_err=0 +[+30292ms] [2026-10-10 07:44:47][ADC_TASK] frames=29951 idle=50 seq=30005 frst_err=0 diff --git a/docs/测试说明/boot_log_data/README.md b/docs/测试说明/boot_log_data/README.md index 1f7239ae..c54ca6ae 100644 --- a/docs/测试说明/boot_log_data/README.md +++ b/docs/测试说明/boot_log_data/README.md @@ -25,7 +25,7 @@ | 日期 | 构建 / 负载 | 关键 `[STACK]` 水位 | 文件 | |---|---|---|---| -| — | — | — | (待台架窗口补齐) | +| 2026-10-10 | `prod_adc_tim6` / 开机 + 30 s 空载 | `adc` 528/2048(74%);`default` 2164/4096(47%);heap free=15088 min_ever=7152 | `20261010_prod_adc_tim6_boot_log.txt` | ## 4. 关联 diff --git a/docs/算法/继电保护功能复现规划.md b/docs/算法/继电保护功能复现规划.md index 570a4ad0..3733fc2c 100644 --- a/docs/算法/继电保护功能复现规划.md +++ b/docs/算法/继电保护功能复现规划.md @@ -238,7 +238,7 @@ | # | 功能点 | 关键参数 | 完成判据 | 状态 | | --- | --- | --- | --- | --- | -| L1-1 | 周期 CONVST 重触发 | 1000 Hz(与保护节拍同源) | 示波器见 U3 `BUSY` 连续脉冲;`tpafe5160_frame_seq()` 持续递增 | ✅ 2026-10-10:**TIM6 更新中断(1 kHz)硬件触发**(ISR 内 `tpafe5160_start_conv_irq()`;方案 A,零引脚/零驱动改动);B1 阶段已台架确认 `frame_seq` 严格 1000 Hz 递增 | +| L1-1 | 周期 CONVST 重触发 | 1000 Hz(与保护节拍同源) | 示波器见 U3 `BUSY` 连续脉冲;`tpafe5160_frame_seq()` 持续递增 | ✅ 2026-10-10:**TIM6 更新中断(1 kHz)硬件触发**(ISR 内 `tpafe5160_start_conv_irq()`;方案 A,零引脚/零驱动改动);台架 `@test` PASS——`seq` 每 10 s 精确 +10000 = 1000.0 Hz、`frst_err=0`(证据 `boot_log_data/20261010_prod_adc_tim6_boot_log.txt`) | | L1-2 | TPAFE 快照消费 | 8 通道 / 帧 | `adc_task` 每拍调 `tpafe5160_snapshot()`,返回 1/0/-1 有处理 | ✅ B1 已实现并 `@test` 闭环(`adc_task.c`;台架 `idle=0`、`frst_err=0`) | | L1-3 | STM32 ADC1 启动与扫描 | 9 通道、144 cycles、软件触发 | 全库出现 `HAL_ADC_Start`;9 通道码值随注入变化 | ⬜ | | L1-4 | 通道语义映射 | 见 `docs/硬件平台/ADC通道映射说明.md`(**按语义取数,不写死下标**) | `UA→buf[6]`、`UN→buf[5]`、`IA→buf[2]`;STM32 侧 `UB→ADC_CHANNEL_14` | ⬜ |