F´ 中的 CCSDS AOS 解帧器:Svc::Ccsds::AosDeframer 深入解析与配置指南
2026/9/15 14:08:35 网站建设 项目流程

F´ 中的 CCSDS AOS 解帧器:Svc::Ccsds::AosDeframer 深入解析与配置指南

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

导读

Svc::Ccsds::AosDeframer是 F´(F Prime)飞行软件框架中针对 CCSDS AOS Space Data Link Protocol(CCSDS 732.0-B-5)标准实现的解帧(Deframing)组件。它是 F´ 上行链路(uplink)数据栈的接收端核心部件:接收上游Svc::FrameAccumulator或通信适配器送来的定长 AOS 传输帧,从帧数据域(M_PDU)中提取完整的数据包,并通过输出端口逐包向下游(通常为Svc::Ccsds::SpacePacketDeframer或路由器)分发。读完本文,你将掌握该组件的协议支持范围、configure()配置方法、端口接线方式、事件与遥测含义,以及从源码与单元测试出发的底层工作机理,能够在自己的 F´ 拓扑中正确部署并定位问题。

AOS 解帧能力(协议支持范围)

AosDeframer遵循 CCSDS 732.0-B-5 第 5 版规范,实现了 AOS SDL 的一个明确子集。依据 组件 SDD 与 FPP 定义(该文件顶部注释同样标注了标准版本),支持项如下:

  • 单一虚拟信道(NumVcs = 1:通过configure()函数指定唯一可接受的虚拟信道(VC);
  • M_PDU(Multiplexing PDU)数据域服务:支持数据包跨多个帧的拼接与重组(spanning packets);
  • 可选的帧错误控制字段(FECF)校验:按规范 4.1.6 节执行 16 位 CRC 校验;
  • 空间数据包协议(SPP)与封装数据包协议(EPP)提取:分别依据 CCSDS 133.0-B-2 与 CCSDS 133.1-B-3,通过 Packet-Version-Number(PVN)掩码按位独立启用;
  • 空闲帧与空闲包丢弃
  • VC 帧计数连续性检查与间隙检测(gap detection)。

明确不支持的特性包括:Space Data Link Security(SDLS)安全服务、传输帧插入域(Transfer Frame Insert Zone)、以及帧头错误控制字段(Frame Header Error Control Field)。在 F´ 的 CCSDS 组件族中,SDLS 相关功能由 CcsdsSdlsDeframer、AesGcmDecryptor 等独立组件承担。

从模块归属看,AosDeframer与 AosFramer 是收发对称的一对:AosFramer负责把包封装进 AOS 帧(下行/遥测方向),AosDeframer负责把帧还原成包(上行/指令方向)。其 FPP 组件定义 中声明为passive component,即被动组件,解帧逻辑全部由dataIn输入端口触发,无需独立线程。

内部工作机理:从帧到包

解帧的主处理流程从 dataIn_handler 实现 开始,可概括为以下步骤。

1. 帧长与 FECF 校验

  • 若接收缓冲区大小小于配置的fixedFrameSize,直接报InvalidFrameLength事件、通过errorNotify通知、并把帧缓冲区经dataReturnOut归还发送方;
  • 若启用了 FECF,调用validateFecf()(实现见 AosDeframer.cpp):对帧前fixedFrameSize - 2字节用Ccsds::Utils::CRC16::compute计算 CRC,与帧尾 trailer 中收到的 FECF 比对,失败即丢弃该帧并累计CrcErrorCount遥测。

2. 帧头解析与校验(parseAndValidateHeader)

parseAndValidateHeader 按规范 4.1.2 节逐字段解析 AOS 主帧头,任一失败都会触发对应事件与errorNotify,并返回nullptr使该帧被丢弃:

  • Transfer Frame Version Number(TFVN):AOS 取二进制01Tfvn::AOS),不匹配报InvalidTfvn
  • Spacecraft ID(10 位):由globalVcId低 8 位与 signaling 字段高 2 位拼接得到,与配置值不匹配报InvalidSpacecraftId
  • Virtual Channel ID(6 位):在已配置 VC 集合(当前仅一个)中查找,找不到报InvalidVcId
  • VC 帧计数(默认 24 位):若使用了帧计数循环(frame count cycle,见规范 4.1.2.5.3),会把 4 位循环计数扩展到第 24~27 位。自该 VC 第一帧被接受后,若接收计数 != (上一计数 + 1) & frameCountMask,则报VcFrameCountGap、通过errorNotify通知,并主动放弃当前正在重组的跨帧包(abandonSpanningPacket)。

