F´ 地面接口(Ground Interface)架构解析与自定义扩展实践指南
F´ 地面接口Ground Interface架构解析与自定义扩展实践指南【免费下载链接】fprimeF´ - A flight software and embedded systems framework项目地址: https://gitcode.com/GitHub_Trending/fpr/fprime本文以 F´F Prime飞行软件框架的地面接口为核心系统拆解其航天器侧的 uplink/downlink 双链路与 framing/driver 双层结构并结合仓库源码说明如何为现有框架添加自定义线协议与自定义 ByteStream 驱动。读完本文你将掌握 F´ 地面接口各组件驱动、帧累积器、成帧器/解帧器、路由器的职责与端口契约能够在不替换整个地面接口的前提下完成针对性适配例如对接 COSMOS、OpenMCT 等地面系统。Ground Interface 总体架构F´ 的地面接口分为两个部分航天器侧spacecraft side与地面侧ground side。本文聚焦航天器侧的适配——最常见的工程模式是改造 F´ 飞行软件以对接某种已有的地面系统如 OpenC3 COSMOS、NASA OpenMCT 等。得益于模块化的分层设计大多数项目只需要做局部适配而无需整体替换地面接口。在最基本的形式下F´ 地面系统由uplink上行与downlink下行两侧组成每一侧又分为framing成帧与driver驱动两层Uplink处理来自接口远端地面站的数据将其解包为 F´ 数据类型并路由到整个 F´ 系统Downlink处理发往远端接口的数据Framing负责在数据与字节缓冲区之间做序列化/反序列化成帧与解帧Driver负责向硬件读写字节。注意本指南中称其为驱动层许多项目中把它叫作电台radio层或通信层。该层的功能就是向某个硬件读写字节只要硬件能收发字节其具体形态TCP、UART、总线等对本层而言并不重要。框架的分层设计使得成帧协议可以独立拆出、快速适配。此外每一级处理都需要分配内存因此使用者还应当参考 缓冲区池管理指南为驱动、成帧/解帧、路由各环节规划好缓冲区来源。标准 F´ 组件处理两类数据com buffers与raw buffers。Com buffers 承载标准的 F´ 条目如事件、遥测、命令raw buffersFw::Buffer承载任意原始字节如文件数据。因此地面接口必须同时处理这两类数据。通信硬件通常只传输字节、对数据本身的性质一无所知地面接口的目标就是把各种 F´ 数据翻译成一段字节序列并保证其在接口另一侧可以被完整重建。Driver 层硬件通信管理驱动负责管理硬件通信。它既可以是简单的硬件接口如 TCP 或 UART也可以是相当复杂的构造如电台、航天器总线。从 F´ 的角度看驱动有两个职能提供输入数据与处理输出数据。注意通常项目使用单个驱动同时处理输入与输出但如果上下行需要不同的行为也可以使用两个驱动例如 UDP 下行追求速度、TCP 上行保证可靠性。所有驱动都实现一个接收成帧器数据的输入端口——驱动应把输入数据写入其管理的硬件。驱动通过recv输出端口递交收到的数据该端口通常由一个读线程支撑。接收方使用完毕后通过驱动的recvReturnIn端口归还缓冲区所有权。发送数据Sending Data要向驱动发送数据需把一个Fw::Buffer传入驱动的 send 输入端口缓冲区包裹的数据会被推送到硬件。同步驱动实现Drv.ByteStreamDriver直接从 send 调用返回Drv.ByteStreamStatus枚举值之一且调用方保留缓冲区所有权ByteStreamStatus.OP_OK发送成功ByteStreamStatus.SEND_RETRY后续重传很可能会成功ByteStreamStatus.OTHER_ERROR发生错误数据未发送重试可能成功。异步驱动实现Drv.AsyncByteStreamDriver在 send 时接管缓冲区所有权并通过其sendReturnOut回调端口同时返回状态与缓冲区。接收数据Receiving Data驱动通常有一个内部任务收到数据时调用recv输出端口。接收端口传递一个Fw::Buffer与一个Drv.ByteStreamStatus状态ByteStreamStatus.OP_OK接收正常缓冲区包含有效数据ByteStreamStatus.RECV_NO_DATA接收正常但没有数据ByteStreamStatus.OTHER_ERROR接收失败缓冲区没有有效数据。当接收组件处理完缓冲区后通过驱动的recvReturnIn端口把所有权归还给驱动。源码中的驱动契约ByteStreamDriver / AsyncByteStreamDriver地面接口对驱动的兼容性要求定义在 Drv/Interfaces 目录的 FPP 接口文件中。同步接口 ByteStreamDriver.fpp 定义如下四个端口output port ready: Drv.ByteStreamReady output port $recv: Drv.ByteStreamData guarded input port $send: Drv.ByteStreamSend guarded input port recvReturnIn: Fw.BufferSendready输出驱动无参调用该端口表示其已就绪、可以收发数据recv输出驱动调用该端口并携带一个Drv.ByteStreamStatus与一个Fw::Buffer用于递交收到的数据send输入客户端调用该端口并传入Fw::Buffer以发送数据状态同步返回调用方保留缓冲区所有权recvReturnIn输入客户端通过该端口归还通过recv收到的缓冲区所有权。异步接口 AsyncByteStreamDriver.fpp 则把同步的$send替换为async input port $send: Fw.BufferSend并新增output port sendReturnOut: Drv.ByteStreamData通过该回调返回发送状态与缓冲区所有权。从源码结构看同一文件还为驱动客户端定义了配套的ByteStreamDriverClient接口drvConnected、drvReceiveIn、drvReceiveReturnOut、drvSendOut供成帧/通信栈一侧连接使用。发送与接收状态的完整语义可进一步查阅 ByteStreamDriverModel 设计文档其中明确了同步与异步两种版本下缓冲区所有权的流转规则并列出框架内实现该模型的组件——Drv::TcpClient、Drv::TcpServer、Drv::Udp 与 Drv::PosixUartDriver。Uplink上行链路组件链Uplink 处理收到的数据解包 F´ 数据类型并将其路由到更大的 F´ 系统。典型组态下解出的 com buffers 被送往命令调度器command dispatcherraw buffers 被送往文件上行组件file uplink。Uplink 由多个组件串联实现Svc.FrameAccumulator从驱动处累积字节直到检测出一个完整帧实现 Svc.DeframerInterface 端口接口的组件把帧解包为 F´ 数据类型。F´ 自带多种协议实现Svc.FprimeDeframer用于轻量级的 F´ 协议Svc.Ccsds 包包含 CCSDS TC 与 Space Packet 协议实现实现 Svc.RouterInterface 端口接口的路由组件把解包后的 F´ 数据类型路由到其目的地命令调度器、文件上行等。F´ 自带 Svc.FprimeRouter 实现 F´ 数据类型的路由。FrameAccumulator从字节流中提取完整帧Svc.FrameAccumulator 把输入的一串Fw::Buffer累积进一个环形缓冲区Utils::CircularBuffer并借助Svc::FrameDetector检测完整帧。每个新缓冲区到达后组件会循环调用detect()依据返回值处理NO_FRAME_DETECTED环形缓冲区头部没有有效帧如起始字不匹配组件将环形缓冲区旋转一个字节后再次检测直到缓冲区耗尽FRAME_DETECTED当前头部存在完整帧组件分配新Fw::Buffer拷贝帧数据连同最近一次dataIn调用的ComCfg::FrameContext一起从dataOut发出随后旋转环形缓冲区移除已提取的数据MORE_DATA_NEEDED数据不足组件释放输入Fw::Buffer并等待下一个缓冲区。上行帧无需与缓冲区边界对齐一个帧可以跨越一个或多个缓冲区。若检测器报告的帧尺寸超过内部累积缓冲容量组件会记录告警事件并继续寻找新帧。值得注意的是FrameDetector是一个 C 辅助类而非 FPP 组件F´ 通信协议的标准实现是Svc::FrameDetectors::FprimeFrameDetector自定义协议场景下可自行实现该类的detect()虚函数见下文自定义成帧协议一节。Deframer解帧并校验Svc.FprimeDeframer 在dataIn端口收到 F´ 帧后依据 F´ 协议帧规范 校验缓冲区是否为有效帧缓冲区足够容纳头部与尾部、以 F´ 起始字开头、长度与帧头长度字段一致、CRC 与帧头载荷计算值一致然后通过修改缓冲区的长度与数据指针偏移来剥离头部与尾部把载荷从dataOut发出。任一校验失败都会丢弃该帧并通过dataReturnOut归还输入缓冲区所有权。该组件不支持单帧内拼接多个数据包。Router路由 F´ 数据包Svc.FprimeRouter 接收Svc.ComDataWithContext类型的数据包依据上下文中的 APID由解帧栈根据包类型设置做同步端口调用完成路由FW_PACKET_COMMAND发往commandOut、FW_PACKET_FILE发往fileOut未知包类型发往unknownDataOut可连接项目自定义组件实现扩展路由。文件与未知包缓冲区不经拷贝直接透传接收方处理完后必须通过fileBufferReturnIn归还路由器才会把原始缓冲区还给解帧器路由器内部用FprimeRouterCfg.BufferContextTableSize容量大小的表维护缓冲区→上下文关联以在归还时恢复原始FrameContext如vcId。表满或查找失败时发出告警事件并以空上下文归还缓冲区。典型组态中commandOut连接 Svc.CmdDispatcherfileOut连接 Svc.FileUplink。Downlink下行链路组件Downlink 接收 F´ 数据用支持所需协议的字节将其包装成帧然后交给驱动发送。Downlink 由一个实现Svc.FramerInterface端口接口的组件实现F´ 自带两种协议的实现Svc.FprimeFramer实现 F´ 轻量协议Svc.Ccsds 包包含 CCSDS TM 与 Space Packet 协议实现。以 Svc.FprimeFramer 为例其内部处理流程为收到数据包后分配一个尺寸为数据包大小 F´ 帧头 帧尾的新outBuffer序列化 F´ 起始字0xDEADBEEF与长度 token再序列化数据包数据计算并序列化 CRC32 校验和最后把outBuffer从dataOut发出所有权转交接收方同时通过dataReturnOut把输入数据包所有权归还给原发送方通常是 Svc.ComQueue。其comStatusIn/comStatusOut端口遵循 Framer Status Protocol 透传Fw.SuccessCondition状态包括启动时的初始SUCCESS、逐消息状态以及故障后的恢复SUCCESS。添加自定义线协议Wire Protocol如需引入自定义协议如私有 CCSDS 变体、自定义遥测格式等请遵循完整的 How-To 实现成帧协议指南。要点摘录如下现代 F´ 部署默认通过Svc.ComCcsds子拓扑使用 CCSDS 协议轻量级的 F´ 协议Svc.ComFprime是 F´ GDS 可理解的低开销替代方案双向实现需要同时实现 framer下行与 deframer上行流式传输TCP、UART下通常还需一个可选的 FrameDetector 辅助类创建组件时推荐使用被动组件并启用事件fprime-util new --component在 FPP 中通过import Svc.Framer与import Svc.Deframer让自定义组件实现对应接口随后实现dataIn_handler、dataReturnIn_handler以及 framer 的comStatusIn_handler等 C 处理函数需在 deframer 中提取并设置FrameContext中的 APID否则 Svc.FprimeRouter 无法确定包的路由去向集成时删除import Svc.ComCcsds、手动把子拓扑代码复制进主拓扑并替换framer/deframer实例若出现缺失头文件或未声明的端口枚举等编译错误需要清理deployment/Top/下自动生成的TopologyDefs.hpp并执行fprime-util generate --force自定义 FrameDetector 还需在CMakeLists.txt中用DEPENDS声明依赖若需要 F´ GDS 支持自定义协议可实现继承FramerDeframer的 GDS 插件详见 GDS 插件开发指南 与 F´ GDS 成帧插件参考并在虚拟环境中打包安装后通过fprime-gds --framing-selection MyCustomProtocol选择协议。添加自定义驱动Custom Driver要与本地面接口兼容驱动必须实现 Drv/Interfaces 中定义的字节流驱动接口之一Drv.ByteStreamDriver同步发送或Drv.AsyncByteStreamDriver异步发送。驱动可以根据需要增加任何其他端口、事件、遥测或其他 F´ 构造。同步接口定义的端口如下output port ready: Drv.ByteStreamReady output port $recv: Drv.ByteStreamData guarded input port $send: Drv.ByteStreamSend guarded input port recvReturnIn: Fw.BufferSendready输出驱动无参调用该端口表示已就绪、可收发数据recv输出驱动调用该端口并携带Drv.ByteStreamStatus与Fw::Buffer提供收到的数据send输入客户端调用该端口并传入Fw::Buffer发送数据状态同步返回调用方保留缓冲区所有权recvReturnIn输入客户端通过该端口归还经recv收到的缓冲区所有权。异步接口则把同步的$send替换为async input port $send: Fw.BufferSend并新增output port sendReturnOut: Drv.ByteStreamData通过该端口返回发送状态与缓冲区所有权实现见 AsyncByteStreamDriver.fpp。从源码结构看仓库中的 Drv::TcpClient、Drv::TcpServer、Drv::Udp 与 Drv::PosixUartDriver 都是基于同步字节流模型的具体驱动实现可作为编写自定义驱动例如封装新型电台、CAN 或空间总线时的参照范本其底层套接字封装位于 Drv/Ip 目录IpSocket、TcpClientSocket、TcpServerSocket、UdpSocket等。总结F´ 地面接口通过上行/下行 × 成帧/驱动的清晰分层把通信协议的适配成本降到最低驱动层只需要满足Drv.ByteStreamDriver或Drv.AsyncByteStreamDriver的端口契约成帧/解帧层则通过Svc.Framer/Svc.Deframer接口与Svc.FrameAccumulator、Svc.FprimeRouter等标准组件即插即用。对大多数项目而言无需整体替换地面接口——只需根据本文所述端口契约新增一个自定义驱动、或按照 自定义成帧协议指南 实现协议组件即可把 F´ 飞行软件接入目标地面系统。【免费下载链接】fprimeF´ - A flight software and embedded systems framework项目地址: https://gitcode.com/GitHub_Trending/fpr/fprime创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考