Files
TCP2UART/工程调试指南.md
gaoro-xiao 5567c7412d docs: sync baud config guidance
Document the AT+BAUD flow in the debug guide, including U0/U1 data-port mapping and the save/reset behavior required for USART2/USART3 baud changes.
2026-04-28 20:28:49 +08:00

24 KiB
Raw Permalink Blame History

TCP2UART 调试指导

1. 适用范围

本指导面向当前 TCP2UART 工程,覆盖以下四类调试场景:

  1. STM32F103R8T6 + CH390D 的基础 bring-up
  2. SEGGER RTT、异常陷阱与主循环运行状态确认
  3. USART1 配置口、USART2/USART3 数据口与 MUX / NET / LINK[idx] 协议联调
  4. TCP Server / TCP Client / UART 三层数据通路联调与问题隔离

本指导默认基线如下:

  1. 当前工程采用裸机主循环架构,未使用 FreeRTOS 参与主业务调度
  2. CH390 运行时访问统一由 ch390_runtime 持有
  3. 调试输出统一使用 SEGGER RTT
  4. 当前应用层协议模型已经收敛到 MUX / NET / LINK[idx]
  5. 当前代码应以 MDK-ARM 工程构建结果为准,而不是 CMake + MSVC 结果

2. 当前工程边界与真实状态

在进入现场调试前,先统一以下工程边界,避免沿用过时结论:

  1. 当前项目的主要软件路径已经切换为:
    • NET:网络基础参数
    • LINK[idx]:链路配置记录
    • MUX:数据口承载模式
  2. 对外 AT 配置面应只围绕以下命令展开:
    • AT
    • AT+?
    • AT+QUERY
    • AT+MUX
    • AT+NET
    • AT+LINK
    • AT+SAVE
    • AT+RESET
    • AT+DEFAULT
  3. 当前 CH390D 的历史“全 0xFF / 全 0x0000”结论不应再直接沿用。
  4. 已有结论表明:
    • MCU 启动、RTT、主循环、TIM4 心跳路径可工作
    • CH390D 基础寄存器读写与 lwIP netif 基本链路已经打通过一次
    • 真实硬件侧曾定位到 CH390D 供电滤波电容虚焊问题
  5. 因此,当前调试重点不再是“CH390 是否完全不通”,而是:
    • 启动阶段是否稳定
    • MUX / NET / LINK[idx] 协议是否与代码一致
    • UART / TCP / CH390 三层通路是否协同稳定
    • 参数保存、复位和恢复流程是否可靠

3. 代码入口与调试责任边界

3.1 启动与主循环入口

以下代码路径是 bring-up 的第一现场:

  1. Core/Src/main.c
    • main():总启动入口
    • SystemClock_Config():时钟初始化
    • App_Init():应用层初始化
    • App_Poll():主循环核心路径
    • BootDiag_ReportCh390():启动阶段 CH390 诊断输出
  2. Core/Src/stm32f1xx_it.c
    • 故障与中断入口
    • USART1/2/3EXTI0、DMA 回调等联调关键入口

3.2 CH390 责任边界

当前 CH390 调试必须遵守以下责任边界:

  1. Drivers/CH390/CH390_Interface.c
    • 只负责 GPIO / SPI / 寄存器与内存事务
  2. Drivers/CH390/CH390.c
    • 只负责芯片级 helper,例如默认配置、PHY、MAC 读写
  3. Drivers/CH390/ch390_runtime.c
    • 唯一的运行时拥有者
    • 负责初始化、链路检查、IRQ 消费、RX/TX 服务与诊断快照
  4. Drivers/LwIP/src/netif/ethernetif.c
    • 只承担 netif glue 与轮询桥接,不应重新下沉复杂 CH390 运行时事务
  5. Core/Src/main.c
    • 启动后只通过 runtime 对外暴露的诊断与轮询接口工作

调试时不要把原始 CH390 寄存器访问重新散回 main.c、中断或多个业务层。