从源码结构看,AosDeframerVc结构体(AosDeframer.hpp)保留了每 VC 的framesProcessedpacketsExtractedvcFrameCount计数以及跨帧包重组状态,其设计刻意镜像了AosFramer::AosVc模式,为将来扩展多 VC 支持预留了结构。

3. M_PDU 数据域提取(extractPackets)

extractPackets 先解析 M_PDU 头的 First Header Pointer(FHP,规范 4.1.4.2.2 节),据此确定数据域内包边界:

  • FHP = 0x7FE(空闲数据标识,FHP_IDLE_DATA_ONLY):整帧只有空闲数据,报IdleFrame事件后返回;
  • FHP = 0x7FF(无包起始,FHP_NO_PACKET_START):整个数据域是上一包的延续数据,追加到跨帧重组缓冲区;
  • FHP >= dataZoneSize:指针越界(不可信输入),报InvalidFhp并放弃进行中的跨帧包;
  • 其余情况:FHP 之前是上一包的延续数据(若有跨帧包则先appendToSpanningPacket),随后从 FHP 处开始循环提取一个个新包。

4. 跨帧包的重组与缓冲生命周期

当一个包超过单帧数据域容量时,解帧器需要跨多帧累积。关键实现是 appendToSpanningPacket,其工作方式非常讲究:

  • 先入静态头缓冲:在确定包总大小之前,最多HEADER_BUF_SIZE = 8字节(EPP 最大头长度)先暂存于 VC 结构体内的静态headerBuf
  • 再动态分配:一旦通过sizePacket()确定包大小,立即经allocate端口(Fw.BufferGet)向 BufferManager 申请整包缓冲区,将已累积的头字节拷入,继续从帧中填充剩余数据;
  • 完成即输出:当bytesReceived >= buffer.getSize()时,把完整包连同上下文经dataOut发出,PacketsExtracted遥测 +1,并清空状态;
  • 失败即放弃:若allocate失败或分配尺寸不足,报SpanningPacketAllocFailed并跳过该包;若因帧计数间隙、FHP 越界等原因无法完成,报SpanningPacketAbandoned(事件中带有已收/应收字节数,便于诊断)。

包大小的判定由 sizePacket 依据首字节高 3 位(PVN)分派:

  • SPP(PVN=0):sizeSppPacket 解析 6 字节空间包主头,按规范 4.1.3.5.2 由packetDataLength + 1计算总长;APID 为0x7FFComCfg::Apid::SPP_IDLE_PACKET,见 default/config/ComCfg.fpp)时判定为空闲包,表示本帧最后一个包;
  • EPP(PVN=7):sizeEppPacket 依据 133.1-B-3 解析可变的 length-of-length(0/1/2/3/4),处理扩展字节与保留字段,并对 32 位目标上可能出现的整数溢出做了静态与运行时双重防护;protocolId = Idle时同样视为本帧结束;
  • 其余 PVN 值在编译期断言拒绝(FW_ASSERT(false)),因为configure()只允许启用 SPP 与/或 EPP。

5. 缓冲所有权管理

所有权流转是 F´ 数据链路的经典模式:

  • 帧缓冲:上游经dataIn送入后,无论成败,最终都经dataReturnOut归还发送方(见 dataIn_handler);
  • 跨帧包缓冲:由解帧器通过allocate端口取得,发出给下游后,下游使用完毕经dataReturnIn送回,dataReturnIn_handler 统一调用deallocate归还 BufferManager;中途放弃的跨帧包缓冲也由解帧器自己释放。

配置:configure() 详解

configure()必须在处理任何帧之前调用。完整签名见 AosDeframer.hpp:

