F´ GDS Framing Plugin 深入指南:帧封装与解帧协议的定制实现

F´ GDS Framing Plugin 深入指南:帧封装与解帧协议的定制实现 F´ GDS Framing Plugin 深入指南帧封装与解帧协议的定制实现【免费下载链接】fprimeF´ - A flight software and embedded systems framework项目地址: https://gitcode.com/GitHub_Trending/fpr/fprime导读F´F Prime飞行软件与地面数据系统GDS之间通过字节流、缓冲区或报文进行通信而 Framing Plugin帧封装插件正是负责在 GDS 一侧完成从协议帧中提取 F Prime 数据单元与将 F Prime 数据单元封装为协议帧的核心扩展点。本文基于docs/reference/gds-plugins/framing.md讲解该插件的职责边界、必选接口与编写方法并结合仓库中的Svc::FprimeFramer、Svc::FprimeDeframer、Svc::FrameAccumulator及 F Prime 协议规范深入剖析帧格式、校验与缓冲区所有权流转机制。读完本文你将能够编写自己的自定义 Framing 插件并理解 F´ 默认帧协议在上下行链路中的完整工作方式。Framing Plugin 是什么Framing Plugin 用于在 GDS 与 F Prime 部署之间进行通信时从原始字节数据中组装出完整报文framing再从组装好的载荷中提取出 F Prime 数据单元deframing。它让用户可以针对不同的通信协议例如 CCSDS定制帧封装逻辑。需要特别强调的是它不做 F Prime 数据的解码只负责从协议特定帧中提取 F Prime 报文packet官方仓库中的 F Prime framing plugin位于src/fprime_gds/common/communication/framing.py是实现了 F Prime 帧协议的标准参考实现Framing 属于SELECTION类型的插件即同一时刻只运行一个 Framing 插件由用户显式选择启用哪一个。运行环境与注意事项Framing 插件运行在GDS 通信线程communication thread内部这意味着所有通过该线程的通信都会经过此插件实现低效或发生阻塞的插件会拖慢全部通信因此编写插件时应避免长时间阻塞操作、全局锁竞争或 CPU 密集的同步计算确保通信线程的及时响应。Required Interface必须实现的接口要创建自定义 Framing 插件需要继承FramerDeframer基类并实现以下两个方法deframe(self, data: bytes, no_copyFalse) - Tuple[bytes, bytes, bytes]将传入的字节数据解析为完整报文。返回一个三元组提取出的报文若数据不完整则返回None剩余待解析的字节当前帧之后尚不构成完整帧的残余数据被丢弃的数据无法归入任何帧、需要舍弃的字节。no_copy参数用于提示实现是否可以进行零拷贝优化避免在不必要时复制数据。frame(self, data: bytes) - bytes准备一条待发送的外出报文。该过程可能包括添加帧头header、校验和checksum或转义序列escape sequences等。最小可运行示例NullFramer文档给出的null_framing.py是一个不进行任何封装/解帧处理的空操作插件可作为自定义插件的最小骨架from typing import Tuple from fprime_gds.common.communication.framing import FramerDeframer from fprime_gds.plugin.definitions import gds_plugin gds_plugin(FramerDeframer) class NullFramer(FramerDeframer): No-op framer/deframer plugin def frame(self, data: bytes) - bytes: return data def deframe(self, data: bytes, no_copyFalse) - Tuple[bytes, bytes, bytes]: return data, b, b要点解读gds_plugin(FramerDeframer)装饰器将类注册为FramerDeframer类型的 GDS 插件使框架能够在插件目录中自动发现并作为SELECTION选项提供给用户frame直接原样返回数据不添加任何帧结构deframe将整段输入视为一个完整报文返回剩余字节与丢弃数据均为空。F Prime 默认帧协议插件背后的字节布局GDS 默认 Framing 插件所实现的 F Prime 协议是一种极简通信协议同时用于上行uplink与下行downlink通信主要用于配合 F´ GDS 快速起步不做任何高级特性侧重测试用途。该协议规范定义于仓库 Svc/FprimeProtocol/docs/sdd.md。一帧由 4 个字段组成字段宽度说明Start word起始字32 位用于标识帧起始恒为0xDEADBEEFPayload length载荷长度32 位载荷数据的字节数Payload data载荷数据变长F Prime 报文Fw::Com::ComPacket长度由上一字段指定内部至少包含一个可配置宽度的FwPacketDescriptorType类型标识字段CRC校验和32 位用于校验帧完整性帧格式示意如下[!NOTE] 由于载荷长度字段仅 4 字节F Prime 协议不支持超过 2^32 - 1 字节约 4 GB的报文。从源码看帧头与帧尾在 FPP 中被建模为可序列化对象Svc::FprimeDeframer的 FprimeDeframer.cpp 引入了Svc/FprimeProtocol/FrameHeaderSerializableAc.hpp与Svc/FprimeProtocol/FrameTrailerSerializableAc.hpp分别对应FprimeProtocol::FrameHeader含startWord与lengthField与FprimeProtocol::FrameTrailer含crcField帧头/帧尾的序列化尺寸由SERIALIZED_SIZE常量给出。与飞行软件侧的对应关系Framer 与 Deframer 组件GDS 的 Framing Plugin 负责地面侧的封装/解帧而飞行软件侧的对应职责由Svc::FprimeFramer下传封装与Svc::FprimeDeframer上传解帧组件完成。理解这两个组件的内部逻辑有助于把握 Framing Plugin 需要匹配的协议细节。下传侧Svc::FprimeFramerSvc::FprimeFramer是 FramerInterface 针对 F Prime 协议的实现定义于 Svc/FprimeFramer/FprimeFramer.fpp其设计说明见 Svc/FprimeFramer/docs/sdd.md。它接收一个 F´ 报文Svc.ComDataWithContext内含承载数据的Fw::Buffer与携带上下文信息如 APID 的context在输出端口产出一帧 F´ 帧。处理流程为分配一个新的outBufferFw::Buffer大小为size(dataPacket) size(FprimeHeader) size(FprimeTrailer)将 F´ 起始字0xDEADBEEF与长度令牌size(dataPacket)序列化进outBuffer将 F´ 报文数据序列化进outBuffer计算并序列化 CRC32 校验和进outBuffer在dataOut输出端口发出outBuffer其所有权移交给接收方将输入dataPacket的所有权经dataReturnOut归还通常应连接到原发送组件。在默认配置配合Svc::ComQueue下context还用于区分报文来自 ComQueue 的Fw::Buffer队列还是ComPacket队列从而决定是否将原始缓冲区返还给发送方。其端口构成如下KindNamePort Type用途guarded inputdataInSvc.ComDataWithContext接收待封装的数据Fw::Buffer 可选 contextoutputdataOutSvc.ComDataWithContext输出已封装帧sync inputdataReturnInSvc.ComDataWithContext收回经dataOut发出的缓冲区所有权outputdataReturnOutSvc.ComDataWithContext归还经dataIn接收的缓冲区所有权sync inputcomStatusInFw.SuccessCondition接收下游通信适配器的状态outputcomStatusOutFw.SuccessCondition向上游Svc::ComQueue上报封装器状态此外组件在无法分配帧缓冲区时会发出NoBufferAvailable告警事件warning high节流 5 次并丢弃该帧。可见缓冲区资源紧张时下行帧会直接丢失这也解释了为什么在 GDS 侧与飞行软件侧都应关注帧缓冲区的配置。上传侧Svc::FprimeDeframerSvc::FprimeDeframer是 DeframerInterface 针对 F´ 通信协议的实现定义于 Svc/FprimeDeframer/FprimeDeframer.fpp设计说明见 Svc/FprimeDeframer/docs/sdd.md。它接收一帧 F´ 帧Fw::Buffer剥离帧头与帧尾后将封装的载荷通过dataOut输出端口交给下游组件通常是 Svc.FprimeRouter。实现上并不复制数据通过data.advance(SERIALIZED_SIZE)让数据指针越过帧头、再setSize(getSize() - TRAILER_SIZE)收缩尺寸以剔除帧尾属于对输入缓冲区的原地修改缓冲区所有权随后转移给dataOut的下游组件。从 FprimeDeframer.cpp 的dataIn_handler可以看到完整的帧校验流程长度下限校验缓冲区至少能容纳帧头 帧尾否则发InvalidBufferReceived事件并丢帧起始字校验反序列化帧头后startWord必须等于默认值即0xDEADBEEF否则发InvalidStartWord事件并丢帧长度一致性校验缓冲区总尺寸必须恰好等于帧头尺寸 帧头中声明的载荷长度 帧尾尺寸否则发InvalidLengthReceived事件并丢帧CRC 校验将 CRC 字段与对帧头 载荷按字节计算所得哈希比对否则发InvalidChecksum事件并丢帧哈希计算使用Utils::Hash最终取asBigEndianU32()与大端序 CRC 字段比较APID 提取若载荷足够长尝试反序列化FwPacketDescriptorType并写入context供下游路由使用若描述符非法则回退为INVALID_UNINITIALIZED交由下游如自定义路由处理。凡是校验失败的帧都会被丢弃不发载荷到输出端口并经由dataReturnOut将输入缓冲区所有权归还发送方。校验失败时对应的事件均以 warning high 等级上报事件触发条件InvalidBufferReceived缓冲区长度不足以容纳帧头 帧尾InvalidStartWord缓冲区不以 F´ 起始字开头InvalidLengthReceived缓冲区尺寸与帧头声明的帧尺寸不符InvalidChecksum帧内 CRC 与接收方计算值不一致PayloadTooShort缓冲区过短无法容纳有效FwPacketDescriptorwarning low同时需要说明的是F´ 通信协议不支持在一个帧内拼接多个报文因此Svc::FprimeDeframer不做多报文解帧。帧的汇聚FrameAccumulator 与检测器GDS 的deframe需要自己从字节流中切分出完整帧而在飞行软件上传侧这一职责由 Svc::FrameAccumulator 承担——它把一串Fw::Buffer累积进环形缓冲区Utils::CircularBuffer再由 Svc::FrameDetector针对 F´ 协议的实现是Svc::FrameDetectors::FprimeFrameDetector在环形缓冲区头部检测帧。每个新缓冲区到达后FrameAccumulator进入detect()循环得到三种结果NO_FRAME_DETECTED头部不是有效帧例如起始字不匹配环形缓冲区逐字节旋转后继续探测直到缓冲区耗尽FRAME_DETECTED头部存在完整帧分配新的Fw::Buffer拷贝该帧并经dataOut发出随后旋转缓冲区移除已消费数据并归还原始缓冲区MORE_DATA_NEEDED数据尚不足以判定是否成帧归还原始缓冲区并挂起等待下一个缓冲区的到来。其典型工作流程如下上行帧不必与缓冲区边界对齐一帧可以横跨多个缓冲区。若检测器报告的帧尺寸超过内部累积缓冲区容量则记录告警事件并继续寻找新帧关闭前需调用cleanup()以释放configure()中分配的环形缓冲区内存。这一点对编写 GDS Framing Plugin 具有直接借鉴意义飞行软件侧的FrameAccumulator通过环形缓冲 状态机式检测容忍任意字节流切分GDS 插件同样需要把不完整的字节保留到下一次deframe调用中继续累积而不是直接丢弃。编写 Framing Plugin 的完整流程与最佳实践综合文档与仓库实现编写并启用一个自定义 Framing Plugin 的步骤为继承基类在 Python 模块中继承fprime_gds.common.communication.framing.FramerDeframer实现frame定义外出数据的封装策略。若要支持 F´ 协议需依次写入起始字0xDEADBEEF4 字节、载荷长度4 字节、载荷数据与 CRC32 校验值并注意大端字节序与飞行软件侧 FprimeFramer 保持一致实现deframe定义进入数据的解帧策略。参照 FprimeDeframer.cpp 的校验顺序——先定位起始字、再核对长度、最后校验 CRC——并以三元组(packet, remaining, discarded)返回结果未凑齐的字节应放入remaining等待下一次调用注册插件使用gds_plugin(FramerDeframer)装饰器注册使插件进入 GDS 的SELECTION候选列表由用户在启动 GDS 时选择启用回归验证可对照飞行软件侧 FprimeFramer/FprimeDeframer 的单元测试见 Svc/FprimeFramer/test/ut/ 与 Svc/FprimeDeframer/test/ut/用其期望的帧字节布局来校验自己插件的封装与解析结果。实践中应遵循的工程原则包括保持deframe/frame为纯字节变换逻辑避免在通信线程内执行文件 I/O、网络重连或大规模内存分配对于不认识的字节应明确归入丢弃数据而不是无限缓存防止内存膨胀同时兼顾no_copy提示以降低高频通信下的拷贝开销。小结Framing Plugin 是 F´ GDS 通信链路上与具体传输协议解耦的关键扩展点它把字节流 ↔ 协议帧 ↔ F Prime 报文的转换逻辑以SELECTION插件的形式开放给用户无论对接 CCSDS 还是自定义链路协议都只需实现frame与deframe两个方法。仓库侧的 Svc/FprimeProtocol/docs/sdd.md、Svc/FprimeFramer/docs/sdd.md、Svc/FprimeDeframer/docs/sdd.md 与 Svc/FrameAccumulator/docs/sdd.md 则完整展示了 F´ 默认帧协议的字节布局、校验规则、缓冲区所有权流转与跨缓冲区帧汇聚机制为自定义插件的正确实现提供了可直接对照的参考实现与测试基准。【免费下载链接】fprimeF´ - A flight software and embedded systems framework项目地址: https://gitcode.com/GitHub_Trending/fpr/fprime创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考