## 1. 构建系统与 FreeRTOS 集成 - [x] 1.1 将 FreeRTOS 内核源文件(tasks.c、queue.c、list.c、timers.c)和内存管理(MemMang/heap_4.c)复制或链接到 TCPClient 工程目录 - [x] 1.2 将 RISC-V 移植文件(portable/GCC/RISC-V/port.c、portASM.S、portmacro.h)加入工程 - [x] 1.3 将 `FreeRTOSConfig.h` 从 `prj/FreeRTOS_Core/User/` 复制到 `prj/TCPClient/User/` 并适配:确认 `configTICK_RATE_HZ=500`、`configTOTAL_HEAP_SIZE=12288`、`configCPU_CLOCK_HZ=SystemCoreClock` - [x] 1.4 更新 TCPClient 工程 makefile/构建配置,添加 FreeRTOS 源文件和 include 路径,确保编译通过 ## 2. net_config.h 双 Socket 配置 - [x] 2.1 修改 `net_config.h` 中 `WCHNET_NUM_TCP` 从 1 改为 2 - [x] 2.2 验证 `WCHNET_MAX_SOCKET_NUM`、`WCHNET_NUM_POOL_BUF`、`WCHNET_NUM_TCP_SEG`、`WCHNET_MEM_HEAP_SIZE` 等联动宏自动调整正确 - [x] 2.3 扩展 `main.c` 中 `SocketRecvBuf` 数组尺寸为 `[2][RECE_BUF_LEN]`,`socket` 数组为 `[2]` ## 3. TIM2 重构——共享 FreeRTOS Tick 与 WCHNET Timer - [x] 3.1 修改 `TIM2_Init` 将定时周期从 10ms 改为 2ms(`TIM_Period = 2000 - 1`) - [x] 3.2 修改 `TIM2_IRQHandler`:每次调用 `xPortSysTickHandler()` 驱动 FreeRTOS tick,并用静态计数器每 5 次调用一次 `WCHNET_TimeIsr(WCHNETTIMERPERIOD)` - [x] 3.3 维护 `sys_tick_ms` 每次 +2 替代原来 +10 ## 4. qdx_port.c 核心实现——时间、延时、互斥、线程 - [x] 4.1 新建 `prj/TCPClient/Middle/QDXnetworkStack/qdx_port.c`(基于 template),include FreeRTOS headers - [x] 4.2 实现 `qdx_port_get_tick_ms()`:返回 `xTaskGetTickCount() * portTICK_PERIOD_MS` - [x] 4.3 实现 `qdx_port_delay_ms()`:调用 `vTaskDelay(pdMS_TO_TICKS(ms))` - [x] 4.4 实现 `qdx_port_mutex_create/lock/unlock/delete`:封装 `xSemaphoreCreateMutex`、`xSemaphoreTake(portMAX_DELAY)`、`xSemaphoreGive`、`vSemaphoreDelete` - [x] 4.5 实现 `qdx_port_thread_create`:调用 `xTaskCreate` 映射 name、entry、arg、stack_size、priority ## 5. qdx_port.c Socket 层实现——映射与桥接 - [x] 5.1 定义 `SocketCtx_t` 结构体(wchnet_sock_id、connected、rx_ring、rx_sem、connect_sem)和静态数组 `g_sock_ctx[2]` - [x] 5.2 实现环形缓冲 `RxRingBuf_t` 的 init/write/read/available 操作(容量 2920 字节) - [x] 5.3 实现 `qdx_port_tcp_connect`:分配空闲 SocketCtx → 填充 SOCK_INF(PROTO_TYPE_TCP、目标 IP/Port)→ `WCHNET_SocketCreat` → `WCHNET_SocketConnect` → `xSemaphoreTake(connect_sem, 5000ms)` 阻塞等待连接完成 - [x] 5.4 实现 `qdx_port_tcp_send`:校验句柄有效性 → 互斥锁保护 → `WCHNET_SocketSend(ctx->wchnet_sock_id, data, &len)` - [x] 5.5 实现 `qdx_port_tcp_recv`:检查 rx_ring 有数据直接读取返回;否则 `xSemaphoreTake(rx_sem, 100ms)` 阻塞 → 唤醒后再次检查 rx_ring → 返回数据或 0(超时)或 <0(连接断开) - [x] 5.6 实现 `qdx_port_tcp_close`:`WCHNET_SocketClose(ctx->wchnet_sock_id, 0)` → 清空 rx_ring → 标记 ctx 为空闲 ## 6. WCHNET 中断回调改造 - [x] 6.1 修改 `WCHNET_HandleSockInt` 的 `SINT_STAT_RECV` 分支:通过 wchnet_sock_id 查找对应 SocketCtx → `WCHNET_SocketRecv` 读数据写入 rx_ring → `xSemaphoreGive(rx_sem)` 通知接收线程 - [x] 6.2 修改 `SINT_STAT_CONNECT` 分支:查找对应 SocketCtx → 标记 `connected = 1` → `xSemaphoreGive(connect_sem)` 唤醒等待线程 - [x] 6.3 修改 `SINT_STAT_DISCONNECT` 和 `SINT_STAT_TIM_OUT` 分支:标记 `connected = 0` → `xSemaphoreGive(rx_sem)` 确保阻塞中的 recv 能被唤醒退出 ## 7. main.c 重构为 RTOS 多任务 - [x] 7.1 新增 `task_wchnet_entry` 函数:循环调用 `WCHNET_MainTask()` + `WCHNET_QueryGlobalInt` / `WCHNET_HandleGlobalInt`,周期约 5ms - [x] 7.2 新增 `task_business_entry` 函数:将原 `while(1)` 中的 DVP_Task + Frame 触发判定 + 预处理 + 封包发送逻辑迁入 - [x] 7.3 修改 `main()` 函数:保留硬件初始化(SystemCoreClockUpdate、USART、DVP_Init、TIM2_Init、ETH_LibInit)→ Preprocess_Init → TcpLogic_Init → TcpLogic_RegisterCallbacks → `xTaskCreate(task_wchnet)` → `xTaskCreate(task_business)` → `vTaskStartScheduler()` - [x] 7.4 删除 `main()` 中的 `while(1)` 裸机主循环 ## 8. 回调逻辑补全 - [x] 8.1 补全 `OnConfigUpdate`:内部调用 `Preprocess_Settings_Change(cfg2d, cfg1d, common)` 将新参数同步至预处理模块 - [x] 8.2 补全 `OnDetectionResult`:当 `isOK == 0` 时拉高 NG DO GPIO 引脚,启动 FreeRTOS 软件定时器(`xTimerCreate`)延时 `NGioDelay` ms 后在回调中拉低复位 - [x] 8.3 初始化 NG DO GPIO 引脚为推挽输出(在 main 硬件初始化阶段添加) ## 9. 验证与调试 - [ ] 9.1 编译整个 TCPClient 工程,修复链接错误 - [ ] 9.2 使用 `uxTaskGetStackHighWaterMark` 验证各任务栈余量,防止溢出 - [ ] 9.3 连接上位机测试控制流(5511)与数据流(5512)双连接建立、心跳和重连 - [ ] 9.4 触发一帧图像,验证完整链路:DVP 采集 → 触发判定 → 预处理提取 → TCP 封包发送 → 上位机收到数据 - [ ] 9.5 测试上位机下发参数更新,验证 Preprocess 参数热更新生效