deframer.configure( fixedFrameSize, // 定长 AOS 帧大小(字节),规范 Section 4.1.1 frameErrorControlField, // 帧尾是否携带 FECF,规范 Section 4.1.6 spacecraftId, // 可接受的 10 位航天器 ID(默认:ComCfg::SpacecraftId) vcId, // 可接受的 6 位虚拟信道 ID(默认:0) pvnMask // 要提取的 PVN 位掩码(默认同时启用 SPP 与 EPP) );

configure 实现 内的校验与副作用如下:

参数类型默认值约束(FW_ASSERT,违反即断言失败)
fixedFrameSizeU32ComCfg::AosMaxFrameFixedSize必须<= ComCfg::AosMaxFrameFixedSize(默认配置为 1536 字节,见 default/config/ComCfg.fpp);必须大于AOSHeader(6) + M_PDUHeader(2) + (FECF? AOSTrailer(2):0)的最小值
frameErrorControlFieldbooltrue(构造函数默认,AosDeframer.cpp)
spacecraftIdU16ComCfg::SpacecraftId(默认0x0044必须满足(spacecraftId & 0xFC00) == 0(10 位有效)
vcIdU80必须满足(vcId & 0xC0) == 0(6 位有效)
pvnMaskU8PvnBitfield::SPP_MASK \| PvnBitfield::EPP_MASK必须至少置位一个有效位,且不能含有有效位之外的位(VALID_MASK

此外,configure()还会断言allocatedeallocate输出端口已连接——因为跨帧包重组依赖动态缓冲分配,未接线即调用会在配置阶段直接暴露问题。调用结束后会重置 FECF 错误计数与各 VC 统计,并清理未完成的跨帧包状态,因此可安全地重复调用。

默认常量可在 default/config/ComCfg.fpp 中查看:SpacecraftId = 0x0044AosMaxFrameFixedSize = 1536。工程部署时应在此配置文件中按任务实际参数调整。注意该文件中的TmFrameFixedSize = 1024针对的是 TM(遥测)帧,AOS 帧尺寸以AosMaxFrameFixedSize为准。

端口描述

组件端口在 AosDeframer.fpp 中声明,SDD 汇总如下:

Kind端口名端口类型说明
guarded inputdataInSvc.ComDataWithContext接收已定帧的 AOS 数据(对应 CCSDS 3.4.3.2 节VC_RECEIVE.indication服务原语)
outputdataOutSvc.ComDataWithContext输出提取出的数据包(携带上下文)
outputdataReturnOutSvc.ComDataWithContext将收到的帧缓冲所有权归还发送方
sync inputdataReturnInSvc.ComDataWithContext接收下游归还的数据包缓冲所有权
outputerrorNotifyCcsds.ErrorNotify向连接的组件通知解帧错误
outputallocateFw.BufferGet为跨多帧的数据包分配缓冲区
outputdeallocateFw.BufferSend释放跨帧包缓冲区

除业务端口外,FPP 定义 还声明了 F´ 标准 AC 端口:timeCaller(取时间)、logTextOut/logOut(事件文本与事件下行)、tlmOut(遥测下行)、prmGetOut/prmSetOut(参数读写)。上下文类型ComCfg::FrameContext(default/config/ComCfg.fpp)在组件间传递comQueueIndexapidsequenceFlags/CountvcIdpvnsaIndexfirstHeaderPointer等字段,其中pvn正是由本组件在跨帧包生命周期内维护的。

典型接线:上游Svc::FrameAccumulator(或直接是TcpServer/Udp等通信适配器)→dataIndataOutSvc::Ccsds::SpacePacketDeframer或路由器;allocate/deallocateSvc::BufferManagererrorNotify→ 错误监测组件。解帧器自身作为DeframerInterface的 AOS 实现,与 TcDeframer、SpacePacketDeframer 处于同一抽象层次,形成可替换的解帧组件族。

事件(Events)

下表事件定义在 AosDeframerEvents.fppi,格式串中的字段可辅助排障:

事件严重级别触发条件
InvalidSpacecraftIdwarning low帧 SCID 与配置不符(事件携带收到的值与配置值)
InvalidFrameLengthwarning high帧长度与配置的定长不符(携带实际/期望长度)
InvalidVcIdactivity low帧 VCID 不在可接受集合中
InvalidFecfwarning highFECF(CRC)校验失败(携带帧尾值与板载计算值)
InvalidTfvnwarning high传输帧版本号非法(携带收到的与期望的 TFVN)
DisabledPvnwarning high包版本号无效或被配置掩码禁用(携带 VC 与 PVN)
IdleFrameactivity low帧仅含空闲数据
SpanningPacketAllocFailedwarning high跨帧包缓冲分配失败,包被丢弃(携带 VC、PVN、请求字节数)
VcFrameCountGapwarning highVC 帧计数序列出现不连续(携带收到值与期望的下一个值)
SpanningPacketAbandonedwarning high跨帧包在完成前被放弃(携带已收/应收字节数)
InvalidFhpwarning highFirst Header Pointer 超出数据域大小

遥测(Telemetry)

遥测通道定义在 AosDeframerTelem.fppi,可用于监控链路健康状况:

通道类型说明
LatestVcFrameCountU32最近一次从帧头收到的 VC 帧计数
FramesProcessedU32每个虚拟信道已处理的帧数
PacketsExtractedU32每个虚拟信道已提取的包数
CrcErrorCountU32FECF(CRC)错误数(按物理信道统计,与 VC 无关)

从实现看,CrcErrorCount是组件级的独立成员m_crcErrorCount(AosDeframer.hpp),因为 FECF 属于物理信道层面的保护,注释明确其按物理信道而非 VC 计数;其余三项为每 VC 状态(AosDeframerVc内成员),当前NumVcs = 1时二者等价。实践中建议用FramesProcessedPacketsExtracted的差值辅助判断是否存在持续无法提取的帧,用VcFrameCountGap事件与CrcErrorCount联动定位上行链路误码或丢帧。

单元测试佐证

组件测试位于 Svc/Ccsds/AosDeframer/test/ut,其中的 AosDeframerTestSupport.cpp 展示了手工构造 AOS 帧的完整套路,可作为理解帧布局与自测工具开发的参考:

  • assembleFrameBuffer()按位构造 6 字节 AOS 主头(TFVN 2 位 | SCID 低 8 位 | VCID 6 位 + 24 位 VC 帧计数 + signaling 字段)、2 字节 M_PDU 头(FHP)、数据区与可选 FECF trailer,并用Ccsds::Utils::CRC16计算帧尾 CRC;
  • createSppPacket()构造 SPP 包(PVN=0、APID、序列号、长度),createEppPacket()构造 EPP 包(含 Idle 填充包、各种 length-of-length 变体);
  • from_allocate_handler模拟 BufferManager,支持注入m_failNextAlloc以测试SpanningPacketAllocFailed路径;
  • configureDefault()使用TEST_FRAME_SIZEComCfg::SpacecraftId、VC 0 以及 SPP|EPP 掩码作为基准配置,印证了configure()的典型调用形态。

测试辅助代码还揭示了一个实用细节:数据域剩余空间不足时用 EPP Idle 填充包(protocolId=0, lengthOfLength=0)补齐,避免将零字节误判为合法 SPP 包——这与生产实现中 Idle 包丢弃逻辑(sizeSppPacket/sizeEppPacket返回 0)完全对应。

部署建议与限制

综合文档与源码,部署AosDeframer时需要注意以下几点:

  1. 先配置后使用configure()必须早于任何dataIn调用,且allocate/deallocate端口必须先接线,否则断言失败;
  2. 定长帧前提:AOS 是定长帧协议,上游(FrameAccumulator 或协议适配器)必须保证交到dataIn的是完整定长帧;本组件只负责长度与 CRC 校验,不做帧同步;
  3. 单 VC 限制:当前NumVcs = 1,若任务需要多虚拟信道,需要等待或自行扩展getVcStructm_vcs数组(源码中已留 TODO 与AosDeframerVc结构);
  4. PVN 掩码选择:默认同时启用 SPP 与 EPP;若链路上只有一种协议,可收窄掩码以降低误判与DisabledPvn事件噪声;
  5. 缓冲容量规划:跨帧包的最大尺寸受allocate端口所接 BufferManager 的容量约束,需按最坏情况(如最大 EPP/SPP 包)规划缓冲池,避免SpanningPacketAllocFailed反复出现。

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

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

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询