3.3 配置口与业务口边界

  1. USART1
    • 配置口
    • 负责接收 AT 命令
    • 当前接收逻辑在:
      • Core/Src/main.cApp_PollUart1ConfigRx()
      • Core/Src/stm32f1xx_it.cHAL_UART_RxCpltCallback()
      • App/config.cconfig_uart_rx_byte() / config_process_at_cmd()
  2. USART2 / USART3
    • 数据口
    • 负责普通透传或 MUX 承载
    • 当前入口在 App/uart_trans.c

4. 当前硬件与调试工具基线

4.1 核心硬件对象

  1. MCUSTM32F103R8T6
  2. 以太网芯片:CH390D
  3. 配置串口:USART1
  4. 数据串口:USART2 / USART3
  5. 调试输出:SEGGER RTT

4.2 构建与下载基线

当前建议优先使用以下工程与产物:

  1. MDK-ARM/TCP2UART.uvprojx
  2. MDK-ARM/TCP2UART/TCP2UART.axf
  3. MDK-ARM/TCP2UART/TCP2UART.hex
  4. MDK-ARM/TCP2UART/TCP2UART.map
  5. MDK-ARM/TCP2UART/TCP2UART.build_log.htm
  6. build_keil.log

说明:

  1. 当前 CMake configure 可以完成,但 CMake + MSVC 不适合作为 STM32/CMSIS 的最终构建验收依据。
  2. 若需要验证“当前代码是否真实可编译”,优先看 MDK-ARM 构建产物与日志。

4.3 常用调试工具

  1. Keil MDK-ARM
  2. ST-Link / J-Link
  3. SEGGER RTT Viewer
  4. PowerShell
  5. tools/start_tcp_debug_server.ps1
  6. tools/tcp_debug_server.py

5. 启动阶段调试顺序

建议按 P0 ~ P5 顺序推进,不要跳层。

5.1 P0:确认最小基础条件

每次现场调试前,先确认:

  1. MDK-ARM 可构建并产出新的 axf/hex/map
  2. 板卡可正常下载与复位
  3. RTT 可连接并看到启动输出
  4. LED 心跳可工作
  5. App_Poll() 已经进入稳定轮询

这一层若失败,不要进入网络或协议调试。

5.2 P1:确认启动日志与 trap 状态

上电或复位后,优先看 RTT 输出中是否出现:

  1. TCP2UART boot
  2. 若 HSE 启动失败,则会出现:
    • WARN: HSE start failed, fallback to HSI PLL
  3. BootDiag_ReportCh390() 输出的 CH390 诊断与网络配置快照

若发生异常,优先观察是否打印:

  1. TRAP: Error_Handler
  2. TRAP: HardFault_Handler
  3. TRAP: MemManage_Handler
  4. TRAP: BusFault_Handler
  5. TRAP: UsageFault_Handler

当前 trap 统一收敛到:

  1. Core/Src/main.cDebug_TrapWithRttHint()
  2. 它会打印 RTT、执行 __BKPT(0) 并停住

因此,若 RTT 中出现 TRAP:,应立即接调试器看断点现场,而不是继续盲猜高层逻辑。

5.3 P2:确认 CH390 初始化链路

启动阶段应重点关注 Drivers/CH390/ch390_runtime.c 中初始化阶段日志,理想情况下应能依次看到:

  1. ETH init: gpio
  2. ETH init: spi
  3. ETH init: reset
  4. ETH init: probe
  5. ETH init: default
  6. ETH init: mac
  7. ETH init: getmac
  8. ETH init: irq
  9. ETH init: done

此阶段重点判定:

  1. VID / PID / REV 是否可信
  2. PHY 寄存器是否稳定可读
  3. MAC 写入与回读是否一致
  4. link_up 是否与真实网线状态一致

若这一层失败,优先做硬件侧量测,而不是先改业务层:

  1. RSTB
  2. CS
  3. SCK
  4. MOSI
  5. MISO
  6. INT
  7. VDDK
  8. AVDD33 / VDDIO / AVDD33
  9. XI / XO

