5.1 KiB
5.1 KiB
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.h从prj/FreeRTOS_Core/User/复制到prj/TCPClient/User/并适配:确认configTICK_RATE_HZ=500、configTOTAL_HEAP_SIZE=12288、configCPU_CLOCK_HZ=SystemCoreClock - 1.4 更新 TCPClient 工程 makefile/构建配置,添加 FreeRTOS 源文件和 include 路径,确保编译通过
2. net_config.h 双 Socket 配置
- 2.1 修改
net_config.h中WCHNET_NUM_TCP从 1 改为 2 - 2.2 验证
WCHNET_MAX_SOCKET_NUM、WCHNET_NUM_POOL_BUF、WCHNET_NUM_TCP_SEG、WCHNET_MEM_HEAP_SIZE等联动宏自动调整正确 - 2.3 扩展
main.c中SocketRecvBuf数组尺寸为[2][RECE_BUF_LEN],socket数组为[2]
3. TIM2 重构——共享 FreeRTOS Tick 与 WCHNET Timer
- 3.1 修改
TIM2_Init将定时周期从 10ms 改为 2ms(TIM_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(基于 template),include 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:封装xSemaphoreCreateMutex、xSemaphoreTake(portMAX_DELAY)、xSemaphoreGive、vSemaphoreDelete - 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_INF(PROTO_TYPE_TCP、目标 IP/Port)→WCHNET_SocketCreat→WCHNET_SocketConnect→xSemaphoreTake(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_close:WCHNET_SocketClose(ctx->wchnet_sock_id, 0)→ 清空 rx_ring → 标记 ctx 为空闲
6. WCHNET 中断回调改造
- 6.1 修改
WCHNET_HandleSockInt的SINT_STAT_RECV分支:通过 wchnet_sock_id 查找对应 SocketCtx →WCHNET_SocketRecv读数据写入 rx_ring →xSemaphoreGive(rx_sem)通知接收线程 - 6.2 修改
SINT_STAT_CONNECT分支:查找对应 SocketCtx → 标记connected = 1→xSemaphoreGive(connect_sem)唤醒等待线程 - 6.3 修改
SINT_STAT_DISCONNECT和SINT_STAT_TIM_OUT分支:标记connected = 0→xSemaphoreGive(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)延时NGioDelayms 后在回调中拉低复位 - 8.3 初始化 NG DO GPIO 引脚为推挽输出(在 main 硬件初始化阶段添加)
9. 验证与调试
- 9.1 编译整个 TCPClient 工程,修复链接错误
- 9.2 使用
uxTaskGetStackHighWaterMark验证各任务栈余量,防止溢出 - 9.3 连接上位机测试控制流(5511)与数据流(5512)双连接建立、心跳和重连
- 9.4 触发一帧图像,验证完整链路:DVP 采集 → 触发判定 → 预处理提取 → TCP 封包发送 → 上位机收到数据
- 9.5 测试上位机下发参数更新,验证 Preprocess 参数热更新生效