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

6.8 KiB
Raw Blame History

ADDED Requirements

Requirement: 系统时间获取

qdx_port_get_tick_ms() 必须返回自系统启动以来的毫秒级单调递增时间戳,精度不低于 FreeRTOS tick 周期2ms

Scenario: 获取系统运行时间

  • WHEN 任意任务或模块调用 qdx_port_get_tick_ms()
  • THEN 返回值为基于 xTaskGetTickCount() 转换的毫秒数,且数值不会回绕至 0在 uint32_t 溢回之前)

Requirement: 任务级阻塞延时

qdx_port_delay_ms() 必须让当前 FreeRTOS 任务挂起指定毫秒数,期间让出 CPU 给其他任务。

Scenario: 延时期间 CPU 让出

  • WHEN 后台线程调用 qdx_port_delay_ms(100)
  • THEN 该任务进入阻塞态约 100ms其余就绪任务在此期间获得调度

Requirement: 互斥锁创建与操作

qdx_port_mutex_create/lock/unlock/delete 必须基于 FreeRTOS 互斥信号量实现,支持跨任务的临界区保护和优先级继承。

Scenario: 并发访问配置结构体

  • WHEN tcp_rx_c 线程正在更新 ConfigCommon_ttask_business 同时读取该结构体
  • THEN 互斥锁确保同一时刻仅一个任务可访问,防止数据撕裂

Scenario: 互斥锁删除

  • WHEN 调用 qdx_port_mutex_delete 并传入有效句柄
  • THEN FreeRTOS 信号量资源被释放,句柄失效

Requirement: 线程(任务)创建

qdx_port_thread_create 必须通过 xTaskCreate 创建 FreeRTOS 任务,并正确映射名称、入口函数、栈大小和优先级参数。

Scenario: TcpLogic_Start 创建三个后台任务

  • WHEN TcpLogic_Start() 依次调用 qdx_port_thread_create 创建 tcp_mgrtcp_rx_ctcp_rx_d
  • THEN 三个 FreeRTOS 任务被成功创建并开始调度执行

Requirement: TCP Socket 连接建立