6. USART1 配置口调试

6.1 当前命令面

根据当前代码与手册,配置口应围绕以下命令验证:

  1. AT
  2. AT+?
  3. AT+QUERY
  4. AT+MUX=...
  5. AT+MUX?
  6. AT+NET=...
  7. AT+NET?
  8. AT+BAUD=...
  9. AT+BAUD?
  10. AT+LINK=...
  11. AT+LINK?
  12. AT+SAVE
  13. AT+RESET
  14. AT+DEFAULT

其中与数据串口相关的固定映射为:

  1. U0 = USART2
  2. U1 = USART3
  3. AT+BAUD=U0,<baud> / AT+BAUD=U1,<baud> 只更新当前运行配置记录
  4. 新波特率不会立即重初始化 USART2/USART3,必须执行 AT+SAVE + AT+RESET 后按保存值生效
  5. 当前代码接受的波特率范围为 1200 ~ 921600

6.2 现场关键规则

根据已有联调记录,配置口最关键的 bench 规则是:

  1. 当前现场验证时,配置命令必须保证以换行完成帧。
  2. 若主机侧发送方式不对,现象会很像“配置口完全无响应”。
  3. 因此,配置口不响应时,第一优先级不是改 parser,而是先验证主机端发送格式与接线。
  4. BAUD 类命令若查询值已变化,但 USART2/USART3 现场波特率尚未变化,不应立即归因为命令无效,应先确认是否已经执行 AT+SAVEAT+RESET

6.3 最小验证步骤

建议按以下顺序验证:

  1. 连接 USART1
  2. 先发 AT
  3. 再发 AT+QUERY
  4. 再发 AT+NET?
  5. 再发 AT+BAUD?
  6. 再发 AT+LINK?
  7. 修改一个最小参数,例如:
    • AT+MUX=1
    • AT+BAUD=U1,38400
  8. 执行:
    • AT+SAVE
    • AT+RESET
  9. 复位后再次查询,确认配置是否保留
  10. 若本轮验证的是 AT+BAUD,还应同步用上位机重新按新波特率连接 USART2/USART3,确认数据口实际生效

6.4 持久化失败时怎么查

优先检查以下路径:

  1. App/config.c
    • config_save()
    • config_load()
    • config_set_defaults()
  2. App/flash_param.c
    • Flash 解锁
    • 页擦除
    • 半字编程
    • 写后校验
  3. 参数页地址:
    • 0x0800FC00

不要在还没证明 AT+SAVE 已真正被接受之前,就直接把 Flash 全 FFFFFFFF 归因到 Flash 驱动错误。


7. MUX / NET / LINK[idx] 联调指导

7.1 协议总则

当前协议必须按以下模型理解:

  1. MUX:全局数据承载模式开关
  2. NETIP / Mask / GW / MAC
  3. LINK[idx]:链路配置项

固定链路索引映射为:

  1. LINK[0] = S1
  2. LINK[1] = S2
  3. LINK[2] = C1
  4. LINK[3] = C2

固定端点编码为:

  1. C1 = 0x01
  2. C2 = 0x02
  3. UART2 = 0x04
  4. UART3 = 0x08
  5. S1 = 0x10
  6. S2 = 0x20

7.2 MUX 数据口规则

MUX=1 时,数据口应使用 MUX 帧。

重点规则:

  1. DSTMASK=0x00 表示系统控制帧
  2. 控制帧中的 AT 文本必须严格按手册要求结束
  3. 普通数据帧走业务转发路径,不应进入配置解析器

7.3 调试时重点检查什么

若怀疑 MUX 模式不工作,优先检查:

  1. App/uart_trans.c
    • uart_mux_try_extract_frame()
    • uart_mux_encode_frame()
  2. Core/Src/main.c
    • App_RouteMuxUartTraffic()
    • App_RouteRawUartTraffic()
    • App_RouteTcpTraffic()
  3. App/config.c
    • config_build_response_frame()
    • config_process_at_cmd()

