---
tags: []
aliases:
- "**前端感知系统通信协议 (ICD) V2.1**"
date created: 星期一, 十二月 8日 2025, 9:01:09 上午
date modified: 星期一, 十二月 8日 2025, 6:08:02 晚上
---
# **前端感知系统通信协议 (ICD) V2.1**
文档编号: FES-SW-ICD-002
版本: V2.1 (Integer-Only + TaskID + ACK/Status Clarified)
说明:版本以本页“版本”字段为准;文档编号用于配置管理索引,不随次版本必然变化。
适用架构: Host (CPU/GPU) <-> Device (Pure Logic FPGA)
物理链路: 10Gbps Ethernet (UDP/IP)
---
## **0. 设计变更与迁移指南 (Design Change Log)**
### **0.1 变更综述 (Executive Summary)**
V2.0/2.1 协议并非 V0.1 的简单增量更新,而是基于 **“软件定义雷达 (SDR)”** 与 **“异构计算适配 (Heterogeneous Computing)”** 理念的架构级重构。本次迭代的核心目标是解决 V0.1 在**高带宽吞吐瓶颈**、**软硬件强耦合**及**可靠性机制缺失**三大方面的系统性缺陷。
V2.0 引入了 **RFC 标准化报文头**、**混合对齐策略**、**微单位整数物理层**以及 **RMA 维护通道**,确保系统能够支撑 10Gbps 线速传输,并具备向后兼容的长期演进能力。
V2.1 在 V2.0 的基础上补齐了 **Status/ACK 报文规范**,明确 **SeqID 的作用域(按流递增,非全局)**,并引入 **TaskID** 以支持并发多任务(多 CPI/Pulse 流交错)。同时将控制/数据关键物理量字段统一为 **整数/微单位整数**,以满足“FPGA 只能处理整数”的实现约束。
### **0.2 详细变更对照表**
#### **1. 架构与拓扑设计 (Architecture & Topology)**
|**变更维度**|**V0.1 / V1.0 (Legacy)**|**V2.0 (Current)**|**设计动机与技术收益**|
|---|---|---|---|
|**拓扑依赖**|**强耦合 (IP Binding)**
依赖 IP 地址 (`192.168.0.x`) 区分阵面。|**完全解耦 (Logical SourceID)**
新增 `SourceID` 字段,支持 DHCP 及动态组网。|支持即插即用,离线数据分析(pcap)无需依赖环境 IP 表。|
|**传输单元**|**MTU 1500 (Standard)**
未明确定义,默认为标准帧。|**MTU 9000 (Jumbo Frame)**
强烈推荐开启巨型帧,且必须兼容 MTU 1500 运行。|在吞吐与部署兼容性之间平衡:优先保证可达与稳定运行,Jumbo 作为性能增强项。|
|**维护通道**|**无 (None)**
仅支持预定义命令。|**RMA Protocol**
引入 `OpCode 0xFF`,支持内存/寄存器直接读写。|实现波形文件的动态下载与任意寄存器的带外调试,无需修改协议固件。|
#### **2. 数据结构与内存布局 (Data Structure & Memory)**
|**变更维度**|**V0.1 / V1.0 (Legacy)**|**V2.0 (Current)**|**设计动机与技术收益**|
|---|---|---|---|
|**报文头对齐**|**非对齐 (15 Bytes)**
奇数长度头部,导致 Payload 内存错位。|**自然对齐 (32 Bytes)**
强制 8 字节对齐,填充至 Cache Line 边界。|适配 FPGA 256-bit 总线与 CPU AVX 指令集,实现零拷贝 (Zero-Copy) DMA。|
|**字节对齐**|**1-Byte Packed**
紧凑排列,无填充。|**Hybrid Alignment (混合策略)**
控制面紧凑,数据面/关键字段强制对齐。|在节省带宽与降低 CPU 访问开销(避免非对齐异常)之间取得最佳平衡。|
|**校验算法**|**XOR / Sum**
抗干扰能力弱,无法检测双位翻转。|**CRC-32C (Castagnoli)**
硬件加速指令级校验。|极大地降低漏检率,特别是在雷达高功率发射环境下的突发误码检测。|
|**扩展性**|**无预留**
新增字段需破坏现有结构。|**预留保留区 (Reserved)**
控制面预留 56 字节,且置于 CRC 保护下。|确保协议升级时旧版固件不崩溃,支持向后兼容。|
#### **3. 物理量定义与精度 (Physics & Precision)**
|**变更维度**|**V0.1 / V1.0 (Legacy)**|**V2.0 (Current)**|**设计动机与技术收益**|
|---|---|---|---|
|**频率定义**|**索引码 (uint8)**
`0=15.5GHz`, Step=10MHz。
范围锁定,无法捷变。|**绝对物理值 (uint64)**
单位:Hz。
例:`15,500,000,000`。|**解耦硬件**:支持任意波段(Ku/Ka)、任意步进的频率捷变与抗干扰策略。|
|**角度定义**|**量化整数 (int16)**
LSB=0.0025°。< br>存在量化噪声,GPU 需转换。|**微单位整数 / 浮点接口**
传输层:`int32` ($\mu^\circ$)。
应用层:`double` (Deg)。|**消除量化误差**:精度提升至 $10^{-6}$ 度,满足 AI 波束成形算法的高精度需求。|
|**增益控制**|**量化步进 (uint16)**
LSB=0.5dB。
依赖硬件非线性特性。|**物理增益 (int32)**
单位:mdB。
FPGA 查表映射。|**算法闭环**:后端直接下发期望增益,底层自动校准,简化业务逻辑。|
|**回波归一化**|**无 (None)**
仅传 ADC 原始值 (Int16)。
后端无法计算 RCS。|**Scale Factor (int32 微单位)**
随包下发物理归一化因子(整数微单位)。|**数据自描述**:GPU 可直接还原真实电压/功率,无需同步查询增益状态,且 FPGA 侧不需要浮点。|
#### **4. 可靠性与时序控制 (Reliability & Timing)**
|**变更维度**|**V0.1 / V1.0 (Legacy)**|**V2.0 (Current)**|**设计动机与技术收益**|
|---|---|---|---|
|**幂等性**|**缺失**
ACK 丢包会导致指令重复执行(如电机步进 2 次)。|**SeqID 去重**
FPGA 缓存 `Last_SeqID`,重复包仅回 ACK 不执行。|**防止状态过冲**:确保控制指令在不可靠网络下的绝对确定性执行。|
|**超时策略**|**激进 (未定义/短)**
易受 OS 调度抖动影响触发重传。|**宽松 (20ms)**
适配 Windows/Linux 非实时核调度。|**减少网络风暴**:避免因系统卡顿导致的虚假超时与不必要的重传。|
|**丢包处理**|**无规范**
直接拼接或补零。|**相干补零 (Coherent Zero-Pad)**
严格补复数零 ($0+j0$)。|**保障信号完整性**:防止时域数据缺失导致的脉冲压缩相位错位与测距误差。|
|**自闭环调度**|**开环 (Open Loop)**
发多少脉冲依赖“停止”指令。|**Pulse Count (自闭环)**
指令携带脉冲数,FPGA 计数自动停止。|**消除网络延迟风险**:防止因网络拥塞导致的发射机“长发”事故。|
#### **5. 字段级优化细节 (Field Optimization)**
- **废弃 (Deprecated)**: `Bit-fields` (位域) —— 调试困难,易引发竞态条件。V2.0 全面改为 `uint8` 枚举。
- **废弃 (Deprecated)**: `FreqCode` (频率码) —— 扩展性极差。
- **新增 (New)**: `Token` (事务令牌) —— 支持异步非阻塞驱动模型(主要用于 RMA)。
- **新增 (New)**: `TaskID` (任务标识) —— 支持并发多任务/多 CPI 流交错传输与无歧义重组。
- **新增 (New)**: `ADC Status` (状态字) —— 实时标记饱和与链路质量。
- **新增 (New)**: `Sample Offset` (采样偏移) —— 支持超长脉冲乱序重组。
---
## **1. 总则与约束 (General Provisions)**
### **1.1 协议设计哲学:微单位整数 (Micro-Unit Integer)**
为兼顾后端算法(SPS)对高精度的需求与前端硬件(FPGA)对整数运算的偏好,V2.x 协议废弃了 V1.0 中低精度的量化因子(如 0.0025° LSB),也放弃了早期草案中激进的 IEEE 754 浮点直传方案,转而采用工业界成熟的 **“微单位整数 (Micro-Unit Integer)”** 策略。
- **后端视角(高精度)**:软件驱动层负责将物理浮点数无损转换为微小单位的整数(例如将 $45.123456^\circ$ 转换为 $45,123,456$)。这一精度($10^{-6}$ 量级)远超物理硬件极限,确保了数据在传输层不引入任何不可忽略的量化噪声。
- **前端视角(纯整数)**:FPGA 将所有字段视为标准的定点整数(Integer),无需消耗逻辑资源去实现浮点运算单元(FPU)。波束解算与相位控制将全部通过高效的整数位移与乘加运算完成。
### **1.2 物理量数据类型定义**
所有控制指令中的物理量必须遵循以下严格的类型与单位定义:
|**物理量分类**|**协议数据类型**|**基础单位 (Unit)**|**换算公式 (Software View)**|**FPGA 处理逻辑**|**示例**|
|---|---|---|---|---|---|
|**频率 (Freq)**|`uint64`|**Hz** (赫兹)|$Val_{phy} = Val_{raw}$|直接写入 DDS 频率控制字 (FCW)|15.5GHz $\to$ `15,500,000,000`|
|**角度 (Angle)**|`int32`|**$\mu^\circ$** (微度)|$Val_{phy} = Val_{raw} \times 10^{-6}$|整数乘法 + 移位计算移相器状态|45.0° $\to$ `45,000,000`|
|**增益 (Gain)**|`int32`|**mdB** (毫分贝)|$Val_{phy} = Val_{raw} \times 10^{-3}$|查表 (LUT) 映射衰减器电压|30.5dB $\to$ `30,500`|
|**时间 (Time)**|`uint64`|**ns** (纳秒)|$Val_{phy} = Val_{raw} \times 10^{-9}$ (sec)|直接与 PTP 计数器比较|1 秒 $\to$ `1,000,000,000`|
|**带宽 (BW)**|`uint64`|**Hz** (赫兹)|$Val_{phy} = Val_{raw}$|用于配置 DDC 抽取率|100MHz $\to$ `100,000,000`|
### **1.3 基础架构约束**
- **适配器模式 (Adapter Pattern)**:
- SPS 主机端的驱动层必须实现 **“物理量 $\leftrightarrow$ 微单位整数”** 的透明转换层。
- 上层算法业务代码应始终操作 `double` 或 `float` 类型的物理值,严禁在业务逻辑中直接硬编码整数魔数。
- **字节序 (Endianness)**:
- 统一采用 **Little-Endian (小端模式)**,符合 x86 主机与大多数 ARM/FPGA 软核的内存布局习惯。
- **物理链路与 MTU**:
- 物理层:10Gbps SFP+ 光纤以太网。
- 传输层:UDP/IP (IPv4)。
- MTU:**强烈推荐**开启 **Jumbo Frames (9000 Bytes)**,以降低高带宽回波数据传输时的 CPU 中断频率。
- **兼容性要求(必须)**:系统必须支持在 **MTU 1500** 的网络环境中运行,协议语义保持不变(仅表现为数据平面分片包数量增加)。
- **分片实现要求(必须)**:发送端必须在**应用层**根据路径 MTU 进行切包,禁止依赖 IP 层分片(IP fragmentation)。
- **部署建议**:若网络设备/网卡/虚拟化环境无法开启 Jumbo,则应优先保证链路可达与稳定运行,再通过提升接收端并行度与缓冲区(例如增大 socket 接收缓冲)抵消分片增多带来的开销。
### **1.4 混合对齐策略 (Hybrid Alignment)**
为平衡传输带宽与处理效率,协议在不同平面采用不同的对齐策略:
1. **控制平面 (SPS $\to$ DACS)**:
- 采用 **1-Byte Packed (紧凑模式)**。
- **理由**:控制指令数据量小,FPGA 解析状态机(FSM)处理逐字节提取(Shift-Register)非常高效,且无需关心 CPU 的缓存行对齐问题。
2. **数据平面 (DACS $\to$ SPS)**:
- 采用 **8-Byte Natural Alignment (自然对齐)**。
- **理由**:高通量回波数据必须适配主机 CPU/GPU 的内存访问特性。数据包头(Header)将填充至 Cache Line 边界,确保后续的原始 I/Q 载荷(Payload)起始地址严格对齐,从而支持 **Zero-Copy DMA** 和 **GPU Direct Storage** 技术。
---
## **2. 通用报文头 (Common Header)**
设计原则:
所有 UDP 报文(包括控制、状态、回波数据及 RMA 维护包)均强制包含此标准头。该头部长度严格固定为 32 Bytes (256 bits),且内部关键字段均按 8-Byte 自然对齐 排列。这一设计不仅适配 64 位 CPU 的内存访问特性,更完美契合 FPGA 内部常见的 256-bit AXI-Stream 数据总线,确保硬件解析实现“零填充、零移位”的高效处理。
### **2.1 报文头结构定义**
| **偏移 (Offset)** | **字段名 (Field Name)** | **数据类型** | **说明与约束** |
| --------------- | -------------------- | ---------- | --------------------------------------------------------------------------------------------------------------------------------------------- |
| **0** | **Magic Word** | `uint32` | 协议同步魔数,固定为 **`0x55AA55AA`**。
用于从二进制流中快速定位帧首,防止滑窗错误。 |
| **4** | **SeqID** | `uint32` | **按流递增的包序列号**(非全局)。
递增作用域:**(SourceID, PacketType, Direction)** 组成的一条逻辑流。接收端用于丢包检测与乱序重排。 |
| **8** | **Timestamp** | `uint64` | **PTP 纳秒时间戳**。
统一使用 Unix Epoch (1970-01-01 00:00:00 ns),用于全系统时序对齐。 |
| **16** | **PayloadLen** | `uint16` | 后续载荷 (Payload) 的有效字节长度。
不包含本 Header 的 32 字节。 |
| **18** | **PacketType** | `uint16` | 报文类型标识:
`0x01`: Control (控制指令)
`0x02`: Status (状态遥测)
`0x03`: Data (回波数据)
`0xFF`: RMA (维护通道) |
| **20** | **ProtoVer** | `uint8` | **协议版本号**。
高 4 位为主版本,低 4 位为次版本。
当前 V2.1 对应 **`0x21`**(V2.0 为 `0x20`)。 |
| **21** | **SourceID** | `uint8` | **源设备逻辑 ID** (拓扑解耦的关键)。
`0x01`: SPS (主控)
`0x10`: DACS-Broadcast
`0x11`~`0x1F`: DACS-Unicast |
| **22** | **FrameFlags** | `uint16` | **分帧标志位 (Bitmask)**。
用于处理跨 UDP 包的巨型数据帧重组。
`Bit0`: **SOF** (Start of Frame)
`Bit1`: **EOF** (End of Frame)
`Bit2-15`: Reserved (0) |
| **24** | **Reserved** | `uint8[8]` | **对齐填充**。
必须全填 `0x00`。确保 Header 总长为 32 字节,且后续 Payload 起始地址满足 8 字节对齐。 |
---
### 2.2 内存布局图解 (Memory Layout)
```plaintext
| 0 1 2 3 | 4 5 6 7 | (Byte Offset)
+-----------------------------+-----------------------------+
| Magic Word | Seq ID |
+-----------------------------+-----------------------------+
| Timestamp (Lo) |
+-----------------------------+-----------------------------+
| Timestamp (Hi) |
+-----------------------------+-----------------------------+
| PayloadLen | PacketType | Ver | SrcID | FrameFlags | <--- 紧凑信息区
+-----------------------------+-----------------------------+
| Reserved (8 Bytes) |
+-----------------------------+-----------------------------+
```
### **2.3 关键字段语义详解**
#### **2.3.0 SeqID 作用域与回绕处理(必须)**
- **Direction 的定义**:本协议中 `Direction` 为“**报文在系统角色维度上的单向方向**”,由 `PacketType` 与系统角色隐含确定:
- Control(`0x01`):SPS → DACS
- Data(`0x03`):DACS → SPS
- Status/ACK(`0x02`):通常为 DACS → SPS(对 Control/RMA 的确认与遥测);若实现需要也可 SPS → DACS 发送 Telemetry/Keepalive,但必须使用独立的 SeqID 流。
- RMA(`0xFF`):双向(SPS ↔ DACS),两方向必须视为两条独立 SeqID 流。
- **回绕(Wraparound)处理(必须)**:`SeqID` 为 32-bit 无符号计数器,比较必须采用模 $2^{32}$ 的“半区间”规则,禁止用简单的 `>` 直接比较(避免回绕后误判)。定义:
- 令 $\Delta = (SeqID_{new} - SeqID_{last})\bmod 2^{32}$(以 `uint32` 自然溢出实现)。
- 当 $0 < \Delta < 2^{31}$ 时,判定为 **新包**。
- 当 $\Delta = 0$ 时,判定为 **重复包**。
- 当 $2^{31} \le \Delta < 2^{32}$ 时,判定为 **旧包/乱序包**。
- **建议实现**:FPGA/软件统一采用上述规则,确保在 `SeqID` 发生回绕时依然能保持幂等与去重正确性。
#### **2.3.1 版本控制 (ProtoVer) —— 解决“协议锁死”**
- **机制**:接收端解析器首先检查 `ProtoVer`。
- 若 `ProtoVer == 本地版本`:正常全速解析。
- 若 `ProtoVer > 本地版本`:进入兼容模式或报错,防止将新版新增字段误读为乱码,避免未定义的行为(Undefined Behavior)。
- **优势**:支持全系统的灰度发布。例如,SPS 可以先升级到 V2.1,同时兼容旧版 V2.0 的 DACS 硬件,无需强制停机全网升级。
#### **2.3.2 源标识 (SourceID) —— 解决“拓扑依赖”**
- **机制**:彻底解耦 IP 地址。SPS 接收逻辑不再依赖 `src_ip` 进行设备区分。
- **ID 分配表**:
- `0x01`: Signal Processing System (SPS)
- `0x11`: DACS - Array 01 (Front)
- `0x12`: DACS - Array 02 (Left)
- `0x13`: DACS - Array 03 (Right)
- **优势**:
- **离线分析**:在 Wireshark 脱机分析(pcap 回放)时,即使没有 IP 环境信息,也能精确识别数据来源。
- **动态部署**:支持 DHCP 环境下的即插即用,硬件更换无需重新绑定 IP。
#### **2.3.3 帧标志 (FrameFlags) —— 解决“数据拼图”**
- **背景**:一个完整的相干处理间隔(CPI)回波数据可能高达数 MB,远超 UDP MTU(1500/9000 Bytes),必须拆分为多个 UDP 包传输。
- **逻辑定义**:
- **单包帧 (Single Packet)**: 数据很小,一个包发完。
- 设置 `SOF=1`, `EOF=1`。
- **多包帧 - 首包 (First Packet)**:
- 设置 `SOF=1`, `EOF=0`。
- **多包帧 - 中间包 (Middle Packet)**:
- 设置 `SOF=0`, `EOF=0`。
- **多包帧 - 尾包 (Last Packet)**:
- 设置 `SOF=0`, `EOF=1`。
- **优势**:接收端无需解析 Payload 内容即可在链路层判断帧边界,并能快速发现“帧内丢包/截断”。对于 Data 包,接收端应优先按 6.3 执行相干补零以保持时间轴;对于 Control/RMA 包,校验失败/缺失则由超时重传机制闭环处理。
---
## **3. 控制平面 (Control Plane)**
方向: Signal Processing System (SPS) $\to$ Data Acquisition Control System (DACS)
协议: UDP Unicast
端口: 20000 (Base Port) + DACS_ID
报文总长: 固定 160 Bytes (32 Bytes Common Header + 128 Bytes Control Payload)
### **3.0 端口与阵面映射约定**
- 服务器侧通过 4 口 10GbE 采集卡接入,其中 3 口分别对应 3 个阵面数据口。
- `DACS_ID` 取值范围:`1..3`(阵面编号)。
- `SourceID` 与 `DACS_ID` 映射(固定约定):
- `DACS_ID=1` -> `SourceID=0x11`(Array 01 / Front)
- `DACS_ID=2` -> `SourceID=0x12`(Array 02 / Left)
- `DACS_ID=3` -> `SourceID=0x13`(Array 03 / Right)
广播约定(必须):
- `SourceID=0x10 (DACS-Broadcast)` 为广播语义保留 ID。
- 本版本中,广播仅用于 **控制平面下行(SPS → DACS)** 的“同参同步”场景:SPS 可向 UDP 目的端口 **20000(Base Port)** 发送一份控制指令,DACS 侧必须同时监听 **20000(广播端口)** 与 **20000 + DACS_ID(单播端口)**。
- DACS 对广播控制指令的 Status/ACK 响应必须使用各自的单播 `SourceID=0x11..0x13` 回传,禁止使用 `0x10` 回传。
- 数据平面(30000+ID)与 RMA(40000+ID)不定义广播语义。
### **3.1 设计约束**
1. **整数/微整数 (Integer-Only)**: 控制面所有关键物理量字段均采用 `int32/uint32/uint64` 等整数表达(角度使用 $\mu^\circ$,增益使用 mdB)。FPGA 侧无需、也不允许实现 IEEE 754 浮点解析与运算。
2. **偏移稳定 (Offset-Stable)**: 为减少固件改动风险,本版本尽量保持 `Center Freq` 等关键 `uint64` 字段偏移不变;在角度字段之间使用显式保留字以保持对齐与兼容。
3. **末尾校验 (Tail Checksum)**: 校验字段 `CRC32C` 固定在载荷最末尾(Offset 124)。该字段用于对**整个 UDP 载荷**进行完整性校验(见 6.4 统一 CRC 覆盖规则)。
4. **自闭环调度**: 引入 `Pulse Count` 字段。FPGA 收到指令后,将严格执行指定数量的脉冲发射,完成后自动停止发射并转入空闲状态,消除因网络延迟导致的波束过时或“长发”风险。
5. **并发任务 (TaskID)**: 为支持“并发多任务”(多个 CPI/Pulse 流交错),控制面下发 `TaskID`,数据面回传同一 `TaskID` 以实现无歧义重组。
### **3.2 载荷定义 (Control Payload)**
|**相对偏移 (Offset)**|**字段名 (Field Name)**|**数据类型**|**单位 (Unit)**|**说明与物理定义**|
|---|---|---|---|---|
|**0**|**Command Mode**|`uint8`|-|**工作模式**。
`0`: Standby (待机/静默)
`1`: Search (搜索)
`2`: Track (跟踪)
`3`: Calibrate (内/外校准)|
|**1**|**Waveform ID**|`uint8`|Index|**基础波形索引**。
指向 FPGA 内部 DDR 预存的波形表(如 LFM 基带数据)。|
|**2**|**Reserved_Pad**|`uint8[2]`|-|**对齐填充**。
必须填 `0x00`。确保后续 `Azimuth` 从 Offset 4 开始。|
|**4**|**Azimuth_uDeg**|`int32`|**$\mu^\circ$**|**方位角 ($\theta$)**。范围 `[-90°, 90°]`。软件换算:$\theta[deg] = Val_{raw} \times 10^{-6}$。|
|**8**|**Reserved_AnglePad0**|`uint32`|-|**对齐保留**(必须为 0)。用于保持后续字段偏移稳定并便于硬件解析。|
|**12**|**Elevation_uDeg**|`int32`|**$\mu^\circ$**|**俯仰角 ($\phi$)**。范围 `[-90°, 90°]`。软件换算:$\phi[deg] = Val_{raw} \times 10^{-6}$。|
|**16**|**Reserved_AnglePad1**|`uint32`|-|**对齐保留**(必须为 0)。|
|**20**|**Center Freq**|`uint64`|**Hz**|**载波中心频率**。
绝对物理值(如 `15,500,000,000`),直接控制本振 (LO)。|
|**28**|**Bandwidth**|`uint64`|**Hz**|**信号瞬时带宽**。
用于配置接收机 DDC 滤波器的抽取率与带宽。|
|**36**|**Pulse Width**|`uint32`|**ns**|**脉冲宽度 ($\tau$)**。
发射波形的有效持续时间,决定雷达盲区与平均功率。|
|**40**|**PRF**|`uint32`|**Hz**|**脉冲重复频率**。
决定最大无模糊距离。|
|**44**|**Sample Points**|`uint32`|Count|**快拍数 (Range Gates)**。
单次脉冲回波的 ADC 采样点数(如 4096)。|
|**48**|**Pulse Count**|`uint32`|Count|**驻留脉冲数 ($N_{cpi}$)**。
本次 CPI 包含的脉冲总数。FPGA 计数达到此值后自动停止。|
|**52**|**GainTarget_mdB**|`int32`|**mdB**|**期望增益**。软件换算:$G[dB] = Val_{raw} \times 10^{-3}$。DACS 通过 LUT/标定表映射为模拟衰减/增益控制量。|
|**56**|**Wave_Param1**|`uint32`|-|**波形动态参数 1**。
例如 LFM 的调频斜率 (Slope) 或相位编码的初相。|
|**60**|**Wave_Param2**|`uint32`|-|**波形动态参数 2**。
预留给特定波形的高级控制参数。|
|**64**|**TaskID**|`uint32`|-|**并发任务标识**。由 SPS 分配(建议单调递增或随机非零)。用于区分同一时刻交错的多 CPI 流。|
|**68**|**Reserved**|`uint8[56]`|-|**扩展保留区**。
必须全填 `0x00`。**处于 CRC 保护之下**。|
|**124**|**CRC32C**|`uint32`|-|**完整性校验**。
算法:CRC-32C (Castagnoli)。
覆盖范围:`Common Header + Control Payload (不含 CRC 字段本身)`(详见 6.4)。|
---
### **3.3 内存布局图解 (Memory Layout)**
为了满足底层驱动开发(Driver Development)与 FPGA 逻辑校验的需求,本节提供载荷的**RFC 标准比特视图**与**Mermaid 现代化视图**。所有多字节字段(`uint16` / `uint32` / `uint64`)均遵循 **Little-Endian (小端序)** 排列。
#### **3.3.1 RFC 标准比特视图 (Bit-Level View)**
此视图主要用于核对字节偏移量(Offset)与字边界(Word Boundary)。每行代表 32-bit (4 Bytes),左侧为起始偏移量。
```Plaintext
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Command Mode | Waveform ID | Reserved_Pad (0x0000) | 0x00
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Azimuth_uDeg (int32) | 0x04
| Reserved_AnglePad0 (uint32=0) | 0x08
| Elevation_uDeg (int32) | 0x0C
| Reserved_AnglePad1 (uint32=0) | 0x10
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Center Freq (uint64) | 0x14
+ +
| (8 Bytes Total) | 0x18
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Bandwidth (uint64) | 0x1C
+ +
| (8 Bytes Total) | 0x20
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Pulse Width (uint32) | PRF (uint32) | 0x24 / 0x28
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Sample Points (uint32) | Pulse Count (uint32) | 0x2C / 0x30
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| GainTarget_mdB (int32) | Wave_Param1 (uint32) | 0x34 / 0x38
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Wave_Param2 (uint32) | TaskID (uint32) | 0x3C / 0x40
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| |
/ Reserved (Total 56 Bytes) /
| |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| CRC32C (End) | 0x7C
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
```
#### **3.3.2 可视化布局 (Mermaid Packet)**
此视图直观展示了字段在 32-bit 宽度下的连续性,重点体现了 **Reserved_Pad** 带来的对齐效果。
```mermaid
packet-beta
title 128-Byte Radar Payload (32-bit Width)
0-7: "Cmd Mode (u8)"
8-15: "Wave ID (u8)"
16-31: "Reserved_Pad (u16)"
32-63: "Azimuth_uDeg (i32)"
64-95: "Pad0 (u32=0)"
96-127: "Elevation_uDeg (i32)"
128-159: "Pad1 (u32=0)"
160-223: "Center Freq (u64)"
224-287: "Bandwidth (u64)"
288-319: "Pulse Width (u32)"
320-351: "PRF (u32)"
352-383: "Sample Points (u32)"
384-415: "Pulse Count (u32)"
416-447: "GainTarget_mdB (i32)"
448-479: "Wave_Param1 (u32)"
480-511: "Wave_Param2 (u32)"
512-543: "TaskID (u32)"
544-991: "Reserved (56 Bytes)"
992-1023: "CRC32C"
```
#### **3.3.3 逻辑功能框图 (Functional Block)**
此视图按照业务逻辑对字段进行分组,便于上层应用开发理解各参数的物理归属。
```mermaid
block-beta
columns 4
block:header:4
CMD["Cmd (u8)"] ID["ID (u8)"] PAD["Pad (u16)"]
end
block:angles:4
AZ["Azimuth_uDeg (i32)"] PAD0["Pad0 (u32=0)"] EL["Elevation_uDeg (i32)"] PAD1["Pad1 (u32=0)"]
end
block:rf:4
FREQ["Center Freq (u64 - 8B)"]:2 BW["Bandwidth (u64 - 8B)"]:2
end
PW["PulseWidth (u32)"] PRF["PRF (u32)"] SAM["Samples (u32)"] CNT["PulseCount (u32)"]
GAIN["Gain_mdB (i32)"] P1["Param1 (u32)"] P2["Param2 (u32)"] TID["TaskID (u32)"]
block:footer:4
RES_BODY["…Reserved (56 Bytes)…"]:3 CRC["CRC32C"]:1
end
style PAD fill:#f9f,stroke:#333,stroke-dasharray: 5 5
style CRC fill:#f96,stroke:#333,stroke-width:2px
style AZ fill:#bbf
style EL fill:#bbf
```
#### **3.3.4 关键字段说明**
- **对齐填充 (`Reserved_Pad`)**:
- **位置**: Offset 2-3 (2 Bytes)。
- **作用**: 强制将当前的写入指针推移至 Offset 4,使后续字段保持偏移稳定并对齐友好。
- **值约束**: 必须填 `0x0000`。
- **物理量整数编码 (`Azimuth_uDeg` / `Elevation_uDeg` / `GainTarget_mdB`)**:
- 角度采用 $\mu^\circ$(微度)整数编码,避免量化误差与 FPGA 浮点。
- 增益采用 mdB(毫分贝)整数编码,满足 0.001 dB 级别控制分辨率。
- **末尾校验 (`CRC32C`)**:
- **位置**: Offset 124 (最后 4 字节)。
- **覆盖范围**: `Common Header + Payload(不含 CRC 字段)`。
- **封闭性**: 这种设计使得整个 128 字节结构体是一个自包含的“安全胶囊”。任何对保留区的无意篡改(如内存越界写)都能被 CRC 检出。
### **3.4 ACK/Status 机制概述(必须)**
- 控制平面基于 UDP 运行,必须通过 `SeqID` 去重 + `PacketType=0x02 (Status/ACK)` 回执 + 超时重传来构建确定性闭环。
- **执行成功的唯一判据**:SPS 必须以收到的 ACK(`StatusFlags.Applied=1` 且 `ErrorCode==0`)作为“指令已执行”的判据;任何未被 ACK 确认的控制指令不得假定已生效。
- Status/ACK 的完整载荷格式定义见 **6.1.2**。
---
## **4. 数据平面 (Data Plane)**
方向: Data Acquisition Control System (DACS) $\to$ Signal Processing System (SPS)
协议: UDP Unicast
端口: 30000 (Base Port) + DACS_ID
> `DACS_ID` 与 `SourceID` 的映射规则同 3.0。
报文结构: [Common Header (32B)] + [Data Specific Header (32B)] + [Pad/Ext Area (64B)] + [RAW Payload]
### **4.1 关键设计准则**
1. **物理闭环 (Physical Scaling)**: 引入 `Scale_uV` 字段(整数微单位)。FPGA 端以整数方式计算/查表得到“每个 ADC LSB 对应的电压微伏数”。后端仅需执行 $V[\mu V] = RawInt16 \times Scale\_uV$(再乘 $10^{-6}$ 转换为 V)即可还原真实物理量。
2. **长脉冲支持 (Long Pulse)**: 引入 `Sample Offset` 字段。针对宽带 LFM 长脉冲产生的超大采样数据块(超过单帧 MTU 上限,典型为 1500/9000),通过显式的偏移量指示,确保后端能将乱序到达的 UDP 分片无误地重组到显存的正确位置。
3. **质量感知 (Quality Aware)**: 引入 `ADC Status` 字段。实时标记当前脉冲是否存在 ADC 饱和(Clipping)或链路丢数,使后端 DSP 算法能及时剔除无效数据,避免虚假目标生成。
4. **扩展保留区 (Pad/Ext Area)**: 数据专用头后固定保留 **64 Bytes** 扩展区(本版本称为 Padding)。
- V2.1 中该 64B 必须全填 `0x00`。
- 未来版本如需新增数据面头字段,必须**仅在该 64B 内扩展**,并保持“扩展区总长度仍为 64B”,从而确保 RAW Payload 的起始偏移恒为 128B(见 4.3)。
### **4.2 数据专用头 (Data Specific Header)**
该头部紧随通用报文头之后,长度固定为 **32 Bytes**。采用紧凑的布局设计,最大化信息密度。
#### **4.2.1 RFC 风格比特视图 (Bit View)**
```Plaintext
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+---------------------------------------------------------------+
| CPI Index (4B) |
+---------------------------------------------------------------+
| Pulse Index (4B) |
+---------------------------------------------------------------+
| Sample Rate (4B) |
+---------------------------------------------------------------+
| Sample Count (4B) |
+---------------------------------------------------------------+
| Sample Offset (4B) |
+---------------------------------------------------------------+
| Scale_uV (4B) |
| (int32, micro-volts per LSB) |
+---------------------------------------------------------------+
| Channel Mask | Data Type | ADC Status |
| (16 bits) | (8 bits) | (8 bits) |
+---------------------------------------------------------------+
| TaskID |
| (uint32, stream key) |
+---------------------------------------------------------------+
```
#### **4.2.2 字段语义详解**
|**相对偏移 (Offset)**|**字段名 (Field Name)**|**数据类型**|**说明与业务逻辑**|
|---|---|---|---|
|**0**|**CPI Index**|`uint32`|**相干处理间隔索引**。
宏观时间计数,标识当前数据属于哪一次波束驻留任务。|
|**4**|**Pulse Index**|`uint32`|**脉冲索引**。
微观时间计数,当前 CPI 内的第 N 个脉冲(从 0 开始)。|
|**8**|**Sample Rate**|`uint32`|**采样率 (Hz)**。
当前数据的 ADC 采样频率,用于时频变换参考。|
|**12**|**Sample Count**|`uint32`|**本包采样点数**(每通道的复数点数 N)。
设 $C$ 为通道数(等于 `Channel Mask` 中置位 bit 数),$B$ 为每个分量字节数(Int16=2,Int32=4,Float32=4),则:
- 每通道每点字节数:$BytesPerComplex = 2 \times B$(I/Q 各一份)
- 本包 Raw Payload 总字节数:$PayloadBytes = N \times C \times BytesPerComplex$
接收端必须用该公式校验 `PayloadLen` 与实际 UDP 长度,防止越界重组。|
|**16**|**Sample Offset**|`uint32`|**采样偏移量**。
指示本包数据在完整脉冲回波序列中的起始位置(点数)。
首包为 0,后续分片包以此递增。|
|**20**|**Scale_uV**|`int32`|**物理归一化因子(微单位整数)**。
单位:$\mu V / LSB$。
换算:$V[V] = RawInt16 \times Scale\_uV \times 10^{-6}$。|
|**24**|**Channel Mask**|`uint16`|**通道掩码**。
`Bit0`: $\Sigma$ (和路/主通道)
`Bit1`: $\Delta_{Az}$ (方位差)
`Bit2`: $\Delta_{El}$ (俯仰差)
`Bit3`: Aux (辅助/旁瓣对消)|
|**26**|**Data Type**|`uint8`|**数据格式类型**。
`0x00`: Int16 (I/Q 交织, 标准格式)
`0x01`: Float32 (**仅用于软件回放/仿真,不要求 FPGA 支持**)
`0x02`: Int32|
|**27**|**ADC Status**|`uint8`|**ADC 健康状态字**。
`Bit0`: CH0 Saturation (饱和告警)
`Bit1`: CH1 Saturation
`Bit7`: Link Error (SerDes 链路失锁)|
|**28**|**TaskID**|`uint32`|**并发任务标识**。与控制面 `TaskID` 一致,用于并发多任务流重组。|
### **4.3 原始载荷 (Raw Payload)**
- **布局**: 紧随 64 字节的扩展保留区(Padding/Ext Area)之后。
- **内存对齐**: 由于扩展保留区总长度固定为 64B,RAW Payload 的起始偏移恒为 $32+32+64 = 128$ 字节。这是 64-byte Cache Line 的整数倍,适配 CPU/GPU 的 DMA 突发传输要求,并为未来字段扩展提供兼容空间。
- **数据排列 (Int16 模式)**:
```Plaintext
[I0_Ch0][Q0_Ch0] [I0_Ch1][Q0_Ch1] … [I1_Ch0][Q1_Ch0] …
```
- **I/Q**: 16-bit Signed Integer (Little Endian).
- **多通道**: 按点交织 (Point-Interleaved),即先排所有通道的第 0 点,再排第 1 点。这种排列最利于 GPU SIMD 并行读取。
#### **4.3.1 Scale_uV 边界与溢出处理(必须)**
- **取值约束(必须)**:
- 当 `Data Type` 为 `0x00 (Int16)` 或 `0x02 (Int32)` 时,`Scale_uV` 表示 $\mu V/LSB$,必须为非零值。
- 当 `Data Type` 为 `0x01 (Float32)` 时,`Scale_uV` **必须填 0**,接收端必须忽略该字段。
- 推荐范围:$|Scale\_uV| \le 2^{30}$(约 $1.07\times 10^9\ \mu V/LSB$)。超出范围应视为配置/标定异常。
- **主机侧计算(必须)**:
- SPS 在将 `RawInt16` 还原为电压时,乘法必须在 **至少 64-bit** 精度下进行(例如 `int64`),避免 `int32` 溢出。
- **异常处理(必须)**:
- 若 `Scale_uV==0` 或超出允许范围,SPS 必须对该帧标记为无效并告警;DACS 侧若检测到标定数据异常也应回传错误状态(可复用 `ADC Status` 的保留位或通过 Telemetry 上报)。
Float32 说明(必须):
- 当 `Data Type=0x01 (Float32)` 时,RAW Payload 中 I/Q 为 IEEE 754 `float32`,其物理量单位由软件回放/仿真系统自行约定;协议不要求 FPGA 产生该格式。
### **4.4 并发多任务重组键 (Reassembly Key)**
为支持多个 CPI/Pulse 流交错到达,SPS 端的逻辑帧键(唯一标识一条“脉冲回波序列”)定义为:
$$
Key = (SourceID,\; TaskID,\; CPI\ Index,\; Pulse\ Index,\; Channel\ Mask,\; Data\ Type)
$$
同一 Key 下,使用 `Sample Offset` 与 `Sample Count` 进行分片写入;缺失区间按 6.3 的规范补零。
### **4.5 FrameFlags 与 Offset 的一致性约定**
对于 PacketType=0x03 (Data):
- `SOF` 建议置 1 当且仅当 `Sample Offset == 0`。
- `EOF` 建议置 1 当且仅当 `Sample Offset + Sample Count == Sample Points`(其中 `Sample Points` 来自同一 `TaskID` 的控制面下发参数)。
- 若实现不便,也可令 `FrameFlags=0`(仅依赖 Offset/Count 重组),但不得与 Offset/Count 语义冲突。
### **4.5.1 数据平面 SeqID 递增规则(必须)**
- 对于 PacketType=0x03 (Data),发送端必须对同一条逻辑流(按 2.3.0 的 `(SourceID, PacketType, Direction)`)满足:**每发送一个 UDP 数据包,`SeqID` 递增 1**(自然回绕按 2.3.0 规则处理)。
- 接收端可使用 `SeqID` 作为快速丢包提示,但**帧重组的最终依据**必须以 4.4/4.6 中的 `Key + Sample Offset/Count` 为准。
### **4.6 跨平面关联与参数一致性(必须)**
数据平面的重组与 EOF 判断依赖控制平面下发的关键参数(尤其是 `Sample Points`、`Pulse Count` 等)。为避免“同一 TaskID 下参数漂移”导致接收端无法正确重组,定义如下强制规则:
1. **TaskID 绑定规则(必须)**:
- 对于任意数据包(PacketType=0x03),其 `(SourceID, TaskID)` 必须能在 SPS 侧找到一条“任务上下文(Task Context)”,该上下文由最近一次成功执行的 Control 指令(PacketType=0x01,ACK Applied)建立。
- 任务上下文至少包含:`Sample Points`、`Pulse Count`、(可选)`Sample Rate` 期望值、以及用于日志/诊断的 `Center Freq/Bandwidth` 等。
2. **参数不变性(必须)**:
- 在同一 `(SourceID, TaskID)` 生命周期内,DACS 回传的数据包必须使用与该任务上下文一致的 `Sample Points` 语义。
- 若 SPS 需要更改 `Sample Points`、`Pulse Count`、波形模式或其它会影响数据长度/重组边界的参数,**必须分配新的 `TaskID`**,不得复用旧 `TaskID`。
3. **上下文缺失处理(必须)**:
- 若 SPS 收到数据包时找不到对应任务上下文(例如控制指令未成功、丢失、或任务已过期),SPS 必须将该 Key 标记为“未绑定任务”,并采取以下之一:
- 丢弃该数据帧并上报错误;或
- 进入隔离缓冲(Quarantine Buffer)等待上下文补齐(有上限与超时)。
- 不允许在缺失 `Sample Points` 约束的情况下,盲目以 `EOF`/长度推断完整帧边界。
4. **上下文超时(建议)**:
- SPS 侧任务上下文应设置超时(例如数秒级,按系统业务节拍配置)。超时后如仍收到相同 `(SourceID, TaskID)` 的数据,视为异常并告警。
---
## **5. 维护平面 (RMA Protocol)**
方向: 双向 (SPS $\leftrightarrow$ DACS)
协议: UDP Unicast
端口: 40000 (Base Port) + DACS_ID
> `DACS_ID` 与 `SourceID` 的映射规则同 3.0。
报文结构: [Common Header (32B)] + [RMA Header (16B)] + [Data Payload] + [CRC32C (4B)]
### **5.1 关键设计准则**
1. **强制对齐 (Alignment Enforcement)**: RMA 头部长度被扩充并锁定为 **16 Bytes**。结合 32 Bytes 的通用头,Payload 的绝对起始偏移量为 **48 Bytes**。这既是 8 字节的倍数也是 16 字节的倍数,确保 CPU AVX 指令集与 FPGA AXI 总线 DMA 引擎均能以最高效率进行突发读写。
2. **异步事务 (Async Transaction)**: 引入 `Token` 字段。SPS 驱动层可为每个读写请求分配唯一的令牌(如 UUID Hash 或自增 ID),DACS 在响应时必须原样回传该令牌。这使得上层软件能够采用高效的**异步 Promise/Future 模式**,无需阻塞等待 IO,彻底消除了并发请求下的乱序匹配风险。
3. **显式状态 (Explicit Status)**: 引入 `Status` 字段。DACS 不再仅仅是“沉默的执行者”,而是具备了反馈能力。针对地址越界、写保护或硬件超时等异常情况,能明确返回错误码,极大降低了系统集成的调试难度。
### **5.2 RMA 专用头 (RMA Specific Header)**
该头部紧随通用报文头之后,长度固定为 **16 Bytes**。
#### **5.2.1 RFC 风格比特视图 (Bit View)**
```Plaintext
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+---------------------------------------------------------------+
| OpCode (8) | Target (8) | Status (8) | Reserved (8) |
+---------------------------------------------------------------+
| Token (32 bits) |
| (Transaction ID for Async Match) |
+---------------------------------------------------------------+
| Address (32 bits) |
| (Target Memory/Register Offset) |
+---------------------------------------------------------------+
| Length (32 bits) |
| (Payload Size in Bytes) |
+---------------------------------------------------------------+
| |
| Data Payload (Variable) |
| (Start at Offset 48, Aligned) |
| |
+---------------------------------------------------------------+
| CRC32C (4B) |
| (Covers Common Header + RMA Header + Data Payload, no CRC) |
+---------------------------------------------------------------+
```
#### **5.2.2 字段语义详解**
|**相对偏移 (Offset)**|**字段名 (Field Name)**|**数据类型**|**说明与业务逻辑**|
|---|---|---|---|
|**0**|**OpCode**|`uint8`|**操作码**。
**请求 (Req)**: `0x01`=Write, `0x02`=Read
**响应 (Resp)**: `0x81`=Write Ack, `0x82`=Read Resp|
|**1**|**Target**|`uint8`|**目标区域**。
`0x00`: FPGA Regs (32-bit MMIO)
`0x01`: Waveform DDR (Bulk Memory)
`0x02`: Flash (Firmware Update)|
|**2**|**Status**|`uint8`|**响应状态码** (仅响应包有效,请求包填 0)。
`0x00`: Success (成功)
`0x01`: Invalid Addr (地址无效/越界)
`0x02`: Write Protected (写保护)
`0x03`: Hardware Timeout (硬件超时)
`0x04`: Bad Length (长度非法)|
|**3**|**Reserved**|`uint8`|**对齐填充**。
必须填 `0x00`。|
|**4**|**Token**|`uint32`|**事务令牌**。
由主机驱动生成(建议单调递增)。FPGA 必须在响应包中原样拷贝此字段,用于软件层的 Request-Response 匹配。|
|**8**|**Address**|`uint32`|**目标地址**。
对于寄存器 (`Target=0x00`),为寄存器偏移量。
对于 DDR/Flash,为绝对字节地址。|
|**12**|**Length**|`uint32`|**载荷长度**。
单位:字节。
对于写操作:Payload 的实际长度。
对于读操作:请求读取的长度。|
> **长度与校验约定**:
>
> - `Length` 仅指 **Data Payload** 的字节数(不包含 RMA Header 与 CRC32C)。
> - `PayloadLen`(Common Header)包含:`RMA Header (16B) + Data Payload (Length) + CRC32C (4B)`。
> - `CRC32C` 为包尾追加字段,计算范围覆盖 `Common Header + RMA Header + Data Payload`(不含 CRC 字段本身)。
### **5.3 典型交互流程 (Transaction Flow)**
#### **场景 1:波形下载 (Write Waveform)**
1. **SPS 发送**:
- `OpCode`: `0x01` (Write)
- `Target`: `0x01` (DDR)
- `Token`: `0x12345678`
- `Address`: `0x10000000`
- `Length`: `4096`
- `Payload`: [4KB Waveform Data…]
2. **DACS 响应**:
- `OpCode`: `0x81` (Write Ack)
- `Status`: `0x00` (Success)
- `Token`: `0x12345678` (原样返回)
- `Length`: `0` (无 Payload)
#### **场景 2:并发状态轮询 (Async Read)**
1. **SPS 发送请求 A (读温度)**: `Token=101`, `Addr=0x10` (Temp Reg)
2. **SPS 发送请求 B (读电压)**: `Token=102`, `Addr=0x20` (Volt Reg)
3. **DACS 响应 B (先返回)**: `Token=102`, `Status=Success`, `Payload`=[电压值]
- _软件驱动层_: 唤醒 Promise B 的回调。
4. **DACS 响应 A (后返回)**: `Token=101`, `Status=Success`, `Payload`=[温度值]
- _软件驱动层_: 唤醒 Promise A 的回调。
---
## **6. 校验与可靠性 (Reliability & Timing)**
适用范围: 全系统 (SPS + DACS)
目标: 确保在 UDP 不可靠传输协议之上,构建满足雷达战术指标的确定性(Determinism)与安全性(Safety)。
### **6.1 控制平面:幂等性设计 (Idempotency)**
风险: 由于 UDP ACK 丢包导致的 SPS 重传,可能使 DACS 重复执行增量指令(如“步进 1°”被执行两次变成 2°),导致物理状态与软件状态失步。
修正: DACS (FPGA) 必须实现基于 SeqID 的指令去重逻辑。
#### **6.1.1 FPGA 接收状态机逻辑**
FPGA 内部需为每条控制/维护逻辑流维护一个寄存器 `Last_Executed_SeqID`(按 2.3.0 的逻辑流维度独立,初始化为 0)。当收到新的控制指令(PacketType=0x01 或 RMA=0xFF)时,必须按 2.3.0 的回绕安全比较规则判定(令 $\Delta=(SeqID_{new}-SeqID_{last})\bmod 2^{32}$):
1. **新指令($0 < \Delta < 2^{31}$)**:
- **动作**:立即执行指令。
- **更新**:`Last_Executed_SeqID \leftarrow SeqID_{new}`。
- **回复**:发送 ACK(PacketType=0x02,`AckSeqID=SeqID_{new}`,并携带执行结果)。
2. **重传指令($\Delta = 0$)**:
- **动作**:**严禁重复执行**(Drop Payload)。
- **更新**:保持不变。
- **回复**:**重发 ACK**(PacketType=0x02,`AckSeqID=SeqID_{new}`,并携带与首次执行一致的结果)。
3. **旧包/乱序包($2^{31} \le \Delta < 2^{32}$)**:
- **动作**:丢弃。
- **回复**:无需回复。
#### **6.1.2 ACK/Status 报文(PacketType=0x02)**
为避免“ACK 未定义导致互操作失败”,本协议统一使用 PacketType=0x02 作为 ACK/状态承载。
报文结构:`[Common Header (32B)] + [Status Payload (32B)] + [CRC32C (4B)]`
Status Payload 定义(固定 32B):
|**相对偏移**|**字段名**|**类型**|**说明**|
|---|---|---|---|
|0|StatusType|`uint16`|`0x0001`: ControlAck, `0x0002`: RmaAck, `0x0003`: Telemetry|
|2|StatusFlags|`uint16`|Bit0: Applied(已执行);Bit1: Duplicate(重复包未执行);其余保留 0|
|4|AckSeqID|`uint32`|被确认/关联的命令 SeqID(Control/RMA 请求的 SeqID)|
|8|Token|`uint32`|RMA 用 Token;ControlAck 填 0|
|12|TaskID|`uint32`|ControlAck 用 TaskID;RmaAck 填 0 或实现自定义|
|16|ErrorCode|`uint32`|`0`: Success;非 0 表示错误码(见下)|
|20|Detail0|`uint32`|可选细节(如错误地址低 32 位、校验失败计数等),无则填 0|
|24|Detail1|`uint32`|可选细节(无则填 0)|
|28|Reserved|`uint32`|必须填 0|
CRC32C 规则:覆盖 `Common Header + Status Payload`(不含 CRC 字段)。
SeqID 规则(必须):
- 对于用于确认/回执的 Status/ACK 报文(`StatusType=ControlAck` 或 `RmaAck`),**Common Header 的 `SeqID` 必须等于 `AckSeqID`**。
- 对于遥测类报文(`StatusType=Telemetry`),`AckSeqID` 必须为 `0`,且其 Common Header 的 `SeqID` 属于 Telemetry 自身的独立序列(仍按 2.3.0 的规则递增/回绕)。
- 设计目的:避免 ACK 自身引入额外的独立 SeqID 流,同时避免 Telemetry 被强行绑定到不存在的 `AckSeqID`。
ErrorCode 建议(可扩展):
- `0x00000000`: Success
- `0x00000001`: BadCRC
- `0x00000002`: BadParam (非法参数/越界)
- `0x00000003`: Busy (资源忙/暂不可用)
- `0x00000004`: Unsupported (不支持的模式/波形)
- `0x00000005`: InternalError
---
### **6.2 控制平面:重传与超时 (Retransmission Strategy)**
现状: 通用操作系统(Linux/Windows 非实时核)的线程调度抖动通常在 10ms~20ms 量级。过激的超时设置会导致虚假重传。
修正: 采用宽松的超时阈值,配合安全互锁机制。
#### **6.2.1 计时器参数**
|**参数项**|**推荐值**|**说明**|
|---|---|---|
|**Initial Timeout**|**20ms**|初始等待时间。涵盖了 "RTT + FPGA 处理时间 + **OS 调度抖动**"。|
|**Max Retries**|**3 次**|最大重试次数。|
|**Link Down Time**|**100ms**|判定链路断开的总时间阈值 ($20ms \times (1+3) + \Delta$)。|
#### **6.2.2 故障处理流程**
1. **SPS 发送**: 发出指令,启动 20ms 计时器。
2. **SPS 等待**:
- 若收到 ACK 且 `AckSeqID == Cmd.SeqID` 且 `ErrorCode==0`: 事务成功,清除计时器。
- 若 20ms 超时: `Retry_Cnt++`,重发指令(SeqID 不变)。
3. **SPS 放弃**:
- 若 `Retry_Cnt > 3`: 判定链路故障 (Link Down)。
- **安全互锁 (Safety Interlock)**: SPS 必须立即停止后续波束调度,并向上层业务软件抛出 `E_LINK_LOST` 异常。若系统包含硬件看门狗,DACS 应在 100ms 无指令后自动切断发射机高压。
4. **DACS 侧强制互锁(必须)**:
- DACS 必须实现独立于 SPS 的安全闭环:当连续 **100ms** 未收到“有效控制指令”(至少要求 CRC 校验通过;若系统启用网络层安全/认证,则还必须通过对应安全校验)时,必须自动进入 `Standby` 并关闭发射相关使能(包括但不限于发射机高压/功放使能/波形播放)。
- 该互锁应优先由硬件看门狗或等效的 FPGA 计时逻辑实现,禁止仅依赖主机软件。
---
### **6.3 数据平面:丢包处理 (Data Loss Handling)**
风险: UDP 回波数据丢失会导致时间轴断裂。如果直接跳过丢失的数据块,会导致后续脉冲压缩(匹配滤波)输出的峰值位置偏移,从而产生巨大的测距误差。
修正: 必须采用 " 相干补零 (Coherent Zero-Padding)" 策略。
#### **6.3.1 补零规范**
当 SPS 检测到丢包(通过 `SeqID` 跳变或 `Pulse/Offset` 不连续)时,必须在接收 Buffer 中填充数据,填补空缺,维持时间轴对齐。
- **填充内容**: **复数零 ($0 + j0$)**。
- I 路 = 0 (`0x0000`)
- Q 路 = 0 (`0x0000`)
- **填充长度**: 严格等于丢失的采样点数(每通道复数点数)$N_{lost}$。
- 设上一包参数为 $(Offset_{prev}, Count_{prev})$,当前包为 $Offset_{curr}$,则:
$$
N_{lost} = Offset_{curr} - (Offset_{prev} + Count_{prev})
$$
- 当 $N_{lost} > 0$:在该 Key 对应的接收缓冲中补 $N_{lost}$ 个复数零(对每个通道均补齐)。
- 当 $N_{lost} \le 0$:表示重复包或乱序到达;SPS 仍可选择“最后写入覆盖”或“忽略”,但必须保持输出长度一致。
> **补零后处理**:为减小窗函数旁瓣污染,允许在缺失区间附近对加权窗做平滑过渡(例如对缺失位置两侧若干点的窗系数做插值/衰减),但不得改变“缺失采样等价为 0”的相干约束。
---
### **6.4 校验和 (Checksum)**
为了在应用层确保数据完整性,抵御链路误码(Bit-flip)和总线错误:
1. **控制/维护/状态包**: 强制开启 **CRC-32C**(包尾)。
- DACS 收到包后,**硬件计算** CRC32C。若校验失败,**直接静默丢弃**,不回 NACK(防止 NACK 风暴)。SPS 会因超时自动重传。
- CRC32C 覆盖范围统一为:`Common Header + Payload(不含 CRC 字段)`。
2. **高速数据包**: 依赖链路层(Ethernet FCS)校验。
- 应用层不额外增加 CRC 字段,以节省 FPGA 逻辑资源并降低 PCIe 带宽开销。链路层校验错误的包会被网卡(NIC)直接丢弃,SPS 软件层通过 Sequence ID 即可感知丢包。
---
### **6.5 安全性与访问控制(必须)**
#### **6.5.1 基本原则**
- 本协议基于 UDP 设计,`SourceID`/`SeqID`/`CRC32C` 仅用于**互操作与误码检测**,不具备任何身份认证或抗伪造能力。
- 生产/外场部署中,必须假设存在:伪造控制指令、重放、篡改、以及通过 RMA 获取“等价远程管理权限”的风险。
#### **6.5.2 生产环境安全要求(至少满足其一,必须)**
为在不破坏 V2.1 报文格式的前提下实现可落地的安全闭环,生产环境必须至少采用以下一种方式提供**加密与认证**:
1. **链路层安全(推荐)**:MACsec (802.1AE)
2. **网络层安全(推荐)**:IPsec(Transport/Tunnel 均可)或等效的专用加密隧道
3. **物理隔离专网(最低要求)**:控制/维护网络必须与办公网/互联网严格隔离,并采用 ACL/白名单限制可达性
> 注:若系统未来需要在不可信网络上直接跑 UDP 明文,则应在后续版本引入协议级认证(例如 HMAC-SHA256),并配套密钥管理与重放防护。本条为 V2.1 的落地约束,不在本版本报文格式中强制定义具体认证字段。
#### **6.5.3 RMA 通道风险控制(必须)**
RMA 可读写寄存器/DDR/Flash,等价于高权限维护接口。为避免误用或被滥用:
- **默认关闭(必须)**:DACS 上电后 RMA 功能应处于关闭或只读受限状态;仅在满足运维流程的情况下才允许开启。
- **网络分区(必须)**:RMA 流量必须运行在独立的维护网络/VLAN 中,禁止与数据平面同网段直连。
- **访问控制(必须)**:
- 至少实施基于五元组/ACL 的白名单(限定 SPS 主机 IP/MAC、端口范围);
- 并建议加入“物理在场”要素(例如拨码开关/跳线/维护口使能)以降低远程攻击面。
- **最小权限(建议)**:对 Flash 写入等高风险操作(固件升级)应要求额外的人工确认流程与分段校验。