硬汉嵌入式论坛

 找回密码
 立即注册
搜索
查看: 435|回复: 3
收起左侧

[AI工具] 记录一次AI自己抓BUG并修复的过程

[复制链接]

35

主题

110

回帖

215

积分

高级会员

积分
215
发表于 2026-9-11 09:53:31 | 显示全部楼层 |阅读模式
本帖最后由 zbq 于 2026-9-11 09:59 编辑


# 网络 wedge 根因定案与修复:ETH RX 描述符环永久挂起(2026-09-07)

分支 `feat/rstp-ring`,STM32H743II + ThreadX + NetX Duo,单板 `192.168.37.11`

## 0. 故障现象

组合负载下(TCP 参数轮询 20ms ≈ 50pps + PC 每 30s 主动 RST 断链),
约 2.5 分钟必现:

- ping 100% 丢包,TCP 拨不上;
- **无 HardFault、无复位**,应用任务全部存活(telnet 有回显、PC 停在正常任务位置);
- **不可自愈** —— 停掉所有压力、等待任意时长,网络都不恢复。

## 1. 根因(已定案,非推测)

wedge 的本质**不是**「NetX 包池耗尽」,而是**包池的一次瞬时耗尽在 ETH RX
描述符环上留下的永久性死锁**。池恢复之后网络也不会自愈。

### 故障链(五步自锁)

| 步 | 位置 | 行为 |
|---|---|---|
| 1 | `nx_stm32_eth_driver.c` `HAL_ETH_RxAllocateCallback` | 包池瞬时空 → `*buff = NULL` |
| 2 | `stm32h7xx_hal_eth.c` `ETH_UpdateDescriptor` | 见 NULL → `allocStatus = 0` → 退出循环,**一个描述符都没补上** |
| 3 | 同上,尾指针更新处 | `if (RxBuildDescCnt != desccount)` 在零补给时为**假****`DMACRDTPR` 永不写入**,尾指针冻结 |
| 4 | ETH DMA 硬件 | 当前指针 `DMACCARDR` 追平冻结的尾指针 → **RX DMA 进入 Suspend** |
| 5 | 中断链 | 挂起 → 无 RI 中断 → 不再调 `HAL_ETH_ReadData` → 不再调 `ETH_UpdateDescriptor`**自锁** |

关键在第 3 步。ST 的原始代码是:

```c
if (heth->RxDescList.RxBuildDescCnt != desccount)   /* 零补给时为假 */
{
  tailidx = (ETH_RX_DESC_CNT + descidx - 1U) % ETH_RX_DESC_CNT;
  __DMB();
  WRITE_REG(heth->Instance->DMACRDTPR, ((uint32_t)(heth->Init.RxDesc + (tailidx))));
  heth->RxDescList.RxBuildDescIdx = descidx;
  heth->RxDescList.RxBuildDescCnt = desccount;
}
```

「一个都没补上」和「全部补完」在这个条件下**走同一条 else 分支(什么都不做)**
而这两种情况的语义天差地别。

### 现场取证(wedge 板,埋点固件 + J-Link 快照)

| 观测项 | 值 | 说明 |
|---|---|---|
| `nx_dbg_rx_alloc_fail` | 16 | 分配失败累计 |
| `nx_dbg_rx_alloc_fail_avail` | 0 | 失败瞬间池确实为空 |
| `nx_dbg_rx_stall` | 13 | 零补给(尾指针未更新)累计 |
| `nx_dbg_rx_stall_desccnt` | 3 | 最后一次有 3 个描述符饿着 |
| 快照 `DMACRDTPR` / `DMACCARDR` | `0x30000030` / `0x30000030` | 两者相等 = DMA 已追平尾指针 |
| **实时**重读同两寄存器 | `0x30000030` / `0x30000030` | 与快照完全一致 → **自 stall 起指针再没动过** |
| `DMACSR` | `0x404` | 仅 TBU+ETI;**RBU=0 / RPS=0 / AIS=0** |
| 包池 available / empty_requests | 31/32 / 95 | **池早已恢复,环仍然死** |
| 描述符 | desc2 `DESC3=0xC1000000`(armed),desc0/1/3 保留陈旧写回 `0x34010113`/`0x3401003D` | 环停在半补给状态 |

`DMACSR=0x404` 这一条尤其重要:**这是 suspend,不是错误中断**。所以社区流传的
「在 `HAL_ETH_ErrorCallback` 里清 RBU + 写 `DMACRDTPR`」那类修复在这里**根本不会被调用**
这也解释了为什么多位报告者说该方案无效。

### 反证实验

用 J-Link 手工把 4 个描述符 `DESC3` 写成 `OWN|IOC|BUF1V`
`DMACRDTPR = 0x30000048``DMACRCR.SR = 1`
ping **立刻**从 100% 丢包恢复到 0% 丢包 / 0ms —— 证明除描述符环外一切正常。

## 2. 这是不是 ST 库原本的问题?——是,且是上游缺陷

两条出问题的代码路径都在 ST 原版文件里:

- `Drivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_eth.c`(Copyright 2017 STMicroelectronics)
- `Middlewares/ST/netxduo/common/drivers/ethernet/nx_stm32_eth_driver.c`(ST 提供的 NetX 驱动)

本项目对这两个文件的改动仅限于埋点计数器与本次修复,缺陷逻辑是原版的。

公开对应记录:

- **STM32CubeH7 Issue #222** —「以太网工作一段时间后停止;有时能跑几周」,
  症状与本次完全吻合(不可自愈、无异常中断)。
- 多个 ST 社区帖讨论 RX 描述符初始化 / `DMACSR.RBU` 卡死,
  其中「在 ErrorCallback 里恢复」的通行做法被多人反馈**无效** ——
  与我们 `DMACSR=0x404`(RBU=0、AIS=0)的实测互相印证。





上述所有操作都是AI自动完成(压测,故障记录,分析,BUG查找修复),我只连了一下网线和Jlink
回复

使用道具 举报

45

主题

346

回帖

481

积分

高级会员

积分
481
发表于 2026-9-12 15:00:13 来自手机 | 显示全部楼层
什么AI呢
回复

使用道具 举报

5

主题

248

回帖

263

积分

高级会员

积分
263
发表于 2026-9-13 17:28:55 | 显示全部楼层
AI做通信类的很好使的,自动改代码,自动编译、自动 下载,自动抓bug,然后重复循环。
不过,没啥值得高兴的,它越厉害,你失业的时间就越近了
回复

使用道具 举报

41

主题

266

回帖

389

积分

高级会员

积分
389
发表于 2026-9-14 17:27:25 | 显示全部楼层
去掉文字底色吧,看着有点难受。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|小黑屋|Archiver|手机版|硬汉嵌入式论坛

GMT+8, 2026-9-23 07:46 , Processed in 0.135206 second(s), 23 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2023, Tencent Cloud.

快速回复 返回顶部 返回列表