2026-03-14 08:47:57 +08:00

5.1 KiB
Raw Blame History

1. 构建系统与 FreeRTOS 集成

  • 1.1 将 FreeRTOS 内核源文件tasks.c、queue.c、list.c、timers.c和内存管理MemMang/heap_4.c复制或链接到 TCPClient 工程目录
  • 1.2 将 RISC-V 移植文件portable/GCC/RISC-V/port.c、portASM.S、portmacro.h加入工程
  • 1.3 将 FreeRTOSConfig.hprj/FreeRTOS_Core/User/ 复制到 prj/TCPClient/User/ 并适配:确认 configTICK_RATE_HZ=500configTOTAL_HEAP_SIZE=12288configCPU_CLOCK_HZ=SystemCoreClock
  • 1.4 更新 TCPClient 工程 makefile/构建配置,添加 FreeRTOS 源文件和 include 路径,确保编译通过

2. net_config.h 双 Socket 配置

  • 2.1 修改 net_config.hWCHNET_NUM_TCP 从 1 改为 2
  • 2.2 验证 WCHNET_MAX_SOCKET_NUMWCHNET_NUM_POOL_BUFWCHNET_NUM_TCP_SEGWCHNET_MEM_HEAP_SIZE 等联动宏自动调整正确
  • 2.3 扩展 main.cSocketRecvBuf 数组尺寸为 [2][RECE_BUF_LEN]socket 数组为 [2]

3. TIM2 重构——共享 FreeRTOS Tick 与 WCHNET Timer

  • 3.1 修改 TIM2_Init 将定时周期从 10ms 改为 2msTIM_Period = 2000 - 1
  • 3.2 修改 TIM2_IRQHandler:每次调用 xPortSysTickHandler() 驱动 FreeRTOS tick并用静态计数器每 5 次调用一次 WCHNET_TimeIsr(WCHNETTIMERPERIOD)
  • 3.3 维护 sys_tick_ms 每次 +2 替代原来 +10

4. qdx_port.c 核心实现——时间、延时、互斥、线程

  • 4.1 新建 prj/TCPClient/Middle/QDXnetworkStack/qdx_port.c(基于 templateinclude FreeRTOS headers
  • 4.2 实现 qdx_port_get_tick_ms():返回 xTaskGetTickCount() * portTICK_PERIOD_MS
  • 4.3 实现 qdx_port_delay_ms():调用 vTaskDelay(pdMS_TO_TICKS(ms))
  • 4.4 实现 qdx_port_mutex_create/lock/unlock/delete:封装 xSemaphoreCreateMutexxSemaphoreTake(portMAX_DELAY)xSemaphoreGivevSemaphoreDelete
  • 4.5 实现 qdx_port_thread_create:调用 xTaskCreate 映射 name、entry、arg、stack_size、priority

5. qdx_port.c Socket 层实现——映射与桥接

  • 5.1 定义 SocketCtx_t 结构体wchnet_sock_id、connected、rx_ring、rx_sem、connect_sem和静态数组 g_sock_ctx[2]
  • 5.2 实现环形缓冲 RxRingBuf_t 的 init/write/read/available 操作(容量 2920 字节)
  • 5.3 实现 qdx_port_tcp_connect:分配空闲 SocketCtx → 填充 SOCK_INFPROTO_TYPE_TCP、目标 IP/PortWCHNET_SocketCreatWCHNET_SocketConnectxSemaphoreTake(connect_sem, 5000ms) 阻塞等待连接完成
  • 5.4 实现 qdx_port_tcp_send:校验句柄有效性 → 互斥锁保护 → WCHNET_SocketSend(ctx->wchnet_sock_id, data, &len)
  • 5.5 实现 qdx_port_tcp_recv:检查 rx_ring 有数据直接读取返回;否则 xSemaphoreTake(rx_sem, 100ms) 阻塞 → 唤醒后再次检查 rx_ring → 返回数据或 0超时或 <0连接断开
  • 5.6 实现 qdx_port_tcp_closeWCHNET_SocketClose(ctx->wchnet_sock_id, 0) → 清空 rx_ring → 标记 ctx 为空闲

6. WCHNET 中断回调改造

  • 6.1 修改 WCHNET_HandleSockIntSINT_STAT_RECV 分支:通过 wchnet_sock_id 查找对应 SocketCtx → WCHNET_SocketRecv 读数据写入 rx_ring → xSemaphoreGive(rx_sem) 通知接收线程
  • 6.2 修改 SINT_STAT_CONNECT 分支:查找对应 SocketCtx → 标记 connected = 1xSemaphoreGive(connect_sem) 唤醒等待线程
  • 6.3 修改 SINT_STAT_DISCONNECTSINT_STAT_TIM_OUT 分支:标记 connected = 0xSemaphoreGive(rx_sem) 确保阻塞中的 recv 能被唤醒退出

7. main.c 重构为 RTOS 多任务

  • 7.1 新增 task_wchnet_entry 函数:循环调用 WCHNET_MainTask() + WCHNET_QueryGlobalInt / WCHNET_HandleGlobalInt,周期约 5ms
  • 7.2 新增 task_business_entry 函数:将原 while(1) 中的 DVP_Task + Frame 触发判定 + 预处理 + 封包发送逻辑迁入
  • 7.3 修改 main() 函数保留硬件初始化SystemCoreClockUpdate、USART、DVP_Init、TIM2_Init、ETH_LibInit→ Preprocess_Init → TcpLogic_Init → TcpLogic_RegisterCallbacks → xTaskCreate(task_wchnet)xTaskCreate(task_business)vTaskStartScheduler()
  • 7.4 删除 main() 中的 while(1) 裸机主循环

8. 回调逻辑补全

  • 8.1 补全 OnConfigUpdate:内部调用 Preprocess_Settings_Change(cfg2d, cfg1d, common) 将新参数同步至预处理模块
  • 8.2 补全 OnDetectionResult:当 isOK == 0 时拉高 NG DO GPIO 引脚,启动 FreeRTOS 软件定时器(xTimerCreate)延时 NGioDelay ms 后在回调中拉低复位
  • 8.3 初始化 NG DO GPIO 引脚为推挽输出(在 main 硬件初始化阶段添加)

9. 验证与调试

  • 9.1 编译整个 TCPClient 工程,修复链接错误
  • 9.2 使用 uxTaskGetStackHighWaterMark 验证各任务栈余量,防止溢出
  • 9.3 连接上位机测试控制流(5511)与数据流(5512)双连接建立、心跳和重连
  • 9.4 触发一帧图像验证完整链路DVP 采集 → 触发判定 → 预处理提取 → TCP 封包发送 → 上位机收到数据
  • 9.5 测试上位机下发参数更新,验证 Preprocess 参数热更新生效