news 2026/9/15 10:00:59

F´ ComFprime 通信子拓扑深度解析:F´ 帧协议上下行的轻量级通信栈实战指南

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
F´ ComFprime 通信子拓扑深度解析:F´ 帧协议上下行的轻量级通信栈实战指南

F´ ComFprime 通信子拓扑深度解析:F´ 帧协议上下行的轻量级通信栈实战指南

【免费下载链接】fprimeF´ - A flight software and embedded systems framework项目地址: https://gitcode.com/GitHub_Trending/fpr/fprime

导读

ComFprime 是 F´(F Prime)飞行软件与嵌入式系统框架内置的一组通信子拓扑(Subtopology),它把 F´ 轻量级通信栈中负责"组帧/解帧(framing/deframing)"的各个标准组件——Svc.FprimeFramerSvc.FprimeDeframerSvc.FprimeRouterSvc.ComQueueSvc.FrameAccumulatorSvc.BufferManager——预装配为两种可直接复用的拓扑变体,并统一通过ComFprimeConfig配置实例属性。本文基于 ComFprime SDD 并结合仓库源码,完整讲解两种变体的接线方式、全部配置项与底层实现细节;读完本文,你将能够在自己部署的 F´ 拓扑中正确复用 ComFprime,把 ByteStream 驱动(TCP/UDP/UART)或自定义通信接口接到 F´ 的帧协议上下行链路上。


1. 设计目标与需求概述

ComFprime 子拓扑聚焦于航天器侧的 F´ 帧协议通信栈,即把飞行软件内部产生的数据包(遥测、事件、文件)按 F Prime 格式组帧下行,并把外部传入的字节流解帧、路由为命令/文件上行。其需求来自 SDD 中的 SVC-COMFPRIME 系列:

ID需求描述验证方式
SVC-COMFPRIME-001提供 F´framer,将 COM 缓冲区转换为 F Prime 格式的帧化数据包下行Inspection
SVC-COMFPRIME-002提供 F´deframer,将上行传入的数据包解析为 COM 缓冲区Inspection
SVC-COMFPRIME-003提供 F´router,将解帧后的数据包(如命令/文件)路由进入飞行软件Inspection
SVC-COMFPRIME-004提供内置Svc::ComStub的子拓扑变体,用于对接 ByteStream 驱动Inspection
SVC-COMFPRIME-005提供期望部署方提供外部Svc::ComInterface的子拓扑变体Inspection
SVC-COMFPRIME-006支持通过ComFprimeConfig配置实例属性(ID、队列深度、栈大小、优先级、CPU 亲和性)Inspection

范围界定:这些子拓扑只实现F´ 通信协议提供 CCSDS 组帧/解帧能力,也不包含 CDH(指令与数据管理)功能。需要 CCSDS 空间包/TC/TM 帧能力时,应选用同目录下的 ComCcsds 子拓扑(见 Svc/Subtopologies/ComCcsds/ComCcsds.fpp)。


2. 架构与核心组件

2.1 实例总览(公共构建块)

两种变体共享同一组核心组件,见下表(与 ComFprime.fpp 中的实例声明一一对应):

实例名类型(Svc)种类核心职责
framerSvc.FprimeFramerPassive将 F´ 数据组帧为可传输的数据包
deframerSvc.FprimeDeframerPassive从传入数据包中解出 F´ 数据
fprimeRouterSvc.FprimeRouterPassive将解帧数据(命令/文件等)路由进飞行软件
comQueueSvc.ComQueueActive为组帧排队数据(遥测、事件、文件等),带run调度口
commsBufferManagerSvc.BufferManagerPassive为子拓扑提供内存分配(缓冲池)
frameAccumulatorSvc.FrameAccumulatorPassive解帧前按帧边界累积完整帧
comStubSvc.ComStubPassive(仅变体 A)将Drv::ByteStreamDriverModel驱动适配为下行链路

各实例在 ComFprime.fpp 中的基地址偏移(以ComFprimeConfig.BASE_ID为基准)依次为:comQueue +0x00000frameAccumulator +0x01000commsBufferManager +0x02000deframer +0x03000framer +0x04000fprimeRouter +0x05000comStub +0x06000。基地址默认值为0x03000000(见 ComFprimeConfig.fpp),部署时应注意与拓扑中其他组件的地址空间不冲突。