推荐最小 MUX 联调顺序:

  1. 先在 MUX=0 下跑通原始透传
  2. 再切换 MUX=1
  3. 先发一个控制帧,确认 DSTMASK=0x00 路径可通
  4. 再发一个单目标数据帧,例如只打到 S1
  5. 最后验证多目标位图转发

8. TCP / UART / CH390 联调顺序

8.1 先做链路,再做业务

CH390 初始化、链路和 IRQ 未被证明稳定前,不要先调高层 TCP/UART 业务。

8.2 推荐顺序

建议按以下顺序推进:

  1. RTT 启动与 trap 状态正常
  2. CH390 启动日志完整
  3. 链路检测可信
  4. TCP server / TCP client 建链可信
  5. UART 原始透传可信
  6. 再切入 MUX 模式联调

8.3 最小 TCP 调试工具

当需要验证板子是否真的把 payload 发到主机时,优先使用仓库内置最小工具:

  1. tools/tcp_debug_server.py
    • 打印连接、收包、文本视图和十六进制视图
  2. tools/start_tcp_debug_server.ps1
    • 会先清理冲突监听,再启动 Python 服务端

推荐命令:

powershell -ExecutionPolicy Bypass -File ".\tools\start_tcp_debug_server.ps1" -Port 8081 -NoStdin

如需回显:

powershell -ExecutionPolicy Bypass -File ".\tools\start_tcp_debug_server.ps1" -Port 8081 -Echo

直接运行 Python 服务端也可以:

python .\tools\tcp_debug_server.py --host 0.0.0.0 --port 8081 --no-stdin

8.4 推荐验证方法

  1. 先关闭 VOFA、ncat 和其它可能占用 8081 的进程
  2. 启动 start_tcp_debug_server.ps1
  3. 让板子连接主机 TCP client 目标端口
  4. 再从主机连接板子的 TCP server 端口发送固定测试文本
  5. 同时观察:
    • Python 工具是否收到连接与 payload
    • 板子 RTT 是否出现连接或错误信息

若板子 RTT 显示已连接,但主机工具无数据,优先检查本机端口占用而不是先改板端逻辑。


9. 异常、卡死与假死排查

9.1 看到 TRAP: 时怎么做

  1. 先记录 RTT 中的 trap 标签
  2. 立刻用调试器查看当前 PC / LR / 调用栈
  3. 结合 Core/Src/stm32f1xx_it.c 中对应 handler 定位异常类型

9.2 没有 TRAP: 但系统不工作时怎么做

若没有 TRAP:,但系统表现异常,应优先区分以下情况:

  1. 主循环仍在跑,只是业务路径没反应
  2. 中断未到或链路未更新
  3. 发生了阻塞式等待或超时问题
  4. 上层工具接错端口或被错误进程抢占

9.3 历史上已经确认过的典型软件问题

以下问题在历史排查中已经出现过,应优先复核,不要重复踩坑:

  1. PHY 访问无超时,导致永久卡死
  2. 刷新未初始化的 IWDG 句柄导致 HardFault
  3. 在长耗时 SPI 路径中错误扩大临界区,导致看似"系统假死"
  4. 在多个层次同时触达 CH390 / SPI,导致运行时边界混乱
  5. 配置口命令结束方式不对,导致误判为 parser 无响应

9.4 2026-04-14 MUX 模式网口失联修复记录

现象

MUX 模式启动后,一段时间后网口失联。重新插拔网线无法恢复,重启后恢复正常。对端主动关闭 TCP 连接后,120 秒内无法重新建立连接。

根因

对端主动关闭 TCP 连接时,tcp_server_on_recv(p=NULL)tcp_client_on_recv(p=NULL) 调用 tcp_close() 关闭本地 pcb。tcp_close() 发送 FIN 后将 pcb 推入 TIME_WAIT 状态,持续 2 × TCP_MSL = 120 秒。在此期间 pcb 占用 MEMP_TCP_PCB 池(总量仅 4 个)。当多条连接同时断开后,pcb 池耗尽,新连接的 tcp_new() 返回 NULL。