qdx_port_tcp_connect 必须创建 WCHNET TCP socket、配置目标 IP/端口,发起连接并阻塞等待三次握手完成(或超时 5 秒返回 NULL

Scenario: 成功连接至上位机

  • WHEN 调用 qdx_port_tcp_connect("192.168.1.50", 5511) 且上位机正在监听
  • THEN WCHNET 完成 TCP 三次握手后,SINT_STAT_CONNECT 中断释放连接信号量,函数返回有效的 qdx_socket_t 句柄

Scenario: 连接超时

  • WHEN 调用 qdx_port_tcp_connect 但目标主机不可达
  • THEN 阻塞等待 5 秒后超时,释放已分配的 WCHNET socket 资源,返回 NULL

Requirement: TCP 数据发送

qdx_port_tcp_send 必须将指定缓冲区数据通过 WCHNET_SocketSend 写入 TCP 发送队列,并返回实际发送的字节数。

Scenario: 发送温度帧数据

  • WHEN TcpLogic_BuildAndSendTemperatureFrame 组装完成后调用 qdx_port_tcp_send 发送到数据流 socket
  • THEN 数据被提交至 WCHNET 发送缓冲,函数返回已发送的字节数

Scenario: 连接已断开时发送

  • WHEN 对一个已断开的 socket 调用 qdx_port_tcp_send
  • THEN 函数返回 < 0 表示错误

Requirement: TCP 数据接收(信号量阻塞模式)

qdx_port_tcp_recv 必须从 socket 关联的接收环形缓冲中读取数据。若缓冲为空,则阻塞等待信号量通知(最长 100ms 超时),超时返回 0。

Scenario: 接收上位机配置指令

  • WHEN 上位机通过 5511 端口发送配置报文WCHNET 中断触发将数据写入环形缓冲并释放信号量
  • THEN tcp_rx_c 线程从阻塞中唤醒,qdx_port_tcp_recv 返回实际读取的字节数和数据

Scenario: 无数据超时

  • WHEN 100ms 内未收到任何数据
  • THEN 函数返回 0调用方继续执行心跳或重连检查逻辑

Scenario: 对端关闭连接

  • WHEN WCHNET 检测到对端断开(SINT_STAT_DISCONNECT
  • THEN 函数返回 < 0通知调用方连接已失效

Requirement: TCP Socket 关闭

qdx_port_tcp_close 必须调用 WCHNET_SocketClose 释放 WCHNET socket 资源,清空关联的环形缓冲,并将 SocketCtx_t 标记为空闲。

Scenario: 正常关闭

  • WHEN 连接管理线程检测到超时并调用 qdx_port_tcp_close
  • THEN WCHNET socket 被关闭,环形缓冲清零,SocketCtx_t.connected = 0,该槽位可被后续连接复用

Requirement: WCHNET 协议栈周期驱动

系统必须在独立的高优先级 FreeRTOS 任务 task_wchnet 中周期调用 WCHNET_MainTask()WCHNET_HandleGlobalInt(),确保以太网帧收发和 TCP 状态机正常运转。

Scenario: 协议栈持续驱动

  • WHEN FreeRTOS 调度器启动后
  • THEN task_wchnet 以约 5~10ms 周期持续驱动 WCHNET 协议栈socket 中断事件被及时处理

Requirement: Socket 映射与上下文管理

系统必须维护静态 SocketCtx_t 数组(容量 = 2管理 WCHNET socket ID 到 qdx_socket_t 不透明句柄的映射,以及每个 socket 关联的环形接收缓冲和信号量。

Scenario: 双流同时活跃

  • WHEN 控制流 (5511) 和数据流 (5512) 同时建立连接
  • THEN 两个 SocketCtx_t 槽位被分别占用,各自拥有独立的 WCHNET socket ID、接收缓冲和信号量

Requirement: net_config.h 双 Socket 配置

WCHNET_NUM_TCP 必须从 1 修改为 2以支持控制流和数据流两个并发 TCP 连接,相关宏(WCHNET_MAX_SOCKET_NUMWCHNET_NUM_POOL_BUFWCHNET_MEM_HEAP_SIZE 等)随之联动更新。

Scenario: 两个 TCP socket 可同时创建

  • WHEN 系统初始化后依次创建控制流和数据流 socket
  • THEN 两个 WCHNET_SocketCreat 调用均成功返回不同的 socket ID

Requirement: TIM2 共享 FreeRTOS Tick 与 WCHNET Timer

TIM2 必须配置为 2ms 周期ISR 中每次调用 FreeRTOS tick handler并以软件计数器每 5 次10ms调用一次 WCHNET_TimeIsr()

Scenario: 双定时源正常工作

  • WHEN 系统运行中
  • THEN FreeRTOS 以 500Hz 频率获得 tick 中断WCHNET 以 100Hz 频率获得定时服务,两者互不干扰

Requirement: main 函数重构为 RTOS 启动模型

main() 在完成硬件初始化和 WCHNET 初始化后,必须创建 task_wchnettask_business 两个初始任务,然后调用 vTaskStartScheduler() 启动调度器,不再使用裸机 while(1) 主循环。

Scenario: 调度器启动

  • WHEN main() 完成 ETH_LibInit、DVP_Init、Preprocess_Init、TcpLogic_Init 后
  • THEN 调用 vTaskStartScheduler() 进入 RTOS 调度,所有业务逻辑在任务上下文中执行

Requirement: FreeRTOS 内核集成

TCPClient 工程必须链接 FreeRTOS 内核源文件tasks.c、queue.c、list.c、timers.c、port.c、heap_4.c和 RISC-V 移植文件,并配置 FreeRTOSConfig.h 适配 CH32V307 时钟和中断。

Scenario: 工程编译通过

  • WHEN 将 FreeRTOS 源文件和 include 路径加入 TCPClient 构建配置
  • THEN 工程编译无错误FreeRTOS API 可正常调用