2.2 两种变体

  • 变体 A("带 ComStub"):子拓扑包含Svc::ComStub,对外暴露 ByteStream 端口,可直接接到你的Drv::ByteStreamDriverModel(TCP/UDP/UART 等)驱动上。
  • 变体 B("带外部 ComInterface"):子拓扑不包含Svc::ComStub,需要部署方自行提供一个实现Svc.Com接口的组件(如Svc::ComStubSvc::ComSplitter等),并将其与子拓扑的 framer/deframer 端口相连。

2.3 运行所需输入

根据 SDD 第 2.2 节,子拓扑正常工作需要三类接线:

  1. 速率组(Rate Groups):将调度器输出连接到comQueue.runSvc.ComQueue的调度口)。
  2. 传输端点(Transport Endpoint)
    • 变体 A:在你的Drv::ByteStreamDriverModel与子拓扑的ComStub之间接好ByteStream send/recv
    • 变体 B:提供你自己的Svc::ComInterface,并接到子拓扑的 framer/deframer 端口。
  3. 飞行侧挂接(Flight-side hookups):将router输出(命令/文件)接入 CDH 栈(如命令分发器Svc.CommandDispatcher、文件上行Svc.FileUplink),并将数据源(遥测/事件/文件下行)接入ComQueue

3. 数据通路详解(从源码看数据流)

ComFprime.fpp 中的两个连接块清晰地刻画了数据流:

下行(Downlink)链路

comQueue.dataOut -> framer.dataIn framer.dataReturnOut -> comQueue.dataReturnIn framer.bufferAllocate -> commsBufferManager.bufferGetCallee framer.bufferDeallocate -> commsBufferManager.bufferSendIn framer.comStatusOut -> comQueue.comStatusIn

遥测/事件/文件数据先进入comQueue排队,comQueue出队后交给framer组帧;组帧所需的Fw::BuffercommsBufferManager缓冲池分配/回收;链路状态(comStatus)回传给comQueue

上行(Uplink)链路

frameAccumulator.bufferDeallocate -> commsBufferManager.bufferSendIn frameAccumulator.bufferAllocate -> commsBufferManager.bufferGetCallee frameAccumulator.dataOut -> deframer.dataIn deframer.dataReturnOut -> frameAccumulator.dataReturnIn deframer.dataOut -> fprimeRouter.dataIn fprimeRouter.dataReturnOut -> deframer.dataReturnIn

外部字节流先进frameAccumulator按 F´ 帧格式累积出完整帧,再交deframer解帧,解出的数据包由fprimeRouter路由到命令分发器或文件上行栈。

Svc.ComQueue的接口定义(ComQueue.fpp)可以看到三个关键端口:comPacketQueueIn(异步输入,接收Fw.Com队列)、bufferQueueIn(异步输入,接收Fw.BufferSend)与run(调度口,Svc.Sched drop),其中run正是 SDD 所述需要速率组驱动的调度输入。

变体 A 的Subtopology通过import FramingSubtopology复用全部公共组件,仅额外增加comStub及三对端口连接(ComFprime.fpp):

  • 下行:framer.dataOut -> comStub.dataIncomStub.dataReturnOut -> framer.dataReturnIncomStub.comStatusOut -> framer.comStatusIn
  • 上行:comStub.dataOut -> frameAccumulator.dataInframeAccumulator.dataReturnOut -> comStub.dataReturnIn

4. 使用方式:两种变体的接线模式

以下两个 FPP 接线示例取自 SDD 第 3 节,接线时请以 ComFprime.fpp 中的确切端口名为准(例如变体 A 的子拓扑端口实际为ComFprime.Subtopology.comQueueRun,而非ComFprime.Subtopology.comQueue.run)。

4.1 变体 A — 带Svc::ComStub(对接 ByteStream 驱动)

