31a3da48fa
根因: tcp_close()将对端关闭的pcb推入TIME_WAIT(120s), 占用MEMP_TCP_PCB池(仅4个), 多连接同时断开后pcb池耗尽, tcp_new()返回NULL, 新连接无法建立直到120s超时释放。 核心修复: - tcp_server/client: 对端关闭(p=NULL)时tcp_abort替代tcp_close, pcb立即释放 - ch390_runtime: PKT_ERR恢复强制OR上RCR_RXEN(与WCH官方一致) - ch390_runtime: TX连续超时3次自动emergency reset - ch390_runtime: 每5秒health_check读VID验证芯片存活 - main: App_StartLinksIfNeeded失败时不标记g_links_started, 允许重试 - main: MUX逐帧RTT printf改为#if DEBUG门控, 减少主循环延迟 - uart_trans: MUX帧解析改为先搜0x7E再消费header, 非法帧只丢1字节
524 lines
15 KiB
Markdown
524 lines
15 KiB
Markdown
# 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/3`、`EXTI0`、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.c` 的 `App_PollUart1ConfigRx()`
|
||
- `Core/Src/stm32f1xx_it.c` 的 `HAL_UART_RxCpltCallback()`
|
||
- `App/config.c` 的 `config_uart_rx_byte()` / `config_process_at_cmd()`
|
||
2. `USART2 / USART3`
|
||
- 数据口
|
||
- 负责普通透传或 MUX 承载
|
||
- 当前入口在 `App/uart_trans.c`
|
||
|
||
---
|
||
|
||
## 4. 当前硬件与调试工具基线
|
||
|
||
### 4.1 核心硬件对象
|
||
|
||
1. MCU:`STM32F103R8T6`
|
||
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.c` 的 `Debug_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+LINK=...`
|
||
9. `AT+LINK?`
|
||
10. `AT+SAVE`
|
||
11. `AT+RESET`
|
||
12. `AT+DEFAULT`
|
||
|
||
### 6.2 现场关键规则
|
||
|
||
根据已有联调记录,配置口最关键的 bench 规则是:
|
||
|
||
1. 当前现场验证时,配置命令必须保证以换行完成帧。
|
||
2. 若主机侧发送方式不对,现象会很像“配置口完全无响应”。
|
||
3. 因此,配置口不响应时,第一优先级不是改 parser,而是先验证主机端发送格式与接线。
|
||
|
||
### 6.3 最小验证步骤
|
||
|
||
建议按以下顺序验证:
|
||
|
||
1. 连接 `USART1`
|
||
2. 先发 `AT`
|
||
3. 再发 `AT+QUERY`
|
||
4. 再发 `AT+NET?`
|
||
5. 再发 `AT+LINK?`
|
||
6. 修改一个最小参数,例如:
|
||
- `AT+MUX=1`
|
||
7. 执行:
|
||
- `AT+SAVE`
|
||
- `AT+RESET`
|
||
8. 复位后再次查询,确认配置是否保留
|
||
|
||
### 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. `NET`:IP / 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
|
||
powershell -ExecutionPolicy Bypass -File ".\tools\start_tcp_debug_server.ps1" -Port 8081 -NoStdin
|
||
```
|
||
|
||
如需回显:
|
||
|
||
```powershell
|
||
powershell -ExecutionPolicy Bypass -File ".\tools\start_tcp_debug_server.ps1" -Port 8081 -Echo
|
||
```
|
||
|
||
直接运行 Python 服务端也可以:
|
||
|
||
```powershell
|
||
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 恢复时 `rcr` → `rcr \| 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%)。
|
||
|
||
---
|
||
|
||
## 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. 下一步动作
|
||
|
||
建议记录格式:
|
||
|
||
```text
|
||
时间:
|
||
板卡:
|
||
固件:
|
||
下载方式:
|
||
操作步骤:
|
||
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`
|