修复内容

文件 修改 说明
App/tcp_server.c tcp_close(pcb)tcp_abort(pcb) 对端关闭时立即释放 pcb,不进入 TIME_WAIT
App/tcp_client.c tcp_close(pcb)tcp_abort(pcb) 同上
Drivers/CH390/ch390_runtime.c PKT_ERR 恢复时 rcrrcr | RCR_RXEN 确保 RX 重新使能,与 WCH 官方参考一致
Drivers/CH390/ch390_runtime.c TX 连续超时 3 次触发 ch390_runtime_emergency_reset() CH390 TX 引擎卡死时自动复位芯片
Drivers/CH390/ch390_runtime.c 新增 ch390_runtime_health_check() 每 5 秒读 VID 验证芯片存活
Core/Src/main.c App_StartLinksIfNeeded 失败时不标记 g_links_started 允许下次 poll 自动重试
Core/Src/main.c MUX 逐帧 RTT printf 改为 #if DEBUG 门控 生产固件不输出,减少主循环延迟
App/uart_trans.c uart_mux_try_extract_frame 先搜 0x7E 再消费 header 非法帧只丢 1 字节而非 5 字节

构建验证

Keil MDK-ARM 构建 0 Error(s), 0 Warning(s)。Flash 52.7 KB / 64.0 KB (82.5%)RAM 20.0 KB / 20.0 KB (100%)。

9.5 2026-04-18 MUX 模式丢包修复记录

现象

MUX=1 模式下进行持续发送测试时,主机侧发送 500 个数据包,只收到 360 个,存在明显丢包。

根因

本轮定位确认软件侧至少存在以下两个直接丢包点:

  1. App/uart_trans.cuart_mux_try_extract_frame() 在确认整帧完整前,就先消费 SYNC 与 header。若 MUX 帧跨越多个 poll 周期到达,半帧会被提前移出 RX ring,导致当前帧失步并被直接丢弃。

  2. App/tcp_server.cApp/tcp_client.cCore/Src/main.c 的发送路径对背压与短写处理不完整:

    • tcp_sndbuf() < len
    • tcp_write() / tcp_output() 返回 ERR_MEM
    • uart_trans_write() 只写入部分字节

    以上情况在旧代码中会被上层静默忽略,表现为“发送函数返回但数据实际未完整进入下游链路”。

修复内容

文件 修改 说明
App/uart_trans.c uart_mux_try_extract_frame() 改为先窥视、后消费 只有在 SYNC + header + payload + tail 全部可用时才推进 rx_tail,避免半帧被破坏性消费
App/tcp_server.c tcp_server_send()tcp_sndbuf()<lenERR_MEM 返回 0 并计入错误 明确表示本次发送未被底层接收,不再伪装成成功
App/tcp_client.c tcp_client_send() 同步处理背压与 ERR_MEM 逻辑与 server 侧保持一致
Core/Src/main.c App_SendToUart() 检查 uart_trans_write() 是否完整写入 TX ring 空间不足时立即显式失败
Core/Src/main.c App_RouteTcpTraffic() / App_RouteRawUartTraffic() / App_RouteMuxUartTraffic() 统一检查发送结果 不再把背压、短写和未完整提交静默当成成功

结果验证

  1. Keil MDK-ARM 构建通过,0 Error(s), 0 Warning(s)
  2. 在最新固件下重新进行 MUX 持续发送测试,主机侧发送 670 个数据包,接收 670 个,0 丢包。
  3. 本轮修复未增加新的常驻队列与缓冲区,保持当前 RAM 占用边界不变。

9.6 2026-04-24 CH390 emergency reset 恢复语义补齐记录

现象

在 CH390 发生 TX timeout 并触发 ch390_runtime_emergency_reset() 后,芯片寄存器访问恢复正常,VID 可读、PHY 链路也可能保持 up,但 TCP 业务流量仍可能长时间不恢复,表现为“芯片还活着,但网络像失联一样,通常只能重启恢复”。

