---
tags: []
aliases:
  - "**前端感知系统通信协议 (ICD) V2.2**"
date created: 星期一, 十二月 8日 2025, 9:01:09 上午
date modified: 星期五, 一月 9日 2026, 7:27:23 晚上
---

# **前端感知系统通信协议 (ICD) V2.2**

文档编号: FES-SW-ICD-002

版本: V2.2 (Header HCS/Epoch/DestID + Control Ext + Data Snapshot)

说明：版本以本页“版本”字段为准；文档编号用于配置管理索引，不随次版本必然变化。

备注：当前文件名包含 “V2.1” 属历史遗留，正文内容为 **V2.2** 规范；互操作时以 `ProtoVer` 字段为准。

适用架构: Host (CPU/GPU) <-> Device (Pure Logic FPGA)

物理链路: 10Gbps Ethernet (UDP/IP)

---

## **0. 设计变更与迁移指南 (Design Change Log)**

### **0.1 变更综述 (Executive Summary)**

本版本关注点（协议层面）：

- **一致性与可解析性**：统一通用头与 `PayloadLen` 语义，避免解析器进入未定义行为。
- **确定性控制闭环**：控制指令具备幂等去重与 ACK 判据，禁止“猜测已执行”。
- **高吞吐数据平面**：固定偏移与自然对齐，支持零拷贝 DMA；数据重组以 `Key + Offset/Count` 为准。
- **可演进**：保留区受校验保护，新增字段不得改变 RAW Payload 起始偏移。

### **0.2 详细变更对照表**

#### **1. 架构与拓扑设计 (Architecture & Topology)**

|**变更维度**|**V0.1 / V1.0 (Legacy)**|**V2.0 (Current)**|**设计动机与技术收益**|
|---|---|---|---|
|**拓扑依赖**|**强耦合 (IP Binding)**<br>依赖 IP 地址 (`192.168.0.x`) 区分阵面。|**完全解耦 (Logical SourceID)**<br>新增 `SourceID` 字段，支持 DHCP 及动态组网。|支持即插即用，离线数据分析（pcap）无需依赖环境 IP 表。|
|**传输单元**|**MTU 1500 (Standard)**<br>未明确定义，默认为标准帧。|**MTU 9000 (Jumbo Frame)**<br>强烈推荐开启巨型帧，且必须兼容 MTU 1500 运行。|在吞吐与部署兼容性之间平衡：优先保证可达与稳定运行，Jumbo 作为性能增强项。|
|**维护通道**|**无 (None)**<br>仅支持预定义命令。|**RMA Protocol**<br>引入 `OpCode 0xFF`，支持内存/寄存器直接读写。|实现波形文件的动态下载与任意寄存器的带外调试，无需修改协议固件。|

#### **2. 数据结构与内存布局 (Data Structure & Memory)**

|**变更维度**|**V0.1 / V1.0 (Legacy)**|**V2.0 (Current)**|**设计动机与技术收益**|
|---|---|---|---|
|**报文头对齐**|**非对齐 (15 Bytes)**<br>奇数长度头部，导致 Payload 内存错位。|**自然对齐 (32 Bytes)**<br>强制 8 字节对齐，填充至 Cache Line 边界。|适配 FPGA 256-bit 总线与 CPU AVX 指令集，实现零拷贝 (Zero-Copy) DMA。|
|**字节对齐**|**1-Byte Packed**<br>紧凑排列，无填充。|**Hybrid Alignment (混合策略)**<br>控制面紧凑，数据面/关键字段强制对齐。|在节省带宽与降低 CPU 访问开销（避免非对齐异常）之间取得最佳平衡。|
|**校验算法**|**XOR / Sum**<br>抗干扰能力弱，无法检测双位翻转。|**CRC-32C (Castagnoli)**<br>硬件加速指令级校验。|极大地降低漏检率，特别是在雷达高功率发射环境下的突发误码检测。|
|**扩展性**|**无预留**<br>新增字段需破坏现有结构。|**预留保留区 (Reserved)**<br>控制面预留 56 字节，且置于 CRC 保护下。|确保协议升级时旧版固件不崩溃，支持向后兼容。|

#### **3. 物理量定义与精度 (Physics & Precision)**

