f849c79b7a
net_pending.c/h 增设第二张挂起表 s_net_send[](与 recv 表完全独立,收发 互不阻塞);net_send_locked 快速路径改为有界自旋,单次等待超出 NET_SEND_SPIN_MS(2ms) 即登记挂起 send,由 net_send_pending_tick 按主循环 节拍分块推进,netTask 最坏停滞由 1s 压到 2ms。net_listener_retry_tick 的 挂起保险扩展到 send 侧;net_close_locked / 网络重建 / 状态对账三路均先 取消再动作(取消必通知,调用方永不挂死)。 台架复测(A/B 对照 + 插桩定位)发现并修复末块挂起越界缺陷:内层"等本块 发完(SENBUF_FREE)"位于写块之后,写完末块时 sent 已 == len,若该次等待越过 2ms 预算便会调用 net_send_pending_register,而登记函数按 sent >= len 拒收 并回 -1,把一次实际已完整交付芯片的发送报成失败。修复为内层等待开头判 sent >= len 即跳出(末块已交付、SENBUF_FREE 等待是纯保守自旋),并置于 超时/自旋判定之前;该守卫同时保证后续登记必伴随 sent < len。 复验:ftp_regression 连续 19 次 11/11;ftp_integrity_test 20 轮 x 64KB STOR/RETR SHA-256 20/20 一致(两轮),吞吐稳定约 80KB/s;设备日志零 write error;ST-LINK 回读 No difference found。 文档:Net层阻塞模型架构设计.md 补二期设计与新增 9.1 缺陷记录,netTask 栈实测峰值按本次台架 920B 订正为 1116/3840(FTP 传输期 1164);网络自愈 架构设计.md 吸收原监听生命周期文档、新增编号术语导读表,并把 5.2 "实验锚点速查"的 E 编号含义与 E-02 审计编号歧义写在表头(用户反馈该表 E 编号无法读懂)。 门禁:Keil 0 错 0 警;cppcheck / 编码规范 / 乱码零告警; check_mem_numbers PASS;check_doc_links --all --sections-strict 142 篇 PASS。
3.9 KiB
3.9 KiB
Drivers/BSP/NET/ — 网络抽象层(BSD Socket API)
在 CH395F 硬件驱动之上提供 BSD Socket 风格 API,使上层(FTP 服务、时间同步、UI 推流) 以标准 socket 语义编程,无需关心芯片细节。核心是阻塞模型 + 事件驱动 + 周期对账自愈。
文件一览
| 文件 | 作用 |
|---|---|
net_socket.c/h |
BSD Socket API 实现:net_socket / net_connect / net_send / net_recv / net_close / net_listen / net_accept,含挂起 recv(pending)与错误码 |
net_pending.c/h |
挂起 recv / send 请求表(阻塞挂起模型:登记 / 每轮完成检查(recv)/ 推进(send)/ 取消 / close 结算;真机专属,模拟器走 net_socket_sim.c) |
net_select.c/h |
select/poll 多路复用(基于芯片中断事件 + 周期轮询) |
net_types.h |
网络层公共类型定义 |
net_config.h |
网络层编译期配置(缓冲区大小、超时、对账周期等) |
lftpd/ |
轻量 FTP 服务器(第三方移植,见其子目录) |
核心机制
阻塞模型(挂起 recv / send / pending)
- 一期(RECV)已落地:
net_recv等支持带超时的阻塞(pending挂起 + tick 唤醒) - 二期(SEND)已落地:
net_send快路径有界自旋(NET_SEND_SPIN_MS= 2ms),超预算登记 挂起 send,由net_send_pending_tick按主循环节拍分块推进;netTask 最坏停滞由 1s 压到 2ms - 二期(ACCEPT)待做 →
docs/任务规划/登记簿.mdN-4 - 架构细节:
docs/网络/Net层阻塞模型架构设计.md
周期对账自愈(TRAP-NET-17 修复;自愈收敛阶段 3 合并 pump)
net_reconcile_tick()(100ms,自愈收敛阶段 3 起判据读驱动状态缓存——唯一 刷新点net_poll每轮全量刷新,E2 实测单次回读 18.1us)修正失同步: 本层 ESTABLISHED 而芯片已断 → 断开;本层 LISTENING 而芯片已握手 → 补 accept; 本层 LISTENING/CLOSED(监听型 fd)而芯片监听消失 → 重建(原 pump③④); 本层 CLOSED 而芯片在听 → 只重同步(U11);芯片静默回收 → RESYNC(⑤)- 分级去抖(②=1 轮 / ③④⑤=2 轮 / ①=4 轮)+ 冷却(1s)——监听失位的重建
动作必须去抖,否则"刚 listen 未生效"瞬态会反复重建直至
relisten retry budget exhausted(三监听口全死);①的 4 轮窗是 F-NET-17 M3 可疑电平的让位租约(勿改小)
异常复监听隔离(TRAP-NET-18 修复)
- 异常释放(TIMEOUT)的 socket 复监听前隔离:排空 RX 残渣 + 主动 close + 等 CLOSED
- 400ms 起、800ms 上限强制放行(上限须 < 重试放弃时限 2000ms)
- 仅异常路径生效,正常 FIN 路径零改动
错误码(E-03 修复)
- 按任务隔离:
s_net_errno_slots[8](每槽{任务句柄, err}),替代原全局s_net_errno net_get_errno()只读本任务槽位,对外语义不变(成功不清零)
依赖关系
上层(FTP / timeSync / UI 推流)
↓ BSD Socket API
net_socket.c ←→ net_select.c
↓ ch395f_* 接口
Drivers/BSP/CH395F/
⚠️ 改本模块前必读
- 就绪屏障位(
SYS_EVT_NET_READY等)等待必须osFlagsNoClear,不能用默认消费型 - 每次 CH395F SPI 事务须
ch395f_spi_begin()/end()包裹 - 改任何自愈/重建逻辑必须去抖,否则会引发重建风暴
- 相关陷阱:
docs/问题记录/CH395F_Trap_Records.mdTRAP-NET-17/-18
相关文档
- 上层用法:
docs/网络/BSD_Socket_API_使用指南.md - 内部调用关系:
docs/网络/BSD_Socket_API_函数调用关系.md - 架构设计:
docs/网络/Net层阻塞模型架构设计.md(阻塞等待 / pending 请求模型) - 二期设计基线:
docs/任务规划/基线与待确认.md§2.1 - 测试:
docs/测试说明/CH395F_Test_Guide.md、docs/测试说明/FTP_Test_Guide.md