在后续实现收敛中,又确认仅依赖单次 VID 异常或单次 TX busy 即立刻 reset 过于激进,容易把瞬时抖动误判为芯片失活,因此当前代码已经演化为“带阈值的恢复策略”。

根因

ch390_runtime_emergency_reset() 旧实现仅执行 ch390_software_reset()ch390_default_config()diag 刷新,缺少 cold init 里已有的两层恢复语义:

  1. MAC 对齐未恢复:旧代码没有重新写回 CH390 PAR,也没有把硬件 MAC 重新同步到 netif->hwaddr。若软件复位后 CH390 的 MAC 过滤状态与 lwIP 侧缓存身份不一致,现象会表现为寄存器可访问、链路仍在,但单播业务流量不通。
  2. 上层链路回收未触发TX-timeout 路径直接调用 ch390_runtime_emergency_reset(),没有保证 App_StopLinksIfNeeded() / App_StartLinksIfNeeded() 观察到一次有效的 link-down 周期,导致旧 TCP client/server 状态可能跨芯片复位残留,业务层没有完成重建。
  3. 恢复策略缺少抖动抑制:若仅凭单次 TX busy 或单次 VID 异常立即 reset,容易在瞬时总线/链路抖动下过度恢复,放大业务扰动,因此当前实现增加了连续失败阈值和失败计数清零逻辑。

修复内容

文件 修改 说明
Drivers/CH390/ch390_runtime.h ch390_runtime_emergency_reset() 改为接收 struct netif * 让 reset 路径能同时修复 CH390 与 lwIP 可见状态
Drivers/CH390/ch390_runtime.c 抽取 ch390_runtime_prepare_netif() 在 init / emergency reset 后统一恢复 hwaddr_lenmtuflags 与 RX 软件状态
Drivers/CH390/ch390_runtime.c 新增 ch390_runtime_sync_mac() emergency reset 后按当前 netif->hwaddr 重写 CH390 PAR,并重新同步硬件 MAC 到 lwIP
Drivers/CH390/ch390_runtime.c emergency reset 成功后清 g_ch390_irq_pending 并置位 g_link_restart_pending 避免复位前遗留中断状态影响恢复
Drivers/CH390/ch390_runtime.c ch390_runtime_check_link() 增加一次性 hold-down 逻辑 保证主循环至少看到一次 link-down,从而触发 app 层 stop/start 回收重建
Drivers/CH390/ch390_runtime.c TX-timeout 与 health-check 两条 reset 路径统一传入 netif 让两类恢复路径都走同一套 MAC 重同步与链路重建语义
Drivers/CH390/ch390_runtime.c 为 TX timeout 与 health-check 增加连续失败阈值 降低瞬时抖动导致的过度 reset 风险

当前实现语义(以源码为准)

  1. TX timeout 阈值

    • 单次判定条件:CH390_TCR.TXREQ busy-wait 持续超过 10 ms
    • 连续阈值:累计 6 次后才触发 ch390_runtime_emergency_reset()
    • 只要有一次成功发送,g_tx_consecutive_timeout 立即清零,因此该阈值针对的是连续失败,不是累计历史失败次数。
  2. health-check 阈值

    • VID 单次读到 0x0000 / 0xFFFF 并不会立即 reset。
    • 只有连续 3 次异常 VID 才触发 emergency reset。
    • g_ch390_ready == 0,则 health-check 会直接尝试 reset,不再等待 VID 连续计数。
  3. restart-pending 的单次语义

    • emergency reset 成功后会置位 restart-pending。
    • 下一次 ch390_runtime_check_link() 先强制执行一次 netif_set_link_down(),随后立即清除此标志并提前返回。
    • 该设计用于保证主循环至少看到一次有效的 logical link-down,从而沿用现有 App_StopLinksIfNeeded() / App_StartLinksIfNeeded() 路径回收并重建 TCP links。
  4. 内部计数与状态

    • g_chip_reset_count:记录 emergency reset 尝试次数,饱和递增到 0xFF
    • g_tx_consecutive_timeout:记录连续 TX busy 超时次数;成功发送或进入 reset 路径后清零。
    • health-check 连续失败计数当前与 g_link_restart_pending 共用一个状态字节的高位 nibble 存储;当 VID 恢复正常、达到 reset 阈值或 emergency reset 成功时会清零。
  5. 失败路径差异

    • 只有当 emergency reset 完成后 g_diag.id_valid 仍然有效,才会置位 restart-pending 并进入后续 app recycle 语义。
    • 若 reset 后芯片仍不响应,则仅记录失败并返回,不会伪装成可恢复状态。