|**变更维度**|**V0.1 / V1.0 (Legacy)**|**V2.0 (Current)**|**设计动机与技术收益**|
|---|---|---|---|
|**频率定义**|**索引码 (uint8)**<br>`0=15.5GHz`, Step=10MHz。<br>范围锁定，无法捷变。|**绝对物理值 (uint64)**<br>单位：Hz。<br>例：`15,500,000,000`。|**解耦硬件**：支持任意波段（Ku/Ka）、任意步进的频率捷变与抗干扰策略。|
|**角度定义**|**量化整数 (int16)**<br>LSB=0.0025°。< br>存在量化噪声，GPU 需转换。|**微单位整数 / 浮点接口**<br>传输层：`int32` ($\mu^\circ$)。<br>应用层：`double` (Deg)。|**消除量化误差**：精度提升至 $10^{-6}$ 度，满足 AI 波束成形算法的高精度需求。|
|**增益控制**|**量化步进 (uint16)**<br>LSB=0.5dB。<br>依赖硬件非线性特性。|**物理增益 (int32)**<br>单位：mdB。<br>FPGA 查表映射。|**算法闭环**：后端直接下发期望增益，底层自动校准，简化业务逻辑。|
|**回波归一化**|**无 (None)**<br>仅传 ADC 原始值 (Int16)。<br>后端无法计算 RCS。|**Scale Factor (int32 微单位)**<br>随包下发物理归一化因子（整数微单位）。|**数据自描述**：GPU 可直接还原真实电压/功率，无需同步查询增益状态，且 FPGA 侧不需要浮点。|

#### **4. 可靠性与时序控制 (Reliability & Timing)**

|**变更维度**|**V0.1 / V1.0 (Legacy)**|**V2.0 (Current)**|**设计动机与技术收益**|
|---|---|---|---|
|**幂等性**|**缺失**<br>ACK 丢包会导致指令重复执行（如电机步进 2 次）。|**SeqID 去重**<br>FPGA 缓存 `Last_SeqID`，重复包仅回 ACK 不执行。|**防止状态过冲**：确保控制指令在不可靠网络下的绝对确定性执行。|
|**超时策略**|**激进 (未定义/短)**<br>易受 OS 调度抖动影响触发重传。|**宽松 (20ms)**<br>适配 Windows/Linux 非实时核调度。|**减少网络风暴**：避免因系统卡顿导致的虚假超时与不必要的重传。|
|**丢包处理**|**无规范**<br>直接拼接或补零。|**相干补零 (Coherent Zero-Pad)**<br>严格补复数零 ($0+j0$)。|**保障信号完整性**：防止时域数据缺失导致的脉冲压缩相位错位与测距误差。|
|**自闭环调度**|**开环 (Open Loop)**<br>发多少脉冲依赖“停止”指令。|**Pulse Count (自闭环)**<br>指令携带脉冲数，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)**

规范：

- 传输层物理量 **必须** 使用整数表示（频率 Hz、角度 $\mu^\circ$、增益 mdB、时间 ns 等），禁止在协议层引入 IEEE 754 浮点依赖（除非字段明确标注为仿真/回放用途）。
- SPS 驱动层 **必须** 负责完成“物理量（浮点）↔ 微单位整数”的无损转换；业务代码 **不得** 直接操作/硬编码协议整数。

### **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 基础架构约束**

规范：

- **字节序**：所有 `uint16/uint32/uint64/int32/int16` 等多字节字段 **必须** 采用 Little-Endian。
- **传输**：UDP/IPv4。
- **MTU**：应优先使用 Jumbo（9000）以降低中断与包头开销；系统 **必须** 能在 MTU 1500 下工作。
- **分片**：发送端 **必须** 在应用层按路径 MTU 切包，禁止依赖 IP 分片。

### **1.4 混合对齐策略 (Hybrid Alignment)**

为平衡传输带宽与处理效率，协议在不同平面采用不同的对齐策略：

1. **控制平面 (SPS $\to$ DACS)**：

    - 采用 **1-Byte Packed (紧凑模式)**（以减少带宽开销）。

2. **数据平面 (DACS $\to$ SPS)**：

    - 采用 **8-Byte Natural Alignment (自然对齐)**（以匹配 DMA/Cache Line/向量化读取）。

---

## **2. 通用报文头 (Common Header)**

规范（必须）：

