docs: 固化ARP与ICMP联调经验
This commit is contained in:
@@ -206,6 +206,93 @@ void vApplicationMallocFailedHook(void)
|
|||||||
2. TCP Server 是否在指定端口监听
|
2. TCP Server 是否在指定端口监听
|
||||||
3. TCP Client 是否成功连接远端
|
3. TCP Client 是否成功连接远端
|
||||||
|
|
||||||
|
### 6.5 P3.5:确认 ARP / ICMP 基础网络可达
|
||||||
|
|
||||||
|
在继续 TCP 联调前,建议先把 `ARP + ping(ICMP)` 跑通。对于当前 `CH390 + lwIP + FreeRTOS` 架构,这一步不是可选项,而是 TCP 可达之前必须成立的网络基线。
|
||||||
|
|
||||||
|
#### 6.5.1 推荐最小验证顺序
|
||||||
|
|
||||||
|
1. 先确认板卡 IP、掩码、MAC 与 PC 所在网段一致
|
||||||
|
2. 上电后先观察 RTT,确认 `ETH init: done` 已出现
|
||||||
|
3. 在 PC 侧执行一次 `ping <板卡IP>`,同时开启 Wireshark 抓包
|
||||||
|
4. 先看是否出现发往板卡 IP 的 ARP request,再看设备是否回 ARP reply
|
||||||
|
5. ARP 正常后,再看是否出现 ICMP echo request / echo reply 成对出现
|
||||||
|
|
||||||
|
#### 6.5.2 当前工程推荐观察点
|
||||||
|
|
||||||
|
如果网络基础链路有疑问,建议按以下分层观察,不要只看某一层:
|
||||||
|
|
||||||
|
1. **raw RX 层**:CH390 是否确实收到了以太网帧
|
||||||
|
2. **Ethernet demux 层**:`ethernet_input()` 是否识别到 `ETHTYPE_ARP` / `ETHTYPE_IP`
|
||||||
|
3. **协议处理层**:`etharp_input()` / `ip_input()` 是否真正进入
|
||||||
|
4. **协议发包层**:lwIP 是否已经生成待发送的 ARP reply / ICMP reply
|
||||||
|
5. **驱动发送层**:`low_level_output()` / CH390 TX 是否真正把帧送出
|
||||||
|
|
||||||
|
这次 bring-up 证明,`raw RX 正常` 并不等于 `lwIP 已真正处理该帧`。如果只看到底层收到了包,就直接假设协议栈一定会回复,通常会把排查方向带偏。
|
||||||
|
|
||||||
|
#### 6.5.3 这次 ARP / ICMP bring-up 的关键结论
|
||||||
|
|
||||||
|
本轮调试中,最终根因位于:
|
||||||
|
|
||||||
|
- `Drivers/LwIP/src/netif/ethernet.c`
|
||||||
|
|
||||||
|
问题本质是:
|
||||||
|
|
||||||
|
1. `ethernet_input()` 在 `ETHTYPE_ARP` 分支中,曾直接调用 `etharp_input(p, netif)`
|
||||||
|
2. 但 `etharp_input()` 要求 `p->payload` 从 **ARP 头** 开始,而不是从 Ethernet 头开始
|
||||||
|
3. 因此如果没有先执行:
|
||||||
|
|
||||||
|
```c
|
||||||
|
pbuf_remove_header(p, SIZEOF_ETH_HDR)
|
||||||
|
```
|
||||||
|
|
||||||
|
则 ARP 包虽然被收到了,但会在 `etharp_input()` 的早期校验中被静默丢弃,最终表现为:
|
||||||
|
|
||||||
|
1. Wireshark 能看到 PC 发来的 ARP request
|
||||||
|
2. 板子侧底层收包计数在增长
|
||||||
|
3. 但设备始终不回 ARP reply
|
||||||
|
4. ping 也自然不会成功
|
||||||
|
|
||||||
|
当前应保留的正确处理方式如下:
|
||||||
|
|
||||||
|
```c
|
||||||
|
case ETHTYPE_ARP:
|
||||||
|
if (netif->flags & NETIF_FLAG_ETHARP) {
|
||||||
|
if (pbuf_remove_header(p, SIZEOF_ETH_HDR)) {
|
||||||
|
pbuf_free(p);
|
||||||
|
return ERR_OK;
|
||||||
|
}
|
||||||
|
etharp_input(p, netif);
|
||||||
|
} else {
|
||||||
|
pbuf_free(p);
|
||||||
|
}
|
||||||
|
return ERR_OK;
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 6.5.4 为什么这类问题容易漏看
|
||||||
|
|
||||||
|
这类问题常见但隐蔽,原因通常有三点:
|
||||||
|
|
||||||
|
1. 根因非常小,外在表现却像“整个发送链路都坏了”
|
||||||
|
2. 多个低层信号可能同时正常,容易误导为 SPI / TX / CH390 初始化问题
|
||||||
|
3. `rx ok`、`ARP 帧计数在涨`、`链路已 up` 都不代表协议层一定接受了该帧
|
||||||
|
|
||||||
|
因此,后续遇到“收得到包但就是不回”的问题时,优先检查:
|
||||||
|
|
||||||
|
1. 传给上层协议处理函数时,`pbuf->payload` 是否已经对齐到正确协议头
|
||||||
|
2. glue-layer 是否和 lwIP 原生调用约定一致
|
||||||
|
3. 观察点是否已经覆盖到 `demux -> protocol handler -> linkoutput` 这一整条链
|
||||||
|
|
||||||
|
#### 6.5.5 建议保留的最小验收标准
|
||||||
|
|
||||||
|
在认定网络基线“已经打通”之前,至少应满足:
|
||||||
|
|
||||||
|
1. Keil 工程可稳定构建通过
|
||||||
|
2. 上电后可稳定看到网络初始化完成日志
|
||||||
|
3. Wireshark 中能看到设备对本机 ARP request 做出 reply
|
||||||
|
4. PC 对设备 `ping` 时,能看到 ICMP echo request / reply 成对出现
|
||||||
|
5. RTT 中无 `STACK OVERFLOW`、`MALLOC FAILED`、异常 trap 等故障信号
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 7. MUX / NET / LINK[idx] 联调指导
|
## 7. MUX / NET / LINK[idx] 联调指导
|
||||||
@@ -256,6 +343,10 @@ void vApplicationMallocFailedHook(void)
|
|||||||
4. 不要在基础寄存器读写尚不可信时,直接调高层业务
|
4. 不要在基础寄存器读写尚不可信时,直接调高层业务
|
||||||
5. 不要在 ISR 中执行复杂 SPI 事务或调用阻塞 API
|
5. 不要在 ISR 中执行复杂 SPI 事务或调用阻塞 API
|
||||||
6. 不要忽视 `configCHECK_FOR_STACK_OVERFLOW` 报告
|
6. 不要忽视 `configCHECK_FOR_STACK_OVERFLOW` 报告
|
||||||
|
7. 不要把“底层已经收到 ARP 包”等同于“lwIP 一定已经正确处理 ARP 包”
|
||||||
|
8. 不要忽略 glue-layer 对 `pbuf->payload` 起始位置的约定,特别是 `Ethernet header -> ARP/IP header` 的切换
|
||||||
|
9. 不要在 ARP / ICMP 还没闭环前,就直接怀疑 TCP Server / TCP Client 逻辑
|
||||||
|
10. 不要在没有抓包和分层观测点的情况下,只凭单一日志就断言故障位于 TX 或 SPI 层
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user