topology Flight { instance ComFprime.Subtopology # (A1) 提供 ByteStreamDriver 接口(例如 Drv.TcpClient) instance comDriver: ... # (A2) 调度 ComQueue connections RateGroups { rg.RateGroupMemberOut[0] -> ComFprime.Subtopology.comQueueRun } # (A3) 连接 ByteStream 驱动 <-> 子拓扑提供的 ComStub connections ComDriver { comDriver.$recv -> ComFprime.Subtopology.drvReceiveIn ComFprime.Subtopology.drvReceiveReturnOut -> comDriver.recvReturnIn ComFprime.Subtopology.drvSendOut -> comDriver.$send comDriver.ready -> ComFprime.Subtopology.drvConnected } }

[!TIP] 若 ByteStream 驱动需要缓冲区管理,可使用ComFprime.Subtopology.commsBufferGetCalleeComFprime.Subtopology.commsBufferSendIn两个端口(分别对应commsBufferManager.bufferGetCallee/bufferSendIn,见 ComFprime.fpp)。

变体 A 对外暴露的完整端口清单(ComFprime.fpp)还包括:

  • 命令路由commandOut(输出,路由后的命令包到命令分发器)、cmdResponseIn(输入,命令响应返回 router);
  • 文件上行fileUplinkOut(输出,上行文件包到文件处理栈)、fileUplinkReturnIn(输入,文件栈归还缓冲区所有权);
  • 排队输入(数组端口,按索引连接)comPacketQueueInFw::ComBuffer队列,如遥测/事件)、bufferQueueInFw::Buffer队列,如文件下行)、bufferReturnOut(出队后归还Fw::Buffer所有权);
  • 驱动接口drvReceiveIndrvReceiveReturnOutdrvSendOutdrvConnected(见上文 A3 接线);
  • 调度comQueueRun

4.2 变体 B — 不带Svc::ComStub(外部提供 ComInterface)