- 所有 UDP 报文（Control/Status/Data/RMA）**必须**携带该通用报文头，且位于 UDP Payload 起始处。
- 报文头长度 **固定为 32 Bytes**；多字节字段 **必须** Little-Endian。
- 接收端 **必须** 先完成以下检查后才允许继续解析：
    - `Magic Word` 正确；
    - `HCS` 校验通过（见 2.3.4）；
    - `PayloadLen` 与实际 UDP 应用层长度一致（`UdpPayloadBytes == 32 + PayloadLen`）。
- 对齐/保留：`Reserved` **必须** 全 0；接收端遇到非 0 时可告警但不得改变兼容性行为。

### **2.1 报文头结构定义**

| **偏移 (Offset)** | **字段名 (Field Name)** | **数据类型**   | **说明与约束**                                                                                                                                     |
| --------------- | -------------------- | ---------- | --------------------------------------------------------------------------------------------------------------------------------------------- |
| **0**           | **Magic Word**       | `uint32`   | 协议同步魔数，固定为 **`0x55AA55AA`**。<br>用于从二进制流中快速定位帧首，防止滑窗错误。                                                                                        |
| **4**           | **SeqID**            | `uint32`   | **按流递增的包序列号**（非全局）。<br>递增作用域：**(SourceID, PacketType, Direction)** 组成的一条逻辑流。接收端用于丢包检测与乱序重排。 |
| **8**           | **Timestamp**        | `uint64`   | **PTP 纳秒时间戳**。<br>统一使用 Unix Epoch (1970-01-01 00:00:00 ns)，用于全系统时序对齐。                                                                         |
| **16**          | **PayloadLen**       | `uint16`   | 后续载荷 (Payload) 的有效字节长度。<br>不包含本 Header 的 32 字节。                                                                                               |
| **18**          | **PacketType**       | `uint16`   | 报文类型标识：<br>`0x01`: Control (控制指令)<br>`0x02`: Status (状态遥测)<br>`0x03`: Data (回波数据)<br>`0xFF`: RMA (维护通道)                                       |
| **20**          | **ProtoVer**         | `uint8`    | **协议版本号**。<br>高 4 位为主版本，低 4 位为次版本。<br>当前 V2.2 对应 **`0x22`**（V2.1 为 `0x21`，V2.0 为 `0x20`）。                                                                                  |
| **21**          | **SourceID**         | `uint8`    | **源设备逻辑 ID** (拓扑解耦的关键)。<br>`0x01`: SPS (主控)<br>`0x10`: DACS-Broadcast<br>`0x11`~`0x1F`: DACS-Unicast                                          |
| **22**          | **FrameFlags**       | `uint16`   | **分帧标志位 (Bitmask)**。<br>用于处理跨 UDP 包的巨型数据帧重组。<br>`Bit0`: **SOF** (Start of Frame)<br>`Bit1`: **EOF** (End of Frame)<br>`Bit2-15`: Reserved (0) |
| **24**          | **HCS**              | `uint16`   | **Header Checksum**。<br>用于校验 Header 前 24 字节，防止 `PayloadLen/PacketType` 位翻转导致解析异常。计算规则见 2.3.4。 |
| **26**          | **Epoch**            | `uint16`   | **会话代号 / SessionID**。<br>SPS 每次启动/链路重建递增，用于区分“新会话”与旧包残留，并解决设备重启后 `SeqID` 回绕导致的幂等性冲突。 |
| **28**          | **DestID**           | `uint8`    | **目的设备逻辑 ID**。<br>用于多阵面环境下的快速过滤与防错发。广播可使用 `0x10`。 |
| **29**          | **Reserved**         | `uint8[3]` | **对齐保留**。<br>必须全填 `0x00`。确保 Header 总长为 32 字节。 |

---

