十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

F´ 通信端口 Fw::Com 深度解析:飞行软件中的二进制数据包传输与序列化机制

F´ 通信端口 Fw::Com 深度解析:飞行软件中的二进制数据包传输与序列化机制 F´ 通信端口 Fw::Com 深度解析飞行软件中的二进制数据包传输与序列化机制【免费下载链接】fprimeF´ - A flight software and embedded systems framework项目地址: https://gitcode.com/GitHub_Trending/fpr/fprimeFw::Com是 F´F Prime飞行软件与嵌入式系统框架中用于传递二进制通信数据包的核心端口系统内外的入站、出站数据包均通过该端口进行序列化与传输。本文将基于 Fw/Com/docs/sdd.md 的设计文档结合仓库源码深入剖析该端口的定义、Fw::ComBuffer与Fw::ComPacket两大核心类型以及它在遥测下行、命令上行等典型拓扑中的实际用法帮助读者掌握 F´ 中数据包通道的设计思路与二次开发方法。1. Fw::Com 端口的设计定位根据 Fw/Com/docs/sdd.md 的说明Fw::Com端口Port用于将二进制数据传递给某个服务以便把数据传出系统used to pass binary data to a service for transporting data out of the system。进出的数据包都会被序列化到这些缓冲区中。在 F´ 的分层架构中FwFoundation层提供最基础的端口与类型定义SvcServices层中的各类通信组件如ComQueue、ComStub、ComLogger、FprimeRouter等正是通过Fw::Com端口完成数据包的接收、排队、记录与转发。可以把它理解为 F´ 中所有字节流级数据进出的标准接口——无论是命令、遥测还是文件数据在底层最终都以Fw::ComBuffer的形式在Fw::Com端口上流动。2. 端口定义与信号签名Fw::Com端口的定义位于 Fw/Com/Com.fpp使用 FPPF´ Prime Prime建模语言声明module Fw { type ComBuffer Port for passing communication packet buffers port Com( ref data: ComBuffer Buffer containing packet data context: U32 Call context value; meaning chosen by user ) }端口签名的两个参数含义如下参数类型说明dataFw::ComBufferref引用传递包含数据包内容的缓冲区contextU32调用上下文值其具体含义由用户自行约定例如用于区分端口数组中的不同实例值得注意的设计点引用传递ref数据包缓冲区以引用方式传递避免大块二进制数据的复制开销这对嵌入式场景下的性能至关重要上下文参数context不参与数据包本身的编码而是由调用方自由定义的语义标记可用于在Com端口数组port array场景下传递端口序号或调用意图。Fw/Com/CMakeLists.txt 中通过register_fprime_module将 Com.fpp 作为 autocoder 输入、ComPacket.cpp作为源文件注册进构建系统FPP 编译器会自动为Com端口生成输入/输出端口类Fw::InputComPort/Fw::OutputComPort。3. Fw::ComBuffer通信数据包的载体3.1 类型定义Fw::ComBuffer是端口上实际承载数据的类型。其定义位于 Fw/Com/ComBuffer.hpp#include Fw/Types/LinearBufferTemplate.hpp namespace Fw { using ComBuffer LinearBufferTemplateFW_COM_BUFFER_MAX_SIZE; } // namespace Fw它本质上是 Fw/Types/LinearBufferTemplate.hpp 这个模板类的实例化别名即以FW_COM_BUFFER_MAX_SIZE为容量的固定大小线性序列化缓冲区。3.2 底层实现LinearBufferTemplate继承自LinearBufferBase参见 Fw/Types/SerialBuffer.hpp 中同基类的用法其核心特征包括内嵌固定大小数组U8 m_bufferData[MaxSize]在栈上/对象内部静态分配不依赖堆内存适合资源受限的飞行软件环境提供setBuff()填充数据、getSize()当前有效数据长度、getCapacity()最大容量等接口具备完整的序列化/反序列化能力作为SerialBufferBase的派生类可直接配合Serializable体系使用模板定义中SERIALIZED_SIZE STATIC_SERIALIZED_SIZE(MaxSize)表示缓冲区被进一步序列化时占用的大小数据本身 长度字段这一点在Svc::ComQueue中有实际应用见下文第 6 节构造函数与拷贝赋值均通过setBuff复制数据并以FW_ASSERT断言序列化状态保证内存安全。由于Fw::ComBuffer只是类型别名端口参数、组件内部成员以及 FPP 生成代码都直接使用这一统一类型避免了为每种包类型手写重复的缓冲区类。4. Fw::ComPacket数据包类型的统一识别4.1 设计意图根据 Fw/Com/docs/sdd.md 的说明Fw::ComPacket类是其他包类型的基类为各数据包子类型提供类型标识能力而Fw::ComBuffer则作为这些包类型序列化时的目标缓冲区。4.2 数据包内存格式ComPacket.hpp头部注释明确给出了包的内存布局| packet type (width FwPacketDescriptorType) | packet type-specific data |即每个数据包开头是一个类型描述符FwPacketDescriptorType其后跟随类型专属的数据内容。接收端通过解析首部类型字段即可分发到对应的处理逻辑。4.3 源码实现Fw/Com/ComPacket.cpp 给出了两个关键保护方法ComPacket::ComPacket() : m_type(ComPacketType::FW_PACKET_UNKNOWN) {} SerializeStatus ComPacket::serializeBase(SerialBufferBase buffer) const { return buffer.serializeFrom(static_castFwPacketDescriptorType(this-m_type)); } SerializeStatus ComPacket::deserializeBase(SerialBufferBase buffer) { FwPacketDescriptorType serVal; SerializeStatus stat buffer.deserializeTo(serVal); if (FW_SERIALIZE_OK stat) { this-m_type static_castComPacketType(serVal); } return stat; }关键点构造函数默认将类型置为FW_PACKET_UNKNOWN未知包serializeBase()/deserializeBase()被派生类调用用于序列化/反序列化公共字段类型描述符类型字段以FwPacketDescriptorType宽度写入缓冲区读取失败时保持类型不变并返回错误状态。4.4 包类型的配置来源ComPacketType来自 default/config/ComCfg.fpp 中定义的dictionary enum Apid : FwPacketDescriptorType其中包括FW_PACKET_UNKNOWN等预定义枚举值。这意味着 F´ 的包类型标识符统一由配置文件管理各协议命令、遥测、事件、文件等的具体包类型可在此基础上扩展。5. 端口的系统图与数据流Fw::Com端口的设计框图位于 Fw/Com/docs/img/FwComBDD.jpg展示了Fw命名空间下ComBuffer数据类型与Com端口类型的关系Com端口携带一个data : ComBuffer参数ComBuffer的定义包含 Fw/Com/ComBuffer.hpp 头文件。Fw::Com 端口设计框图在典型拓扑中的数据流为上层组件如遥测组包器Svc::TlmPacketizer、命令分发器Svc::CmdDispatcher将数据序列化到Fw::ComBuffer通过Fw::Com输出端口comOut将缓冲区下发给通信服务组件通信服务组件如ComQueue、ComStub、FprimeRouter接收后执行排队、路由或物理链路发送入站方向反之链路层数据被反序列化到Fw::ComBuffer再经Fw::Com输入端口comIn上交给上层解析。6. 仓库中的实际应用ComQueue 等组件的使用证据Fw::Com端口在Svc层被广泛实例化最典型的证据是 Svc/ComQueue/ComQueue.fpp 与 Svc/ComQueue/ComQueue.cppComQueue声明了接收Fw::ComBuffer的端口数组并为每个Fw::Com端口配置独立的队列深度在 ComQueue.cpp#L96-L97 中队列条目大小按Fw::ComBuffer::SERIALIZED_SIZE计算说明LinearBufferTemplate的序列化大小常量被实际用于存储规划ComQueue.cpp#L232 的comPacketQueueIn_handler(const FwIndexType portNum, Fw::ComBuffer data, U32 context)正是 FPP 自动生成的Fw::Com输入端口处理函数其签名与第 2 节端口定义一一对应ComQueue.cpp#L335 的enqueue与 ComQueue.cpp#L405 的sendComBuffer分别完成入队与向下游转发转发时同样通过Fw::Com输出端口传递Fw::ComBuffer。此外Svc下的ComStub、ComLogger、FprimeRouter、FprimeFramer等组件均以Fw::Com端口作为标准通信接口共同构成 F´ 的下行链路downlink/上行链路uplink数据通路。7. 容量配置FW_COM_BUFFER_MAX_SIZEFw::ComBuffer的容量上限由宏FW_COM_BUFFER_MAX_SIZE决定定义于 default/config/FpConstants.fppconstant FW_COM_BUFFER_MAX_SIZE 512该常量是整个 F´ 通信体系的基础容量基准并且被其他缓冲区的尺寸直接派生constant FW_CMD_ARG_BUFFER_MAX_SIZE FW_COM_BUFFER_MAX_SIZE - sizeof(FwOpcodeType) - sizeof(FwPacketDescriptorType) constant FW_LOG_BUFFER_MAX_SIZE FW_COM_BUFFER_MAX_SIZE - sizeof(FwEventIdType) - sizeof(FwPacketDescriptorType) constant FW_TLM_BUFFER_MAX_SIZE FW_COM_BUFFER_MAX_SIZE - sizeof(FwChanIdType) - sizeof(FwPacketDescriptorType)也就是说命令参数缓冲区、日志事件缓冲区、遥测缓冲区的最大尺寸都从FW_COM_BUFFER_MAX_SIZE中减去各自包头字段后得到——它们最终都以Fw::ComBuffer为载体在Fw::Com端口上传输。默认值为 512 字节开发者可以在项目的config目录中按需调整。8. 变更日志Fw/Com/docs/sdd.md 记录的变更历史如下日期描述2015-06-22初始版本Initial Version9. 总结与二次开发指引Fw::Com端口是 F´ 框架中数据包进出系统的统一标准接口其设计核心可以概括为三点统一的缓冲区类型Fw::ComBuffer基于LinearBufferTemplateFW_COM_BUFFER_MAX_SIZE提供固定容量、免堆分配的二进制载体统一的数据包模型Fw::ComPacket以FwPacketDescriptorType类型字段打头为命令包、遥测包等子类型提供公共的序列化基础与类型分发能力标准化的端口签名(ref data: ComBuffer, context: U32)简单而通用配合 FPP 自动代码生成任何组件只需声明comIn/comOut即可无缝接入 F´ 的通信链路。若需在自有组件中使用该端口可参考 Svc/ComQueue/ComQueue.fpp 的声明方式sync input port comPacketQueueIn: [COM_PORT_COUNT] Fw.Com之类并阅读 Svc/ComQueue/ComQueue.cpp 中对应的*_handler实现来了解完整的收发流程。FPP 工具链会自动生成端口类的调用与实现代码开发者只需在组件实现中填充业务逻辑即可。【免费下载链接】fprimeF´ - A flight software and embedded systems framework项目地址: https://gitcode.com/GitHub_Trending/fpr/fprime创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表