topology Flight { import ComFprime.FramingSubtopology # (B1) 提供你自己的 ComInterface instance radio: ... # (B2) 调度 ComQueue connections RateGroups { rg.RateGroupMemberOut[0] -> ComFprime.comQueue.run } # (B3) 将你的 ComInterface 接到 ComFprime 的 framer/deframer connections Link { # Framer <-> ComInterface(下行) ComFprime.framer.dataOut -> radio.dataIn radio.dataReturnOut -> ComFprime.framer.dataReturnIn radio.comStatusOut -> ComFprime.framer.comStatusIn # ComInterface <-> FrameAccumulator(上行) radio.dataOut -> ComFprime.frameAccumulator.dataIn ComFprime.frameAccumulator.dataReturnOut -> radio.dataReturnIn } }

[!NOTE] 在变体 B 中,ComFprime.FramingSubtopology不定义comStub实例,且上行/下行与 ComInterface 的 5 个连接(2 个输出、3 个输入)必须由使用方在部署中自行建立,详见 ComFprime.fpp 顶部的用法注释。


5. 配置详解:ComFprimeConfig

SDD 明确要求只配置 ComFprime 子拓扑自身拥有的实例属性,所有配置旋钮统一位于:

Svc/Subtopologies/ComFprime/ComFprimeConfig/ComFprimeConfig.fpp

5.1 组件属性(ComFprimeConfig.fpp

下表汇总了 ComFprimeConfig.fpp 中的全部常量及其默认值,供实战参考:

配置项所属模块默认值说明
BASE_IDComFprimeConfig0x03000000子拓扑实例基地址,各组件在此基础上偏移
comQueueQueueSizes50ComQueue消息队列深度
comQueueStackSizes64 * 1024ComQueue任务栈大小
comQueuePriorities29ComQueue任务的 RTOS 优先级
comQueueCpuAffinitiesOs.TASK_DEFAULTCPU 亲和性,默认不绑定核心
eventsQueueDepths100事件子队列深度(最高优先级)
tlmQueueDepths500遥测子队列深度
fileQueueDepths100文件下行子队列深度
eventsQueuePriorities0事件子队列优先级(最高)
tlmQueuePriorities2遥测子队列优先级
fileQueuePriorities1文件子队列优先级

CpuAffinities默认值Os.TASK_DEFAULT表示不进行核绑定(无固定核心)。若部署硬件为多核且需要为通信任务分配专用核心,可在此改为具体核号。

5.2 ComQueue 排队配置(源码中的实际落地)

QueueDepthsQueuePriorities并不直接作为实例属性生效,而是通过ComQueueconfigComponents阶段写入其QueueConfigurationTable(见 ComFprime.fpp):

Svc::ComQueue::QueueConfigurationTable configurationTable; // Events(最高优先级) configurationTable.entries[Ports_ComPacketQueue::EVENTS].depth = ComFprimeConfig::QueueDepths::events; configurationTable.entries[Ports_ComPacketQueue::EVENTS].priority = ComFprimeConfig::QueuePriorities::events; // Telemetry configurationTable.entries[Ports_ComPacketQueue::TELEMETRY].depth = ComFprimeConfig::QueueDepths::tlm; configurationTable.entries[Ports_ComPacketQueue::TELEMETRY].priority = ComFprimeConfig::QueuePriorities::tlm; // File Downlink Queue(buffer 类队列排在 packet 队列之后) configurationTable.entries[Ports_ComPacketQueue::NUM_CONSTANTS + Ports_ComBufferQueue::FILE].depth = ComFprimeConfig::QueueDepths::file; configurationTable.entries[Ports_ComPacketQueue::NUM_CONSTANTS + Ports_ComBufferQueue::FILE].priority = ComFprimeConfig::QueuePriorities::file; // 分配器标识为 0(MallocAllocator 会忽略该值) ComFprime::comQueue.configure(configurationTable, 0, ComFprime::Allocation::memAllocator);

队列类型枚举定义于 ComFprime.fpp:Ports_ComPacketQueueEVENTSTELEMETRY(U8 枚举),Ports_ComBufferQueueFILE。可见comQueue实际由三个子队列构成,events优先级 0 最高、tlm优先级 2 最低、file居中。注意:上表中的优先级是子队列内部相对优先级,与 5.1 中Priorities.comQueue = 29(RTOS 任务优先级)含义不同,二者并存、互不替代。

5.3 Buffer Manager 缓冲池配置(module BuffMgr

module BuffMgrcommsBufferManager提供缓冲池(bins)常量(ComFprimeConfig.fpp):

常量默认值说明
frameAccumulatorSize2048frameAccumulator内部缓冲大小(字节)
commsBuffSize2048bin[0] 普通通信缓冲大小(字节)
commsFileBuffSize3000bin[1] 文件通信缓冲大小(字节)
commsBuffCount20bin[0] 缓冲数量
commsFileBuffCount30bin[1] 缓冲数量
commsBuffMgrId200缓冲池管理 ID

这些常量在commsBufferManagerconfigComponents阶段写入Svc::BufferManager::BufferBins结构并调用setup(ComFprime.fpp):

memset(&ConfigObjects::ComFprime_commsBufferManager::bins, 0, sizeof(...bins)); ConfigObjects::ComFprime_commsBufferManager::bins.bins[0].bufferSize = ComFprimeConfig::BuffMgr::commsBuffSize; ConfigObjects::ComFprime_commsBufferManager::bins.bins[0].numBuffers = ComFprimeConfig::BuffMgr::commsBuffCount; ConfigObjects::ComFprime_commsBufferManager::bins.bins[1].bufferSize = ComFprimeConfig::BuffMgr::commsFileBuffSize; ConfigObjects::ComFprime_commsBufferManager::bins.bins[1].numBuffers = ComFprimeConfig::BuffMgr::commsFileBuffCount; ComFprime::commsBufferManager.setup(ComFprimeConfig::BuffMgr::commsBuffMgrId, 0, ComFprime::Allocation::memAllocator, bins);

同理,frameAccumulatorconfigComponents阶段以FprimeFrameDetector作为帧检测器完成配置:

Svc::FrameDetectors::FprimeFrameDetector frameDetector; ComFprime::frameAccumulator.configure( ConfigObjects::ComFprime_frameAccumulator::frameDetector, 1, ComFprime::Allocation::memAllocator, ComFprimeConfig::BuffMgr::frameAccumulatorSize );

5.4 分配器(Allocator)

整个子拓扑的内存分配统一走ComFprime::Allocation::memAllocator,其实现位于 ComFprimeSubtopologyConfig.cpp:

namespace ComFprime { namespace Allocation { // 该实例可在 ComFprime 子拓扑中替换为其他分配器 Fw::MallocAllocator mallocatorInstance; Fw::MemAllocator& memAllocator = mallocatorInstance; } // namespace Allocation } // namespace ComFprime

默认使用Fw::MallocAllocator(堆分配)。对于安全关键/资源受限的嵌入式部署,可在 ComFprimeSubtopologyConfig.hpp 声明的ComFprime::Allocation命名空间中替换为静态内存池等自定义Fw::MemAllocator实现,无需改动子拓扑接线。

5.5 生命周期管理

comQueueframeAccumulatorcommsBufferManager三个带资源实例均注册了tearDownComponents阶段的清理逻辑(comQueue.cleanup()frameAccumulator.cleanup()commsBufferManager.cleanup(),见 ComFprime.fpp),框架会自动在拓扑拆除阶段释放其分配的资源,部署方无需额外处理。

5.6 辅助定义文件

子拓扑还附带两个轻量级辅助头文件,供部署的TopologyDefs.hpp/PingEntries.hpp复用:

  • SubtopologyTopologyDefs.hpp:定义ComFprime::SubtopologyState(当前为空结构,无需外部状态)与ComFprime::TopologyState
  • PingEntries.hpp:定义PingEntries命名空间(当前无支持 Ping 的组件,为空)。

6. 需求追溯矩阵

需求 ID满足者(实例/类型)
SVC-COMFPRIME-001framerSvc.FprimeFramer
SVC-COMFPRIME-002deframerSvc.FprimeDeframer
SVC-COMFPRIME-003routerSvc.FprimeRouter
SVC-COMFPRIME-004Subtopology
SVC-COMFPRIME-005FramingSubtopology
SVC-COMFPRIME-006ComFprimeConfig

7. 部署自检清单

结合 SDD 与源码实现,接入 ComFprime 时建议逐项确认:

  1. 基地址唯一性ComFprimeConfig.BASE_ID(默认0x03000000)不与部署中其他组件地址空间重叠;
  2. 速率组驱动:已把某个RateGroupMemberOut接到comQueueRun(变体 A)/comQueue.run(变体 B),否则ComQueue不会输出排队的遥测/事件;
  3. 传输端点完整接线:变体 A 的 4 根驱动线($recvrecvReturnIn$sendready)均已接好;变体 B 的 5 根 ComInterface 线(2 出 3 入)均已建立;
  4. 飞行侧挂接commandOut/cmdResponseIn已连命令分发器,fileUplinkOut/fileUplinkReturnIn已连文件上行栈,遥测/事件源已连comPacketQueueIn,文件下行源已连bufferQueueIn
  5. 缓冲池容量匹配BuffMgr的缓冲大小/数量应满足最坏情况下的飞行遥测速率与文件传输并发需求,避免commsBufferManager分配失败导致丢帧。

通过以上配置,ComFprime 即可作为标准 F´ 通信栈的即插即用模块,与Drv.TcpClient/Drv.Udp/Drv.PosixUartDriver等 ByteStream 驱动协同工作。如需 CCSDS 协议栈,可参考 Svc/Subtopologies/ComCcsds 进行对比选型。

【免费下载链接】fprimeF´ - A flight software and embedded systems framework项目地址: https://gitcode.com/GitHub_Trending/fpr/fprime

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/15 10:00:51

Spring Boot传统文化传播网站项目:从需求拆分到部署上线全流程

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/15 10:00:23

Python批量PDF水印工具开发实战

1. 项目概述&#xff1a;批量PDF水印工具的核心价值每次收到客户发来的几十份合同PDF&#xff0c;手动一页页添加公司水印的日子终于可以结束了。这个批量PDF水印工具正是为解决这类重复性劳动而生&#xff0c;它能自动在数百个PDF文件的指定位置&#xff08;页眉、页脚或任意位…

作者头像 李华
网站建设 2026/9/15 9:57:18

如何免费批量下载抖音无水印视频:douyin-downloader 完整指南

如何免费批量下载抖音无水印视频&#xff1a;douyin-downloader 完整指南 【免费下载链接】douyin-downloader A practical Douyin downloader for both single-item and profile batch downloads, with progress display, retries, SQLite deduplication, and browser fallbac…

作者头像 李华
网站建设 2026/9/15 9:56:06

多串口工控主板与串口服务器的本质区别及选型指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华