### 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  | <--- 紧凑信息区
+-----------------------------+-----------------------------+
|   HCS (2B)   |  Epoch (2B)  | DestID (1B) | Reserved (3B) |
+-----------------------------+-----------------------------+
```

### **2.3 关键字段语义详解**

#### **2.3.0 SeqID 作用域与回绕处理（必须）**

`SeqID` 规范（必须）：

- `SeqID` 为 **按逻辑流递增** 的序列号，递增作用域为 `(SourceID, PacketType, 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 流。
- 回绕比较 **必须** 使用模 $2^{32}$ 的半区间规则（禁止用 `>` 直接比较）：
    - 令 $\Delta = (SeqID_{new} - SeqID_{last})\bmod 2^{32}$（以 `uint32` 自然溢出实现）。
    - 当 $0 < \Delta < 2^{31}$ 时，判定为 **新包**。
    - 当 $\Delta = 0$ 时，判定为 **重复包**。
    - 当 $2^{31} \le \Delta < 2^{32}$ 时，判定为 **旧包/乱序包**。

实现建议：FPGA/软件统一采用上述规则，确保回绕时幂等/去重一致。

#### **2.3.1 版本控制 (ProtoVer) —— 解决“协议锁死”**

规范（必须）：接收端 **必须** 先检查 `ProtoVer`。

- `ProtoVer == 本地版本`：按本规范解析。
- `ProtoVer > 本地版本`：接收端 **不得** 继续按旧格式“猜测解析”；应进入兼容模式或直接丢弃并告警。
- `ProtoVer < 本地版本`：接收端应按向后兼容策略解析（至少保证通用头字段语义不变），并忽略未定义/保留字段。

#### **2.3.2 源标识 (SourceID) —— 解决“拓扑依赖”**

规范（必须）：接收端设备识别 **必须** 以 `SourceID` 为准，不得依赖 `src_ip`。

ID 分配表：
    - `0x01`: Signal Processing System (SPS)
    - `0x11`: DACS - Array 01 (Front)
    - `0x12`: DACS - Array 02 (Left)
    - `0x13`: DACS - Array 03 (Right)

说明：离线分析与 DHCP 环境下均可保持一致识别。

#### **2.3.3 帧标志 (FrameFlags) —— 解决“数据拼图”**

规范（推荐）：`FrameFlags` 用于显式标记同一“帧”的边界。

- 一条待重组的上层数据帧（典型为单脉冲回波序列；也可扩展到 CPI 级帧）可能远超 MTU，需拆分为多个 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`。

接收端处理建议：对 Data 包优先按 6.3 的相干补零策略保持时间轴；对 Control/RMA 由超时重传闭环。

> 约定说明（推荐）：对于 PacketType=0x03 (Data)，若实现需要使用 `FrameFlags`，建议将其“帧”边界按 4.4 的 `Key` 维度（即单脉冲回波序列）定义；若仅依赖 `Sample Offset/Sample Count` 重组，则可将 `FrameFlags` 置 0。

#### **2.3.4 HCS / Epoch / DestID（V2.2 新增）**

- **HCS (Header Checksum)**：
    - **覆盖范围**：Header 的前 24 字节（Offset 0..23），即从 `Magic Word` 到 `FrameFlags`。
    - **算法（必须）**：CRC-16/CCITT-FALSE（Poly `0x1021`，Init `0xFFFF`，RefIn=false，RefOut=false，XorOut `0x0000`）。
    - **校验失败处理（必须）**：接收端必须直接丢弃该包（静默丢弃），不得继续解析 `PayloadLen`。
- **Epoch (SessionID)**：
    - SPS 必须在每次启动或链路重建时递增 `Epoch`（16-bit 自然回绕）。
    - DACS/SPS 在做幂等去重与乱序处理时，应将 `Epoch` 视为逻辑流键的一部分；当 `Epoch` 变化时，应重置该流的 `Last_Executed_SeqID` 等状态。
- **DestID**：
    - `DestID` 为目的设备逻辑 ID，用于快速过滤与防错发。
    - 推荐约定：
        - SPS → DACS 单播 Control/RMA：`DestID = 0x11..0x13`（目标阵面）
        - SPS → DACS 广播 Control：`DestID = 0x10`
        - DACS → SPS Data/Status：`DestID = 0x01`

---

## **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` 以实现无歧义重组。

参数校验规范（必须）：

- DACS 在执行控制指令前 **必须** 完成关键字段的范围与一致性检查；检查失败则 **不得执行**，并通过 Status/ACK 返回 `Applied=0` 且 `ErrorCode=BadParam`。
- 关键一致性最小集合（必须）：
    - `Pulse Width` 必须满足 $PulseWidth < 10^9/PRF$（单位换算后等价于脉宽小于 PRI），否则拒绝；
    - `Sample Points > 0` 且不得超过硬件上限（实现需给出上限常量）；
    - `Pulse Count > 0` 且不得超过硬件上限；
    - `Bandwidth > 0` 且不得超过 ADC/DDC 允许带宽；
    - `Center Freq` 必须落在前端射频工作带内；
    - `GainTarget_mdB` 必须落在可控增益范围内。
- `TaskID` 语义（必须）：若上述任一会影响数据平面重组边界/数据长度的参数发生变化（如 `Sample Points`、`Pulse Count`、波形模式），SPS **必须** 分配新的 `TaskID`，不得复用旧 `TaskID`。

### **3.2 载荷定义 (Control Payload)**

|**相对偏移 (Offset)**|**字段名 (Field Name)**|**数据类型**|**单位 (Unit)**|**说明与物理定义**|
|---|---|---|---|---|
|**0**|**Command Mode**|`uint8`|-|**工作模式**。<br>`0`: Standby (待机/静默)<br>`1`: Search (搜索)<br>`2`: Track (跟踪)<br>`3`: Calibrate (内/外校准)|
|**1**|**Waveform ID**|`uint8`|Index|**基础波形索引**。<br>指向 FPGA 内部 DDR 预存的波形表（如 LFM 基带数据）。|
|**2**|**Reserved_Pad**|`uint8[2]`|-|**对齐填充**。<br>必须填 `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**|**载波中心频率**。<br>绝对物理值（如 `15,500,000,000`），直接控制本振 (LO)。|
|**28**|**Bandwidth**|`uint64`|**Hz**|**信号瞬时带宽**。<br>用于配置接收机 DDC 滤波器的抽取率与带宽。|
|**36**|**Pulse Width**|`uint32`|**ns**|**脉冲宽度 ($\tau$)**。<br>发射波形的有效持续时间，决定雷达盲区与平均功率。|
|**40**|**PRF**|`uint32`|**Hz**|**脉冲重复频率**。<br>决定最大无模糊距离。|
|**44**|**Sample Points**|`uint32`|Count|**快拍数 (Range Gates)**。<br>单次脉冲回波的 ADC 采样点数（如 4096）。|
|**48**|**Pulse Count**|`uint32`|Count|**驻留脉冲数 ($N_{cpi}$)**。<br>本次 CPI 包含的脉冲总数。FPGA 计数达到此值后自动停止。|
|**52**|**GainTarget_mdB**|`int32`|**mdB**|**期望增益**。软件换算：$G[dB] = Val_{raw} \times 10^{-3}$。DACS 通过 LUT/标定表映射为模拟衰减/增益控制量。|
|**56**|**Wave_Param1**|`uint32`|-|**波形动态参数 1**。<br>例如 LFM 的调频斜率 (Slope) 或相位编码的初相。|
|**60**|**Wave_Param2**|`uint32`|-|**波形动态参数 2**。<br>预留给特定波形的高级控制参数。|
|**64**|**TaskID**|`uint32`|-|**并发任务标识**。由 SPS 分配（建议单调递增或随机非零）。用于区分同一时刻交错的多 CPI 流。|
|**68**|**Az_Broaden_Factor**|`uint8`|Index|**方位展宽倍数索引**。<br>`0`: 1x（不展宽）; `1`: 2x; `2`: 3x…（具体映射由系统配置表定义）。|
|**69**|**El_Broaden_Factor**|`uint8`|Index|**俯仰展宽倍数索引**。<br>编码同上。|
|**70**|**PRF_Jitter_Mode**|`uint8`|Enum|**PRF 抖动模式**。<br>`0`: Off; `1`: Deterministic (参差); `2`: Random (随机)。|
|**71**|**Reserved_ExtPad0**|`uint8`|-|**对齐填充**，必须为 0。确保后续 `uint32` 4 字节对齐。|
|**72**|**Sample_Delay_ns**|`uint32`|ns|**采样起始延迟**。<br>定义采样窗起点相对发射时刻的纳秒延迟，用于波门控制。|
|**76**|**Sim_Target_Dist_ns**|`uint32`|ns|**模拟目标距离延迟**（内测/校准）。<br>以等效传播时延（ns）表达。|
|**80**|**Sim_Target_Vel_mmps**|`int32`|mm/s|**模拟目标速度**（内测/校准）。|
|**84**|**Phase_Init**|`uint32`|-|**脉冲初始相位控制字**（波形精细化）。|
|**88**|**Reserved**|`uint8[36]`|-|**扩展保留区（剩余）**。<br>必须全填 `0x00`。**处于 CRC 保护之下**。|
|**124**|**CRC32C**|`uint32`|-|**完整性校验**。<br>算法：CRC-32C (Castagnoli)。<br>覆盖范围：`Common Header + Control Payload (不含 CRC 字段本身)`（详见 6.4）。|

---

### **3.3 内存布局图解 (Memory Layout)**

以下视图用于核对控制载荷的字节偏移与字边界。

#### **3.3.1 RFC 标准比特视图 (Bit-Level View)**

每行代表 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 36 Bytes)                   /
|                                                               |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                        CRC32C (End)                           | 0x7C
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
```

#### **3.3.2 关键字段说明**

- **对齐填充 (`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)**

方向: DACS $\to$ SPS

协议: UDP Unicast

端口: 30000 (Base Port) + DACS_ID（映射规则同 3.0）

PacketType（必须）：`PacketType == 0x03 (Data)`。

### **4.1 报文格式与校验 (Format & Validation)**

报文结构（固定前缀）：

- `[Common Header (32B)] + [Data Specific Header (32B)] + [Execution Snapshot (64B)] + [RAW Payload (Variable)]`

长度与一致性（必须）：

- 设 `UdpPayloadBytes` 为 UDP Payload 的实际字节数，则接收端 **必须** 校验：`UdpPayloadBytes == 32 + PayloadLen`。
- 对于 Data 包，`PayloadLen` **必须** 满足：
  - `PayloadLen == 32 + 64 + RawPayloadBytes`
  - 令 `C = PopCount(Channel Mask)`，`B` 为每个分量的字节数（由 `Data Type` 决定：Int16=2，Int32=4，Float32=4），则：
    - `RawPayloadBytes == SampleCount * C * (2 * B)`
- 任一校验失败：接收端 **必须** 丢弃该包（防止越界重组）。

对齐（必须）：

- RAW Payload 起始偏移固定为 128 字节（$32+32+64$），为 64B Cache Line 的整数倍。

SeqID（必须）：

- 对于同一逻辑流（按 2.3.0 的 `(SourceID, PacketType, Direction)`），发送端 **必须** 每发送一个 UDP 数据包使 `SeqID` 递增 1（自然回绕按 2.3.0 规则处理）。

### **4.2 数据专用头 (Data Specific Header, 32B)**

位置：紧随通用报文头之后，长度固定 32B。

|**偏移**|**字段名**|**类型**|**规范与语义（必须/推荐）**|
|---:|---|---|---|
|0|CPI_Index|`uint32`|相干处理间隔索引（同一任务内的宏观时间维度）。|
|4|Pulse_Index|`uint32`|脉冲索引（同一 CPI 内从 0 开始）。|
|8|Sample_Rate_Hz|`uint32`|采样率（Hz）。推荐与任务上下文一致；不一致时接收端应告警并可丢弃该帧。|
|12|SampleCount|`uint32`|本包采样点数（每通道复数点数）。**必须 > 0**。与 `PayloadLen` 的关系必须满足 4.1。|
|16|SampleOffset|`uint32`|本包数据在同一重组键 `Key` 对应序列中的起始点号（点数）。首片通常为 0。|
|20|Scale_uV|`int32`|当 `Data Type` 为 Int16/Int32 时表示 $\mu V/LSB$；当 `Data Type` 为 Float32 时 **必须为 0**。|
|24|ChannelMask|`uint16`|通道掩码。`Bit0`=$\Sigma$，`Bit1`=$\Delta_{Az}$，`Bit2`=$\Delta_{El}$，`Bit3`=Aux；其余位保留 0。|
|26|DataType|`uint8`|`0x00`=Int16，`0x01`=Float32（仅回放/仿真），`0x02`=Int32。|
|27|ADC_Status|`uint8`|ADC/链路状态位图（按实现定义扩展）。保留位必须为 0。|
|28|TaskID|`uint32`|任务标识（与控制面一致）。用于跨包/跨流重组与跨平面绑定。|

### **4.3 执行状态快照区 (Execution Snapshot, 64B, V2.2)**

位置：紧随 Data Specific Header 之后，长度固定 64B。

规范（必须）：

- 该区长度 **必须固定为 64B**；旧实现可将其视为 Padding 并填 0。
- 所有 `Reserved_*` 字段 **必须** 填 0；接收端可告警但不得依赖其非 0 语义。

字段布局（相对快照区起始偏移）：

|**偏移**|**字段名**|**类型**|**单位**|**说明**|
|---:|---|---|---|---|
|0|Applied_Freq_Hz|`uint64`|Hz|硬件实际发射/本振频率快照。|
|8|Applied_Gain_mdB|`int32`|mdB|接收链路物理增益快照。|
|12|Applied_Azimuth_uDeg|`int32`|$\mu^\circ$|硬件实际方位角快照。|
|16|Applied_Elevation_uDeg|`int32`|$\mu^\circ$|硬件实际俯仰角快照。|
|20|Hardware_Health_Bitmask|`uint32`|-|硬件健康位图（按实现定义）。|
|24|Device_Temp_0p1C|`int16`|0.1°C|温度快照。|
|26|Reserved_SnapPad0|`uint16`|-|必须为 0。|
|28|Broaden_Snapshot|`uint8`|-|展宽实际状态快照。|
|29|Data_Source_Attr|`uint8`|-|数据来源属性（示例：0=真实回波，1=内校准）。|
|30|Reserved_SnapPad1|`uint16`|-|必须为 0。|
|32|Reserved_Snapshot|`uint8[32]`|-|必须为 0。|

### **4.4 原始载荷 (Raw Payload)**

位置：紧随 64B 快照区之后（起始偏移固定 128B）。

排列（必须）：按“点交织（Point-Interleaved）+ I/Q 交织”排列：

```Plaintext
[I0_Ch0][Q0_Ch0] [I0_Ch1][Q0_Ch1] ... [I0_Ch(C-1)][Q0_Ch(C-1)]
[I1_Ch0][Q1_Ch0] [I1_Ch1][Q1_Ch1] ...
...
```

数据类型（必须）：

- Int16：I/Q 为 `int16` Little-Endian。
- Int32：I/Q 为 `int32` Little-Endian。
- Float32：I/Q 为 IEEE754 `float32`（仅回放/仿真）；`Scale_uV` 必须为 0。

Scale_uV 处理（必须）：

- 当 `DataType` 为 Int16/Int32：`Scale_uV` 必须非 0，且建议满足 $|Scale\_uV| \le 2^{30}$。
- 主机侧换算推荐：乘法在至少 64-bit 精度下进行。

### **4.5 重组规则 (Reassembly)**

重组键（必须）：

$$
Key = (SourceID,\; TaskID,\; CPI\_Index,\; Pulse\_Index,\; ChannelMask,\; DataType)
$$

分片写入（必须）：

- 同一 `Key` 下，使用 `SampleOffset` 与 `SampleCount` 将 RAW Payload 写入对应接收缓冲。
- 缺失区间必须按 6.3 执行相干补零。
- `SeqID` 仅可作为“全局丢包提示”；**不得** 用 `SeqID` 推导某个 `Key` 的缺失 Offset。

### **4.6 跨平面绑定与帧边界 (Control Binding)**

任务上下文（必须）：

- 对于任意 Data 包，其 `(SourceID, TaskID)` 必须能在 SPS 侧命中任务上下文（由最近一次成功执行的 Control 指令建立）。
- 上下文至少包含：`Sample Points`、`Pulse Count`，（可选）期望 `Sample Rate`、以及用于诊断的中心频率/带宽等。

参数不变性（必须）：

- 在同一 `(SourceID, TaskID)` 生命周期内，影响数据长度/帧边界的参数不得漂移；若需要变更，SPS 必须分配新的 `TaskID`。

FrameFlags（推荐）：

- 若实现使用 `FrameFlags` 标记边界，则对 Data 包建议满足：
  - `SOF==1` 当且仅当 `SampleOffset==0`；
  - `EOF==1` 当且仅当 `SampleOffset + SampleCount == Sample Points`（来自任务上下文）。
- 若实现不使用 `FrameFlags`，可置 0，但不得与 `SampleOffset/SampleCount` 语义冲突。

---

## **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`|**操作码**。<br>**请求 (Req)**: `0x01`=Write, `0x02`=Read<br>**响应 (Resp)**: `0x81`=Write Ack, `0x82`=Read Resp|
|**1**|**Target**|`uint8`|**目标区域**。<br>`0x00`: FPGA Regs (32-bit MMIO)<br>`0x01`: Waveform DDR (Bulk Memory)<br>`0x02`: Flash (Firmware Update)|
|**2**|**Status**|`uint8`|**响应状态码** (仅响应包有效，请求包填 0)。<br>`0x00`: Success (成功)<br>`0x01`: Invalid Addr (地址无效/越界)<br>`0x02`: Write Protected (写保护)<br>`0x03`: Hardware Timeout (硬件超时)<br>`0x04`: Bad Length (长度非法)|
|**3**|**Reserved**|`uint8`|**对齐填充**。<br>必须填 `0x00`。|
|**4**|**Token**|`uint32`|**事务令牌**。<br>由主机驱动生成（建议单调递增）。FPGA 必须在响应包中原样拷贝此字段，用于软件层的 Request-Response 匹配。|
|**8**|**Address**|`uint32`|**目标地址**。<br>对于寄存器 (`Target=0x00`)，为寄存器偏移量。<br>对于 DDR/Flash，为绝对字节地址。|
|**12**|**Length**|`uint32`|**载荷长度**。<br>单位：字节。<br>对于写操作：Payload 的实际长度。<br>对于读操作：请求读取的长度。|

> **长度与校验约定**：
>
> - `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 重传场景下 **必须幂等**；DACS 必须按 `SeqID` 去重，重复包只回 ACK 不重复执行。

#### **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）**

规范（必须）：本协议使用 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 的规则递增/回绕）。


ErrorCode 建议（可扩展）：

- `0x00000000`: Success
- `0x00000001`: BadCRC
- `0x00000002`: BadParam (非法参数/越界)
- `0x00000003`: Busy (资源忙/暂不可用)
- `0x00000004`: Unsupported (不支持的模式/波形)
- `0x00000005`: InternalError

---

### **6.2 控制平面：重传与超时 (Retransmission Strategy)**

规范（推荐）：采用固定超时 + 有界重试；超时/重试达到上限后进入链路故障处理，并触发安全互锁。

#### **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)**

规范（必须）：数据平面丢包后 **必须** 执行相干补零（缺失采样等价为复数 0），以保持时间轴与相位一致性。

#### **6.3.1 补零规范**

当 SPS 在同一重组键 `Key` 下检测到丢包（通过 `Sample Offset/Sample Count` 不连续）时，必须在接收 Buffer 中填充数据，填补空缺，维持时间轴对齐。

> 注意：在允许多个 `Key` 交织到达的前提下，`SeqID` 跳变只能说明数据平面“全局存在丢包”，**无法唯一定位**是哪个 `Key` 缺失，因此不得单独据此计算缺失区间并补零。

- **填充内容**: **复数零 ($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)**

校验规范：

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.2 报文格式的前提下实现可落地的安全闭环，生产环境必须至少采用以下一种方式提供**加密与认证**：

1. **链路层安全（推荐）**：MACsec (802.1AE)
2. **网络层安全（推荐）**：IPsec（Transport/Tunnel 均可）或等效的专用加密隧道
3. **物理隔离专网（最低要求）**：控制/维护网络必须与办公网/互联网严格隔离，并采用 ACL/白名单限制可达性

> 注：若系统未来需要在不可信网络上直接跑 UDP 明文，则应在后续版本引入协议级认证（例如 HMAC-SHA256），并配套密钥管理与重放防护。本条为 V2.2 的落地约束，不在本版本报文格式中强制定义具体认证字段。

#### **6.5.3 RMA 通道风险控制（必须）**

RMA 可读写寄存器/DDR/Flash，等价于高权限维护接口。为避免误用或被滥用：

- **默认关闭（必须）**：DACS 上电后 RMA 功能应处于关闭或只读受限状态；仅在满足运维流程的情况下才允许开启。
- **网络分区（必须）**：RMA 流量必须运行在独立的维护网络/VLAN 中，禁止与数据平面同网段直连。
- **访问控制（必须）**：
    - 至少实施基于五元组/ACL 的白名单（限定 SPS 主机 IP/MAC、端口范围）；
    - 并建议加入“物理在场”要素（例如拨码开关/跳线/维护口使能）以降低远程攻击面。
- **最小权限（建议）**：对 Flash 写入等高风险操作（固件升级）应要求额外的人工确认流程与分段校验。