预期结果

  1. CH390 发生 emergency reset 后,硬件 MAC、netif->hwaddr 与当前业务身份重新对齐。
  2. 即使物理网线始终保持连接,主循环仍会在后续 poll 中观察到一次有效 link-down,并按既有 App_StopLinksIfNeeded() / App_StartLinksIfNeeded() 路径回收并重建 TCP links。
  3. 恢复策略对瞬时异常更保守:只有连续超时或连续 VID 异常达到阈值才会触发 reset,降低误触发恢复的概率。
  4. 复位后的恢复语义与 cold init 更接近,不再停留在“芯片寄存器恢复正常,但业务流量仍死掉”的半恢复状态。

构建验证

  1. 已由现场手动执行工程构建,构建通过。
  2. 本轮修改覆盖 Drivers/CH390/ch390_runtime.cDrivers/CH390/ch390_runtime.h 与本手册记录,未改动 TCP client/server 模块对外接口。

10. 常见误区

调试当前工程时,应避免以下误区:

  1. 不要继续沿用“CH390 恒为全 0xFF”这一过时结论
  2. 不要在 main.c、IRQ、netif 多处重新插入原始 CH390 访问
  3. 不要在没有芯片脚侧证据前,只凭 MCU 侧 GPIO 判断总线正常
  4. 不要在基础寄存器读写尚不可信时,直接调高层 TCP/UART/MUX 业务逻辑
  5. 不要把一次性 bring-up 实验代码长期留在正式路径中
  6. 不要让多个本机进程同时监听板子要连接的 TCP 端口
  7. 不要在尚未证明命令已真正进入 parser 之前,直接归因到 Flash、协议或网络层

11. 推荐的现场记录模板

建议每次现场调试至少记录以下信息:

  1. 日期时间
  2. 板卡编号
  3. 固件产物路径
  4. 下载方式
  5. RTT 关键日志
  6. 串口发送内容
  7. TCP 调试工具输出
  8. 关键波形或电压量测点
  9. 结论
  10. 下一步动作

建议记录格式:

时间:
板卡:
固件:
下载方式:
操作步骤:
RTT输出:
串口/TCP现象:
硬件量测:
结论:
下一步:

12. 当前推荐的结论表达方式

若需要向项目成员同步当前状态,建议采用以下口径:

  1. 当前工程软件架构已稳定在 bare-metal + lwIP RAW + ch390_runtime 单一拥有者
  2. 当前调试重点已经从“CH390 是否完全无响应”转移到协议、链路和系统级联调
  3. 当前对外协议和配置模型应以 MUX / NET / LINK[idx] 为准
  4. USART1 配置口、USART2/3 数据口与 TCP 路由必须按最新代码路径调试,不应再参照历史 IP/MASK/GW/PORT/RIP/RPORT 公开接口模型
  5. 硬件验证仍必须以 CH390 芯片脚侧波形和供电域量测为准

13. 建议配套阅读

建议与本指导配套阅读:

  1. AT固件使用手册.md
  2. 项目技术实现.md
  3. 项目需求说明.md
  4. uart-ch390-debug-handoff.md
  5. CH390_最终结论报告.md
  6. build_keil.log
  7. PCB/SCH_Schematic1_2026-03-26.pdf
  8. tools/tcp_debug_server.py
  9. tools/start_tcp_debug_server.ps1