STM32使用Jlink下载时 "Can not attach to CPU" 调试笔记

现象:J-Link 能识别 SW-DP (ID 0x2BA01477),但无法挂载 CPU 核心,RTT Viewer 和 J-Link Commander 均连接失败。长按复位键后恢复正常。

环境

项目 详情
MCU STM32F411RET6 (Cortex-M4F, 100MHz)
调试器 J-Link V11, SWD 接口
工具链 arm-none-eabi-gcc 15.2.1, CMake, FreeRTOS V11.3.0
固件 IAP Bootloader (Ymodem), 纯轮询架构, 100MHz 全速运行
硬件 最小系统板, BOOT0 硬接地, NRST 未接 J-Link

症状

LOG: Found SW-DP with ID 0x2BA01477
LOG: STM32 (connect): Can not attach to CPU. Trying connect under reset.
LOG: Found SW-DP with ID 0x2BA01477
ERROR: STM32: Connecting to CPU via connect under reset failed.
ERROR: Could not connect to target device.
  • J-Link 可以读取 SW-DP ID 寄存器(物理 SWD 连接正常)
  • 无法访问 AHB-AP(CPU 调试访问端口)
  • "connect under reset" 也失败(NRST 引脚未连接)

排查过程

第一步:排除代码显式禁用

全面审查 IAP 固件源码:

排查项 结果
PA13/PA14 复用为 GPIO 未发生
RDP 读保护 Level 0 (未开启)
低功耗模式 (Sleep/Stop/Standby) 未进入
DBGMCU 调试寄存器修改 未发生
__WFI / __WFE 无调用
HAL_PWR_EnterSTOPMode 无调用

固件没有显式禁用 SWD。

第二步:电路检查

  • VTref = 3.314V,供电正常
  • SWDIO、SWCLK、GND 连通性正常
  • BOOT0 硬接地 — 无法进入系统 Bootloader 模式
  • NRST 未接 J-Link Pin 15 — "connect under reset" 不可用

第三步:固件行为分析

IAP Bootloader 的主循环:

// 当没有有效 APP 时, CPU 死循环在此
while (1) {
    printf("run in boot while(1)\r\n");   // 阻塞轮询 UART TX
    printf("there is no legal APP\r\n");  // 阻塞轮询 UART TX
    HAL_Delay(500);                       // 轮询 SysTick uwTick 变量
    Power_DisEnable();                    // GPIO 操作
}

整个固件没有使用任何中断驱动 I/O,所有 UART 收发均为阻塞轮询,CPU 以 100MHz 持续运转。

第四步:根因确认

用 J-Link Commander 配合上电时序抢占验证:

# 先拔掉目标板电源
# 终端准备好连接命令
$ JLink.exe -device STM32F411RE -if SWD -speed 100 -autoconnect 1

# 回车启动扫描的同时立刻给目标板上电
# → 连接成功

抢占窗口约 5-10ms(从上电到 main() 执行),在此窗口内 AHB 总线空闲,J-Link 可正常 attach。


根因

AHB 总线竞争,而非 SWD 被禁用。

┌─────────────┐     SWD (物理层)      ┌──────────────┐
│   J-Link    │ ◄──────────────────► │  STM32F411   │
│             │    SW-DP 响应 ✓       │              │
│  halt请求 → │    AHB-AP 无响应 ✗    │  CPU @100MHz │
│             │                       │  全速轮询     │
└─────────────┘                       │  AHB 持续占用  │
                                      └──────────────┘
  • SW-DP(调试端口)是独立于 CPU 的硬件模块,始终可访问
  • AHB-AP(访问端口)需要通过 AHB 总线矩阵访问 CPU 核心
  • J-Link 发起 halt 请求时,需要在 AHB 总线上获得仲裁时隙
  • 纯轮询固件以 100MHz 持续访问 Flash 和 UART 寄存器,AHB 总线几乎无空闲
  • J-Link 的 SWD 时钟(4MHz)相对较慢,在总线竞争中长期抢不到窗口 → 超时

按复位键后,CPU 停在 Reset_Handler,AHB 空闲 → J-Link 立即可连。


解决方案

临时方案:上电时序抢占

断电 → 启动 J-Link 扫描 → 立即上电 → 抢占成功 → erase → 烧新固件

适用于紧急恢复,可能需要多次尝试。

永久方案一:接 NRST(推荐)

J-Link Pin 15 → STM32 Pin 7 (NRST),一根飞线即可。之后 connect under reset 正常工作,无论固件状态如何都能强制连接。

永久方案二:避免纯轮询架构

在固件空闲路径中使用 __WFI() 或 RTOS 的空闲任务(vApplicationIdleHook 中执行 __WFI())。FreeRTOS 默认在 idle task 中调用 __WFI(),AHB 总线有充足的空闲窗口供调试器访问。


教训

  1. SWD 连接失败 ≠ 接口被禁用。 先检查固件的总线占用模式,再怀疑 RDP 或 GPIO 复用。
  2. NRST 线建议永远接上。 它是在固件失控时唯一的硬件级恢复通道,成本仅一根飞线。
  3. BOOT0 不要硬接地。 留一个跳线或按键,在 RDP 意外开启时还能通过系统 Bootloader 擦除。
  4. 调试受阻时先分析固件行为,而非硬件。 VTref 正常 + SW-DP 可读 = 硬件链路大概率正常。

快速诊断流程图

J-Link 连接失败
      │
      ├─ 能读到 SW-DP ID?
      │   ├─ 否 → 检查 SWD 接线 / 供电
      │   └─ 是 ↓
      │
      ├─ 按复位键后能连?
      │   ├─ 是 → AHB 总线竞争(本文场景)
      │   │      ├─ 接 NRST(永久修复)
      │   │      └─ 固件空闲路径加 __WFI()
      │   │
      │   └─ 否 ↓
      │
      ├─ BOOT0 拉高 + 复位后能连?
      │   ├─ 是 → 固件可能禁用了 SWD
      │   │      └─ 擦除旧固件,烧新固件
      │   │
      │   └─ 否 ↓
      │
      └─ 可能原因:RDP 已开启、芯片损坏
             ├─ RDP Level 1 → 系统 Bootloader mass erase
             └─ RDP Level 2 → 无解,换芯片

2026-06-29, STM32F411RET6 / J-Link / FreeRTOS / RTT

posted @ 2026-06-29 13:05  alanala  阅读(38)  评论(0)    收藏  举报